@integrity-labs/agt-cli 0.10.8 → 0.10.10
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/dist/bin/agt.js +236 -83
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-VDUA5FEW.js → chunk-PZG4XPJV.js} +5 -8
- package/dist/chunk-PZG4XPJV.js.map +1 -0
- package/dist/lib/manager-worker.js +172 -81
- package/dist/lib/manager-worker.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-VDUA5FEW.js.map +0 -1
package/dist/bin/agt.js
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
resolveChannels,
|
|
33
33
|
serializeManifestForSlackCli,
|
|
34
34
|
setActiveTeam
|
|
35
|
-
} from "../chunk-
|
|
35
|
+
} from "../chunk-PZG4XPJV.js";
|
|
36
36
|
|
|
37
37
|
// src/bin/agt.ts
|
|
38
38
|
import { join as join11 } from "path";
|
|
@@ -107,7 +107,7 @@ async function whoamiCommand() {
|
|
|
107
107
|
jsonOutput({
|
|
108
108
|
ok: true,
|
|
109
109
|
api_key_prefix: apiKey.slice(0, 8) + "****",
|
|
110
|
-
host: getHost()
|
|
110
|
+
host: getHost(),
|
|
111
111
|
host_id: exchange.hostId,
|
|
112
112
|
team: exchange.teamSlug,
|
|
113
113
|
team_id: exchange.teamId,
|
|
@@ -117,7 +117,7 @@ async function whoamiCommand() {
|
|
|
117
117
|
}
|
|
118
118
|
success("Authenticated via API key");
|
|
119
119
|
info(`API Key: ${chalk3.bold(apiKey.slice(0, 8) + "****")}`);
|
|
120
|
-
info(`Host: ${chalk3.bold(getHost()
|
|
120
|
+
info(`Host: ${chalk3.bold(getHost())}`);
|
|
121
121
|
info(`Host ID: ${exchange.hostId}`);
|
|
122
122
|
info(`Team: ${chalk3.bold(exchange.teamSlug ?? exchange.teamId)}`);
|
|
123
123
|
info(`User: ${chalk3.bold(exchange.userEmail ?? "unknown")}`);
|
|
@@ -2053,8 +2053,160 @@ async function hostDecommissionCommand(hostName) {
|
|
|
2053
2053
|
}
|
|
2054
2054
|
}
|
|
2055
2055
|
|
|
2056
|
-
// src/commands/
|
|
2056
|
+
// src/commands/host-pair.ts
|
|
2057
|
+
import { spawn, spawnSync } from "child_process";
|
|
2057
2058
|
import chalk14 from "chalk";
|
|
2059
|
+
async function hostPairCommand(name, opts) {
|
|
2060
|
+
const teamSlug = requireTeam();
|
|
2061
|
+
if (!teamSlug) return;
|
|
2062
|
+
const json = isJsonMode();
|
|
2063
|
+
const localPort = Number(opts.port ?? "54545");
|
|
2064
|
+
if (!Number.isInteger(localPort) || localPort < 1024 || localPort > 65535) {
|
|
2065
|
+
error("--port must be an integer between 1024 and 65535");
|
|
2066
|
+
process.exitCode = 1;
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
let host2;
|
|
2070
|
+
try {
|
|
2071
|
+
const data = await api.get(`/hosts/${encodeURIComponent(name)}`);
|
|
2072
|
+
host2 = data.host;
|
|
2073
|
+
} catch (err) {
|
|
2074
|
+
if (json) jsonOutput({ ok: false, error: err.message });
|
|
2075
|
+
else error(`Failed to look up host: ${err.message}`);
|
|
2076
|
+
process.exitCode = 1;
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
if (host2.provision_source !== "augmented-ec2") {
|
|
2080
|
+
const msg = `Host "${name}" is ${host2.provision_source ?? "self"}-provisioned, not an Augmented-managed EC2. agt host pair is only for EC2 hosts provisioned through the Augmented API.`;
|
|
2081
|
+
if (json) jsonOutput({ ok: false, error: msg });
|
|
2082
|
+
else error(msg);
|
|
2083
|
+
process.exitCode = 1;
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
if (!host2.ec2_instance_id) {
|
|
2087
|
+
const msg = `Host "${name}" has no EC2 instance ID yet. Provision it first with \`agt host provision\`.`;
|
|
2088
|
+
if (json) jsonOutput({ ok: false, error: msg });
|
|
2089
|
+
else error(msg);
|
|
2090
|
+
process.exitCode = 1;
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2093
|
+
const region = host2.ec2_region ?? process.env.AWS_REGION ?? "us-east-2";
|
|
2094
|
+
const instanceId = host2.ec2_instance_id;
|
|
2095
|
+
const preflightErr = preflightAws();
|
|
2096
|
+
if (preflightErr) {
|
|
2097
|
+
if (json) jsonOutput({ ok: false, error: preflightErr });
|
|
2098
|
+
else error(preflightErr);
|
|
2099
|
+
process.exitCode = 1;
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
if (json) {
|
|
2103
|
+
jsonOutput({
|
|
2104
|
+
ok: true,
|
|
2105
|
+
host: { name: host2.name, id: host2.id, instance_id: instanceId, region },
|
|
2106
|
+
port_forward: {
|
|
2107
|
+
command: "aws",
|
|
2108
|
+
args: [
|
|
2109
|
+
"ssm",
|
|
2110
|
+
"start-session",
|
|
2111
|
+
"--region",
|
|
2112
|
+
region,
|
|
2113
|
+
"--target",
|
|
2114
|
+
instanceId,
|
|
2115
|
+
"--document-name",
|
|
2116
|
+
"AWS-StartPortForwardingSession",
|
|
2117
|
+
"--parameters",
|
|
2118
|
+
JSON.stringify({ portNumber: [String(localPort)], localPortNumber: [String(localPort)] })
|
|
2119
|
+
]
|
|
2120
|
+
},
|
|
2121
|
+
shell: {
|
|
2122
|
+
command: "aws",
|
|
2123
|
+
args: ["ssm", "start-session", "--region", region, "--target", instanceId]
|
|
2124
|
+
}
|
|
2125
|
+
});
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
info(`Pairing Claude Code on ${chalk14.bold(name)} (${instanceId}, ${region})`);
|
|
2129
|
+
info(`Local port ${chalk14.cyan(String(localPort))} will be forwarded to the host.`);
|
|
2130
|
+
console.log();
|
|
2131
|
+
console.log(chalk14.dim("In the shell that opens, run:"));
|
|
2132
|
+
console.log(` ${chalk14.cyan(`CLAUDE_CODE_OAUTH_PORT=${localPort} claude /login`)}`);
|
|
2133
|
+
console.log(chalk14.dim("Then click the printed URL on this machine. The OAuth callback"));
|
|
2134
|
+
console.log(chalk14.dim(`will reach Claude Code via the port-forward tunnel.`));
|
|
2135
|
+
console.log();
|
|
2136
|
+
console.log(chalk14.dim("Exit the shell (Ctrl+D) when Claude Code reports successful login."));
|
|
2137
|
+
console.log();
|
|
2138
|
+
const tunnel = spawn(
|
|
2139
|
+
"aws",
|
|
2140
|
+
[
|
|
2141
|
+
"ssm",
|
|
2142
|
+
"start-session",
|
|
2143
|
+
"--region",
|
|
2144
|
+
region,
|
|
2145
|
+
"--target",
|
|
2146
|
+
instanceId,
|
|
2147
|
+
"--document-name",
|
|
2148
|
+
"AWS-StartPortForwardingSession",
|
|
2149
|
+
"--parameters",
|
|
2150
|
+
JSON.stringify({ portNumber: [String(localPort)], localPortNumber: [String(localPort)] })
|
|
2151
|
+
],
|
|
2152
|
+
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
2153
|
+
);
|
|
2154
|
+
tunnel.stderr?.on("data", (buf) => {
|
|
2155
|
+
const line = buf.toString().trim();
|
|
2156
|
+
if (line.startsWith("An error occurred")) {
|
|
2157
|
+
console.error(chalk14.red(`[tunnel] ${line}`));
|
|
2158
|
+
}
|
|
2159
|
+
});
|
|
2160
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
2161
|
+
if (tunnel.exitCode !== null) {
|
|
2162
|
+
error("Port-forward tunnel failed to start. Check AWS credentials and session-manager-plugin.");
|
|
2163
|
+
process.exitCode = 1;
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
if (opts.noShell) {
|
|
2167
|
+
console.log(chalk14.dim("--no-shell set; tunnel is running. Press Ctrl+C to exit."));
|
|
2168
|
+
await new Promise((resolve2) => {
|
|
2169
|
+
const onSignal = () => {
|
|
2170
|
+
terminate(tunnel);
|
|
2171
|
+
resolve2();
|
|
2172
|
+
};
|
|
2173
|
+
process.once("SIGINT", onSignal);
|
|
2174
|
+
process.once("SIGTERM", onSignal);
|
|
2175
|
+
});
|
|
2176
|
+
} else {
|
|
2177
|
+
await runInteractive("aws", ["ssm", "start-session", "--region", region, "--target", instanceId]);
|
|
2178
|
+
terminate(tunnel);
|
|
2179
|
+
}
|
|
2180
|
+
success("Pair session ended.");
|
|
2181
|
+
}
|
|
2182
|
+
function preflightAws() {
|
|
2183
|
+
const aws = spawnSync("aws", ["--version"], { stdio: "ignore" });
|
|
2184
|
+
if (aws.status !== 0) {
|
|
2185
|
+
return "AWS CLI not found. Install: https://aws.amazon.com/cli/";
|
|
2186
|
+
}
|
|
2187
|
+
const plugin2 = spawnSync("session-manager-plugin", [], { stdio: "ignore" });
|
|
2188
|
+
if (plugin2.error) {
|
|
2189
|
+
return "session-manager-plugin not found. Install: brew install --cask session-manager-plugin";
|
|
2190
|
+
}
|
|
2191
|
+
return null;
|
|
2192
|
+
}
|
|
2193
|
+
function runInteractive(cmd, args) {
|
|
2194
|
+
return new Promise((resolve2) => {
|
|
2195
|
+
const child = spawn(cmd, args, { stdio: "inherit" });
|
|
2196
|
+
child.on("exit", (code) => resolve2(code ?? 0));
|
|
2197
|
+
child.on("error", () => resolve2(1));
|
|
2198
|
+
});
|
|
2199
|
+
}
|
|
2200
|
+
function terminate(child) {
|
|
2201
|
+
if (child.exitCode !== null) return;
|
|
2202
|
+
try {
|
|
2203
|
+
child.kill("SIGTERM");
|
|
2204
|
+
} catch {
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
// src/commands/manager.ts
|
|
2209
|
+
import chalk15 from "chalk";
|
|
2058
2210
|
import { join as join8 } from "path";
|
|
2059
2211
|
import { homedir } from "os";
|
|
2060
2212
|
|
|
@@ -2172,16 +2324,6 @@ function getManagerStatus() {
|
|
|
2172
2324
|
// src/commands/manager.ts
|
|
2173
2325
|
function managerStartCommand(opts) {
|
|
2174
2326
|
const json = isJsonMode();
|
|
2175
|
-
if (!getHost()) {
|
|
2176
|
-
const msg = "AGT_HOST is not set. Export it to point at the Augmented API (e.g. export AGT_HOST=https://your-api.example.com)";
|
|
2177
|
-
if (json) {
|
|
2178
|
-
jsonOutput({ ok: false, error: msg });
|
|
2179
|
-
} else {
|
|
2180
|
-
error(msg);
|
|
2181
|
-
}
|
|
2182
|
-
process.exitCode = 1;
|
|
2183
|
-
return;
|
|
2184
|
-
}
|
|
2185
2327
|
const apiKey = getApiKey();
|
|
2186
2328
|
if (!apiKey) {
|
|
2187
2329
|
const msg = "AGT_API_KEY is not set. Export it with your host API key (tlk_...)";
|
|
@@ -2267,10 +2409,10 @@ function managerStatusCommand() {
|
|
|
2267
2409
|
jsonOutput({ ok: true, running: true, ...status });
|
|
2268
2410
|
return;
|
|
2269
2411
|
}
|
|
2270
|
-
console.log(
|
|
2412
|
+
console.log(chalk15.bold("\nManager Status\n"));
|
|
2271
2413
|
info(`PID: ${status.pid}`);
|
|
2272
2414
|
info(`Started: ${status.startedAt}`);
|
|
2273
|
-
info(`Last poll: ${status.lastPollAt ??
|
|
2415
|
+
info(`Last poll: ${status.lastPollAt ?? chalk15.dim("none")}`);
|
|
2274
2416
|
info(`Polls: ${status.pollCount}`);
|
|
2275
2417
|
info(`Errors: ${status.errorCount}`);
|
|
2276
2418
|
console.log();
|
|
@@ -2279,19 +2421,19 @@ function managerStatusCommand() {
|
|
|
2279
2421
|
return;
|
|
2280
2422
|
}
|
|
2281
2423
|
const rows = status.agents.map((a) => {
|
|
2282
|
-
let gwStatus =
|
|
2424
|
+
let gwStatus = chalk15.dim("\u2014");
|
|
2283
2425
|
if (a.gatewayRunning) {
|
|
2284
|
-
gwStatus =
|
|
2426
|
+
gwStatus = chalk15.green(`:${a.gatewayPort} (PID ${a.gatewayPid})`);
|
|
2285
2427
|
} else if (a.gatewayPort) {
|
|
2286
|
-
gwStatus =
|
|
2428
|
+
gwStatus = chalk15.red(`:${a.gatewayPort} (down)`);
|
|
2287
2429
|
}
|
|
2288
2430
|
return [
|
|
2289
2431
|
a.codeName,
|
|
2290
|
-
a.status === "active" ?
|
|
2291
|
-
a.charterVersion ||
|
|
2432
|
+
a.status === "active" ? chalk15.green(a.status) : a.status === "paused" ? chalk15.yellow(a.status) : chalk15.dim(a.status ?? "\u2014"),
|
|
2433
|
+
a.charterVersion || chalk15.dim("\u2014"),
|
|
2292
2434
|
gwStatus,
|
|
2293
|
-
a.lastProvisionAt ? new Date(a.lastProvisionAt).toLocaleTimeString() :
|
|
2294
|
-
a.lastDriftCheckAt ? new Date(a.lastDriftCheckAt).toLocaleTimeString() :
|
|
2435
|
+
a.lastProvisionAt ? new Date(a.lastProvisionAt).toLocaleTimeString() : chalk15.dim("\u2014"),
|
|
2436
|
+
a.lastDriftCheckAt ? new Date(a.lastDriftCheckAt).toLocaleTimeString() : chalk15.dim("\u2014")
|
|
2295
2437
|
];
|
|
2296
2438
|
});
|
|
2297
2439
|
table(
|
|
@@ -2300,13 +2442,13 @@ function managerStatusCommand() {
|
|
|
2300
2442
|
);
|
|
2301
2443
|
const acpAgents = status.agents.filter((a) => a.acpSessions && a.acpSessions.length > 0);
|
|
2302
2444
|
if (acpAgents.length > 0) {
|
|
2303
|
-
console.log(
|
|
2445
|
+
console.log(chalk15.bold("\nACP Sessions\n"));
|
|
2304
2446
|
const acpRows = acpAgents.flatMap(
|
|
2305
2447
|
(a) => a.acpSessions.map((s) => [
|
|
2306
2448
|
a.codeName,
|
|
2307
2449
|
s.agentCommand,
|
|
2308
|
-
s.sessionName ??
|
|
2309
|
-
s.queueState === "running" ?
|
|
2450
|
+
s.sessionName ?? chalk15.dim("default"),
|
|
2451
|
+
s.queueState === "running" ? chalk15.green(s.queueState) : s.queueState === "queued" ? chalk15.yellow(s.queueState) : chalk15.dim(s.queueState),
|
|
2310
2452
|
String(s.turnCount),
|
|
2311
2453
|
new Date(s.startedAt).toLocaleTimeString()
|
|
2312
2454
|
])
|
|
@@ -2319,7 +2461,7 @@ function managerStatusCommand() {
|
|
|
2319
2461
|
}
|
|
2320
2462
|
|
|
2321
2463
|
// src/commands/agent.ts
|
|
2322
|
-
import
|
|
2464
|
+
import chalk16 from "chalk";
|
|
2323
2465
|
import JSON52 from "json5";
|
|
2324
2466
|
import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
|
|
2325
2467
|
import { join as join9 } from "path";
|
|
@@ -2453,7 +2595,7 @@ async function agentShowCommand(codeName, opts) {
|
|
|
2453
2595
|
return;
|
|
2454
2596
|
}
|
|
2455
2597
|
const displayName = apiAgent?.display_name ?? charter?.display_name ?? codeName;
|
|
2456
|
-
console.log(
|
|
2598
|
+
console.log(chalk16.bold(`
|
|
2457
2599
|
Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "\n");
|
|
2458
2600
|
if (charter || apiAgent) {
|
|
2459
2601
|
const agentId = apiAgent?.agent_id ?? charter?.agent_id;
|
|
@@ -2485,7 +2627,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
|
|
|
2485
2627
|
info("No agent metadata available");
|
|
2486
2628
|
}
|
|
2487
2629
|
const filtered = opts.allChannels ? channelRows : channelRows.filter((c) => c.enabled);
|
|
2488
|
-
console.log(
|
|
2630
|
+
console.log(chalk16.bold("\nChannels:"));
|
|
2489
2631
|
if (filtered.length === 0) {
|
|
2490
2632
|
info("(none enabled)");
|
|
2491
2633
|
} else {
|
|
@@ -2501,7 +2643,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
|
|
|
2501
2643
|
);
|
|
2502
2644
|
}
|
|
2503
2645
|
if (tools) {
|
|
2504
|
-
console.log(
|
|
2646
|
+
console.log(chalk16.bold("\nTools:"));
|
|
2505
2647
|
if (tools.tools.length === 0) {
|
|
2506
2648
|
info("(none configured)");
|
|
2507
2649
|
} else {
|
|
@@ -2512,7 +2654,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
|
|
|
2512
2654
|
}
|
|
2513
2655
|
if (tools.global_controls) {
|
|
2514
2656
|
const gc = tools.global_controls;
|
|
2515
|
-
console.log(
|
|
2657
|
+
console.log(chalk16.bold("\nGlobal Controls:"));
|
|
2516
2658
|
info(`Network: ${gc.default_network_policy === "deny" ? "deny-by-default" : "allow-by-default"}`);
|
|
2517
2659
|
info(`Timeout: ${gc.default_timeout_ms}ms`);
|
|
2518
2660
|
info(`Rate: ${gc.default_rate_limit_rpm} rpm`);
|
|
@@ -2528,7 +2670,7 @@ function formatTimestamp(iso) {
|
|
|
2528
2670
|
}
|
|
2529
2671
|
|
|
2530
2672
|
// src/commands/kanban-recurring.ts
|
|
2531
|
-
import
|
|
2673
|
+
import chalk17 from "chalk";
|
|
2532
2674
|
import ora12 from "ora";
|
|
2533
2675
|
async function resolveAgentId(codeName) {
|
|
2534
2676
|
try {
|
|
@@ -2540,10 +2682,10 @@ async function resolveAgentId(codeName) {
|
|
|
2540
2682
|
}
|
|
2541
2683
|
}
|
|
2542
2684
|
function priorityLabel(p) {
|
|
2543
|
-
return p === 1 ?
|
|
2685
|
+
return p === 1 ? chalk17.red("HIGH") : p === 3 ? chalk17.dim("LOW") : chalk17.yellow("MED");
|
|
2544
2686
|
}
|
|
2545
2687
|
function formatSpawnTime(isoDate, timezone) {
|
|
2546
|
-
if (!isoDate) return
|
|
2688
|
+
if (!isoDate) return chalk17.dim("\u2014");
|
|
2547
2689
|
try {
|
|
2548
2690
|
return new Intl.DateTimeFormat("en-AU", {
|
|
2549
2691
|
dateStyle: "medium",
|
|
@@ -2608,8 +2750,8 @@ async function kanbanRecurringAddCommand(title, opts) {
|
|
|
2608
2750
|
jsonOutput({ ok: true, template: data.template });
|
|
2609
2751
|
return;
|
|
2610
2752
|
}
|
|
2611
|
-
success(`Recurring task created: ${
|
|
2612
|
-
info(`Schedule: ${
|
|
2753
|
+
success(`Recurring task created: ${chalk17.bold(title)}`);
|
|
2754
|
+
info(`Schedule: ${chalk17.cyan(data.template.natural_language ?? data.template.expression ?? data.template.every_interval ?? "")}`);
|
|
2613
2755
|
info(`Next spawn: ${formatSpawnTime(data.template.next_spawn_at, data.template.timezone)}`);
|
|
2614
2756
|
info(`Timezone: ${data.template.timezone}`);
|
|
2615
2757
|
} catch (err) {
|
|
@@ -2652,7 +2794,7 @@ async function kanbanRecurringListCommand(opts) {
|
|
|
2652
2794
|
t.title,
|
|
2653
2795
|
t.natural_language ?? t.expression ?? t.every_interval ?? "\u2014",
|
|
2654
2796
|
priorityLabel(t.priority),
|
|
2655
|
-
t.enabled ?
|
|
2797
|
+
t.enabled ? chalk17.green("Active") : chalk17.dim("Disabled"),
|
|
2656
2798
|
formatSpawnTime(t.next_spawn_at, t.timezone),
|
|
2657
2799
|
String(t.spawn_count)
|
|
2658
2800
|
]);
|
|
@@ -2709,7 +2851,7 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
2709
2851
|
if (json) {
|
|
2710
2852
|
jsonOutput({ ok: true, id: match.id, title: match.title, enabled: false });
|
|
2711
2853
|
} else {
|
|
2712
|
-
success(`Disabled: ${
|
|
2854
|
+
success(`Disabled: ${chalk17.bold(match.title)}`);
|
|
2713
2855
|
}
|
|
2714
2856
|
} catch (err) {
|
|
2715
2857
|
spinner.fail("Failed to disable recurring template");
|
|
@@ -2726,7 +2868,7 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
2726
2868
|
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
2727
2869
|
import { join as join10, dirname } from "path";
|
|
2728
2870
|
import { homedir as homedir2 } from "os";
|
|
2729
|
-
import
|
|
2871
|
+
import chalk18 from "chalk";
|
|
2730
2872
|
import ora13 from "ora";
|
|
2731
2873
|
function detectShellProfile() {
|
|
2732
2874
|
const shell = process.env["SHELL"] ?? "";
|
|
@@ -2779,7 +2921,7 @@ async function setupCommand(token) {
|
|
|
2779
2921
|
if (!apiUrl) {
|
|
2780
2922
|
apiUrl = "https://api.augmented.team";
|
|
2781
2923
|
if (!json) {
|
|
2782
|
-
info(`No AGT_HOST set \u2014 using default: ${
|
|
2924
|
+
info(`No AGT_HOST set \u2014 using default: ${chalk18.bold(apiUrl)}`);
|
|
2783
2925
|
}
|
|
2784
2926
|
}
|
|
2785
2927
|
const spinner = ora13({ text: "Exchanging provisioning token\u2026", isSilent: json });
|
|
@@ -2816,11 +2958,11 @@ async function setupCommand(token) {
|
|
|
2816
2958
|
const exchange = await exchangeApiKey(setupResult.api_key);
|
|
2817
2959
|
verifySpinner.succeed("Connection verified");
|
|
2818
2960
|
if (!json) {
|
|
2819
|
-
info(`Host: ${
|
|
2961
|
+
info(`Host: ${chalk18.bold(setupResult.host_name)}`);
|
|
2820
2962
|
info(`Host ID: ${exchange.hostId}`);
|
|
2821
|
-
info(`Team: ${
|
|
2963
|
+
info(`Team: ${chalk18.bold(exchange.teamSlug ?? setupResult.team_slug ?? "unknown")}`);
|
|
2822
2964
|
if (exchange.userEmail) {
|
|
2823
|
-
info(`User: ${
|
|
2965
|
+
info(`User: ${chalk18.bold(exchange.userEmail)}`);
|
|
2824
2966
|
}
|
|
2825
2967
|
}
|
|
2826
2968
|
} catch (err) {
|
|
@@ -2859,7 +3001,7 @@ async function setupCommand(token) {
|
|
|
2859
3001
|
writeFileSync5(profilePath, updated.endsWith("\n") ? updated : `${updated}
|
|
2860
3002
|
`);
|
|
2861
3003
|
if (!json) {
|
|
2862
|
-
success(`Environment variables written to ${
|
|
3004
|
+
success(`Environment variables written to ${chalk18.bold(profilePath)}`);
|
|
2863
3005
|
}
|
|
2864
3006
|
const managerSpinner = ora13({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
2865
3007
|
managerSpinner.start();
|
|
@@ -2881,25 +3023,30 @@ async function setupCommand(token) {
|
|
|
2881
3023
|
host_id: setupResult.host_id,
|
|
2882
3024
|
team_slug: setupResult.team_slug,
|
|
2883
3025
|
api_url: finalApiUrl,
|
|
3026
|
+
// Host API key — exposed only in JSON mode so bootstrap/automation can
|
|
3027
|
+
// persist it system-wide. The token the caller just supplied grants
|
|
3028
|
+
// access to this key anyway; re-emitting it here just saves the caller
|
|
3029
|
+
// from having to parse the shell profile we wrote.
|
|
3030
|
+
api_key: setupResult.api_key,
|
|
2884
3031
|
agents: setupResult.agents,
|
|
2885
3032
|
profile: profilePath
|
|
2886
3033
|
});
|
|
2887
3034
|
} else {
|
|
2888
3035
|
console.log();
|
|
2889
|
-
console.log(
|
|
3036
|
+
console.log(chalk18.green.bold(" Setup complete!"));
|
|
2890
3037
|
console.log();
|
|
2891
3038
|
if (setupResult.agents.length > 0) {
|
|
2892
|
-
info(`Agents: ${setupResult.agents.map((a) =>
|
|
3039
|
+
info(`Agents: ${setupResult.agents.map((a) => chalk18.cyan(a)).join(", ")}`);
|
|
2893
3040
|
} else {
|
|
2894
3041
|
info("No agents assigned yet. Assign agents in the dashboard or with: agt host assign");
|
|
2895
3042
|
}
|
|
2896
3043
|
console.log();
|
|
2897
|
-
info(`Restart your shell or run: ${
|
|
3044
|
+
info(`Restart your shell or run: ${chalk18.bold(`source ${profilePath}`)}`);
|
|
2898
3045
|
}
|
|
2899
3046
|
}
|
|
2900
3047
|
|
|
2901
3048
|
// src/commands/kanban.ts
|
|
2902
|
-
import
|
|
3049
|
+
import chalk19 from "chalk";
|
|
2903
3050
|
import ora14 from "ora";
|
|
2904
3051
|
async function resolveAgentId2(codeName) {
|
|
2905
3052
|
try {
|
|
@@ -2910,14 +3057,14 @@ async function resolveAgentId2(codeName) {
|
|
|
2910
3057
|
}
|
|
2911
3058
|
}
|
|
2912
3059
|
function priorityLabel2(p) {
|
|
2913
|
-
return p === 1 ?
|
|
3060
|
+
return p === 1 ? chalk19.red("HIGH") : p === 3 ? chalk19.dim("LOW") : chalk19.yellow("MED");
|
|
2914
3061
|
}
|
|
2915
3062
|
function statusLabel(s) {
|
|
2916
3063
|
const map = {
|
|
2917
|
-
in_progress:
|
|
2918
|
-
today:
|
|
2919
|
-
backlog:
|
|
2920
|
-
done:
|
|
3064
|
+
in_progress: chalk19.blue("In Progress"),
|
|
3065
|
+
today: chalk19.green("Today"),
|
|
3066
|
+
backlog: chalk19.dim("Backlog"),
|
|
3067
|
+
done: chalk19.gray("Done")
|
|
2921
3068
|
};
|
|
2922
3069
|
return map[s] ?? s;
|
|
2923
3070
|
}
|
|
@@ -2953,7 +3100,7 @@ async function kanbanListCommand(opts) {
|
|
|
2953
3100
|
item.estimated_minutes ? `~${item.estimated_minutes}min` : "",
|
|
2954
3101
|
item.id.slice(0, 8)
|
|
2955
3102
|
]);
|
|
2956
|
-
console.log(
|
|
3103
|
+
console.log(chalk19.bold(`
|
|
2957
3104
|
Kanban: ${opts.agent}
|
|
2958
3105
|
`));
|
|
2959
3106
|
table(["Pri", "Status", "Title", "Est", "ID"], rows);
|
|
@@ -3193,7 +3340,7 @@ function getAcpAgent(name) {
|
|
|
3193
3340
|
}
|
|
3194
3341
|
|
|
3195
3342
|
// ../../packages/core/dist/acp/client.js
|
|
3196
|
-
import { spawn } from "child_process";
|
|
3343
|
+
import { spawn as spawn2 } from "child_process";
|
|
3197
3344
|
function resolveAgentCommand(agentName) {
|
|
3198
3345
|
const adapter = getAcpAgent(agentName);
|
|
3199
3346
|
if (adapter) {
|
|
@@ -3209,7 +3356,7 @@ function resolveAgentCommand(agentName) {
|
|
|
3209
3356
|
}
|
|
3210
3357
|
async function runAcpx(args, options = {}) {
|
|
3211
3358
|
return new Promise((resolve2) => {
|
|
3212
|
-
const child =
|
|
3359
|
+
const child = spawn2("acpx", args, {
|
|
3213
3360
|
cwd: options.cwd,
|
|
3214
3361
|
stdio: ["pipe", "pipe", "pipe"],
|
|
3215
3362
|
env: { ...process.env }
|
|
@@ -3409,9 +3556,9 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
3409
3556
|
|
|
3410
3557
|
// src/commands/update.ts
|
|
3411
3558
|
import { execSync } from "child_process";
|
|
3412
|
-
import
|
|
3559
|
+
import chalk20 from "chalk";
|
|
3413
3560
|
import ora15 from "ora";
|
|
3414
|
-
var cliVersion = true ? "0.10.
|
|
3561
|
+
var cliVersion = true ? "0.10.10" : "dev";
|
|
3415
3562
|
async function fetchLatestVersion() {
|
|
3416
3563
|
const host2 = getHost();
|
|
3417
3564
|
if (!host2) return null;
|
|
@@ -3490,13 +3637,13 @@ async function updateCommand(opts = {}) {
|
|
|
3490
3637
|
if (json) {
|
|
3491
3638
|
jsonOutput({ ok: true, current: cliVersion, latest: versionInfo.latest, update_available: false });
|
|
3492
3639
|
} else {
|
|
3493
|
-
success(`You're on the latest version (${
|
|
3640
|
+
success(`You're on the latest version (${chalk20.bold(cliVersion)})`);
|
|
3494
3641
|
}
|
|
3495
3642
|
return;
|
|
3496
3643
|
}
|
|
3497
3644
|
spinner.stop();
|
|
3498
3645
|
if (!json) {
|
|
3499
|
-
info(`Update available: ${
|
|
3646
|
+
info(`Update available: ${chalk20.dim(cliVersion)} \u2192 ${chalk20.bold.green(versionInfo.latest)}`);
|
|
3500
3647
|
if (versionInfo.changelog_url) {
|
|
3501
3648
|
info(`Changelog: ${versionInfo.changelog_url}`);
|
|
3502
3649
|
}
|
|
@@ -3507,16 +3654,16 @@ async function updateCommand(opts = {}) {
|
|
|
3507
3654
|
if (!json) {
|
|
3508
3655
|
warn("Active processes detected:");
|
|
3509
3656
|
if (managerPid) {
|
|
3510
|
-
console.error(
|
|
3657
|
+
console.error(chalk20.yellow(` \u2022 Manager process running (PID ${managerPid})`));
|
|
3511
3658
|
}
|
|
3512
3659
|
if (tmuxSessions.length > 0) {
|
|
3513
|
-
console.error(
|
|
3660
|
+
console.error(chalk20.yellow(` \u2022 ${tmuxSessions.length} active agent session(s): ${tmuxSessions.join(", ")}`));
|
|
3514
3661
|
}
|
|
3515
3662
|
console.error();
|
|
3516
3663
|
warn("Updating while the manager is running will leave it on the old version until restarted.");
|
|
3517
3664
|
warn("Active agent sessions will continue with stale MCP servers.");
|
|
3518
3665
|
console.error();
|
|
3519
|
-
info(`Run ${
|
|
3666
|
+
info(`Run ${chalk20.bold("agt update --force")} to update anyway, then restart the manager.`);
|
|
3520
3667
|
} else {
|
|
3521
3668
|
jsonOutput({
|
|
3522
3669
|
ok: false,
|
|
@@ -3548,8 +3695,8 @@ async function updateCommand(opts = {}) {
|
|
|
3548
3695
|
updated: true
|
|
3549
3696
|
});
|
|
3550
3697
|
} else {
|
|
3551
|
-
success(`Updated to ${
|
|
3552
|
-
info(`If you have a running manager, restart it: ${
|
|
3698
|
+
success(`Updated to ${chalk20.bold(versionInfo.latest)}`);
|
|
3699
|
+
info(`If you have a running manager, restart it: ${chalk20.bold("agt manager stop && agt manager start")}`);
|
|
3553
3700
|
}
|
|
3554
3701
|
} catch (err) {
|
|
3555
3702
|
updateSpinner.fail("Update failed");
|
|
@@ -3575,8 +3722,8 @@ async function checkForUpdateOnStartup() {
|
|
|
3575
3722
|
if (!versionInfo) return;
|
|
3576
3723
|
if (isNewerVersion(cliVersion, versionInfo.latest)) {
|
|
3577
3724
|
console.error(
|
|
3578
|
-
|
|
3579
|
-
Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${
|
|
3725
|
+
chalk20.yellow(`
|
|
3726
|
+
Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${chalk20.bold("agt update")} to install.`) + chalk20.dim("\n Note: Restart the manager after updating.\n")
|
|
3580
3727
|
);
|
|
3581
3728
|
}
|
|
3582
3729
|
} catch {
|
|
@@ -3584,7 +3731,7 @@ async function checkForUpdateOnStartup() {
|
|
|
3584
3731
|
}
|
|
3585
3732
|
|
|
3586
3733
|
// src/commands/plugin.ts
|
|
3587
|
-
import
|
|
3734
|
+
import chalk21 from "chalk";
|
|
3588
3735
|
import ora16 from "ora";
|
|
3589
3736
|
async function pluginListCommand() {
|
|
3590
3737
|
const json = isJsonMode();
|
|
@@ -3600,11 +3747,11 @@ async function pluginListCommand() {
|
|
|
3600
3747
|
info("No plugins found for this team.");
|
|
3601
3748
|
return;
|
|
3602
3749
|
}
|
|
3603
|
-
console.log(
|
|
3750
|
+
console.log(chalk21.bold("\nAvailable Plugins:\n"));
|
|
3604
3751
|
for (const p of data) {
|
|
3605
|
-
const statusColor = p.status === "published" ?
|
|
3752
|
+
const statusColor = p.status === "published" ? chalk21.green : p.status === "archived" ? chalk21.gray : chalk21.yellow;
|
|
3606
3753
|
console.log(
|
|
3607
|
-
` ${
|
|
3754
|
+
` ${chalk21.bold(p.name)} ${chalk21.dim(`(${p.slug})`)} ${statusColor(p.status)} v${p.version} ${chalk21.dim(`${p.skills?.length ?? 0} skills, ${p.defined_scopes?.length ?? 0} scopes`)}`
|
|
3608
3755
|
);
|
|
3609
3756
|
}
|
|
3610
3757
|
console.log();
|
|
@@ -3631,21 +3778,21 @@ async function pluginShowCommand(slug) {
|
|
|
3631
3778
|
jsonOutput({ plugin: plugin2, scopes });
|
|
3632
3779
|
return;
|
|
3633
3780
|
}
|
|
3634
|
-
console.log(
|
|
3635
|
-
${plugin2.name}`),
|
|
3636
|
-
if (plugin2.description) console.log(
|
|
3781
|
+
console.log(chalk21.bold(`
|
|
3782
|
+
${plugin2.name}`), chalk21.dim(`(${plugin2.slug})`));
|
|
3783
|
+
if (plugin2.description) console.log(chalk21.dim(plugin2.description));
|
|
3637
3784
|
console.log();
|
|
3638
3785
|
console.log(` Status: ${plugin2.status} v${plugin2.version}`);
|
|
3639
3786
|
console.log(` Category: ${plugin2.category}`);
|
|
3640
3787
|
console.log(` Toolkits: ${plugin2.required_toolkits.join(", ") || "none"}`);
|
|
3641
3788
|
console.log(` Skills: ${plugin2.skills?.length ?? 0}`);
|
|
3642
3789
|
if (scopes.length > 0) {
|
|
3643
|
-
console.log(
|
|
3790
|
+
console.log(chalk21.bold("\n Permission Scopes:\n"));
|
|
3644
3791
|
for (const s of scopes) {
|
|
3645
|
-
const roleColor = s.can_grant ?
|
|
3646
|
-
const overrideTag = s.is_overridden ?
|
|
3792
|
+
const roleColor = s.can_grant ? chalk21.green : chalk21.red;
|
|
3793
|
+
const overrideTag = s.is_overridden ? chalk21.cyan(" [team override]") : "";
|
|
3647
3794
|
console.log(
|
|
3648
|
-
` ${
|
|
3795
|
+
` ${chalk21.bold(s.id)} ${s.name} min: ${roleColor(s.effective_min_role)}${overrideTag} ${s.can_grant ? chalk21.green("\u2713 grantable") : chalk21.red("\u2717 needs approval")}`
|
|
3649
3796
|
);
|
|
3650
3797
|
}
|
|
3651
3798
|
}
|
|
@@ -3696,7 +3843,7 @@ async function pluginInstallCommand(slug, options) {
|
|
|
3696
3843
|
const needsApproval = err.body["needs_approval"];
|
|
3697
3844
|
error("Some scopes exceed your role ceiling:");
|
|
3698
3845
|
for (const s of needsApproval) {
|
|
3699
|
-
console.log(
|
|
3846
|
+
console.log(chalk21.yellow(` - ${s}`));
|
|
3700
3847
|
}
|
|
3701
3848
|
info("To request elevated scopes, use the web dashboard or contact your team admin.");
|
|
3702
3849
|
process.exitCode = 1;
|
|
@@ -3750,10 +3897,10 @@ async function pluginRequestsCommand() {
|
|
|
3750
3897
|
info("No pending scope requests.");
|
|
3751
3898
|
return;
|
|
3752
3899
|
}
|
|
3753
|
-
console.log(
|
|
3900
|
+
console.log(chalk21.bold("\nPending Scope Requests:\n"));
|
|
3754
3901
|
for (const r of requests) {
|
|
3755
|
-
console.log(` ${
|
|
3756
|
-
if (r.reason) console.log(` reason: ${
|
|
3902
|
+
console.log(` ${chalk21.bold(r.id)} scopes: ${r.requested_scopes.join(", ")}`);
|
|
3903
|
+
if (r.reason) console.log(` reason: ${chalk21.dim(r.reason)}`);
|
|
3757
3904
|
console.log(` status: ${r.status} requested: ${r.created_at}`);
|
|
3758
3905
|
console.log();
|
|
3759
3906
|
}
|
|
@@ -3810,7 +3957,7 @@ function handleError(err) {
|
|
|
3810
3957
|
}
|
|
3811
3958
|
|
|
3812
3959
|
// src/bin/agt.ts
|
|
3813
|
-
var cliVersion2 = true ? "0.10.
|
|
3960
|
+
var cliVersion2 = true ? "0.10.10" : "dev";
|
|
3814
3961
|
var program = new Command();
|
|
3815
3962
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
3816
3963
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -3850,6 +3997,12 @@ host.command("unassign <host-name> <agent-code-names...>").description("Unassign
|
|
|
3850
3997
|
host.command("agents [host-name]").description("List agents assigned to a host (omit name to auto-resolve from AGT_API_KEY)").action(hostAgentsCommand);
|
|
3851
3998
|
host.command("rotate-key <host-name>").description("Rotate the API key for a host (revokes the old key)").action(hostRotateKeyCommand);
|
|
3852
3999
|
host.command("decommission <host-name>").description("Decommission a host (revokes key, marks inactive)").action(hostDecommissionCommand);
|
|
4000
|
+
host.command("pair <host-name>").description("Start an SSM port-forward + shell to re-authenticate Claude Code on an EC2 host").option("--port <port>", "Local port to forward for the OAuth callback", "54545").option("--no-shell", "Start the tunnel only; do not open an interactive shell").action(
|
|
4001
|
+
(hostName, opts) => hostPairCommand(hostName, {
|
|
4002
|
+
port: opts.port,
|
|
4003
|
+
noShell: opts.shell === false
|
|
4004
|
+
})
|
|
4005
|
+
);
|
|
3853
4006
|
var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
|
|
3854
4007
|
manager.command("start").description("Start the manager daemon (polls API for config changes and detects local drift)").option("--interval <seconds>", "Poll interval in seconds (min 5)", "10").option("--config-dir <dir>", "Config directory for agent files", join11(homedir3(), ".augmented")).action(managerStartCommand);
|
|
3855
4008
|
manager.command("stop").description("Stop the running manager daemon").action(managerStopCommand);
|