@integrity-labs/agt-cli 0.6.6 → 0.6.7
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 +433 -54
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-EUF2V4N5.js → chunk-UIWXBJSX.js} +98 -20
- package/dist/chunk-UIWXBJSX.js.map +1 -0
- package/dist/host-security-6PDFG7F5.js +36 -0
- package/dist/host-security-6PDFG7F5.js.map +1 -0
- package/dist/lib/manager-worker.js +77 -6
- package/dist/lib/manager-worker.js.map +1 -1
- package/package.json +5 -3
- package/dist/chunk-EUF2V4N5.js.map +0 -1
package/dist/bin/agt.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
AGT_HOST,
|
|
4
|
+
ApiError,
|
|
4
5
|
CHANNEL_REGISTRY,
|
|
5
6
|
DEPLOYMENT_TEMPLATES,
|
|
6
7
|
SLACK_SCOPE_CATEGORY_LABELS,
|
|
@@ -31,11 +32,11 @@ import {
|
|
|
31
32
|
resolveChannels,
|
|
32
33
|
serializeManifestForSlackCli,
|
|
33
34
|
setActiveTeam
|
|
34
|
-
} from "../chunk-
|
|
35
|
+
} from "../chunk-UIWXBJSX.js";
|
|
35
36
|
|
|
36
37
|
// src/bin/agt.ts
|
|
37
|
-
import { join as
|
|
38
|
-
import { homedir as
|
|
38
|
+
import { join as join11 } from "path";
|
|
39
|
+
import { homedir as homedir3 } from "os";
|
|
39
40
|
import { Command } from "commander";
|
|
40
41
|
|
|
41
42
|
// src/lib/globals.ts
|
|
@@ -582,16 +583,16 @@ async function lintCommand(path) {
|
|
|
582
583
|
return;
|
|
583
584
|
}
|
|
584
585
|
}
|
|
585
|
-
let
|
|
586
|
+
let orgPolicy;
|
|
586
587
|
const teamSlug = requireTeam();
|
|
587
588
|
if (teamSlug) {
|
|
588
|
-
const spinner = ora4({ text: "Fetching
|
|
589
|
+
const spinner = ora4({ text: "Fetching org channel policy\u2026", isSilent: json });
|
|
589
590
|
spinner.start();
|
|
590
591
|
try {
|
|
591
592
|
const data = await api.get(`/teams/${encodeURIComponent(teamSlug)}/channel-policy`);
|
|
592
593
|
if (data.channel_policy) {
|
|
593
|
-
|
|
594
|
-
|
|
594
|
+
orgPolicy = {
|
|
595
|
+
organization_id: data.channel_policy.team_id,
|
|
595
596
|
allowed_channels: data.channel_policy.allowed_channels ?? [],
|
|
596
597
|
denied_channels: data.channel_policy.denied_channels ?? [],
|
|
597
598
|
require_elevated_for_pii: data.channel_policy.require_elevated_for_pii ?? false
|
|
@@ -621,10 +622,10 @@ Linting ${name}:`));
|
|
|
621
622
|
const toolsContent = hasTools ? readFileSync(toolsPath, "utf-8") : void 0;
|
|
622
623
|
let result;
|
|
623
624
|
if (charterContent && toolsContent) {
|
|
624
|
-
result = lintAll(charterContent, toolsContent, {
|
|
625
|
+
result = lintAll(charterContent, toolsContent, { orgChannelPolicy: orgPolicy });
|
|
625
626
|
if (!json) printResult("Full lint", result);
|
|
626
627
|
} else if (charterContent) {
|
|
627
|
-
result = lintCharter(charterContent, {
|
|
628
|
+
result = lintCharter(charterContent, { orgChannelPolicy: orgPolicy });
|
|
628
629
|
if (!json) printResult("CHARTER.md", result);
|
|
629
630
|
} else {
|
|
630
631
|
result = lintTools(toolsContent);
|
|
@@ -708,23 +709,23 @@ async function channelsCheckCommand(agentCodeName) {
|
|
|
708
709
|
denied: [],
|
|
709
710
|
require_approval_to_change: false
|
|
710
711
|
};
|
|
711
|
-
const
|
|
712
|
-
|
|
712
|
+
const orgPolicy = data.channel_policy ? {
|
|
713
|
+
organization_id: data.channel_policy.team_id,
|
|
713
714
|
allowed_channels: data.channel_policy.allowed_channels ?? [],
|
|
714
715
|
denied_channels: data.channel_policy.denied_channels ?? [],
|
|
715
716
|
require_elevated_for_pii: data.channel_policy.require_elevated_for_pii ?? false
|
|
716
717
|
} : void 0;
|
|
717
|
-
const resolved = resolveChannels(agentPolicy,
|
|
718
|
+
const resolved = resolveChannels(agentPolicy, orgPolicy);
|
|
718
719
|
spinner.stop();
|
|
719
720
|
if (json) {
|
|
720
721
|
jsonOutput({
|
|
721
722
|
ok: true,
|
|
722
723
|
agent: agentCodeName,
|
|
723
724
|
agent_allowlist: agentPolicy.allowed,
|
|
724
|
-
|
|
725
|
-
allowed:
|
|
726
|
-
denied:
|
|
727
|
-
require_elevated_for_pii:
|
|
725
|
+
org_policy: orgPolicy ? {
|
|
726
|
+
allowed: orgPolicy.allowed_channels,
|
|
727
|
+
denied: orgPolicy.denied_channels,
|
|
728
|
+
require_elevated_for_pii: orgPolicy.require_elevated_for_pii
|
|
728
729
|
} : null,
|
|
729
730
|
resolved_channels: resolved,
|
|
730
731
|
count: resolved.length
|
|
@@ -735,14 +736,14 @@ async function channelsCheckCommand(agentCodeName) {
|
|
|
735
736
|
Channel Resolution: ${agentCodeName}
|
|
736
737
|
`));
|
|
737
738
|
info(`Agent allowlist: ${agentPolicy.allowed.length > 0 ? agentPolicy.allowed.join(", ") : "none"}`);
|
|
738
|
-
if (
|
|
739
|
-
info(`
|
|
740
|
-
info(`
|
|
741
|
-
if (
|
|
742
|
-
info("
|
|
739
|
+
if (orgPolicy) {
|
|
740
|
+
info(`Org allowed: ${orgPolicy.allowed_channels.length > 0 ? orgPolicy.allowed_channels.join(", ") : "all (no restriction)"}`);
|
|
741
|
+
info(`Org denied: ${orgPolicy.denied_channels.length > 0 ? orgPolicy.denied_channels.join(", ") : "none"}`);
|
|
742
|
+
if (orgPolicy.require_elevated_for_pii) {
|
|
743
|
+
info("Org requires elevated tier for PII channels");
|
|
743
744
|
}
|
|
744
745
|
} else {
|
|
745
|
-
info("No
|
|
746
|
+
info("No org channel policy configured.");
|
|
746
747
|
}
|
|
747
748
|
console.log();
|
|
748
749
|
if (resolved.length === 0) {
|
|
@@ -1437,17 +1438,17 @@ async function provisionCommand(codeName, options) {
|
|
|
1437
1438
|
denied: [],
|
|
1438
1439
|
require_approval_to_change: true
|
|
1439
1440
|
};
|
|
1440
|
-
let
|
|
1441
|
+
let orgChannelPolicy;
|
|
1441
1442
|
const policyData = provisionData.team_channel_policy;
|
|
1442
1443
|
if (policyData) {
|
|
1443
|
-
|
|
1444
|
-
|
|
1444
|
+
orgChannelPolicy = {
|
|
1445
|
+
organization_id: policyData.team_id,
|
|
1445
1446
|
allowed_channels: policyData.allowed_channels ?? [],
|
|
1446
1447
|
denied_channels: policyData.denied_channels ?? [],
|
|
1447
1448
|
require_elevated_for_pii: policyData.require_elevated_for_pii ?? false
|
|
1448
1449
|
};
|
|
1449
1450
|
}
|
|
1450
|
-
const resolvedChannels = resolveChannels(agentChannelPolicy,
|
|
1451
|
+
const resolvedChannels = resolveChannels(agentChannelPolicy, orgChannelPolicy);
|
|
1451
1452
|
const frameworkId = agentData.framework ?? "openclaw";
|
|
1452
1453
|
const adapter = getFramework(frameworkId);
|
|
1453
1454
|
spinner.text = `Building ${adapter.label} config\u2026`;
|
|
@@ -2526,26 +2527,399 @@ function formatTimestamp(iso) {
|
|
|
2526
2527
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
2527
2528
|
}
|
|
2528
2529
|
|
|
2529
|
-
// src/commands/kanban.ts
|
|
2530
|
+
// src/commands/kanban-recurring.ts
|
|
2530
2531
|
import chalk16 from "chalk";
|
|
2531
2532
|
import ora12 from "ora";
|
|
2532
2533
|
async function resolveAgentId(codeName) {
|
|
2533
2534
|
try {
|
|
2534
2535
|
const data = await api.get(`/agents/${codeName}`);
|
|
2535
2536
|
return data.agent_id;
|
|
2536
|
-
} catch {
|
|
2537
|
-
return null;
|
|
2537
|
+
} catch (err) {
|
|
2538
|
+
if (err instanceof ApiError && err.status === 404) return null;
|
|
2539
|
+
throw err;
|
|
2538
2540
|
}
|
|
2539
2541
|
}
|
|
2540
2542
|
function priorityLabel(p) {
|
|
2541
2543
|
return p === 1 ? chalk16.red("HIGH") : p === 3 ? chalk16.dim("LOW") : chalk16.yellow("MED");
|
|
2542
2544
|
}
|
|
2545
|
+
function formatSpawnTime(isoDate, timezone) {
|
|
2546
|
+
if (!isoDate) return chalk16.dim("\u2014");
|
|
2547
|
+
try {
|
|
2548
|
+
return new Intl.DateTimeFormat("en-AU", {
|
|
2549
|
+
dateStyle: "medium",
|
|
2550
|
+
timeStyle: "short",
|
|
2551
|
+
timeZone: timezone
|
|
2552
|
+
}).format(new Date(isoDate));
|
|
2553
|
+
} catch {
|
|
2554
|
+
return new Date(isoDate).toLocaleString();
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
async function kanbanRecurringAddCommand(title, opts) {
|
|
2558
|
+
const teamSlug = requireTeam();
|
|
2559
|
+
if (!teamSlug) return;
|
|
2560
|
+
const json = isJsonMode();
|
|
2561
|
+
let priority;
|
|
2562
|
+
if (opts.priority) {
|
|
2563
|
+
priority = Number(opts.priority);
|
|
2564
|
+
if (!Number.isInteger(priority) || priority < 1 || priority > 3) {
|
|
2565
|
+
if (json) {
|
|
2566
|
+
jsonOutput({ ok: false, error: "Priority must be 1, 2, or 3" });
|
|
2567
|
+
} else {
|
|
2568
|
+
error("Priority must be 1 (high), 2 (medium), or 3 (low)");
|
|
2569
|
+
}
|
|
2570
|
+
process.exitCode = 1;
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
let estimatedMinutes;
|
|
2575
|
+
if (opts.estimate) {
|
|
2576
|
+
estimatedMinutes = Number(opts.estimate);
|
|
2577
|
+
if (!Number.isInteger(estimatedMinutes) || estimatedMinutes <= 0) {
|
|
2578
|
+
if (json) {
|
|
2579
|
+
jsonOutput({ ok: false, error: "Estimate must be a positive integer (minutes)" });
|
|
2580
|
+
} else {
|
|
2581
|
+
error("Estimate must be a positive integer (minutes)");
|
|
2582
|
+
}
|
|
2583
|
+
process.exitCode = 1;
|
|
2584
|
+
return;
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
const spinner = ora12({ text: "Creating recurring template\u2026", isSilent: json });
|
|
2588
|
+
spinner.start();
|
|
2589
|
+
const agentId = await resolveAgentId(opts.agent);
|
|
2590
|
+
if (!agentId) {
|
|
2591
|
+
spinner.fail(`Agent "${opts.agent}" not found`);
|
|
2592
|
+
process.exitCode = 1;
|
|
2593
|
+
return;
|
|
2594
|
+
}
|
|
2595
|
+
try {
|
|
2596
|
+
const data = await api.post("/host/kanban/recurring", {
|
|
2597
|
+
agent_id: agentId,
|
|
2598
|
+
title,
|
|
2599
|
+
description: opts.description ?? void 0,
|
|
2600
|
+
priority,
|
|
2601
|
+
estimated_minutes: estimatedMinutes,
|
|
2602
|
+
deliverable: opts.deliverable ?? void 0,
|
|
2603
|
+
schedule: opts.every,
|
|
2604
|
+
timezone: opts.timezone ?? void 0
|
|
2605
|
+
});
|
|
2606
|
+
spinner.stop();
|
|
2607
|
+
if (json) {
|
|
2608
|
+
jsonOutput({ ok: true, template: data.template });
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
success(`Recurring task created: ${chalk16.bold(title)}`);
|
|
2612
|
+
info(`Schedule: ${chalk16.cyan(data.template.natural_language ?? data.template.expression ?? data.template.every_interval ?? "")}`);
|
|
2613
|
+
info(`Next spawn: ${formatSpawnTime(data.template.next_spawn_at, data.template.timezone)}`);
|
|
2614
|
+
info(`Timezone: ${data.template.timezone}`);
|
|
2615
|
+
} catch (err) {
|
|
2616
|
+
spinner.fail("Failed to create recurring template");
|
|
2617
|
+
if (json) {
|
|
2618
|
+
jsonOutput({ ok: false, error: err.message });
|
|
2619
|
+
} else {
|
|
2620
|
+
error(err.message);
|
|
2621
|
+
}
|
|
2622
|
+
process.exitCode = 1;
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
async function kanbanRecurringListCommand(opts) {
|
|
2626
|
+
const teamSlug = requireTeam();
|
|
2627
|
+
if (!teamSlug) return;
|
|
2628
|
+
const json = isJsonMode();
|
|
2629
|
+
const spinner = ora12({ text: "Fetching recurring templates\u2026", isSilent: json });
|
|
2630
|
+
spinner.start();
|
|
2631
|
+
const agentId = await resolveAgentId(opts.agent);
|
|
2632
|
+
if (!agentId) {
|
|
2633
|
+
spinner.fail(`Agent "${opts.agent}" not found`);
|
|
2634
|
+
process.exitCode = 1;
|
|
2635
|
+
return;
|
|
2636
|
+
}
|
|
2637
|
+
try {
|
|
2638
|
+
const data = await api.get(
|
|
2639
|
+
`/host/kanban/recurring?agent_id=${agentId}`
|
|
2640
|
+
);
|
|
2641
|
+
spinner.stop();
|
|
2642
|
+
if (json) {
|
|
2643
|
+
jsonOutput({ ok: true, templates: data.templates });
|
|
2644
|
+
return;
|
|
2645
|
+
}
|
|
2646
|
+
if (data.templates.length === 0) {
|
|
2647
|
+
info("No recurring templates found.");
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
const rows = data.templates.map((t) => [
|
|
2651
|
+
t.id.slice(0, 8),
|
|
2652
|
+
t.title,
|
|
2653
|
+
t.natural_language ?? t.expression ?? t.every_interval ?? "\u2014",
|
|
2654
|
+
priorityLabel(t.priority),
|
|
2655
|
+
t.enabled ? chalk16.green("Active") : chalk16.dim("Disabled"),
|
|
2656
|
+
formatSpawnTime(t.next_spawn_at, t.timezone),
|
|
2657
|
+
String(t.spawn_count)
|
|
2658
|
+
]);
|
|
2659
|
+
table(
|
|
2660
|
+
["ID", "Title", "Schedule", "Priority", "Status", "Next Spawn", "Spawned"],
|
|
2661
|
+
rows
|
|
2662
|
+
);
|
|
2663
|
+
} catch (err) {
|
|
2664
|
+
spinner.fail("Failed to fetch recurring templates");
|
|
2665
|
+
if (json) {
|
|
2666
|
+
jsonOutput({ ok: false, error: err.message });
|
|
2667
|
+
} else {
|
|
2668
|
+
error(err.message);
|
|
2669
|
+
}
|
|
2670
|
+
process.exitCode = 1;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
async function kanbanRecurringDisableCommand(titleOrId, opts) {
|
|
2674
|
+
const teamSlug = requireTeam();
|
|
2675
|
+
if (!teamSlug) return;
|
|
2676
|
+
const json = isJsonMode();
|
|
2677
|
+
const spinner = ora12({ text: "Disabling recurring template\u2026", isSilent: json });
|
|
2678
|
+
spinner.start();
|
|
2679
|
+
const agentId = await resolveAgentId(opts.agent);
|
|
2680
|
+
if (!agentId) {
|
|
2681
|
+
spinner.fail(`Agent "${opts.agent}" not found`);
|
|
2682
|
+
process.exitCode = 1;
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
try {
|
|
2686
|
+
const data = await api.get(
|
|
2687
|
+
`/host/kanban/recurring?agent_id=${agentId}`
|
|
2688
|
+
);
|
|
2689
|
+
const matches = data.templates.filter(
|
|
2690
|
+
(t) => t.id.startsWith(titleOrId) || t.title.toLowerCase() === titleOrId.toLowerCase()
|
|
2691
|
+
);
|
|
2692
|
+
if (matches.length === 0) {
|
|
2693
|
+
spinner.fail(`Recurring template "${titleOrId}" not found`);
|
|
2694
|
+
process.exitCode = 1;
|
|
2695
|
+
return;
|
|
2696
|
+
}
|
|
2697
|
+
if (matches.length > 1) {
|
|
2698
|
+
spinner.fail(`Ambiguous match for "${titleOrId}" \u2014 ${matches.length} templates found:`);
|
|
2699
|
+
for (const m of matches) {
|
|
2700
|
+
info(` ${m.id.slice(0, 8)} \u2014 ${m.title}`);
|
|
2701
|
+
}
|
|
2702
|
+
info("Use a longer ID prefix to disambiguate.");
|
|
2703
|
+
process.exitCode = 1;
|
|
2704
|
+
return;
|
|
2705
|
+
}
|
|
2706
|
+
const match = matches[0];
|
|
2707
|
+
await api.patch(`/host/kanban/recurring/${match.id}`, { enabled: false });
|
|
2708
|
+
spinner.stop();
|
|
2709
|
+
if (json) {
|
|
2710
|
+
jsonOutput({ ok: true, id: match.id, title: match.title, enabled: false });
|
|
2711
|
+
} else {
|
|
2712
|
+
success(`Disabled: ${chalk16.bold(match.title)}`);
|
|
2713
|
+
}
|
|
2714
|
+
} catch (err) {
|
|
2715
|
+
spinner.fail("Failed to disable recurring template");
|
|
2716
|
+
if (json) {
|
|
2717
|
+
jsonOutput({ ok: false, error: err.message });
|
|
2718
|
+
} else {
|
|
2719
|
+
error(err.message);
|
|
2720
|
+
}
|
|
2721
|
+
process.exitCode = 1;
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
// src/commands/setup.ts
|
|
2726
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
2727
|
+
import { join as join10, dirname } from "path";
|
|
2728
|
+
import { homedir as homedir2 } from "os";
|
|
2729
|
+
import chalk17 from "chalk";
|
|
2730
|
+
import ora13 from "ora";
|
|
2731
|
+
function detectShellProfile() {
|
|
2732
|
+
const shell = process.env["SHELL"] ?? "";
|
|
2733
|
+
const home = homedir2();
|
|
2734
|
+
if (shell.includes("zsh")) {
|
|
2735
|
+
const zshrc = join10(home, ".zshrc");
|
|
2736
|
+
if (existsSync4(zshrc)) return zshrc;
|
|
2737
|
+
return join10(home, ".zprofile");
|
|
2738
|
+
}
|
|
2739
|
+
if (shell.includes("fish")) {
|
|
2740
|
+
const fishConfig = join10(home, ".config", "fish", "config.fish");
|
|
2741
|
+
return fishConfig;
|
|
2742
|
+
}
|
|
2743
|
+
const bashrc = join10(home, ".bashrc");
|
|
2744
|
+
if (existsSync4(bashrc)) return bashrc;
|
|
2745
|
+
return join10(home, ".bash_profile");
|
|
2746
|
+
}
|
|
2747
|
+
function buildExportLines(shell, apiUrl, apiKey) {
|
|
2748
|
+
if (shell.includes("fish")) {
|
|
2749
|
+
return [
|
|
2750
|
+
"",
|
|
2751
|
+
"# Augmented (agt) host configuration",
|
|
2752
|
+
`set -gx AGT_HOST "${apiUrl}"`,
|
|
2753
|
+
`set -gx AGT_API_KEY "${apiKey}"`,
|
|
2754
|
+
""
|
|
2755
|
+
].join("\n");
|
|
2756
|
+
}
|
|
2757
|
+
return [
|
|
2758
|
+
"",
|
|
2759
|
+
"# Augmented (agt) host configuration",
|
|
2760
|
+
`export AGT_HOST="${apiUrl}"`,
|
|
2761
|
+
`export AGT_API_KEY="${apiKey}"`,
|
|
2762
|
+
""
|
|
2763
|
+
].join("\n");
|
|
2764
|
+
}
|
|
2765
|
+
async function setupCommand(token) {
|
|
2766
|
+
const json = isJsonMode();
|
|
2767
|
+
const shortTokenPattern = /^[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4}$/i;
|
|
2768
|
+
const legacyTokenPattern = /^prov_[a-f0-9]{64}$/i;
|
|
2769
|
+
if (!token || !shortTokenPattern.test(token) && !legacyTokenPattern.test(token)) {
|
|
2770
|
+
if (json) {
|
|
2771
|
+
jsonOutput({ ok: false, error: "Invalid provisioning token. Expected format: XXXX-XXXX or prov_<64 hex>" });
|
|
2772
|
+
} else {
|
|
2773
|
+
error("Invalid provisioning token. Expected format: XXXX-XXXX or prov_<64 hex>");
|
|
2774
|
+
info("Get a provisioning token from the Augmented dashboard after creating a host.");
|
|
2775
|
+
}
|
|
2776
|
+
process.exitCode = 1;
|
|
2777
|
+
return;
|
|
2778
|
+
}
|
|
2779
|
+
const normalizedToken = shortTokenPattern.test(token) ? token.toUpperCase() : token.toLowerCase();
|
|
2780
|
+
let apiUrl = process.env["AGT_HOST"];
|
|
2781
|
+
if (!apiUrl) {
|
|
2782
|
+
apiUrl = "https://api.augmented.team";
|
|
2783
|
+
if (!json) {
|
|
2784
|
+
info(`No AGT_HOST set \u2014 using default: ${chalk17.bold(apiUrl)}`);
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
const spinner = ora13({ text: "Exchanging provisioning token\u2026", isSilent: json });
|
|
2788
|
+
spinner.start();
|
|
2789
|
+
let setupResult;
|
|
2790
|
+
try {
|
|
2791
|
+
const res = await fetch(`${apiUrl}/host/setup`, {
|
|
2792
|
+
method: "POST",
|
|
2793
|
+
headers: { "Content-Type": "application/json" },
|
|
2794
|
+
body: JSON.stringify({ token: normalizedToken })
|
|
2795
|
+
});
|
|
2796
|
+
if (!res.ok) {
|
|
2797
|
+
const body = await res.json().catch(() => ({}));
|
|
2798
|
+
throw new Error(body["error"] ?? `Setup failed: HTTP ${res.status}`);
|
|
2799
|
+
}
|
|
2800
|
+
setupResult = await res.json();
|
|
2801
|
+
spinner.succeed("Provisioning token accepted");
|
|
2802
|
+
} catch (err) {
|
|
2803
|
+
spinner.fail("Failed to exchange provisioning token");
|
|
2804
|
+
if (json) {
|
|
2805
|
+
jsonOutput({ ok: false, error: err.message });
|
|
2806
|
+
} else {
|
|
2807
|
+
error(err.message);
|
|
2808
|
+
}
|
|
2809
|
+
process.exitCode = 1;
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2812
|
+
const finalApiUrl = setupResult.api_url || apiUrl;
|
|
2813
|
+
process.env["AGT_HOST"] = finalApiUrl;
|
|
2814
|
+
process.env["AGT_API_KEY"] = setupResult.api_key;
|
|
2815
|
+
const verifySpinner = ora13({ text: "Verifying connection\u2026", isSilent: json });
|
|
2816
|
+
verifySpinner.start();
|
|
2817
|
+
try {
|
|
2818
|
+
const exchange = await exchangeApiKey(setupResult.api_key);
|
|
2819
|
+
verifySpinner.succeed("Connection verified");
|
|
2820
|
+
if (!json) {
|
|
2821
|
+
info(`Host: ${chalk17.bold(setupResult.host_name)}`);
|
|
2822
|
+
info(`Host ID: ${exchange.hostId}`);
|
|
2823
|
+
info(`Team: ${chalk17.bold(exchange.teamSlug ?? setupResult.team_slug ?? "unknown")}`);
|
|
2824
|
+
if (exchange.userEmail) {
|
|
2825
|
+
info(`User: ${chalk17.bold(exchange.userEmail)}`);
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
} catch (err) {
|
|
2829
|
+
verifySpinner.fail("Connection verification failed");
|
|
2830
|
+
if (json) {
|
|
2831
|
+
jsonOutput({ ok: false, error: err.message });
|
|
2832
|
+
} else {
|
|
2833
|
+
error(err.message);
|
|
2834
|
+
info("Connection could not be verified. No changes were written to your shell profile.");
|
|
2835
|
+
info("Check your network connection and try: agt whoami");
|
|
2836
|
+
}
|
|
2837
|
+
process.exitCode = 1;
|
|
2838
|
+
return;
|
|
2839
|
+
}
|
|
2840
|
+
const profilePath = detectShellProfile();
|
|
2841
|
+
const shell = process.env["SHELL"] ?? "bash";
|
|
2842
|
+
const exportLines = buildExportLines(shell, finalApiUrl, setupResult.api_key);
|
|
2843
|
+
const profileDir = dirname(profilePath);
|
|
2844
|
+
if (!existsSync4(profileDir)) {
|
|
2845
|
+
mkdirSync5(profileDir, { recursive: true });
|
|
2846
|
+
}
|
|
2847
|
+
const marker = "# Augmented (agt) host configuration";
|
|
2848
|
+
const current = existsSync4(profilePath) ? readFileSync4(profilePath, "utf-8") : "";
|
|
2849
|
+
let updated;
|
|
2850
|
+
if (current.includes(marker)) {
|
|
2851
|
+
updated = current.replace(
|
|
2852
|
+
/# Augmented \(agt\) host configuration[\s\S]*?(?=\n# |\s*$)/m,
|
|
2853
|
+
exportLines.trimEnd()
|
|
2854
|
+
);
|
|
2855
|
+
if (!json) {
|
|
2856
|
+
info("Replacing existing Augmented config block in shell profile.");
|
|
2857
|
+
}
|
|
2858
|
+
} else {
|
|
2859
|
+
updated = current + exportLines;
|
|
2860
|
+
}
|
|
2861
|
+
writeFileSync5(profilePath, updated.endsWith("\n") ? updated : `${updated}
|
|
2862
|
+
`);
|
|
2863
|
+
if (!json) {
|
|
2864
|
+
success(`Environment variables written to ${chalk17.bold(profilePath)}`);
|
|
2865
|
+
}
|
|
2866
|
+
const managerSpinner = ora13({ text: "Starting manager daemon\u2026", isSilent: json });
|
|
2867
|
+
managerSpinner.start();
|
|
2868
|
+
try {
|
|
2869
|
+
const configDir = join10(homedir2(), ".augmented");
|
|
2870
|
+
const { pid } = startWatchdog({ intervalMs: 1e4, configDir });
|
|
2871
|
+
managerSpinner.succeed(`Manager started (PID ${pid})`);
|
|
2872
|
+
} catch (err) {
|
|
2873
|
+
managerSpinner.warn("Could not start manager daemon");
|
|
2874
|
+
if (!json) {
|
|
2875
|
+
warn(err.message);
|
|
2876
|
+
info("Start it manually with: agt manager start");
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
if (json) {
|
|
2880
|
+
jsonOutput({
|
|
2881
|
+
ok: true,
|
|
2882
|
+
host_name: setupResult.host_name,
|
|
2883
|
+
host_id: setupResult.host_id,
|
|
2884
|
+
team_slug: setupResult.team_slug,
|
|
2885
|
+
api_url: finalApiUrl,
|
|
2886
|
+
agents: setupResult.agents,
|
|
2887
|
+
profile: profilePath
|
|
2888
|
+
});
|
|
2889
|
+
} else {
|
|
2890
|
+
console.log();
|
|
2891
|
+
console.log(chalk17.green.bold(" Setup complete!"));
|
|
2892
|
+
console.log();
|
|
2893
|
+
if (setupResult.agents.length > 0) {
|
|
2894
|
+
info(`Agents: ${setupResult.agents.map((a) => chalk17.cyan(a)).join(", ")}`);
|
|
2895
|
+
} else {
|
|
2896
|
+
info("No agents assigned yet. Assign agents in the dashboard or with: agt host assign");
|
|
2897
|
+
}
|
|
2898
|
+
console.log();
|
|
2899
|
+
info(`Restart your shell or run: ${chalk17.bold(`source ${profilePath}`)}`);
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
|
|
2903
|
+
// src/commands/kanban.ts
|
|
2904
|
+
import chalk18 from "chalk";
|
|
2905
|
+
import ora14 from "ora";
|
|
2906
|
+
async function resolveAgentId2(codeName) {
|
|
2907
|
+
try {
|
|
2908
|
+
const data = await api.get(`/agents/${codeName}`);
|
|
2909
|
+
return data.agent_id;
|
|
2910
|
+
} catch {
|
|
2911
|
+
return null;
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
function priorityLabel2(p) {
|
|
2915
|
+
return p === 1 ? chalk18.red("HIGH") : p === 3 ? chalk18.dim("LOW") : chalk18.yellow("MED");
|
|
2916
|
+
}
|
|
2543
2917
|
function statusLabel(s) {
|
|
2544
2918
|
const map = {
|
|
2545
|
-
in_progress:
|
|
2546
|
-
today:
|
|
2547
|
-
backlog:
|
|
2548
|
-
done:
|
|
2919
|
+
in_progress: chalk18.blue("In Progress"),
|
|
2920
|
+
today: chalk18.green("Today"),
|
|
2921
|
+
backlog: chalk18.dim("Backlog"),
|
|
2922
|
+
done: chalk18.gray("Done")
|
|
2549
2923
|
};
|
|
2550
2924
|
return map[s] ?? s;
|
|
2551
2925
|
}
|
|
@@ -2553,9 +2927,9 @@ async function kanbanListCommand(opts) {
|
|
|
2553
2927
|
const teamSlug = requireTeam();
|
|
2554
2928
|
if (!teamSlug) return;
|
|
2555
2929
|
const json = isJsonMode();
|
|
2556
|
-
const spinner =
|
|
2930
|
+
const spinner = ora14({ text: "Fetching kanban board\u2026", isSilent: json });
|
|
2557
2931
|
spinner.start();
|
|
2558
|
-
const agentId = await
|
|
2932
|
+
const agentId = await resolveAgentId2(opts.agent);
|
|
2559
2933
|
if (!agentId) {
|
|
2560
2934
|
spinner.fail(`Agent "${opts.agent}" not found.`);
|
|
2561
2935
|
process.exitCode = 1;
|
|
@@ -2575,13 +2949,13 @@ async function kanbanListCommand(opts) {
|
|
|
2575
2949
|
return;
|
|
2576
2950
|
}
|
|
2577
2951
|
const rows = data.items.map((item) => [
|
|
2578
|
-
|
|
2952
|
+
priorityLabel2(item.priority),
|
|
2579
2953
|
statusLabel(item.status),
|
|
2580
2954
|
item.title.length > 50 ? item.title.slice(0, 47) + "\u2026" : item.title,
|
|
2581
2955
|
item.estimated_minutes ? `~${item.estimated_minutes}min` : "",
|
|
2582
2956
|
item.id.slice(0, 8)
|
|
2583
2957
|
]);
|
|
2584
|
-
console.log(
|
|
2958
|
+
console.log(chalk18.bold(`
|
|
2585
2959
|
Kanban: ${opts.agent}
|
|
2586
2960
|
`));
|
|
2587
2961
|
table(["Pri", "Status", "Title", "Est", "ID"], rows);
|
|
@@ -2599,7 +2973,7 @@ async function kanbanAddCommand(title, opts) {
|
|
|
2599
2973
|
const teamSlug = requireTeam();
|
|
2600
2974
|
if (!teamSlug) return;
|
|
2601
2975
|
const json = isJsonMode();
|
|
2602
|
-
const agentId = await
|
|
2976
|
+
const agentId = await resolveAgentId2(opts.agent);
|
|
2603
2977
|
if (!agentId) {
|
|
2604
2978
|
error(`Agent "${opts.agent}" not found.`);
|
|
2605
2979
|
process.exitCode = 1;
|
|
@@ -2644,7 +3018,7 @@ async function kanbanMoveCommand(titleOrId, status, opts) {
|
|
|
2644
3018
|
process.exitCode = 1;
|
|
2645
3019
|
return;
|
|
2646
3020
|
}
|
|
2647
|
-
const agentId = await
|
|
3021
|
+
const agentId = await resolveAgentId2(opts.agent);
|
|
2648
3022
|
if (!agentId) {
|
|
2649
3023
|
error(`Agent "${opts.agent}" not found.`);
|
|
2650
3024
|
process.exitCode = 1;
|
|
@@ -2686,7 +3060,7 @@ async function kanbanUpdateCommand(titleOrId, opts) {
|
|
|
2686
3060
|
const teamSlug = requireTeam();
|
|
2687
3061
|
if (!teamSlug) return;
|
|
2688
3062
|
const json = isJsonMode();
|
|
2689
|
-
const agentId = await
|
|
3063
|
+
const agentId = await resolveAgentId2(opts.agent);
|
|
2690
3064
|
if (!agentId) {
|
|
2691
3065
|
error(`Agent "${opts.agent}" not found.`);
|
|
2692
3066
|
process.exitCode = 1;
|
|
@@ -2749,7 +3123,7 @@ async function kanbanDoneCommand(titleOrId, opts) {
|
|
|
2749
3123
|
const teamSlug = requireTeam();
|
|
2750
3124
|
if (!teamSlug) return;
|
|
2751
3125
|
const json = isJsonMode();
|
|
2752
|
-
const agentId = await
|
|
3126
|
+
const agentId = await resolveAgentId2(opts.agent);
|
|
2753
3127
|
if (!agentId) {
|
|
2754
3128
|
error(`Agent "${opts.agent}" not found.`);
|
|
2755
3129
|
process.exitCode = 1;
|
|
@@ -3037,9 +3411,9 @@ async function acpxCloseCommand(agent2, _opts, cmd) {
|
|
|
3037
3411
|
|
|
3038
3412
|
// src/commands/update.ts
|
|
3039
3413
|
import { execSync } from "child_process";
|
|
3040
|
-
import
|
|
3041
|
-
import
|
|
3042
|
-
var cliVersion = true ? "0.6.
|
|
3414
|
+
import chalk19 from "chalk";
|
|
3415
|
+
import ora15 from "ora";
|
|
3416
|
+
var cliVersion = true ? "0.6.7" : "dev";
|
|
3043
3417
|
async function fetchLatestVersion() {
|
|
3044
3418
|
const host2 = AGT_HOST;
|
|
3045
3419
|
if (!host2) return null;
|
|
@@ -3075,7 +3449,7 @@ function performUpdate(version) {
|
|
|
3075
3449
|
}
|
|
3076
3450
|
async function updateCommand() {
|
|
3077
3451
|
const json = isJsonMode();
|
|
3078
|
-
const spinner =
|
|
3452
|
+
const spinner = ora15({ text: "Checking for updates\u2026", isSilent: json });
|
|
3079
3453
|
spinner.start();
|
|
3080
3454
|
const versionInfo = await fetchLatestVersion();
|
|
3081
3455
|
if (!versionInfo) {
|
|
@@ -3094,18 +3468,18 @@ async function updateCommand() {
|
|
|
3094
3468
|
if (json) {
|
|
3095
3469
|
jsonOutput({ ok: true, current: cliVersion, latest: versionInfo.latest, update_available: false });
|
|
3096
3470
|
} else {
|
|
3097
|
-
success(`You're on the latest version (${
|
|
3471
|
+
success(`You're on the latest version (${chalk19.bold(cliVersion)})`);
|
|
3098
3472
|
}
|
|
3099
3473
|
return;
|
|
3100
3474
|
}
|
|
3101
3475
|
spinner.stop();
|
|
3102
3476
|
if (!json) {
|
|
3103
|
-
info(`Update available: ${
|
|
3477
|
+
info(`Update available: ${chalk19.dim(cliVersion)} \u2192 ${chalk19.bold.green(versionInfo.latest)}`);
|
|
3104
3478
|
if (versionInfo.changelog_url) {
|
|
3105
3479
|
info(`Changelog: ${versionInfo.changelog_url}`);
|
|
3106
3480
|
}
|
|
3107
3481
|
}
|
|
3108
|
-
const updateSpinner =
|
|
3482
|
+
const updateSpinner = ora15({ text: "Installing update\u2026", isSilent: json });
|
|
3109
3483
|
updateSpinner.start();
|
|
3110
3484
|
try {
|
|
3111
3485
|
performUpdate(versionInfo.latest);
|
|
@@ -3119,7 +3493,7 @@ async function updateCommand() {
|
|
|
3119
3493
|
updated: true
|
|
3120
3494
|
});
|
|
3121
3495
|
} else {
|
|
3122
|
-
success(`Updated to ${
|
|
3496
|
+
success(`Updated to ${chalk19.bold(versionInfo.latest)}`);
|
|
3123
3497
|
}
|
|
3124
3498
|
} catch (err) {
|
|
3125
3499
|
updateSpinner.fail("Update failed");
|
|
@@ -3145,8 +3519,8 @@ async function checkForUpdateOnStartup() {
|
|
|
3145
3519
|
if (!versionInfo) return;
|
|
3146
3520
|
if (isNewerVersion(cliVersion, versionInfo.latest)) {
|
|
3147
3521
|
console.error(
|
|
3148
|
-
|
|
3149
|
-
Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${
|
|
3522
|
+
chalk19.yellow(`
|
|
3523
|
+
Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${chalk19.bold("agt update")} to install.
|
|
3150
3524
|
`)
|
|
3151
3525
|
);
|
|
3152
3526
|
}
|
|
@@ -3155,7 +3529,7 @@ async function checkForUpdateOnStartup() {
|
|
|
3155
3529
|
}
|
|
3156
3530
|
|
|
3157
3531
|
// src/bin/agt.ts
|
|
3158
|
-
var cliVersion2 = true ? "0.6.
|
|
3532
|
+
var cliVersion2 = true ? "0.6.7" : "dev";
|
|
3159
3533
|
var program = new Command();
|
|
3160
3534
|
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");
|
|
3161
3535
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -3165,6 +3539,7 @@ program.hook("preAction", (thisCommand) => {
|
|
|
3165
3539
|
}
|
|
3166
3540
|
});
|
|
3167
3541
|
program.command("whoami").description("Show the authenticated host, team, and user from AGT_API_KEY").action(whoamiCommand);
|
|
3542
|
+
program.command("setup <token>").description("One-command host setup: exchange provisioning token, configure env vars, verify, and start manager").action(setupCommand);
|
|
3168
3543
|
var team = program.command("team").description("Manage teams");
|
|
3169
3544
|
team.command("list").description("List teams you belong to").action(teamListCommand);
|
|
3170
3545
|
team.command("create <name>").description("Create a new team and set it as active").action(teamCreateCommand);
|
|
@@ -3195,17 +3570,21 @@ host.command("agents [host-name]").description("List agents assigned to a host (
|
|
|
3195
3570
|
host.command("rotate-key <host-name>").description("Rotate the API key for a host (revokes the old key)").action(hostRotateKeyCommand);
|
|
3196
3571
|
host.command("decommission <host-name>").description("Decommission a host (revokes key, marks inactive)").action(hostDecommissionCommand);
|
|
3197
3572
|
var manager = program.command("manager").description("Host config sync daemon \u2014 keeps local agent files in sync with API");
|
|
3198
|
-
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",
|
|
3573
|
+
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);
|
|
3199
3574
|
manager.command("stop").description("Stop the running manager daemon").action(managerStopCommand);
|
|
3200
3575
|
manager.command("status").description("Show the current manager daemon status and discovered agents").action(managerStatusCommand);
|
|
3201
3576
|
var agent = program.command("agent").description("Inspect and manage agents");
|
|
3202
|
-
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory",
|
|
3577
|
+
agent.command("show <code-name>").description("Display an agent's provisioned OpenClaw configuration").option("--config-dir <dir>", "Config directory", join11(homedir3(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
|
|
3203
3578
|
var kanban = program.command("kanban").description("Manage agent kanban boards");
|
|
3204
3579
|
kanban.command("list").description("List kanban board items for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanListCommand);
|
|
3205
3580
|
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);
|
|
3206
3581
|
kanban.command("move <title-or-id> <status>").description("Move a kanban item to a different status").requiredOption("--agent <code-name>", "Agent code name").option("--notes <text>", "Progress notes").action(kanbanMoveCommand);
|
|
3207
3582
|
kanban.command("update <title-or-id>").description("Update notes or result on a kanban item").requiredOption("--agent <code-name>", "Agent code name").option("--notes <text>", "Progress notes").option("--result <text>", "Result/output produced").action(kanbanUpdateCommand);
|
|
3208
3583
|
kanban.command("done <title-or-id>").description("Mark a kanban item as done").requiredOption("--agent <code-name>", "Agent code name").option("--result <text>", "What was produced/delivered").option("--notes <text>", "Completion notes").action(kanbanDoneCommand);
|
|
3584
|
+
var recurring = kanban.command("recurring").description("Manage recurring kanban tasks");
|
|
3585
|
+
recurring.command("add <title>").description("Create a recurring kanban task").requiredOption("--agent <code-name>", "Agent code name").requiredOption("--every <schedule>", 'Schedule: "every Monday at 9am", "daily at 8:30am", "every 2 hours", or cron').option("--priority <1|2|3>", "Priority: 1=high, 2=medium, 3=low", "2").option("--description <text>", "Task description").option("--estimate <minutes>", "Estimated time in minutes").option("--deliverable <text>", "Expected output/deliverable").option("--timezone <tz>", "Timezone (default: UTC)").action(kanbanRecurringAddCommand);
|
|
3586
|
+
recurring.command("list").description("List recurring kanban templates for an agent").requiredOption("--agent <code-name>", "Agent code name").action(kanbanRecurringListCommand);
|
|
3587
|
+
recurring.command("disable <title-or-id>").description("Disable a recurring kanban template").requiredOption("--agent <code-name>", "Agent code name").action(kanbanRecurringDisableCommand);
|
|
3209
3588
|
var acpx = program.command("acpx").description("Agent Client Protocol (ACP) session management via acpx").option("--cwd <path>", "Working directory for session routing").option("-s, --name <name>", "Named session for parallel workstreams").option("--approve-all", "Auto-approve all agent tool permissions").option("--format <type>", "Output format: text | json | json-strict | quiet", "text").option("--ttl <seconds>", "Queue owner idle TTL in seconds (0 = indefinite)").option("--timeout <seconds>", "Prompt execution timeout").option("--no-wait", "Submit prompt without waiting for completion");
|
|
3210
3589
|
acpx.command("spawn <agent>").description("Spawn or ensure an ACP session for an agent (claude, codex, openclaw)").action(acpxSpawnCommand);
|
|
3211
3590
|
acpx.command("prompt <agent> <prompt>").description("Send a prompt to an ACP session").action(acpxPromptCommand);
|