@integrity-labs/agt-cli 0.14.7 → 0.14.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 +211 -548
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-JL4XSENX.js → chunk-4CZUEGNQ.js} +11 -17
- package/dist/chunk-4CZUEGNQ.js.map +1 -0
- package/dist/{chunk-5SFAHM2Z.js → chunk-RMTMETCK.js} +479 -24
- package/dist/chunk-RMTMETCK.js.map +1 -0
- package/dist/lib/manager-worker.js +44 -16
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-SRUW7AWU.js → persistent-session-GBQ3VQK3.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-5SFAHM2Z.js.map +0 -1
- package/dist/chunk-JL4XSENX.js.map +0 -1
- /package/dist/{persistent-session-SRUW7AWU.js.map → persistent-session-GBQ3VQK3.js.map} +0 -0
package/dist/bin/agt.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
api,
|
|
10
10
|
createSlackApp,
|
|
11
11
|
detectDrift,
|
|
12
|
+
error,
|
|
12
13
|
exchangeApiKey,
|
|
13
14
|
extractFrontmatter,
|
|
14
15
|
generateCharterMd,
|
|
@@ -24,68 +25,35 @@ import {
|
|
|
24
25
|
getHostId,
|
|
25
26
|
getScopesByCategory,
|
|
26
27
|
getTemplate,
|
|
28
|
+
info,
|
|
29
|
+
isJsonMode,
|
|
30
|
+
jsonOutput,
|
|
27
31
|
lintAll,
|
|
28
32
|
lintCharter,
|
|
29
33
|
lintTools,
|
|
34
|
+
managerStartCommand,
|
|
35
|
+
managerStatusCommand,
|
|
36
|
+
managerStopCommand,
|
|
30
37
|
provision,
|
|
31
38
|
renderTemplate,
|
|
32
39
|
resolveChannels,
|
|
33
40
|
serializeManifestForSlackCli,
|
|
34
|
-
setActiveTeam
|
|
35
|
-
|
|
41
|
+
setActiveTeam,
|
|
42
|
+
setJsonMode,
|
|
43
|
+
startWatchdog,
|
|
44
|
+
success,
|
|
45
|
+
table,
|
|
46
|
+
warn
|
|
47
|
+
} from "../chunk-RMTMETCK.js";
|
|
36
48
|
|
|
37
49
|
// src/bin/agt.ts
|
|
38
|
-
import { join as
|
|
39
|
-
import { homedir as
|
|
50
|
+
import { join as join9 } from "path";
|
|
51
|
+
import { homedir as homedir2 } from "os";
|
|
40
52
|
import { Command } from "commander";
|
|
41
53
|
|
|
42
|
-
// src/lib/globals.ts
|
|
43
|
-
import chalk from "chalk";
|
|
44
|
-
var _jsonMode = false;
|
|
45
|
-
function setJsonMode(enabled) {
|
|
46
|
-
_jsonMode = enabled;
|
|
47
|
-
if (enabled) {
|
|
48
|
-
chalk.level = 0;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function isJsonMode() {
|
|
52
|
-
return _jsonMode;
|
|
53
|
-
}
|
|
54
|
-
function jsonOutput(data) {
|
|
55
|
-
console.log(JSON.stringify(data, null, 2));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
54
|
// src/commands/whoami.ts
|
|
59
|
-
import
|
|
55
|
+
import chalk from "chalk";
|
|
60
56
|
import ora from "ora";
|
|
61
|
-
|
|
62
|
-
// src/lib/output.ts
|
|
63
|
-
import chalk2 from "chalk";
|
|
64
|
-
import Table from "cli-table3";
|
|
65
|
-
function success(msg) {
|
|
66
|
-
console.log(chalk2.green(`\u2714 ${msg}`));
|
|
67
|
-
}
|
|
68
|
-
function error(msg) {
|
|
69
|
-
console.error(chalk2.red(`\u2718 ${msg}`));
|
|
70
|
-
}
|
|
71
|
-
function warn(msg) {
|
|
72
|
-
console.warn(chalk2.yellow(`\u26A0 ${msg}`));
|
|
73
|
-
}
|
|
74
|
-
function info(msg) {
|
|
75
|
-
console.log(chalk2.cyan(`\u2139 ${msg}`));
|
|
76
|
-
}
|
|
77
|
-
function table(headers, rows) {
|
|
78
|
-
const t = new Table({
|
|
79
|
-
head: headers.map((h) => chalk2.bold.cyan(h)),
|
|
80
|
-
style: { head: [], border: [] }
|
|
81
|
-
});
|
|
82
|
-
for (const row of rows) {
|
|
83
|
-
t.push(row);
|
|
84
|
-
}
|
|
85
|
-
console.log(t.toString());
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// src/commands/whoami.ts
|
|
89
57
|
async function whoamiCommand() {
|
|
90
58
|
const json = isJsonMode();
|
|
91
59
|
const apiKey = getApiKey();
|
|
@@ -121,14 +89,14 @@ async function whoamiCommand() {
|
|
|
121
89
|
return;
|
|
122
90
|
}
|
|
123
91
|
success("Authenticated via API key");
|
|
124
|
-
info(`API Key: ${
|
|
125
|
-
info(`Host: ${
|
|
92
|
+
info(`API Key: ${chalk.bold(apiKey.slice(0, 8) + "****")}`);
|
|
93
|
+
info(`Host: ${chalk.bold(getHost())}`);
|
|
126
94
|
info(`Host ID: ${exchange.hostId}`);
|
|
127
|
-
info(`Team: ${
|
|
128
|
-
info(`User: ${
|
|
129
|
-
info(`Framework: ${
|
|
95
|
+
info(`Team: ${chalk.bold(exchange.teamSlug ?? exchange.teamId)}`);
|
|
96
|
+
info(`User: ${chalk.bold(exchange.userEmail ?? "unknown")}`);
|
|
97
|
+
info(`Framework: ${chalk.bold(framework)}`);
|
|
130
98
|
if (framework === "claude-code") {
|
|
131
|
-
info(`Claude Auth: ${
|
|
99
|
+
info(`Claude Auth: ${chalk.bold(claudeAuthLabel)}`);
|
|
132
100
|
}
|
|
133
101
|
} catch (err) {
|
|
134
102
|
spinner.fail("Failed to exchange API key.");
|
|
@@ -142,7 +110,7 @@ async function whoamiCommand() {
|
|
|
142
110
|
}
|
|
143
111
|
|
|
144
112
|
// src/commands/team.ts
|
|
145
|
-
import
|
|
113
|
+
import chalk2 from "chalk";
|
|
146
114
|
import ora2 from "ora";
|
|
147
115
|
|
|
148
116
|
// src/lib/auth-guard.ts
|
|
@@ -189,7 +157,7 @@ async function teamListCommand() {
|
|
|
189
157
|
return;
|
|
190
158
|
}
|
|
191
159
|
const rows = data.teams.map((ws) => {
|
|
192
|
-
const active = ws.slug === activeSlug ?
|
|
160
|
+
const active = ws.slug === activeSlug ? chalk2.green("*") : "";
|
|
193
161
|
return [active, ws.name, ws.slug, ws.role];
|
|
194
162
|
});
|
|
195
163
|
table(["", "Name", "Slug", "Role"], rows);
|
|
@@ -221,13 +189,13 @@ async function teamCreateCommand(name) {
|
|
|
221
189
|
try {
|
|
222
190
|
const data = await api.post("/teams", { name, slug });
|
|
223
191
|
setActiveTeam(data.team.slug);
|
|
224
|
-
spinner.succeed(`Team "${
|
|
192
|
+
spinner.succeed(`Team "${chalk2.bold(name)}" created.`);
|
|
225
193
|
if (json) {
|
|
226
194
|
jsonOutput({ ok: true, name, slug: data.team.slug, role: data.team.role });
|
|
227
195
|
return;
|
|
228
196
|
}
|
|
229
|
-
info(`Slug: ${
|
|
230
|
-
success(`Active team set to ${
|
|
197
|
+
info(`Slug: ${chalk2.bold(data.team.slug)}`);
|
|
198
|
+
success(`Active team set to ${chalk2.bold(data.team.slug)}.`);
|
|
231
199
|
} catch (err) {
|
|
232
200
|
spinner.fail("Failed to create team.");
|
|
233
201
|
if (json) {
|
|
@@ -246,7 +214,7 @@ async function teamSwitchCommand(slug) {
|
|
|
246
214
|
try {
|
|
247
215
|
await api.get(`/teams/${encodeURIComponent(slug)}`);
|
|
248
216
|
setActiveTeam(slug);
|
|
249
|
-
spinner.succeed(`Active team set to ${
|
|
217
|
+
spinner.succeed(`Active team set to ${chalk2.bold(slug)}.`);
|
|
250
218
|
if (json) {
|
|
251
219
|
jsonOutput({ ok: true, team: slug });
|
|
252
220
|
}
|
|
@@ -262,7 +230,7 @@ async function teamSwitchCommand(slug) {
|
|
|
262
230
|
}
|
|
263
231
|
|
|
264
232
|
// src/commands/init.ts
|
|
265
|
-
import
|
|
233
|
+
import chalk3 from "chalk";
|
|
266
234
|
import ora3 from "ora";
|
|
267
235
|
import { input, select, checkbox } from "@inquirer/prompts";
|
|
268
236
|
import { randomUUID } from "crypto";
|
|
@@ -273,8 +241,8 @@ function toSlug(name) {
|
|
|
273
241
|
}
|
|
274
242
|
function printDiagnostics(diagnostics) {
|
|
275
243
|
for (const d of diagnostics) {
|
|
276
|
-
const prefix = d.severity === "error" ?
|
|
277
|
-
const path = d.path ?
|
|
244
|
+
const prefix = d.severity === "error" ? chalk3.red("ERR") : chalk3.yellow("WARN");
|
|
245
|
+
const path = d.path ? chalk3.dim(` (${d.path})`) : "";
|
|
278
246
|
console.log(` ${prefix} [${d.code}] ${d.message}${path}`);
|
|
279
247
|
}
|
|
280
248
|
}
|
|
@@ -311,7 +279,7 @@ async function initCommand(opts) {
|
|
|
311
279
|
selectedChannels = opts.channels ? opts.channels.split(",").map((c) => c.trim()) : [];
|
|
312
280
|
loggingMode = opts.logging ?? "redacted";
|
|
313
281
|
} else {
|
|
314
|
-
console.log(
|
|
282
|
+
console.log(chalk3.bold("\nAugmented \u2014 Agent Init Wizard\n"));
|
|
315
283
|
displayName = await input({
|
|
316
284
|
message: "Agent display name:",
|
|
317
285
|
validate: (v) => v.trim().length > 0 || "Name is required"
|
|
@@ -473,7 +441,7 @@ async function initCommand(opts) {
|
|
|
473
441
|
mkdirSync(agentDir, { recursive: true });
|
|
474
442
|
writeFileSync(join(agentDir, "CHARTER.md"), charterMd);
|
|
475
443
|
writeFileSync(join(agentDir, "TOOLS.md"), toolsMd);
|
|
476
|
-
spinner.succeed(`Agent "${
|
|
444
|
+
spinner.succeed(`Agent "${chalk3.bold(displayName)}" created.`);
|
|
477
445
|
if (json) {
|
|
478
446
|
jsonOutput({
|
|
479
447
|
ok: true,
|
|
@@ -515,22 +483,22 @@ async function initCommand(opts) {
|
|
|
515
483
|
}
|
|
516
484
|
console.log();
|
|
517
485
|
info(`Next steps:`);
|
|
518
|
-
info(` 1. Edit ${
|
|
519
|
-
info(` 2. Edit ${
|
|
520
|
-
info(` 3. Run ${
|
|
521
|
-
info(` 4. Run ${
|
|
486
|
+
info(` 1. Edit ${chalk3.bold(".augmented/" + codeName + "/CHARTER.md")} to refine the agent charter`);
|
|
487
|
+
info(` 2. Edit ${chalk3.bold(".augmented/" + codeName + "/TOOLS.md")} to add tools`);
|
|
488
|
+
info(` 3. Run ${chalk3.bold("agt lint")} to validate`);
|
|
489
|
+
info(` 4. Run ${chalk3.bold("agt deploy")} to generate deployment config`);
|
|
522
490
|
}
|
|
523
491
|
|
|
524
492
|
// src/commands/lint.ts
|
|
525
|
-
import
|
|
493
|
+
import chalk4 from "chalk";
|
|
526
494
|
import ora4 from "ora";
|
|
527
495
|
import { readFileSync, existsSync } from "fs";
|
|
528
496
|
import { join as join2, resolve } from "path";
|
|
529
497
|
function printDiagnostics2(diagnostics) {
|
|
530
498
|
for (const d of diagnostics) {
|
|
531
|
-
const prefix = d.severity === "error" ?
|
|
532
|
-
const file =
|
|
533
|
-
const path = d.path ?
|
|
499
|
+
const prefix = d.severity === "error" ? chalk4.red("ERR") : chalk4.yellow("WARN");
|
|
500
|
+
const file = chalk4.dim(`[${d.file}]`);
|
|
501
|
+
const path = d.path ? chalk4.dim(` (${d.path})`) : "";
|
|
534
502
|
console.log(` ${prefix} ${file} ${d.code}: ${d.message}${path}`);
|
|
535
503
|
}
|
|
536
504
|
}
|
|
@@ -616,7 +584,7 @@ async function lintCommand(path) {
|
|
|
616
584
|
let totalWarnings = 0;
|
|
617
585
|
const jsonResults = [];
|
|
618
586
|
for (const { name, dir } of dirs) {
|
|
619
|
-
if (!json) console.log(
|
|
587
|
+
if (!json) console.log(chalk4.bold(`
|
|
620
588
|
Linting ${name}:`));
|
|
621
589
|
const charterPath = join2(dir, "CHARTER.md");
|
|
622
590
|
const toolsPath = join2(dir, "TOOLS.md");
|
|
@@ -677,7 +645,7 @@ Linting ${name}:`));
|
|
|
677
645
|
}
|
|
678
646
|
|
|
679
647
|
// src/commands/channels.ts
|
|
680
|
-
import
|
|
648
|
+
import chalk5 from "chalk";
|
|
681
649
|
import ora5 from "ora";
|
|
682
650
|
function channelsListCommand() {
|
|
683
651
|
const json = isJsonMode();
|
|
@@ -693,14 +661,14 @@ function channelsListCommand() {
|
|
|
693
661
|
jsonOutput({ ok: true, channels: channels2 });
|
|
694
662
|
return;
|
|
695
663
|
}
|
|
696
|
-
console.log(
|
|
664
|
+
console.log(chalk5.bold("\nChannel Registry (18 channels)\n"));
|
|
697
665
|
const rows = CHANNEL_REGISTRY.map((ch) => [
|
|
698
666
|
ch.id,
|
|
699
667
|
ch.name,
|
|
700
|
-
ch.securityTier === "elevated" ?
|
|
701
|
-
typeof ch.e2eEncrypted === "boolean" ? ch.e2eEncrypted ?
|
|
702
|
-
typeof ch.auditTrail === "boolean" ? ch.auditTrail ?
|
|
703
|
-
ch.publicExposureRisk === "High" ?
|
|
668
|
+
ch.securityTier === "elevated" ? chalk5.green(ch.securityTier) : ch.securityTier === "limited" ? chalk5.red(ch.securityTier) : chalk5.cyan(ch.securityTier),
|
|
669
|
+
typeof ch.e2eEncrypted === "boolean" ? ch.e2eEncrypted ? chalk5.green("yes") : chalk5.dim("no") : chalk5.yellow(ch.e2eEncrypted),
|
|
670
|
+
typeof ch.auditTrail === "boolean" ? ch.auditTrail ? chalk5.green("yes") : chalk5.dim("no") : chalk5.yellow(ch.auditTrail),
|
|
671
|
+
ch.publicExposureRisk === "High" ? chalk5.red(ch.publicExposureRisk) : ch.publicExposureRisk === "Medium" ? chalk5.yellow(ch.publicExposureRisk) : chalk5.green(ch.publicExposureRisk)
|
|
704
672
|
]);
|
|
705
673
|
table(["ID", "Name", "Security Tier", "E2E Encrypted", "Audit Trail", "Public Risk"], rows);
|
|
706
674
|
}
|
|
@@ -741,7 +709,7 @@ async function channelsCheckCommand(agentCodeName) {
|
|
|
741
709
|
});
|
|
742
710
|
return;
|
|
743
711
|
}
|
|
744
|
-
console.log(
|
|
712
|
+
console.log(chalk5.bold(`
|
|
745
713
|
Channel Resolution: ${agentCodeName}
|
|
746
714
|
`));
|
|
747
715
|
info(`Agent allowlist: ${agentPolicy.allowed.length > 0 ? agentPolicy.allowed.join(", ") : "none"}`);
|
|
@@ -783,7 +751,7 @@ Channel Resolution: ${agentCodeName}
|
|
|
783
751
|
}
|
|
784
752
|
|
|
785
753
|
// src/commands/channel-slack.ts
|
|
786
|
-
import
|
|
754
|
+
import chalk6 from "chalk";
|
|
787
755
|
import ora6 from "ora";
|
|
788
756
|
import { checkbox as checkbox2, confirm as confirm2, input as input2 } from "@inquirer/prompts";
|
|
789
757
|
import { writeFile } from "fs/promises";
|
|
@@ -828,9 +796,9 @@ async function channelSlackSetupCommand(agentCodeName, options) {
|
|
|
828
796
|
const label = SLACK_SCOPE_CATEGORY_LABELS[category];
|
|
829
797
|
choices.push({ type: "separator", separator: `\u2500\u2500 ${label} \u2500\u2500` });
|
|
830
798
|
for (const def of defs) {
|
|
831
|
-
const riskColor = def.risk === "high" ?
|
|
799
|
+
const riskColor = def.risk === "high" ? chalk6.red : def.risk === "medium" ? chalk6.yellow : chalk6.green;
|
|
832
800
|
choices.push({
|
|
833
|
-
name: `${def.scope} ${
|
|
801
|
+
name: `${def.scope} ${chalk6.dim(`\u2014 ${def.description}`)} ${riskColor(`[${def.risk}]`)}`,
|
|
834
802
|
value: def.scope,
|
|
835
803
|
checked: defaults.includes(def.scope)
|
|
836
804
|
});
|
|
@@ -858,7 +826,7 @@ async function channelSlackSetupCommand(agentCodeName, options) {
|
|
|
858
826
|
const manifestPath = join3(tmpdir(), `augmented-slack-manifest-${agentCodeName}.json`);
|
|
859
827
|
await writeFile(manifestPath, manifestJson, "utf-8");
|
|
860
828
|
success(`Manifest written to ${manifestPath}`);
|
|
861
|
-
console.log(
|
|
829
|
+
console.log(chalk6.dim(manifestJson));
|
|
862
830
|
let appId;
|
|
863
831
|
let botTokenRef = options.botToken;
|
|
864
832
|
let signingSecretRef = options.signingSecret;
|
|
@@ -979,15 +947,15 @@ async function channelSlackStatusCommand(agentCodeName) {
|
|
|
979
947
|
});
|
|
980
948
|
return;
|
|
981
949
|
}
|
|
982
|
-
console.log(
|
|
950
|
+
console.log(chalk6.bold(`
|
|
983
951
|
Slack Configuration: ${agentCodeName}
|
|
984
952
|
`));
|
|
985
953
|
const rows = [
|
|
986
954
|
["App Name", config.app_name ?? "-"],
|
|
987
955
|
["App ID", config.app_id ?? "-"],
|
|
988
956
|
["Team ID", config.team_id ?? "-"],
|
|
989
|
-
["Bot Token", config.bot_token_ref ?
|
|
990
|
-
["Signing Secret", config.signing_secret_ref ?
|
|
957
|
+
["Bot Token", config.bot_token_ref ? chalk6.green("configured") : chalk6.dim("not set")],
|
|
958
|
+
["Signing Secret", config.signing_secret_ref ? chalk6.green("configured") : chalk6.dim("not set")],
|
|
991
959
|
["Scopes", (config.scopes ?? []).join(", ") || "-"]
|
|
992
960
|
];
|
|
993
961
|
table(["Field", "Value"], rows);
|
|
@@ -1067,7 +1035,7 @@ async function channelSlackRemoveCommand(agentCodeName) {
|
|
|
1067
1035
|
}
|
|
1068
1036
|
|
|
1069
1037
|
// src/commands/channel-beam.ts
|
|
1070
|
-
import
|
|
1038
|
+
import chalk7 from "chalk";
|
|
1071
1039
|
import ora7 from "ora";
|
|
1072
1040
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
1073
1041
|
async function channelBeamSetupCommand(agentCodeName, options) {
|
|
@@ -1089,7 +1057,7 @@ async function channelBeamSetupCommand(agentCodeName, options) {
|
|
|
1089
1057
|
spinner.succeed(`Found agent "${agentCodeName}"`);
|
|
1090
1058
|
const existingConfig = await api.get(`/agents/${encodeURIComponent(agentCodeName)}/channel-configs/beam`).catch(() => ({ config: null }));
|
|
1091
1059
|
if (existingConfig.config?.beam_id) {
|
|
1092
|
-
info(`Agent already has Beam identity: ${
|
|
1060
|
+
info(`Agent already has Beam identity: ${chalk7.cyan(String(existingConfig.config.beam_id))}`);
|
|
1093
1061
|
const proceed = await confirm3({
|
|
1094
1062
|
message: "Regenerate identity? This will create a new keypair and re-register.",
|
|
1095
1063
|
default: false
|
|
@@ -1123,15 +1091,15 @@ async function channelBeamSetupCommand(agentCodeName, options) {
|
|
|
1123
1091
|
table(
|
|
1124
1092
|
["Field", "Value"],
|
|
1125
1093
|
[
|
|
1126
|
-
["Beam ID",
|
|
1127
|
-
["DID",
|
|
1094
|
+
["Beam ID", chalk7.cyan(result.beam_id)],
|
|
1095
|
+
["DID", chalk7.dim(result.did)],
|
|
1128
1096
|
["Trust Score", String(result.trust_score)],
|
|
1129
1097
|
["Verification", result.verification_tier],
|
|
1130
|
-
["Capabilities", result.published_capabilities.length > 0 ? result.published_capabilities.join(", ") :
|
|
1098
|
+
["Capabilities", result.published_capabilities.length > 0 ? result.published_capabilities.join(", ") : chalk7.dim("none published")]
|
|
1131
1099
|
]
|
|
1132
1100
|
);
|
|
1133
1101
|
console.log();
|
|
1134
|
-
success(`Agent "${agentCodeName}" is now reachable at ${
|
|
1102
|
+
success(`Agent "${agentCodeName}" is now reachable at ${chalk7.cyan(result.beam_id)}`);
|
|
1135
1103
|
} catch (err) {
|
|
1136
1104
|
spinner.fail("Setup failed");
|
|
1137
1105
|
error(err instanceof Error ? err.message : "Unknown error");
|
|
@@ -1160,13 +1128,13 @@ async function channelBeamStatusCommand(agentCodeName) {
|
|
|
1160
1128
|
table(
|
|
1161
1129
|
["Field", "Value"],
|
|
1162
1130
|
[
|
|
1163
|
-
["Beam ID",
|
|
1164
|
-
["DID",
|
|
1165
|
-
["Public Key",
|
|
1131
|
+
["Beam ID", chalk7.cyan(String(cfg.beam_id))],
|
|
1132
|
+
["DID", chalk7.dim(String(cfg.did ?? "\u2014"))],
|
|
1133
|
+
["Public Key", chalk7.dim(String(cfg.public_key ?? "").slice(0, 24) + "\u2026")],
|
|
1166
1134
|
["Trust Score", String(cfg.trust_score ?? 0)],
|
|
1167
1135
|
["Verification", String(cfg.verification_tier ?? "basic")],
|
|
1168
|
-
["Auto-publish", cfg.auto_publish_capabilities ?
|
|
1169
|
-
["Capabilities", Array.isArray(cfg.published_capabilities) && cfg.published_capabilities.length > 0 ? cfg.published_capabilities.join(", ") :
|
|
1136
|
+
["Auto-publish", cfg.auto_publish_capabilities ? chalk7.green("yes") : chalk7.dim("no")],
|
|
1137
|
+
["Capabilities", Array.isArray(cfg.published_capabilities) && cfg.published_capabilities.length > 0 ? cfg.published_capabilities.join(", ") : chalk7.dim("none")],
|
|
1170
1138
|
["Status", data.status ?? "\u2014"]
|
|
1171
1139
|
]
|
|
1172
1140
|
);
|
|
@@ -1204,7 +1172,7 @@ async function channelBeamRemoveCommand(agentCodeName) {
|
|
|
1204
1172
|
}
|
|
1205
1173
|
|
|
1206
1174
|
// src/commands/deploy.ts
|
|
1207
|
-
import
|
|
1175
|
+
import chalk8 from "chalk";
|
|
1208
1176
|
import ora8 from "ora";
|
|
1209
1177
|
import { select as select2, input as input3 } from "@inquirer/prompts";
|
|
1210
1178
|
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
@@ -1229,7 +1197,7 @@ async function deployCommand(opts) {
|
|
|
1229
1197
|
return;
|
|
1230
1198
|
}
|
|
1231
1199
|
} else {
|
|
1232
|
-
console.log(
|
|
1200
|
+
console.log(chalk8.bold("\nAugmented \u2014 Deploy\n"));
|
|
1233
1201
|
templateId = await select2({
|
|
1234
1202
|
message: "Deployment template:",
|
|
1235
1203
|
choices: DEPLOYMENT_TEMPLATES.map((t) => ({
|
|
@@ -1333,7 +1301,7 @@ async function deployCommand(opts) {
|
|
|
1333
1301
|
return;
|
|
1334
1302
|
}
|
|
1335
1303
|
console.log();
|
|
1336
|
-
info(`Template: ${
|
|
1304
|
+
info(`Template: ${chalk8.bold(tmpl.name)}`);
|
|
1337
1305
|
info(`Agents: ${agents.map((a) => a.code_name).join(", ")}`);
|
|
1338
1306
|
info(`Output: ${outPath}`);
|
|
1339
1307
|
console.log();
|
|
@@ -1342,14 +1310,14 @@ async function deployCommand(opts) {
|
|
|
1342
1310
|
}
|
|
1343
1311
|
|
|
1344
1312
|
// src/commands/provision.ts
|
|
1345
|
-
import
|
|
1313
|
+
import chalk9 from "chalk";
|
|
1346
1314
|
import ora9 from "ora";
|
|
1347
1315
|
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
1348
1316
|
import { join as join5 } from "path";
|
|
1349
1317
|
function printDiagnostics3(diagnostics) {
|
|
1350
1318
|
for (const d of diagnostics) {
|
|
1351
|
-
const prefix = d.severity === "error" ?
|
|
1352
|
-
const path = d.path ?
|
|
1319
|
+
const prefix = d.severity === "error" ? chalk9.red("ERR") : chalk9.yellow("WARN");
|
|
1320
|
+
const path = d.path ? chalk9.dim(` (${d.path})`) : "";
|
|
1353
1321
|
console.log(` ${prefix} [${d.code}] ${d.message}${path}`);
|
|
1354
1322
|
}
|
|
1355
1323
|
}
|
|
@@ -1360,7 +1328,7 @@ async function provisionCommand(codeName, options) {
|
|
|
1360
1328
|
const target = options.target ?? "local_docker";
|
|
1361
1329
|
const outputDir = options.output ?? join5(process.cwd(), ".augmented", codeName, "provision");
|
|
1362
1330
|
const dryRun = options.dryRun ?? false;
|
|
1363
|
-
if (!json) console.log(
|
|
1331
|
+
if (!json) console.log(chalk9.bold("\nAugmented \u2014 Provision\n"));
|
|
1364
1332
|
const spinner = ora9({ text: "Fetching agent data\u2026", isSilent: json });
|
|
1365
1333
|
spinner.start();
|
|
1366
1334
|
let provisionData;
|
|
@@ -1513,11 +1481,11 @@ async function provisionCommand(codeName, options) {
|
|
|
1513
1481
|
info("Dry run \u2014 no files written.");
|
|
1514
1482
|
console.log();
|
|
1515
1483
|
for (const artifact of provisionOutput.artifacts) {
|
|
1516
|
-
console.log(
|
|
1484
|
+
console.log(chalk9.bold(`${artifact.relativePath}:`));
|
|
1517
1485
|
console.log(artifact.content);
|
|
1518
1486
|
}
|
|
1519
1487
|
if (deploymentYaml) {
|
|
1520
|
-
console.log(
|
|
1488
|
+
console.log(chalk9.bold("Deployment Template:"));
|
|
1521
1489
|
console.log(deploymentYaml);
|
|
1522
1490
|
}
|
|
1523
1491
|
console.log();
|
|
@@ -1546,7 +1514,7 @@ async function provisionCommand(codeName, options) {
|
|
|
1546
1514
|
spinner.stop();
|
|
1547
1515
|
if (!json) warn(`Provision completed but could not store snapshot: ${err.message}`);
|
|
1548
1516
|
}
|
|
1549
|
-
spinner.succeed(`Agent "${
|
|
1517
|
+
spinner.succeed(`Agent "${chalk9.bold(agentData.display_name)}" provisioned.`);
|
|
1550
1518
|
if (json) {
|
|
1551
1519
|
jsonOutput({
|
|
1552
1520
|
ok: true,
|
|
@@ -1577,7 +1545,7 @@ async function provisionCommand(codeName, options) {
|
|
|
1577
1545
|
}
|
|
1578
1546
|
|
|
1579
1547
|
// src/commands/drift.ts
|
|
1580
|
-
import
|
|
1548
|
+
import chalk10 from "chalk";
|
|
1581
1549
|
import ora10 from "ora";
|
|
1582
1550
|
|
|
1583
1551
|
// ../../packages/core/dist/drift/live-state-reader.js
|
|
@@ -1623,15 +1591,15 @@ var KEBAB_CASE_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
|
1623
1591
|
function severityColor(severity) {
|
|
1624
1592
|
switch (severity) {
|
|
1625
1593
|
case "critical":
|
|
1626
|
-
return
|
|
1594
|
+
return chalk10.red(severity);
|
|
1627
1595
|
case "warning":
|
|
1628
|
-
return
|
|
1596
|
+
return chalk10.yellow(severity);
|
|
1629
1597
|
default:
|
|
1630
|
-
return
|
|
1598
|
+
return chalk10.dim(severity);
|
|
1631
1599
|
}
|
|
1632
1600
|
}
|
|
1633
1601
|
function printDriftReport(report) {
|
|
1634
|
-
console.log(
|
|
1602
|
+
console.log(chalk10.bold(`
|
|
1635
1603
|
Drift Report: ${report.codeName}
|
|
1636
1604
|
`));
|
|
1637
1605
|
info(`Agent ID: ${report.agentId}`);
|
|
@@ -1742,7 +1710,7 @@ async function driftWatchCommand(codeName, opts) {
|
|
|
1742
1710
|
const trackedFiles = adapter.driftTrackedFiles();
|
|
1743
1711
|
if (!useJson) {
|
|
1744
1712
|
console.log(
|
|
1745
|
-
|
|
1713
|
+
chalk10.bold(`
|
|
1746
1714
|
Watching drift for "${codeName}" every ${intervalSec}s. Press Ctrl+C to stop.
|
|
1747
1715
|
`)
|
|
1748
1716
|
);
|
|
@@ -1813,13 +1781,13 @@ Watching drift for "${codeName}" every ${intervalSec}s. Press Ctrl+C to stop.
|
|
|
1813
1781
|
}, intervalSec * 1e3);
|
|
1814
1782
|
process.on("SIGINT", () => {
|
|
1815
1783
|
clearInterval(timer);
|
|
1816
|
-
if (!useJson) console.log(
|
|
1784
|
+
if (!useJson) console.log(chalk10.dim("\nStopped watching."));
|
|
1817
1785
|
process.exit(0);
|
|
1818
1786
|
});
|
|
1819
1787
|
}
|
|
1820
1788
|
|
|
1821
1789
|
// src/commands/host.ts
|
|
1822
|
-
import
|
|
1790
|
+
import chalk11 from "chalk";
|
|
1823
1791
|
import ora11 from "ora";
|
|
1824
1792
|
async function hostListCommand() {
|
|
1825
1793
|
const teamSlug = requireTeam();
|
|
@@ -1843,10 +1811,10 @@ async function hostListCommand() {
|
|
|
1843
1811
|
return;
|
|
1844
1812
|
}
|
|
1845
1813
|
const rows = data.hosts.map((h) => {
|
|
1846
|
-
const status = h.status === "active" ?
|
|
1814
|
+
const status = h.status === "active" ? chalk11.green("active") : chalk11.red("decommissioned");
|
|
1847
1815
|
const agents = String(h.agents);
|
|
1848
|
-
const lastSeen = h.last_seen_at ? new Date(h.last_seen_at).toLocaleDateString() :
|
|
1849
|
-
const prefix = h.key_prefix ? `tlk_${h.key_prefix}\u2026` :
|
|
1816
|
+
const lastSeen = h.last_seen_at ? new Date(h.last_seen_at).toLocaleDateString() : chalk11.dim("never");
|
|
1817
|
+
const prefix = h.key_prefix ? `tlk_${h.key_prefix}\u2026` : chalk11.dim("none");
|
|
1850
1818
|
return [h.name, status, agents, lastSeen, prefix];
|
|
1851
1819
|
});
|
|
1852
1820
|
table(["Name", "Status", "Agents", "Last Seen", "Key"], rows);
|
|
@@ -1880,7 +1848,7 @@ async function hostAssignCommand(hostName, agentCodeNames, opts) {
|
|
|
1880
1848
|
agents: agentCodeNames,
|
|
1881
1849
|
force: opts.force
|
|
1882
1850
|
});
|
|
1883
|
-
spinner.succeed(`Agents assigned to ${
|
|
1851
|
+
spinner.succeed(`Agents assigned to ${chalk11.bold(hostName)}.`);
|
|
1884
1852
|
if (json) {
|
|
1885
1853
|
jsonOutput({ ok: true, host: hostName, assigned: agentCodeNames });
|
|
1886
1854
|
return;
|
|
@@ -1917,7 +1885,7 @@ async function hostUnassignCommand(hostName, agentCodeNames) {
|
|
|
1917
1885
|
await api.post(`/hosts/${encodeURIComponent(hostName)}/unassign`, {
|
|
1918
1886
|
agents: agentCodeNames
|
|
1919
1887
|
});
|
|
1920
|
-
spinner.succeed(`Agents unassigned from ${
|
|
1888
|
+
spinner.succeed(`Agents unassigned from ${chalk11.bold(hostName)}.`);
|
|
1921
1889
|
if (json) {
|
|
1922
1890
|
jsonOutput({ ok: true, host: hostName, unassigned: agentCodeNames });
|
|
1923
1891
|
return;
|
|
@@ -1976,7 +1944,7 @@ async function hostAgentsCommand(hostName) {
|
|
|
1976
1944
|
return;
|
|
1977
1945
|
}
|
|
1978
1946
|
const rows = agents.map((a) => {
|
|
1979
|
-
const statusColor = a.status === "active" ?
|
|
1947
|
+
const statusColor = a.status === "active" ? chalk11.green : chalk11.yellow;
|
|
1980
1948
|
return [
|
|
1981
1949
|
a.code_name,
|
|
1982
1950
|
a.display_name,
|
|
@@ -2003,7 +1971,7 @@ async function hostRotateKeyCommand(hostName) {
|
|
|
2003
1971
|
spinner.start();
|
|
2004
1972
|
try {
|
|
2005
1973
|
const data = await api.post(`/hosts/${encodeURIComponent(hostName)}/rotate-key`);
|
|
2006
|
-
spinner.succeed(`Key rotated for ${
|
|
1974
|
+
spinner.succeed(`Key rotated for ${chalk11.bold(hostName)}.`);
|
|
2007
1975
|
if (json) {
|
|
2008
1976
|
jsonOutput({
|
|
2009
1977
|
ok: true,
|
|
@@ -2013,12 +1981,12 @@ async function hostRotateKeyCommand(hostName) {
|
|
|
2013
1981
|
return;
|
|
2014
1982
|
}
|
|
2015
1983
|
console.log();
|
|
2016
|
-
info(`Host: ${
|
|
1984
|
+
info(`Host: ${chalk11.bold(hostName)}`);
|
|
2017
1985
|
info(`Prefix: ${data.key.prefix}`);
|
|
2018
1986
|
console.log();
|
|
2019
|
-
console.log(
|
|
1987
|
+
console.log(chalk11.yellow.bold(" Save this key now \u2014 it will not be shown again:"));
|
|
2020
1988
|
console.log();
|
|
2021
|
-
console.log(` ${
|
|
1989
|
+
console.log(` ${chalk11.green.bold(data.key.raw_key)}`);
|
|
2022
1990
|
console.log();
|
|
2023
1991
|
} catch (err) {
|
|
2024
1992
|
spinner.fail("Failed to rotate key.");
|
|
@@ -2038,7 +2006,7 @@ async function hostDecommissionCommand(hostName) {
|
|
|
2038
2006
|
spinner.start();
|
|
2039
2007
|
try {
|
|
2040
2008
|
await api.post(`/hosts/${encodeURIComponent(hostName)}/decommission`);
|
|
2041
|
-
spinner.succeed(`Host "${
|
|
2009
|
+
spinner.succeed(`Host "${chalk11.bold(hostName)}" decommissioned.`);
|
|
2042
2010
|
if (json) {
|
|
2043
2011
|
jsonOutput({
|
|
2044
2012
|
ok: true,
|
|
@@ -2048,7 +2016,7 @@ async function hostDecommissionCommand(hostName) {
|
|
|
2048
2016
|
return;
|
|
2049
2017
|
}
|
|
2050
2018
|
info(`Host: ${hostName}`);
|
|
2051
|
-
info(`Status: ${
|
|
2019
|
+
info(`Status: ${chalk11.red("decommissioned")}`);
|
|
2052
2020
|
info("API key revoked. Agents remain assigned for audit visibility.");
|
|
2053
2021
|
info("Reassign agents to another host with `agt host assign --force`.");
|
|
2054
2022
|
} catch (err) {
|
|
@@ -2064,7 +2032,7 @@ async function hostDecommissionCommand(hostName) {
|
|
|
2064
2032
|
|
|
2065
2033
|
// src/commands/host-pair.ts
|
|
2066
2034
|
import { spawn, spawnSync } from "child_process";
|
|
2067
|
-
import
|
|
2035
|
+
import chalk12 from "chalk";
|
|
2068
2036
|
async function hostPairCommand(name, opts) {
|
|
2069
2037
|
const teamSlug = requireTeam();
|
|
2070
2038
|
if (!teamSlug) return;
|
|
@@ -2134,15 +2102,15 @@ async function hostPairCommand(name, opts) {
|
|
|
2134
2102
|
});
|
|
2135
2103
|
return;
|
|
2136
2104
|
}
|
|
2137
|
-
info(`Pairing Claude Code on ${
|
|
2138
|
-
info(`Local port ${
|
|
2105
|
+
info(`Pairing Claude Code on ${chalk12.bold(name)} (${instanceId}, ${region})`);
|
|
2106
|
+
info(`Local port ${chalk12.cyan(String(localPort))} will be forwarded to the host.`);
|
|
2139
2107
|
console.log();
|
|
2140
|
-
console.log(
|
|
2141
|
-
console.log(` ${
|
|
2142
|
-
console.log(
|
|
2143
|
-
console.log(
|
|
2108
|
+
console.log(chalk12.dim("In the shell that opens, run:"));
|
|
2109
|
+
console.log(` ${chalk12.cyan(`CLAUDE_CODE_OAUTH_PORT=${localPort} claude /login`)}`);
|
|
2110
|
+
console.log(chalk12.dim("Then click the printed URL on this machine. The OAuth callback"));
|
|
2111
|
+
console.log(chalk12.dim(`will reach Claude Code via the port-forward tunnel.`));
|
|
2144
2112
|
console.log();
|
|
2145
|
-
console.log(
|
|
2113
|
+
console.log(chalk12.dim("Exit the shell (Ctrl+D) when Claude Code reports successful login."));
|
|
2146
2114
|
console.log();
|
|
2147
2115
|
const tunnel = spawn(
|
|
2148
2116
|
"aws",
|
|
@@ -2163,7 +2131,7 @@ async function hostPairCommand(name, opts) {
|
|
|
2163
2131
|
tunnel.stderr?.on("data", (buf) => {
|
|
2164
2132
|
const line = buf.toString().trim();
|
|
2165
2133
|
if (line.startsWith("An error occurred")) {
|
|
2166
|
-
console.error(
|
|
2134
|
+
console.error(chalk12.red(`[tunnel] ${line}`));
|
|
2167
2135
|
}
|
|
2168
2136
|
});
|
|
2169
2137
|
await new Promise((r) => setTimeout(r, 1500));
|
|
@@ -2173,7 +2141,7 @@ async function hostPairCommand(name, opts) {
|
|
|
2173
2141
|
return;
|
|
2174
2142
|
}
|
|
2175
2143
|
if (opts.noShell) {
|
|
2176
|
-
console.log(
|
|
2144
|
+
console.log(chalk12.dim("--no-shell set; tunnel is running. Press Ctrl+C to exit."));
|
|
2177
2145
|
await new Promise((resolve2) => {
|
|
2178
2146
|
const onSignal = () => {
|
|
2179
2147
|
terminate(tunnel);
|
|
@@ -2214,322 +2182,17 @@ function terminate(child) {
|
|
|
2214
2182
|
}
|
|
2215
2183
|
}
|
|
2216
2184
|
|
|
2217
|
-
// src/commands/manager.ts
|
|
2218
|
-
import chalk15 from "chalk";
|
|
2219
|
-
import { join as join8 } from "path";
|
|
2220
|
-
import { homedir } from "os";
|
|
2221
|
-
|
|
2222
|
-
// src/lib/watchdog.ts
|
|
2223
|
-
import { readFileSync as readFileSync2, writeFileSync as writeFileSync4, unlinkSync, existsSync as existsSync2, mkdirSync as mkdirSync4, openSync, closeSync, chmodSync } from "fs";
|
|
2224
|
-
import { join as join7 } from "path";
|
|
2225
|
-
import { spawn as spawn2 } from "child_process";
|
|
2226
|
-
var DEFAULT_CONFIG_DIR = join7(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
2227
|
-
function getManagerPaths(configDir) {
|
|
2228
|
-
return {
|
|
2229
|
-
pidFile: join7(configDir, "manager.pid"),
|
|
2230
|
-
stateFile: join7(configDir, "manager-state.json"),
|
|
2231
|
-
logFile: join7(configDir, "manager.log")
|
|
2232
|
-
};
|
|
2233
|
-
}
|
|
2234
|
-
function ensureDir(configDir) {
|
|
2235
|
-
if (!existsSync2(configDir)) {
|
|
2236
|
-
mkdirSync4(configDir, { recursive: true });
|
|
2237
|
-
}
|
|
2238
|
-
}
|
|
2239
|
-
function writePidFile(configDir, pid) {
|
|
2240
|
-
ensureDir(configDir);
|
|
2241
|
-
writeFileSync4(getManagerPaths(configDir).pidFile, String(pid), { mode: 384 });
|
|
2242
|
-
}
|
|
2243
|
-
function readPidFile(configDir) {
|
|
2244
|
-
try {
|
|
2245
|
-
const raw = readFileSync2(getManagerPaths(configDir).pidFile, "utf-8").trim();
|
|
2246
|
-
const pid = parseInt(raw, 10);
|
|
2247
|
-
return isNaN(pid) ? null : pid;
|
|
2248
|
-
} catch {
|
|
2249
|
-
return null;
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2252
|
-
function removePidFile(configDir) {
|
|
2253
|
-
try {
|
|
2254
|
-
unlinkSync(getManagerPaths(configDir).pidFile);
|
|
2255
|
-
} catch {
|
|
2256
|
-
}
|
|
2257
|
-
}
|
|
2258
|
-
function isProcessAlive(pid) {
|
|
2259
|
-
try {
|
|
2260
|
-
process.kill(pid, 0);
|
|
2261
|
-
return true;
|
|
2262
|
-
} catch {
|
|
2263
|
-
return false;
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
function readStateFile(configDir) {
|
|
2267
|
-
try {
|
|
2268
|
-
const raw = readFileSync2(getManagerPaths(configDir).stateFile, "utf-8");
|
|
2269
|
-
return JSON.parse(raw);
|
|
2270
|
-
} catch {
|
|
2271
|
-
return null;
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
function removeStateFile(configDir) {
|
|
2275
|
-
try {
|
|
2276
|
-
unlinkSync(getManagerPaths(configDir).stateFile);
|
|
2277
|
-
} catch {
|
|
2278
|
-
}
|
|
2279
|
-
}
|
|
2280
|
-
function startWatchdog(opts) {
|
|
2281
|
-
const { configDir } = opts;
|
|
2282
|
-
const existingPid = readPidFile(configDir);
|
|
2283
|
-
if (existingPid !== null) {
|
|
2284
|
-
if (isProcessAlive(existingPid)) {
|
|
2285
|
-
throw new Error(`Manager already running (PID ${existingPid}). Use \`agt manager stop\` first.`);
|
|
2286
|
-
}
|
|
2287
|
-
removePidFile(configDir);
|
|
2288
|
-
removeStateFile(configDir);
|
|
2289
|
-
}
|
|
2290
|
-
if (opts.detached) {
|
|
2291
|
-
ensureDir(configDir);
|
|
2292
|
-
const { logFile } = getManagerPaths(configDir);
|
|
2293
|
-
const logFd = openSync(logFile, "a", 384);
|
|
2294
|
-
try {
|
|
2295
|
-
chmodSync(logFile, 384);
|
|
2296
|
-
} catch {
|
|
2297
|
-
}
|
|
2298
|
-
const intervalSec = String(Math.max(Math.floor(opts.intervalMs / 1e3), 5));
|
|
2299
|
-
const child = spawn2(
|
|
2300
|
-
process.execPath,
|
|
2301
|
-
[process.argv[1], "manager", "start", "--interval", intervalSec, "--config-dir", configDir],
|
|
2302
|
-
{
|
|
2303
|
-
detached: true,
|
|
2304
|
-
stdio: ["ignore", logFd, logFd],
|
|
2305
|
-
env: process.env
|
|
2306
|
-
}
|
|
2307
|
-
);
|
|
2308
|
-
child.unref();
|
|
2309
|
-
closeSync(logFd);
|
|
2310
|
-
if (!child.pid) {
|
|
2311
|
-
throw new Error("Failed to spawn detached manager process");
|
|
2312
|
-
}
|
|
2313
|
-
const { pidFile } = getManagerPaths(configDir);
|
|
2314
|
-
const deadline = Date.now() + 5e3;
|
|
2315
|
-
const sleepBuf = new Int32Array(new SharedArrayBuffer(4));
|
|
2316
|
-
while (Date.now() < deadline) {
|
|
2317
|
-
if (existsSync2(pidFile)) {
|
|
2318
|
-
return { pid: child.pid };
|
|
2319
|
-
}
|
|
2320
|
-
if (child.exitCode !== null) {
|
|
2321
|
-
throw new Error(
|
|
2322
|
-
`Manager exited during startup (code ${child.exitCode}). See ${logFile} for details.`
|
|
2323
|
-
);
|
|
2324
|
-
}
|
|
2325
|
-
Atomics.wait(sleepBuf, 0, 0, 100);
|
|
2326
|
-
}
|
|
2327
|
-
throw new Error(
|
|
2328
|
-
`Manager did not become ready within 5s. See ${logFile} for details.`
|
|
2329
|
-
);
|
|
2330
|
-
}
|
|
2331
|
-
writePidFile(configDir, process.pid);
|
|
2332
|
-
void import("../lib/manager-worker.js").then(({ startManager }) => {
|
|
2333
|
-
startManager({
|
|
2334
|
-
intervalMs: opts.intervalMs,
|
|
2335
|
-
configDir
|
|
2336
|
-
});
|
|
2337
|
-
});
|
|
2338
|
-
process.on("exit", () => {
|
|
2339
|
-
removePidFile(configDir);
|
|
2340
|
-
});
|
|
2341
|
-
return { pid: process.pid };
|
|
2342
|
-
}
|
|
2343
|
-
async function stopWatchdog(configDir = DEFAULT_CONFIG_DIR) {
|
|
2344
|
-
const pid = readPidFile(configDir);
|
|
2345
|
-
if (pid === null) {
|
|
2346
|
-
return { stopped: false };
|
|
2347
|
-
}
|
|
2348
|
-
if (!isProcessAlive(pid)) {
|
|
2349
|
-
removePidFile(configDir);
|
|
2350
|
-
removeStateFile(configDir);
|
|
2351
|
-
return { stopped: true, pid };
|
|
2352
|
-
}
|
|
2353
|
-
process.kill(pid, "SIGTERM");
|
|
2354
|
-
const deadline = Date.now() + 5e3;
|
|
2355
|
-
while (Date.now() < deadline) {
|
|
2356
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
2357
|
-
if (!isProcessAlive(pid)) {
|
|
2358
|
-
removePidFile(configDir);
|
|
2359
|
-
return { stopped: true, pid };
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
try {
|
|
2363
|
-
process.kill(pid, "SIGKILL");
|
|
2364
|
-
} catch {
|
|
2365
|
-
}
|
|
2366
|
-
removePidFile(configDir);
|
|
2367
|
-
removeStateFile(configDir);
|
|
2368
|
-
return { stopped: true, pid };
|
|
2369
|
-
}
|
|
2370
|
-
function getManagerStatus(configDir = DEFAULT_CONFIG_DIR) {
|
|
2371
|
-
const pid = readPidFile(configDir);
|
|
2372
|
-
if (pid === null) return null;
|
|
2373
|
-
if (!isProcessAlive(pid)) {
|
|
2374
|
-
removePidFile(configDir);
|
|
2375
|
-
removeStateFile(configDir);
|
|
2376
|
-
return null;
|
|
2377
|
-
}
|
|
2378
|
-
return readStateFile(configDir);
|
|
2379
|
-
}
|
|
2380
|
-
|
|
2381
|
-
// src/commands/manager.ts
|
|
2382
|
-
function managerStartCommand(opts) {
|
|
2383
|
-
const json = isJsonMode();
|
|
2384
|
-
const apiKey = getApiKey();
|
|
2385
|
-
if (!apiKey) {
|
|
2386
|
-
const msg = "AGT_API_KEY is not set. Export it with your host API key (tlk_...)";
|
|
2387
|
-
if (json) {
|
|
2388
|
-
jsonOutput({ ok: false, error: msg });
|
|
2389
|
-
} else {
|
|
2390
|
-
error(msg);
|
|
2391
|
-
}
|
|
2392
|
-
process.exitCode = 1;
|
|
2393
|
-
return;
|
|
2394
|
-
}
|
|
2395
|
-
const intervalSec = parseInt(opts.interval ?? "10", 10);
|
|
2396
|
-
if (isNaN(intervalSec) || intervalSec < 5) {
|
|
2397
|
-
if (json) {
|
|
2398
|
-
jsonOutput({ ok: false, error: "Interval must be at least 10 seconds" });
|
|
2399
|
-
} else {
|
|
2400
|
-
error("Interval must be at least 10 seconds.");
|
|
2401
|
-
}
|
|
2402
|
-
process.exitCode = 1;
|
|
2403
|
-
return;
|
|
2404
|
-
}
|
|
2405
|
-
const configDir = opts.configDir ?? join8(homedir(), ".augmented");
|
|
2406
|
-
try {
|
|
2407
|
-
const { pid } = startWatchdog({
|
|
2408
|
-
intervalMs: intervalSec * 1e3,
|
|
2409
|
-
configDir
|
|
2410
|
-
});
|
|
2411
|
-
if (json) {
|
|
2412
|
-
jsonOutput({ ok: true, pid, interval: intervalSec, configDir });
|
|
2413
|
-
} else {
|
|
2414
|
-
success(`Manager started (PID ${pid}, interval ${intervalSec}s)`);
|
|
2415
|
-
info(`Config dir: ${configDir}`);
|
|
2416
|
-
info("Stop with: agt manager stop");
|
|
2417
|
-
}
|
|
2418
|
-
} catch (err) {
|
|
2419
|
-
if (json) {
|
|
2420
|
-
jsonOutput({ ok: false, error: err.message });
|
|
2421
|
-
} else {
|
|
2422
|
-
error(err.message);
|
|
2423
|
-
}
|
|
2424
|
-
process.exitCode = 1;
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
2427
|
-
async function managerStopCommand(opts = {}) {
|
|
2428
|
-
const json = isJsonMode();
|
|
2429
|
-
const configDir = opts.configDir ?? join8(homedir(), ".augmented");
|
|
2430
|
-
try {
|
|
2431
|
-
const result = await stopWatchdog(configDir);
|
|
2432
|
-
if (!result.stopped && !result.pid) {
|
|
2433
|
-
if (json) {
|
|
2434
|
-
jsonOutput({ ok: false, error: "Manager is not running" });
|
|
2435
|
-
} else {
|
|
2436
|
-
error("Manager is not running.");
|
|
2437
|
-
}
|
|
2438
|
-
process.exitCode = 1;
|
|
2439
|
-
return;
|
|
2440
|
-
}
|
|
2441
|
-
if (json) {
|
|
2442
|
-
jsonOutput({ ok: true, stopped: true, pid: result.pid });
|
|
2443
|
-
} else {
|
|
2444
|
-
success(`Manager stopped (PID ${result.pid})`);
|
|
2445
|
-
}
|
|
2446
|
-
} catch (err) {
|
|
2447
|
-
if (json) {
|
|
2448
|
-
jsonOutput({ ok: false, error: err.message });
|
|
2449
|
-
} else {
|
|
2450
|
-
error(err.message);
|
|
2451
|
-
}
|
|
2452
|
-
process.exitCode = 1;
|
|
2453
|
-
}
|
|
2454
|
-
}
|
|
2455
|
-
function managerStatusCommand(opts = {}) {
|
|
2456
|
-
const json = isJsonMode();
|
|
2457
|
-
const configDir = opts.configDir ?? join8(homedir(), ".augmented");
|
|
2458
|
-
const status = getManagerStatus(configDir);
|
|
2459
|
-
if (!status) {
|
|
2460
|
-
if (json) {
|
|
2461
|
-
jsonOutput({ ok: true, running: false });
|
|
2462
|
-
} else {
|
|
2463
|
-
info("Manager is not running.");
|
|
2464
|
-
}
|
|
2465
|
-
return;
|
|
2466
|
-
}
|
|
2467
|
-
if (json) {
|
|
2468
|
-
jsonOutput({ ok: true, running: true, ...status });
|
|
2469
|
-
return;
|
|
2470
|
-
}
|
|
2471
|
-
console.log(chalk15.bold("\nManager Status\n"));
|
|
2472
|
-
info(`PID: ${status.pid}`);
|
|
2473
|
-
info(`Started: ${status.startedAt}`);
|
|
2474
|
-
info(`Last poll: ${status.lastPollAt ?? chalk15.dim("none")}`);
|
|
2475
|
-
info(`Polls: ${status.pollCount}`);
|
|
2476
|
-
info(`Errors: ${status.errorCount}`);
|
|
2477
|
-
console.log();
|
|
2478
|
-
if (status.agents.length === 0) {
|
|
2479
|
-
info("No agents discovered yet.");
|
|
2480
|
-
return;
|
|
2481
|
-
}
|
|
2482
|
-
const rows = status.agents.map((a) => {
|
|
2483
|
-
let gwStatus = chalk15.dim("\u2014");
|
|
2484
|
-
if (a.gatewayRunning) {
|
|
2485
|
-
gwStatus = chalk15.green(`:${a.gatewayPort} (PID ${a.gatewayPid})`);
|
|
2486
|
-
} else if (a.gatewayPort) {
|
|
2487
|
-
gwStatus = chalk15.red(`:${a.gatewayPort} (down)`);
|
|
2488
|
-
}
|
|
2489
|
-
return [
|
|
2490
|
-
a.codeName,
|
|
2491
|
-
a.status === "active" ? chalk15.green(a.status) : a.status === "paused" ? chalk15.yellow(a.status) : chalk15.dim(a.status ?? "\u2014"),
|
|
2492
|
-
a.charterVersion || chalk15.dim("\u2014"),
|
|
2493
|
-
gwStatus,
|
|
2494
|
-
a.lastProvisionAt ? new Date(a.lastProvisionAt).toLocaleTimeString() : chalk15.dim("\u2014"),
|
|
2495
|
-
a.lastDriftCheckAt ? new Date(a.lastDriftCheckAt).toLocaleTimeString() : chalk15.dim("\u2014")
|
|
2496
|
-
];
|
|
2497
|
-
});
|
|
2498
|
-
table(
|
|
2499
|
-
["Agent", "Status", "Charter", "Gateway", "Last Provision", "Last Drift"],
|
|
2500
|
-
rows
|
|
2501
|
-
);
|
|
2502
|
-
const acpAgents = status.agents.filter((a) => a.acpSessions && a.acpSessions.length > 0);
|
|
2503
|
-
if (acpAgents.length > 0) {
|
|
2504
|
-
console.log(chalk15.bold("\nACP Sessions\n"));
|
|
2505
|
-
const acpRows = acpAgents.flatMap(
|
|
2506
|
-
(a) => a.acpSessions.map((s) => [
|
|
2507
|
-
a.codeName,
|
|
2508
|
-
s.agentCommand,
|
|
2509
|
-
s.sessionName ?? chalk15.dim("default"),
|
|
2510
|
-
s.queueState === "running" ? chalk15.green(s.queueState) : s.queueState === "queued" ? chalk15.yellow(s.queueState) : chalk15.dim(s.queueState),
|
|
2511
|
-
String(s.turnCount),
|
|
2512
|
-
new Date(s.startedAt).toLocaleTimeString()
|
|
2513
|
-
])
|
|
2514
|
-
);
|
|
2515
|
-
table(
|
|
2516
|
-
["Agent", "Coding Agent", "Session", "Queue", "Turns", "Started"],
|
|
2517
|
-
acpRows
|
|
2518
|
-
);
|
|
2519
|
-
}
|
|
2520
|
-
}
|
|
2521
|
-
|
|
2522
2185
|
// src/commands/agent.ts
|
|
2523
|
-
import
|
|
2186
|
+
import chalk13 from "chalk";
|
|
2524
2187
|
import JSON52 from "json5";
|
|
2525
|
-
import { readFileSync as
|
|
2526
|
-
import { join as
|
|
2188
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
2189
|
+
import { join as join7 } from "path";
|
|
2527
2190
|
async function agentShowCommand(codeName, opts) {
|
|
2528
2191
|
const json = isJsonMode();
|
|
2529
|
-
const unifiedDir =
|
|
2530
|
-
const legacyDir =
|
|
2531
|
-
const agentDir =
|
|
2532
|
-
const hasLocalConfig =
|
|
2192
|
+
const unifiedDir = join7(opts.configDir, codeName, "provision");
|
|
2193
|
+
const legacyDir = join7(opts.configDir, codeName, "claudecode", "provision");
|
|
2194
|
+
const agentDir = existsSync2(unifiedDir) ? unifiedDir : legacyDir;
|
|
2195
|
+
const hasLocalConfig = existsSync2(agentDir);
|
|
2533
2196
|
let apiChannels = null;
|
|
2534
2197
|
let apiAgent = null;
|
|
2535
2198
|
if (getApiKey()) {
|
|
@@ -2562,34 +2225,34 @@ async function agentShowCommand(codeName, opts) {
|
|
|
2562
2225
|
let openclawConfig = null;
|
|
2563
2226
|
let agentState = null;
|
|
2564
2227
|
if (hasLocalConfig) {
|
|
2565
|
-
const charterPath =
|
|
2566
|
-
if (
|
|
2567
|
-
const raw =
|
|
2228
|
+
const charterPath = join7(agentDir, "CHARTER.md");
|
|
2229
|
+
if (existsSync2(charterPath)) {
|
|
2230
|
+
const raw = readFileSync2(charterPath, "utf-8");
|
|
2568
2231
|
const parsed = extractFrontmatter(raw);
|
|
2569
2232
|
if (parsed.frontmatter) {
|
|
2570
2233
|
charter = parsed.frontmatter;
|
|
2571
2234
|
}
|
|
2572
2235
|
}
|
|
2573
|
-
const toolsPath =
|
|
2574
|
-
if (
|
|
2575
|
-
const raw =
|
|
2236
|
+
const toolsPath = join7(agentDir, "TOOLS.md");
|
|
2237
|
+
if (existsSync2(toolsPath)) {
|
|
2238
|
+
const raw = readFileSync2(toolsPath, "utf-8");
|
|
2576
2239
|
const parsed = extractFrontmatter(raw);
|
|
2577
2240
|
if (parsed.frontmatter) {
|
|
2578
2241
|
tools = parsed.frontmatter;
|
|
2579
2242
|
}
|
|
2580
2243
|
}
|
|
2581
|
-
const openclawPath =
|
|
2582
|
-
if (
|
|
2244
|
+
const openclawPath = join7(agentDir, "openclaw.json5");
|
|
2245
|
+
if (existsSync2(openclawPath)) {
|
|
2583
2246
|
try {
|
|
2584
|
-
const raw =
|
|
2247
|
+
const raw = readFileSync2(openclawPath, "utf-8");
|
|
2585
2248
|
openclawConfig = JSON52.parse(raw);
|
|
2586
2249
|
} catch {
|
|
2587
2250
|
}
|
|
2588
2251
|
}
|
|
2589
|
-
const statePath =
|
|
2590
|
-
if (
|
|
2252
|
+
const statePath = join7(opts.configDir, "manager-state.json");
|
|
2253
|
+
if (existsSync2(statePath)) {
|
|
2591
2254
|
try {
|
|
2592
|
-
const raw =
|
|
2255
|
+
const raw = readFileSync2(statePath, "utf-8");
|
|
2593
2256
|
const state = JSON.parse(raw);
|
|
2594
2257
|
agentState = state.agents?.find((a) => a.codeName === codeName) ?? null;
|
|
2595
2258
|
} catch {
|
|
@@ -2656,7 +2319,7 @@ async function agentShowCommand(codeName, opts) {
|
|
|
2656
2319
|
return;
|
|
2657
2320
|
}
|
|
2658
2321
|
const displayName = apiAgent?.display_name ?? charter?.display_name ?? codeName;
|
|
2659
|
-
console.log(
|
|
2322
|
+
console.log(chalk13.bold(`
|
|
2660
2323
|
Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "\n");
|
|
2661
2324
|
if (charter || apiAgent) {
|
|
2662
2325
|
const agentId = apiAgent?.agent_id ?? charter?.agent_id;
|
|
@@ -2688,7 +2351,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
|
|
|
2688
2351
|
info("No agent metadata available");
|
|
2689
2352
|
}
|
|
2690
2353
|
const filtered = opts.allChannels ? channelRows : channelRows.filter((c) => c.enabled);
|
|
2691
|
-
console.log(
|
|
2354
|
+
console.log(chalk13.bold("\nChannels:"));
|
|
2692
2355
|
if (filtered.length === 0) {
|
|
2693
2356
|
info("(none enabled)");
|
|
2694
2357
|
} else {
|
|
@@ -2704,7 +2367,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
|
|
|
2704
2367
|
);
|
|
2705
2368
|
}
|
|
2706
2369
|
if (tools) {
|
|
2707
|
-
console.log(
|
|
2370
|
+
console.log(chalk13.bold("\nTools:"));
|
|
2708
2371
|
if (tools.tools.length === 0) {
|
|
2709
2372
|
info("(none configured)");
|
|
2710
2373
|
} else {
|
|
@@ -2715,7 +2378,7 @@ Agent: ${codeName}`) + (displayName !== codeName ? ` (${displayName})` : "") + "
|
|
|
2715
2378
|
}
|
|
2716
2379
|
if (tools.global_controls) {
|
|
2717
2380
|
const gc = tools.global_controls;
|
|
2718
|
-
console.log(
|
|
2381
|
+
console.log(chalk13.bold("\nGlobal Controls:"));
|
|
2719
2382
|
info(`Network: ${gc.default_network_policy === "deny" ? "deny-by-default" : "allow-by-default"}`);
|
|
2720
2383
|
info(`Timeout: ${gc.default_timeout_ms}ms`);
|
|
2721
2384
|
info(`Rate: ${gc.default_rate_limit_rpm} rpm`);
|
|
@@ -2731,7 +2394,7 @@ function formatTimestamp(iso) {
|
|
|
2731
2394
|
}
|
|
2732
2395
|
|
|
2733
2396
|
// src/commands/kanban-recurring.ts
|
|
2734
|
-
import
|
|
2397
|
+
import chalk14 from "chalk";
|
|
2735
2398
|
import ora12 from "ora";
|
|
2736
2399
|
async function resolveAgentId(codeName) {
|
|
2737
2400
|
try {
|
|
@@ -2743,10 +2406,10 @@ async function resolveAgentId(codeName) {
|
|
|
2743
2406
|
}
|
|
2744
2407
|
}
|
|
2745
2408
|
function priorityLabel(p) {
|
|
2746
|
-
return p === 1 ?
|
|
2409
|
+
return p === 1 ? chalk14.red("HIGH") : p === 3 ? chalk14.dim("LOW") : chalk14.yellow("MED");
|
|
2747
2410
|
}
|
|
2748
2411
|
function formatSpawnTime(isoDate, timezone) {
|
|
2749
|
-
if (!isoDate) return
|
|
2412
|
+
if (!isoDate) return chalk14.dim("\u2014");
|
|
2750
2413
|
try {
|
|
2751
2414
|
return new Intl.DateTimeFormat("en-AU", {
|
|
2752
2415
|
dateStyle: "medium",
|
|
@@ -2811,8 +2474,8 @@ async function kanbanRecurringAddCommand(title, opts) {
|
|
|
2811
2474
|
jsonOutput({ ok: true, template: data.template });
|
|
2812
2475
|
return;
|
|
2813
2476
|
}
|
|
2814
|
-
success(`Recurring task created: ${
|
|
2815
|
-
info(`Schedule: ${
|
|
2477
|
+
success(`Recurring task created: ${chalk14.bold(title)}`);
|
|
2478
|
+
info(`Schedule: ${chalk14.cyan(data.template.natural_language ?? data.template.expression ?? data.template.every_interval ?? "")}`);
|
|
2816
2479
|
info(`Next spawn: ${formatSpawnTime(data.template.next_spawn_at, data.template.timezone)}`);
|
|
2817
2480
|
info(`Timezone: ${data.template.timezone}`);
|
|
2818
2481
|
} catch (err) {
|
|
@@ -2855,7 +2518,7 @@ async function kanbanRecurringListCommand(opts) {
|
|
|
2855
2518
|
t.title,
|
|
2856
2519
|
t.natural_language ?? t.expression ?? t.every_interval ?? "\u2014",
|
|
2857
2520
|
priorityLabel(t.priority),
|
|
2858
|
-
t.enabled ?
|
|
2521
|
+
t.enabled ? chalk14.green("Active") : chalk14.dim("Disabled"),
|
|
2859
2522
|
formatSpawnTime(t.next_spawn_at, t.timezone),
|
|
2860
2523
|
String(t.spawn_count)
|
|
2861
2524
|
]);
|
|
@@ -2912,7 +2575,7 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
2912
2575
|
if (json) {
|
|
2913
2576
|
jsonOutput({ ok: true, id: match.id, title: match.title, enabled: false });
|
|
2914
2577
|
} else {
|
|
2915
|
-
success(`Disabled: ${
|
|
2578
|
+
success(`Disabled: ${chalk14.bold(match.title)}`);
|
|
2916
2579
|
}
|
|
2917
2580
|
} catch (err) {
|
|
2918
2581
|
spinner.fail("Failed to disable recurring template");
|
|
@@ -2926,24 +2589,24 @@ async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
|
2926
2589
|
}
|
|
2927
2590
|
|
|
2928
2591
|
// src/commands/setup.ts
|
|
2929
|
-
import { existsSync as
|
|
2930
|
-
import { join as
|
|
2931
|
-
import { homedir
|
|
2932
|
-
import
|
|
2592
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, accessSync, constants as fsConstants } from "fs";
|
|
2593
|
+
import { join as join8, dirname } from "path";
|
|
2594
|
+
import { homedir } from "os";
|
|
2595
|
+
import chalk15 from "chalk";
|
|
2933
2596
|
import ora13 from "ora";
|
|
2934
2597
|
function detectShellProfile() {
|
|
2935
2598
|
const shell = process.env["SHELL"] ?? "";
|
|
2936
|
-
const home =
|
|
2599
|
+
const home = homedir();
|
|
2937
2600
|
if (shell.includes("zsh")) {
|
|
2938
|
-
return
|
|
2601
|
+
return join8(home, ".zshrc");
|
|
2939
2602
|
}
|
|
2940
2603
|
if (shell.includes("fish")) {
|
|
2941
|
-
const fishConfig =
|
|
2604
|
+
const fishConfig = join8(home, ".config", "fish", "config.fish");
|
|
2942
2605
|
return fishConfig;
|
|
2943
2606
|
}
|
|
2944
|
-
const bashrc =
|
|
2945
|
-
if (
|
|
2946
|
-
return
|
|
2607
|
+
const bashrc = join8(home, ".bashrc");
|
|
2608
|
+
if (existsSync3(bashrc)) return bashrc;
|
|
2609
|
+
return join8(home, ".bash_profile");
|
|
2947
2610
|
}
|
|
2948
2611
|
function maybeWriteSystemWideEnv(apiUrl, apiKey) {
|
|
2949
2612
|
const empty = { etcEnvironment: false, profileD: false, bashrc: false };
|
|
@@ -2966,21 +2629,21 @@ function quoteForPosixShell(value) {
|
|
|
2966
2629
|
}
|
|
2967
2630
|
function writeEtcEnvironment(apiUrl, apiKey) {
|
|
2968
2631
|
const envPath = "/etc/environment";
|
|
2969
|
-
if (!
|
|
2632
|
+
if (!existsSync3(envPath)) return false;
|
|
2970
2633
|
try {
|
|
2971
2634
|
accessSync(envPath, fsConstants.W_OK);
|
|
2972
2635
|
} catch {
|
|
2973
2636
|
return false;
|
|
2974
2637
|
}
|
|
2975
2638
|
try {
|
|
2976
|
-
const current =
|
|
2639
|
+
const current = readFileSync3(envPath, "utf-8");
|
|
2977
2640
|
const stripped = current.split(/\r?\n/).filter((line) => !/^\s*(?:export\s+)?AGT_(?:HOST|API_KEY)=/.test(line)).join("\n");
|
|
2978
2641
|
const base = stripped.endsWith("\n") || stripped.length === 0 ? stripped : `${stripped}
|
|
2979
2642
|
`;
|
|
2980
2643
|
const appended = `${base}AGT_HOST=${quoteForEtcEnvironment(apiUrl)}
|
|
2981
2644
|
AGT_API_KEY=${quoteForEtcEnvironment(apiKey)}
|
|
2982
2645
|
`;
|
|
2983
|
-
|
|
2646
|
+
writeFileSync4(envPath, appended, { mode: 420 });
|
|
2984
2647
|
return true;
|
|
2985
2648
|
} catch {
|
|
2986
2649
|
return false;
|
|
@@ -2988,7 +2651,7 @@ AGT_API_KEY=${quoteForEtcEnvironment(apiKey)}
|
|
|
2988
2651
|
}
|
|
2989
2652
|
function writeProfileDScript(apiUrl, apiKey) {
|
|
2990
2653
|
const profileD = "/etc/profile.d";
|
|
2991
|
-
if (!
|
|
2654
|
+
if (!existsSync3(profileD)) return false;
|
|
2992
2655
|
try {
|
|
2993
2656
|
accessSync(profileD, fsConstants.W_OK);
|
|
2994
2657
|
} catch {
|
|
@@ -3002,7 +2665,7 @@ function writeProfileDScript(apiUrl, apiKey) {
|
|
|
3002
2665
|
`export AGT_API_KEY=${quoteForPosixShell(apiKey)}`,
|
|
3003
2666
|
""
|
|
3004
2667
|
].join("\n");
|
|
3005
|
-
|
|
2668
|
+
writeFileSync4(scriptPath, content, { mode: 420 });
|
|
3006
2669
|
return true;
|
|
3007
2670
|
} catch {
|
|
3008
2671
|
return false;
|
|
@@ -3010,14 +2673,14 @@ function writeProfileDScript(apiUrl, apiKey) {
|
|
|
3010
2673
|
}
|
|
3011
2674
|
function ensureBashrcSourcesProfileD() {
|
|
3012
2675
|
const bashrc = "/etc/bashrc";
|
|
3013
|
-
if (!
|
|
2676
|
+
if (!existsSync3(bashrc)) return false;
|
|
3014
2677
|
try {
|
|
3015
2678
|
accessSync(bashrc, fsConstants.W_OK);
|
|
3016
2679
|
} catch {
|
|
3017
2680
|
return false;
|
|
3018
2681
|
}
|
|
3019
2682
|
try {
|
|
3020
|
-
const current =
|
|
2683
|
+
const current = readFileSync3(bashrc, "utf-8");
|
|
3021
2684
|
const marker = "# Augmented (agt) \u2014 source system-wide AGT env";
|
|
3022
2685
|
if (current.includes(marker)) return true;
|
|
3023
2686
|
const snippet = [
|
|
@@ -3028,7 +2691,7 @@ function ensureBashrcSourcesProfileD() {
|
|
|
3028
2691
|
"fi",
|
|
3029
2692
|
""
|
|
3030
2693
|
].join("\n");
|
|
3031
|
-
|
|
2694
|
+
writeFileSync4(bashrc, current + snippet);
|
|
3032
2695
|
return true;
|
|
3033
2696
|
} catch {
|
|
3034
2697
|
return false;
|
|
@@ -3071,7 +2734,7 @@ async function setupCommand(token) {
|
|
|
3071
2734
|
if (!apiUrl) {
|
|
3072
2735
|
apiUrl = "https://api.augmented.team";
|
|
3073
2736
|
if (!json) {
|
|
3074
|
-
info(`No AGT_HOST set \u2014 using default: ${
|
|
2737
|
+
info(`No AGT_HOST set \u2014 using default: ${chalk15.bold(apiUrl)}`);
|
|
3075
2738
|
}
|
|
3076
2739
|
}
|
|
3077
2740
|
const spinner = ora13({ text: "Exchanging provisioning token\u2026", isSilent: json });
|
|
@@ -3108,11 +2771,11 @@ async function setupCommand(token) {
|
|
|
3108
2771
|
const exchange = await exchangeApiKey(setupResult.api_key);
|
|
3109
2772
|
verifySpinner.succeed("Connection verified");
|
|
3110
2773
|
if (!json) {
|
|
3111
|
-
info(`Host: ${
|
|
2774
|
+
info(`Host: ${chalk15.bold(setupResult.host_name)}`);
|
|
3112
2775
|
info(`Host ID: ${exchange.hostId}`);
|
|
3113
|
-
info(`Team: ${
|
|
2776
|
+
info(`Team: ${chalk15.bold(exchange.teamSlug ?? setupResult.team_slug ?? "unknown")}`);
|
|
3114
2777
|
if (exchange.userEmail) {
|
|
3115
|
-
info(`User: ${
|
|
2778
|
+
info(`User: ${chalk15.bold(exchange.userEmail)}`);
|
|
3116
2779
|
}
|
|
3117
2780
|
}
|
|
3118
2781
|
} catch (err) {
|
|
@@ -3131,11 +2794,11 @@ async function setupCommand(token) {
|
|
|
3131
2794
|
const shell = process.env["SHELL"] ?? "bash";
|
|
3132
2795
|
const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key);
|
|
3133
2796
|
const profileDir = dirname(profilePath);
|
|
3134
|
-
if (!
|
|
3135
|
-
|
|
2797
|
+
if (!existsSync3(profileDir)) {
|
|
2798
|
+
mkdirSync4(profileDir, { recursive: true });
|
|
3136
2799
|
}
|
|
3137
2800
|
const marker = "# Augmented (agt) host configuration";
|
|
3138
|
-
const current =
|
|
2801
|
+
const current = existsSync3(profilePath) ? readFileSync3(profilePath, "utf-8") : "";
|
|
3139
2802
|
let updated;
|
|
3140
2803
|
if (current.includes(marker)) {
|
|
3141
2804
|
updated = current.replace(
|
|
@@ -3148,10 +2811,10 @@ async function setupCommand(token) {
|
|
|
3148
2811
|
} else {
|
|
3149
2812
|
updated = current + exportLines;
|
|
3150
2813
|
}
|
|
3151
|
-
|
|
2814
|
+
writeFileSync4(profilePath, updated.endsWith("\n") ? updated : `${updated}
|
|
3152
2815
|
`);
|
|
3153
2816
|
if (!json) {
|
|
3154
|
-
success(`Environment variables written to ${
|
|
2817
|
+
success(`Environment variables written to ${chalk15.bold(profilePath)}`);
|
|
3155
2818
|
}
|
|
3156
2819
|
const sys = maybeWriteSystemWideEnv(finalApiUrl, setupResult.api_key);
|
|
3157
2820
|
const valueChannelsWritten = sys.etcEnvironment || sys.profileD;
|
|
@@ -3166,7 +2829,7 @@ async function setupCommand(token) {
|
|
|
3166
2829
|
const managerSpinner = ora13({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
3167
2830
|
managerSpinner.start();
|
|
3168
2831
|
try {
|
|
3169
|
-
const configDir =
|
|
2832
|
+
const configDir = join8(homedir(), ".augmented");
|
|
3170
2833
|
const { pid } = startWatchdog({ intervalMs: 1e4, configDir, detached: true });
|
|
3171
2834
|
managerSpinner.succeed(`Manager started (PID ${pid})`);
|
|
3172
2835
|
} catch (err) {
|
|
@@ -3191,20 +2854,20 @@ async function setupCommand(token) {
|
|
|
3191
2854
|
process.exit(0);
|
|
3192
2855
|
} else {
|
|
3193
2856
|
console.log();
|
|
3194
|
-
console.log(
|
|
2857
|
+
console.log(chalk15.green.bold(" Setup complete!"));
|
|
3195
2858
|
console.log();
|
|
3196
2859
|
if (setupResult.agents.length > 0) {
|
|
3197
|
-
info(`Agents: ${setupResult.agents.map((a) =>
|
|
2860
|
+
info(`Agents: ${setupResult.agents.map((a) => chalk15.cyan(a)).join(", ")}`);
|
|
3198
2861
|
} else {
|
|
3199
2862
|
info("No agents assigned yet. Assign agents in the dashboard or with: agt host assign");
|
|
3200
2863
|
}
|
|
3201
2864
|
console.log();
|
|
3202
|
-
info(`Restart your shell or run: ${
|
|
2865
|
+
info(`Restart your shell or run: ${chalk15.bold(`source ${profilePath}`)}`);
|
|
3203
2866
|
}
|
|
3204
2867
|
}
|
|
3205
2868
|
|
|
3206
2869
|
// src/commands/kanban.ts
|
|
3207
|
-
import
|
|
2870
|
+
import chalk16 from "chalk";
|
|
3208
2871
|
import ora14 from "ora";
|
|
3209
2872
|
async function resolveAgentId2(codeName) {
|
|
3210
2873
|
try {
|
|
@@ -3215,14 +2878,14 @@ async function resolveAgentId2(codeName) {
|
|
|
3215
2878
|
}
|
|
3216
2879
|
}
|
|
3217
2880
|
function priorityLabel2(p) {
|
|
3218
|
-
return p === 1 ?
|
|
2881
|
+
return p === 1 ? chalk16.red("HIGH") : p === 3 ? chalk16.dim("LOW") : chalk16.yellow("MED");
|
|
3219
2882
|
}
|
|
3220
2883
|
function statusLabel(s) {
|
|
3221
2884
|
const map = {
|
|
3222
|
-
in_progress:
|
|
3223
|
-
today:
|
|
3224
|
-
backlog:
|
|
3225
|
-
done:
|
|
2885
|
+
in_progress: chalk16.blue("In Progress"),
|
|
2886
|
+
today: chalk16.green("Today"),
|
|
2887
|
+
backlog: chalk16.dim("Backlog"),
|
|
2888
|
+
done: chalk16.gray("Done")
|
|
3226
2889
|
};
|
|
3227
2890
|
return map[s] ?? s;
|
|
3228
2891
|
}
|
|
@@ -3258,7 +2921,7 @@ async function kanbanListCommand(opts) {
|
|
|
3258
2921
|
item.estimated_minutes ? `~${item.estimated_minutes}min` : "",
|
|
3259
2922
|
item.id.slice(0, 8)
|
|
3260
2923
|
]);
|
|
3261
|
-
console.log(
|
|
2924
|
+
console.log(chalk16.bold(`
|
|
3262
2925
|
Kanban: ${opts.agent}
|
|
3263
2926
|
`));
|
|
3264
2927
|
table(["Pri", "Status", "Title", "Est", "ID"], rows);
|
|
@@ -3498,7 +3161,7 @@ function getAcpAgent(name) {
|
|
|
3498
3161
|
}
|
|
3499
3162
|
|
|
3500
3163
|
// ../../packages/core/dist/acp/client.js
|
|
3501
|
-
import { spawn as
|
|
3164
|
+
import { spawn as spawn2 } from "child_process";
|
|
3502
3165
|
function resolveAgentCommand(agentName) {
|
|
3503
3166
|
const adapter = getAcpAgent(agentName);
|
|
3504
3167
|
if (adapter) {
|
|
@@ -3514,7 +3177,7 @@ function resolveAgentCommand(agentName) {
|
|
|
3514
3177
|
}
|
|
3515
3178
|
async function runAcpx(args, options = {}) {
|
|
3516
3179
|
return new Promise((resolve2) => {
|
|
3517
|
-
const child =
|
|
3180
|
+
const child = spawn2("acpx", args, {
|
|
3518
3181
|
cwd: options.cwd,
|
|
3519
3182
|
stdio: ["pipe", "pipe", "pipe"],
|
|
3520
3183
|
env: { ...process.env }
|
|
@@ -3714,10 +3377,10 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
3714
3377
|
|
|
3715
3378
|
// src/commands/update.ts
|
|
3716
3379
|
import { execFileSync, execSync } from "child_process";
|
|
3717
|
-
import { existsSync as
|
|
3718
|
-
import
|
|
3380
|
+
import { existsSync as existsSync4, realpathSync } from "fs";
|
|
3381
|
+
import chalk17 from "chalk";
|
|
3719
3382
|
import ora15 from "ora";
|
|
3720
|
-
var cliVersion = true ? "0.14.
|
|
3383
|
+
var cliVersion = true ? "0.14.10" : "dev";
|
|
3721
3384
|
async function fetchLatestVersion() {
|
|
3722
3385
|
const host2 = getHost();
|
|
3723
3386
|
if (!host2) return null;
|
|
@@ -3812,7 +3475,7 @@ function performUpdate(version) {
|
|
|
3812
3475
|
function detectBrewOwner() {
|
|
3813
3476
|
for (const prefix of ["/home/linuxbrew/.linuxbrew", "/opt/homebrew", "/usr/local"]) {
|
|
3814
3477
|
const cellar = `${prefix}/Cellar`;
|
|
3815
|
-
if (!
|
|
3478
|
+
if (!existsSync4(cellar)) continue;
|
|
3816
3479
|
try {
|
|
3817
3480
|
return execSync(`stat -c %U "${cellar}" 2>/dev/null || stat -f %Su "${cellar}"`, { encoding: "utf-8" }).trim() || null;
|
|
3818
3481
|
} catch {
|
|
@@ -3841,13 +3504,13 @@ async function updateCommand(opts = {}) {
|
|
|
3841
3504
|
if (json) {
|
|
3842
3505
|
jsonOutput({ ok: true, current: cliVersion, latest: versionInfo.latest, update_available: false });
|
|
3843
3506
|
} else {
|
|
3844
|
-
success(`You're on the latest version (${
|
|
3507
|
+
success(`You're on the latest version (${chalk17.bold(cliVersion)})`);
|
|
3845
3508
|
}
|
|
3846
3509
|
return;
|
|
3847
3510
|
}
|
|
3848
3511
|
spinner.stop();
|
|
3849
3512
|
if (!json) {
|
|
3850
|
-
info(`Update available: ${
|
|
3513
|
+
info(`Update available: ${chalk17.dim(cliVersion)} \u2192 ${chalk17.bold.green(versionInfo.latest)}`);
|
|
3851
3514
|
if (versionInfo.changelog_url) {
|
|
3852
3515
|
info(`Changelog: ${versionInfo.changelog_url}`);
|
|
3853
3516
|
}
|
|
@@ -3858,16 +3521,16 @@ async function updateCommand(opts = {}) {
|
|
|
3858
3521
|
if (!json) {
|
|
3859
3522
|
warn("Active processes detected:");
|
|
3860
3523
|
if (managerPid) {
|
|
3861
|
-
console.error(
|
|
3524
|
+
console.error(chalk17.yellow(` \u2022 Manager process running (PID ${managerPid})`));
|
|
3862
3525
|
}
|
|
3863
3526
|
if (tmuxSessions.length > 0) {
|
|
3864
|
-
console.error(
|
|
3527
|
+
console.error(chalk17.yellow(` \u2022 ${tmuxSessions.length} active agent session(s): ${tmuxSessions.join(", ")}`));
|
|
3865
3528
|
}
|
|
3866
3529
|
console.error();
|
|
3867
3530
|
warn("Updating while the manager is running will leave it on the old version until restarted.");
|
|
3868
3531
|
warn("Active agent sessions will continue with stale MCP servers.");
|
|
3869
3532
|
console.error();
|
|
3870
|
-
info(`Run ${
|
|
3533
|
+
info(`Run ${chalk17.bold("agt update --force")} to update anyway, then restart the manager.`);
|
|
3871
3534
|
} else {
|
|
3872
3535
|
jsonOutput({
|
|
3873
3536
|
ok: false,
|
|
@@ -3899,8 +3562,8 @@ async function updateCommand(opts = {}) {
|
|
|
3899
3562
|
updated: true
|
|
3900
3563
|
});
|
|
3901
3564
|
} else {
|
|
3902
|
-
success(`Updated to ${
|
|
3903
|
-
info(`If you have a running manager, restart it: ${
|
|
3565
|
+
success(`Updated to ${chalk17.bold(versionInfo.latest)}`);
|
|
3566
|
+
info(`If you have a running manager, restart it: ${chalk17.bold("agt manager stop && agt manager start")}`);
|
|
3904
3567
|
}
|
|
3905
3568
|
} catch (err) {
|
|
3906
3569
|
updateSpinner.fail("Update failed");
|
|
@@ -3931,8 +3594,8 @@ async function checkForUpdateOnStartup() {
|
|
|
3931
3594
|
if (!versionInfo) return;
|
|
3932
3595
|
if (isNewerVersion(cliVersion, versionInfo.latest)) {
|
|
3933
3596
|
console.error(
|
|
3934
|
-
|
|
3935
|
-
Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${
|
|
3597
|
+
chalk17.yellow(`
|
|
3598
|
+
Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${chalk17.bold("agt update")} to install.`) + chalk17.dim("\n Note: Restart the manager after updating.\n")
|
|
3936
3599
|
);
|
|
3937
3600
|
}
|
|
3938
3601
|
} catch {
|
|
@@ -3940,7 +3603,7 @@ async function checkForUpdateOnStartup() {
|
|
|
3940
3603
|
}
|
|
3941
3604
|
|
|
3942
3605
|
// src/commands/plugin.ts
|
|
3943
|
-
import
|
|
3606
|
+
import chalk18 from "chalk";
|
|
3944
3607
|
import ora16 from "ora";
|
|
3945
3608
|
async function pluginListCommand() {
|
|
3946
3609
|
const json = isJsonMode();
|
|
@@ -3956,11 +3619,11 @@ async function pluginListCommand() {
|
|
|
3956
3619
|
info("No plugins found for this team.");
|
|
3957
3620
|
return;
|
|
3958
3621
|
}
|
|
3959
|
-
console.log(
|
|
3622
|
+
console.log(chalk18.bold("\nAvailable Plugins:\n"));
|
|
3960
3623
|
for (const p of data) {
|
|
3961
|
-
const statusColor = p.status === "published" ?
|
|
3624
|
+
const statusColor = p.status === "published" ? chalk18.green : p.status === "archived" ? chalk18.gray : chalk18.yellow;
|
|
3962
3625
|
console.log(
|
|
3963
|
-
` ${
|
|
3626
|
+
` ${chalk18.bold(p.name)} ${chalk18.dim(`(${p.slug})`)} ${statusColor(p.status)} v${p.version} ${chalk18.dim(`${p.skills?.length ?? 0} skills, ${p.defined_scopes?.length ?? 0} scopes`)}`
|
|
3964
3627
|
);
|
|
3965
3628
|
}
|
|
3966
3629
|
console.log();
|
|
@@ -3987,21 +3650,21 @@ async function pluginShowCommand(slug) {
|
|
|
3987
3650
|
jsonOutput({ plugin: plugin2, scopes });
|
|
3988
3651
|
return;
|
|
3989
3652
|
}
|
|
3990
|
-
console.log(
|
|
3991
|
-
${plugin2.name}`),
|
|
3992
|
-
if (plugin2.description) console.log(
|
|
3653
|
+
console.log(chalk18.bold(`
|
|
3654
|
+
${plugin2.name}`), chalk18.dim(`(${plugin2.slug})`));
|
|
3655
|
+
if (plugin2.description) console.log(chalk18.dim(plugin2.description));
|
|
3993
3656
|
console.log();
|
|
3994
3657
|
console.log(` Status: ${plugin2.status} v${plugin2.version}`);
|
|
3995
3658
|
console.log(` Category: ${plugin2.category}`);
|
|
3996
3659
|
console.log(` Toolkits: ${plugin2.required_toolkits.join(", ") || "none"}`);
|
|
3997
3660
|
console.log(` Skills: ${plugin2.skills?.length ?? 0}`);
|
|
3998
3661
|
if (scopes.length > 0) {
|
|
3999
|
-
console.log(
|
|
3662
|
+
console.log(chalk18.bold("\n Permission Scopes:\n"));
|
|
4000
3663
|
for (const s of scopes) {
|
|
4001
|
-
const roleColor = s.can_grant ?
|
|
4002
|
-
const overrideTag = s.is_overridden ?
|
|
3664
|
+
const roleColor = s.can_grant ? chalk18.green : chalk18.red;
|
|
3665
|
+
const overrideTag = s.is_overridden ? chalk18.cyan(" [team override]") : "";
|
|
4003
3666
|
console.log(
|
|
4004
|
-
` ${
|
|
3667
|
+
` ${chalk18.bold(s.id)} ${s.name} min: ${roleColor(s.effective_min_role)}${overrideTag} ${s.can_grant ? chalk18.green("\u2713 grantable") : chalk18.red("\u2717 needs approval")}`
|
|
4005
3668
|
);
|
|
4006
3669
|
}
|
|
4007
3670
|
}
|
|
@@ -4052,7 +3715,7 @@ async function pluginInstallCommand(slug, options) {
|
|
|
4052
3715
|
const needsApproval = err.body["needs_approval"];
|
|
4053
3716
|
error("Some scopes exceed your role ceiling:");
|
|
4054
3717
|
for (const s of needsApproval) {
|
|
4055
|
-
console.log(
|
|
3718
|
+
console.log(chalk18.yellow(` - ${s}`));
|
|
4056
3719
|
}
|
|
4057
3720
|
info("To request elevated scopes, use the web dashboard or contact your team admin.");
|
|
4058
3721
|
process.exitCode = 1;
|
|
@@ -4106,10 +3769,10 @@ async function pluginRequestsCommand() {
|
|
|
4106
3769
|
info("No pending scope requests.");
|
|
4107
3770
|
return;
|
|
4108
3771
|
}
|
|
4109
|
-
console.log(
|
|
3772
|
+
console.log(chalk18.bold("\nPending Scope Requests:\n"));
|
|
4110
3773
|
for (const r of requests) {
|
|
4111
|
-
console.log(` ${
|
|
4112
|
-
if (r.reason) console.log(` reason: ${
|
|
3774
|
+
console.log(` ${chalk18.bold(r.id)} scopes: ${r.requested_scopes.join(", ")}`);
|
|
3775
|
+
if (r.reason) console.log(` reason: ${chalk18.dim(r.reason)}`);
|
|
4113
3776
|
console.log(` status: ${r.status} requested: ${r.created_at}`);
|
|
4114
3777
|
console.log();
|
|
4115
3778
|
}
|
|
@@ -4166,7 +3829,7 @@ function handleError(err) {
|
|
|
4166
3829
|
}
|
|
4167
3830
|
|
|
4168
3831
|
// src/bin/agt.ts
|
|
4169
|
-
var cliVersion2 = true ? "0.14.
|
|
3832
|
+
var cliVersion2 = true ? "0.14.10" : "dev";
|
|
4170
3833
|
var program = new Command();
|
|
4171
3834
|
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");
|
|
4172
3835
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -4213,11 +3876,11 @@ host.command("pair <host-name>").description("Start an SSM port-forward + shell
|
|
|
4213
3876
|
})
|
|
4214
3877
|
);
|
|
4215
3878
|
var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
|
|
4216
|
-
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",
|
|
4217
|
-
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files",
|
|
4218
|
-
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files",
|
|
3879
|
+
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", join9(homedir2(), ".augmented")).option("--supervise", "Wrap the manager in a respawn-on-clean-exit loop so auto-upgrades can restart it transparently (ENG-4488)", false).action(managerStartCommand);
|
|
3880
|
+
manager.command("stop").description("Stop the running manager daemon").option("--config-dir <dir>", "Config directory for agent files", join9(homedir2(), ".augmented")).action(managerStopCommand);
|
|
3881
|
+
manager.command("status").description("Show the current manager daemon status and discovered agents").option("--config-dir <dir>", "Config directory for agent files", join9(homedir2(), ".augmented")).action(managerStatusCommand);
|
|
4219
3882
|
var agent = program.command("agent").description("Inspect and manage agents");
|
|
4220
|
-
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory",
|
|
3883
|
+
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join9(homedir2(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
|
|
4221
3884
|
var kanban = program.command("kanban").description("Manage agent kanban boards");
|
|
4222
3885
|
kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
|
|
4223
3886
|
kanban.command("add <title>").description("Add a new item to an agent kanban board").requiredOption("--agent <code-name>", "Agent code name").option("--priority <1|2|3>", "Priority: 1=high, 2=medium, 3=low", "2").option("--status <status>", "Initial status: backlog | today | in_progress", "today").option("--description <text>", "Item description").option("--estimate <minutes>", "Estimated time in minutes").option("--deliverable <text>", "Expected output/deliverable").action(kanbanAddCommand);
|