aiur-cli 0.0.9-nightly.5a0d430 → 0.0.9-nightly.d4c6e4c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aiur.js +37 -17
- package/libexec/aiur-engine.sh +110 -15
- package/package.json +4 -4
package/bin/aiur.js
CHANGED
|
@@ -165,8 +165,8 @@ function ensureTmux() {
|
|
|
165
165
|
// True only when the pinned opencode is on PATH; a wrong (e.g. newer,
|
|
166
166
|
// unverified) version must be replaced with the pin, so presence alone
|
|
167
167
|
// isn't enough.
|
|
168
|
-
function opencodeMatchesPin() {
|
|
169
|
-
const result = safeSpawn(
|
|
168
|
+
function opencodeMatchesPin(command = "opencode") {
|
|
169
|
+
const result = safeSpawn(command, ["--version"], { encoding: "utf8" });
|
|
170
170
|
return !result.error && result.status === 0 && (result.stdout || "").trim() === opencodeVersion();
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -185,40 +185,60 @@ function installOpencode() {
|
|
|
185
185
|
return !result.error && result.status === 0;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
// npm's global bin may be shadowed by another OpenCode on the incoming PATH.
|
|
189
|
+
// Verify the actual installed executable before making it the release's choice.
|
|
190
|
+
function selectGlobalOpencode() {
|
|
191
|
+
const result = safeSpawn("npm", ["prefix", "-g"], { encoding: "utf8" });
|
|
192
|
+
if (result.error || result.status !== 0) return false;
|
|
193
|
+
const prefix = (result.stdout || "").trim();
|
|
194
|
+
if (!path.isAbsolute(prefix)) return false;
|
|
195
|
+
const bin = path.join(prefix, "bin");
|
|
196
|
+
if (!opencodeMatchesPin(path.join(bin, "opencode"))) return false;
|
|
197
|
+
process.env.PATH = `${bin}${path.delimiter}${process.env.PATH || ""}`;
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
188
201
|
// opencode powers the interactive "take the wheel" panes. Non-fatal: everything
|
|
189
202
|
// else works without it.
|
|
190
203
|
function ensureOpencode() {
|
|
191
|
-
if (opencodeMatchesPin()) return;
|
|
204
|
+
if (opencodeMatchesPin() || selectGlobalOpencode()) return;
|
|
192
205
|
if (process.env.AIUR_SKIP_OPENCODE_INSTALL !== "1") {
|
|
193
206
|
process.stderr.write(
|
|
194
207
|
`aiur: provisioning opencode@${opencodeVersion()} (one-time, for the interactive 'take the wheel' panes)…\n`,
|
|
195
208
|
);
|
|
196
209
|
installOpencode();
|
|
197
|
-
if (opencodeMatchesPin()) return;
|
|
210
|
+
if (opencodeMatchesPin() || selectGlobalOpencode()) return;
|
|
198
211
|
}
|
|
199
212
|
process.stderr.write(
|
|
200
|
-
|
|
213
|
+
`aiur: opencode@${opencodeVersion()} is unavailable. The interactive 'take the wheel' ` +
|
|
201
214
|
"feature needs it; everything else works without it. " +
|
|
202
|
-
|
|
215
|
+
`Install with: npm install -g opencode-ai@${opencodeVersion()}, ` +
|
|
216
|
+
"and put npm's global bin ahead of other opencode binaries on PATH.\n",
|
|
203
217
|
);
|
|
204
218
|
}
|
|
205
219
|
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
220
|
+
// Match the shared engine's first-argument dispatch: only session launch paths
|
|
221
|
+
// need interactive tools. Unknown commands still reach the engine's usage error.
|
|
222
|
+
function requiresInteractiveTools(argv) {
|
|
223
|
+
const command = argv[0] || "";
|
|
224
|
+
if (["", "run", "restart", "--bg"].includes(command)) return true;
|
|
225
|
+
const nonLaunchCommands = new Set([
|
|
226
|
+
"__identity", "help", "-h", "-help", "--h", "--help", "--version", "--todo", "--only",
|
|
227
|
+
"init", "findings", "ask", "asks", "status", "usage", "agents", "commands", "units",
|
|
228
|
+
"build-orders", "analytics", "github-cost", "github-usage", "alerts", "watch", "set",
|
|
229
|
+
"upgrade", "pause", "resume", "reset-budget", "message", "cleanup-stale", "stop",
|
|
230
|
+
"executor-answer", "executor-escalate", "executor-moot", "executor-listen", "executor-wait",
|
|
231
|
+
"executor-emit", "executor-subscribe", "executor-unsubscribe", "executor-subscriptions",
|
|
232
|
+
"executor-roster", "executor-fast-forward", "executor-claim", "executor-release", "executor-revoke",
|
|
233
|
+
]);
|
|
234
|
+
if (nonLaunchCommands.has(command)) return false;
|
|
235
|
+
return command.startsWith("-") || fs.existsSync(command);
|
|
216
236
|
}
|
|
217
237
|
|
|
218
238
|
function main() {
|
|
219
239
|
const releaseDir = resolveReleaseDir();
|
|
220
240
|
|
|
221
|
-
if (
|
|
241
|
+
if (requiresInteractiveTools(process.argv.slice(2))) {
|
|
222
242
|
ensureTmux();
|
|
223
243
|
ensureOpencode();
|
|
224
244
|
}
|
package/libexec/aiur-engine.sh
CHANGED
|
@@ -450,6 +450,9 @@ usage() {
|
|
|
450
450
|
Usage: aiur [--interactive] [--no-dashboard] [--executor] [--pause] [--max-agents <n>] [--logs-root <path>] [--port <port>] [--host <host>] [config-path]
|
|
451
451
|
aiur run [--bg] [--no-dashboard] [--executor] [--debug] explicit launch form (foreground unless --bg)
|
|
452
452
|
aiur init [--force] scaffold .aiur/config (interactive setup wizard)
|
|
453
|
+
aiur login <harness> <name> [--dir <path>] sign in to a supported backend account
|
|
454
|
+
aiur accounts [<harness>] [--json] list registered accounts
|
|
455
|
+
aiur logout <harness> <name> [--purge] remove a backend account
|
|
453
456
|
aiur --bg [--no-dashboard] [--executor] [--debug] start detached; dashboard on unless suppressed
|
|
454
457
|
aiur stop stop the running session
|
|
455
458
|
aiur restart [--no-build] [run flags] stop, refresh the build, start again (detached)
|
|
@@ -472,6 +475,7 @@ Usage: aiur [--interactive] [--no-dashboard] [--executor] [--pause] [--max-agent
|
|
|
472
475
|
aiur executor-emit <topic> --payload <json> publish an Executor event
|
|
473
476
|
aiur executor-subscribe|executor-unsubscribe <pattern>
|
|
474
477
|
aiur executor-subscriptions list persistent Executor bindings
|
|
478
|
+
aiur workspace-recover <ticket-identifier> <generation> release a held workspace after verified provider exit
|
|
475
479
|
aiur executor-roster [--json] list Executor consumers with their liveness evidence
|
|
476
480
|
aiur executor-claim [--as <id>] claim the wake stream, or refuse and name the live owner
|
|
477
481
|
aiur executor-release [--as <id>] give up this consumer's claim
|
|
@@ -522,6 +526,47 @@ run_init() {
|
|
|
522
526
|
exec "${release_cmd[@]}"
|
|
523
527
|
}
|
|
524
528
|
|
|
529
|
+
run_local_cli() {
|
|
530
|
+
resolve_release
|
|
531
|
+
build_init_cmd
|
|
532
|
+
init_argv_file
|
|
533
|
+
write_argv "$@"
|
|
534
|
+
export AIUR_ARGV_FILE="$argv_file"
|
|
535
|
+
exec "${release_cmd[@]}"
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
run_claude_login() {
|
|
539
|
+
resolve_release
|
|
540
|
+
local profile_dir
|
|
541
|
+
build_init_cmd
|
|
542
|
+
init_argv_file
|
|
543
|
+
write_argv "__login_prepare" "${@:2}"
|
|
544
|
+
export AIUR_ARGV_FILE="$argv_file"
|
|
545
|
+
profile_dir="$("${release_cmd[@]}")" || return $?
|
|
546
|
+
[ -n "$profile_dir" ] || { echo "aiur: account profile directory is unavailable" >&2; return 1; }
|
|
547
|
+
exec env "CLAUDE_CONFIG_DIR=$profile_dir" claude
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
run_account_login() {
|
|
551
|
+
local harness="$2"
|
|
552
|
+
case "$harness" in
|
|
553
|
+
kimi|deepseek|openrouter) run_local_cli "$@"; return $? ;;
|
|
554
|
+
esac
|
|
555
|
+
resolve_release
|
|
556
|
+
local profile_dir
|
|
557
|
+
build_init_cmd
|
|
558
|
+
init_argv_file
|
|
559
|
+
write_argv "__login_prepare" "$harness" "${@:3}"
|
|
560
|
+
export AIUR_ARGV_FILE="$argv_file"
|
|
561
|
+
profile_dir="$("${release_cmd[@]}")" || return $?
|
|
562
|
+
[ -n "$profile_dir" ] || { echo "aiur: account profile directory is unavailable" >&2; return 1; }
|
|
563
|
+
case "$harness" in
|
|
564
|
+
claude) exec env "CLAUDE_CONFIG_DIR=$profile_dir" claude ;;
|
|
565
|
+
codex) exec env "CODEX_HOME=$profile_dir" codex ;;
|
|
566
|
+
*) echo "aiur: unsupported account harness: $harness" >&2; return 64 ;;
|
|
567
|
+
esac
|
|
568
|
+
}
|
|
569
|
+
|
|
525
570
|
# --- one-shot: --todo (control RPC; requires a running daemon) ----------------
|
|
526
571
|
|
|
527
572
|
parsed_todo_only=0
|
|
@@ -723,22 +768,10 @@ scrub_run_only_env() {
|
|
|
723
768
|
}
|
|
724
769
|
|
|
725
770
|
run_argv=()
|
|
726
|
-
# Default dashboard bind host.
|
|
727
|
-
#
|
|
728
|
-
# fall back to loopback when Tailscale is absent, or when dashboard credentials
|
|
729
|
-
# are unset (a non-loopback bind requires them, so we stay on loopback rather
|
|
730
|
-
# than refuse to start). The BEAM applies this below an explicit `server.host`,
|
|
731
|
-
# while an explicit `--host` remains the highest-precedence value.
|
|
771
|
+
# Default dashboard bind host. Remote access is an explicit operator choice.
|
|
772
|
+
# The BEAM applies this below `server.host`; `--host` has highest precedence.
|
|
732
773
|
default_dashboard_host() {
|
|
733
|
-
|
|
734
|
-
if command -v tailscale >/dev/null 2>&1; then
|
|
735
|
-
ip="$(tailscale ip -4 2>/dev/null | grep -m1 -E '^100\.[0-9]+\.[0-9]+\.[0-9]+$' || true)"
|
|
736
|
-
fi
|
|
737
|
-
if [ -n "$ip" ] && [ -n "${AIUR_DASHBOARD_USERNAME:-}" ] && [ -n "${AIUR_DASHBOARD_PASSWORD:-}" ]; then
|
|
738
|
-
printf '%s' "$ip"
|
|
739
|
-
else
|
|
740
|
-
printf '127.0.0.1'
|
|
741
|
-
fi
|
|
774
|
+
printf '%s' "${AIUR_DEFAULT_DASHBOARD_HOST:-127.0.0.1}"
|
|
742
775
|
}
|
|
743
776
|
|
|
744
777
|
build_run_argv() {
|
|
@@ -2633,6 +2666,44 @@ cmd_usage() {
|
|
|
2633
2666
|
run_control_rpc "Aiur.AgentControlCLI.usage()"
|
|
2634
2667
|
}
|
|
2635
2668
|
|
|
2669
|
+
cmd_accounts() {
|
|
2670
|
+
local json_arg=false harness="" arg encoded expression
|
|
2671
|
+
for arg in "$@"; do
|
|
2672
|
+
case "$arg" in
|
|
2673
|
+
--json)
|
|
2674
|
+
[ "$json_arg" = false ] || die "accounts accepts --json only once"
|
|
2675
|
+
json_arg=true
|
|
2676
|
+
;;
|
|
2677
|
+
--all)
|
|
2678
|
+
;;
|
|
2679
|
+
-*)
|
|
2680
|
+
die "accounts accepts an optional harness and --json"
|
|
2681
|
+
;;
|
|
2682
|
+
*)
|
|
2683
|
+
[ -z "$harness" ] || die "accounts accepts only one harness"
|
|
2684
|
+
harness="$arg"
|
|
2685
|
+
;;
|
|
2686
|
+
esac
|
|
2687
|
+
done
|
|
2688
|
+
|
|
2689
|
+
resolve_release || return $?
|
|
2690
|
+
prepare_distribution || die "distribution setup failed; cannot contact aiur"
|
|
2691
|
+
resolve_control_identity_from_records
|
|
2692
|
+
if [ "$(probe_node_liveness)" = "down" ]; then
|
|
2693
|
+
# The local one-shot CLI renders the identity and marks usage unavailable.
|
|
2694
|
+
# It never makes a provider request.
|
|
2695
|
+
run_local_cli accounts "$@"
|
|
2696
|
+
else
|
|
2697
|
+
if [ -n "$harness" ]; then
|
|
2698
|
+
encoded="$(printf '%s' "$harness" | base64 | tr -d '\n')"
|
|
2699
|
+
expression="Aiur.AgentControlCLI.accounts($json_arg, Base.decode64!(\"$encoded\"))"
|
|
2700
|
+
else
|
|
2701
|
+
expression="Aiur.AgentControlCLI.accounts($json_arg)"
|
|
2702
|
+
fi
|
|
2703
|
+
run_control_rpc "$expression"
|
|
2704
|
+
fi
|
|
2705
|
+
}
|
|
2706
|
+
|
|
2636
2707
|
cmd_pause_resume() {
|
|
2637
2708
|
local command="$1"
|
|
2638
2709
|
shift
|
|
@@ -2680,6 +2751,16 @@ cmd_reset_budget() {
|
|
|
2680
2751
|
run_control_rpc "$expression"
|
|
2681
2752
|
}
|
|
2682
2753
|
|
|
2754
|
+
# Requires the operator to name the exact ticket and generation shown by
|
|
2755
|
+
# status. The daemon independently verifies the recorded boot proof.
|
|
2756
|
+
cmd_workspace_recover() {
|
|
2757
|
+
[ "$#" -eq 2 ] || { echo "aiur: workspace-recover expects a ticket identifier and generation (e.g. aiur workspace-recover ENG-123 7)" >&2; exit 64; }
|
|
2758
|
+
local ticket="$1" generation="$2" encoded
|
|
2759
|
+
[[ "$generation" =~ ^[1-9][0-9]*$ ]] || { echo "aiur: workspace-recover generation must be a positive integer" >&2; exit 64; }
|
|
2760
|
+
encoded="$(printf '%s' "$ticket" | base64 | tr -d '\n')"
|
|
2761
|
+
run_control_rpc "Aiur.AgentControlCLI.recover_workspace(Base.decode64!(\"$encoded\"), $generation)"
|
|
2762
|
+
}
|
|
2763
|
+
|
|
2683
2764
|
# `aiur message <issue> <text>` — deliver Executor text to one running agent.
|
|
2684
2765
|
# The text is base64-encoded for the RPC hop so arbitrary content (quotes,
|
|
2685
2766
|
# backslashes, `#{}`, newlines) survives without Elixir-string escaping.
|
|
@@ -4106,6 +4187,16 @@ aiur_engine_main() {
|
|
|
4106
4187
|
init)
|
|
4107
4188
|
run_init "$@"
|
|
4108
4189
|
;;
|
|
4190
|
+
login)
|
|
4191
|
+
run_account_login "$@"
|
|
4192
|
+
;;
|
|
4193
|
+
accounts)
|
|
4194
|
+
shift
|
|
4195
|
+
cmd_accounts "$@"
|
|
4196
|
+
;;
|
|
4197
|
+
logout)
|
|
4198
|
+
run_local_cli "$@"
|
|
4199
|
+
;;
|
|
4109
4200
|
findings)
|
|
4110
4201
|
run_findings "$@"
|
|
4111
4202
|
;;
|
|
@@ -4231,6 +4322,10 @@ aiur_engine_main() {
|
|
|
4231
4322
|
shift
|
|
4232
4323
|
cmd_reset_budget "$@"
|
|
4233
4324
|
;;
|
|
4325
|
+
workspace-recover)
|
|
4326
|
+
shift
|
|
4327
|
+
cmd_workspace_recover "$@"
|
|
4328
|
+
;;
|
|
4234
4329
|
message)
|
|
4235
4330
|
shift
|
|
4236
4331
|
cmd_message "$@"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiur-cli",
|
|
3
|
-
"version": "0.0.9-nightly.
|
|
3
|
+
"version": "0.0.9-nightly.d4c6e4c",
|
|
4
4
|
"description": "AI Unit Runtime for Executors.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/aiur-team/aiur",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
],
|
|
36
36
|
"opencodeVersion": "1.17.10",
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"aiur-cli-linux-x64": "0.0.9-nightly.
|
|
39
|
-
"aiur-cli-linux-arm64": "0.0.9-nightly.
|
|
40
|
-
"aiur-cli-darwin-arm64": "0.0.9-nightly.
|
|
38
|
+
"aiur-cli-linux-x64": "0.0.9-nightly.d4c6e4c",
|
|
39
|
+
"aiur-cli-linux-arm64": "0.0.9-nightly.d4c6e4c",
|
|
40
|
+
"aiur-cli-darwin-arm64": "0.0.9-nightly.d4c6e4c"
|
|
41
41
|
}
|
|
42
42
|
}
|