@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 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-EUF2V4N5.js";
35
+ } from "../chunk-UIWXBJSX.js";
35
36
 
36
37
  // src/bin/agt.ts
37
- import { join as join10 } from "path";
38
- import { homedir as homedir2 } from "os";
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 teamPolicy;
586
+ let orgPolicy;
586
587
  const teamSlug = requireTeam();
587
588
  if (teamSlug) {
588
- const spinner = ora4({ text: "Fetching team channel policy\u2026", isSilent: json });
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
- teamPolicy = {
594
- team_id: data.channel_policy.team_id,
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, { teamChannelPolicy: teamPolicy });
625
+ result = lintAll(charterContent, toolsContent, { orgChannelPolicy: orgPolicy });
625
626
  if (!json) printResult("Full lint", result);
626
627
  } else if (charterContent) {
627
- result = lintCharter(charterContent, { teamChannelPolicy: teamPolicy });
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 teamPolicy = data.channel_policy ? {
712
- team_id: data.channel_policy.team_id,
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, teamPolicy);
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
- team_policy: teamPolicy ? {
725
- allowed: teamPolicy.allowed_channels,
726
- denied: teamPolicy.denied_channels,
727
- require_elevated_for_pii: teamPolicy.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 (teamPolicy) {
739
- info(`Team allowed: ${teamPolicy.allowed_channels.length > 0 ? teamPolicy.allowed_channels.join(", ") : "all (no restriction)"}`);
740
- info(`Team denied: ${teamPolicy.denied_channels.length > 0 ? teamPolicy.denied_channels.join(", ") : "none"}`);
741
- if (teamPolicy.require_elevated_for_pii) {
742
- info("Team requires elevated tier for PII channels");
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 team channel policy configured.");
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 teamChannelPolicy;
1441
+ let orgChannelPolicy;
1441
1442
  const policyData = provisionData.team_channel_policy;
1442
1443
  if (policyData) {
1443
- teamChannelPolicy = {
1444
- team_id: policyData.team_id,
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, teamChannelPolicy);
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: chalk16.blue("In Progress"),
2546
- today: chalk16.green("Today"),
2547
- backlog: chalk16.dim("Backlog"),
2548
- done: chalk16.gray("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 = ora12({ text: "Fetching kanban board\u2026", isSilent: json });
2930
+ const spinner = ora14({ text: "Fetching kanban board\u2026", isSilent: json });
2557
2931
  spinner.start();
2558
- const agentId = await resolveAgentId(opts.agent);
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
- priorityLabel(item.priority),
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(chalk16.bold(`
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 resolveAgentId(opts.agent);
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 resolveAgentId(opts.agent);
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 resolveAgentId(opts.agent);
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 resolveAgentId(opts.agent);
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 chalk17 from "chalk";
3041
- import ora13 from "ora";
3042
- var cliVersion = true ? "0.6.6" : "dev";
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 = ora13({ text: "Checking for updates\u2026", isSilent: json });
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 (${chalk17.bold(cliVersion)})`);
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: ${chalk17.dim(cliVersion)} \u2192 ${chalk17.bold.green(versionInfo.latest)}`);
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 = ora13({ text: "Installing update\u2026", isSilent: json });
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 ${chalk17.bold(versionInfo.latest)}`);
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
- chalk17.yellow(`
3149
- Update available: ${cliVersion} \u2192 ${versionInfo.latest}. Run ${chalk17.bold("agt update")} to install.
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.6" : "dev";
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", join10(homedir2(), ".augmented")).action(managerStartCommand);
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", join10(homedir2(), ".augmented")).option("--all-channels", "Show all channels (including disabled)").action(agentShowCommand);
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);