@integrity-labs/agt-cli 0.15.0 → 0.15.1

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
@@ -45,7 +45,7 @@ import {
45
45
  success,
46
46
  table,
47
47
  warn
48
- } from "../chunk-WB3T6XIV.js";
48
+ } from "../chunk-7QE6SJQB.js";
49
49
 
50
50
  // src/bin/agt.ts
51
51
  import { join as join9 } from "path";
@@ -3402,7 +3402,7 @@ import { execFileSync, execSync } from "child_process";
3402
3402
  import { existsSync as existsSync4, realpathSync } from "fs";
3403
3403
  import chalk17 from "chalk";
3404
3404
  import ora15 from "ora";
3405
- var cliVersion = true ? "0.15.0" : "dev";
3405
+ var cliVersion = true ? "0.15.1" : "dev";
3406
3406
  async function fetchLatestVersion() {
3407
3407
  const host2 = getHost();
3408
3408
  if (!host2) return null;
@@ -3851,7 +3851,7 @@ function handleError(err) {
3851
3851
  }
3852
3852
 
3853
3853
  // src/bin/agt.ts
3854
- var cliVersion2 = true ? "0.15.0" : "dev";
3854
+ var cliVersion2 = true ? "0.15.1" : "dev";
3855
3855
  var program = new Command();
3856
3856
  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");
3857
3857
  program.hook("preAction", (thisCommand) => {
@@ -533,6 +533,45 @@ function getIntegration(id) {
533
533
  return integrationMap.get(id);
534
534
  }
535
535
 
536
+ // ../../packages/core/dist/provisioning/hook-env.js
537
+ function augmentedHookPath(currentPath) {
538
+ const extras = [
539
+ "/home/linuxbrew/.linuxbrew/bin",
540
+ "/opt/homebrew/bin",
541
+ "/usr/local/bin",
542
+ "/usr/bin",
543
+ "/bin"
544
+ ];
545
+ const seen = /* @__PURE__ */ new Set();
546
+ const parts = [];
547
+ const push = (p) => {
548
+ if (!p || seen.has(p))
549
+ return;
550
+ seen.add(p);
551
+ parts.push(p);
552
+ };
553
+ for (const p of (currentPath ?? "").split(":"))
554
+ push(p);
555
+ for (const p of extras)
556
+ push(p);
557
+ return parts.join(":");
558
+ }
559
+ function extractCommandNotFound(stderr) {
560
+ if (!stderr)
561
+ return null;
562
+ const SAFE_CMD = /^[A-Za-z][A-Za-z0-9._-]{0,63}$/;
563
+ for (const line of stderr.split(/\r?\n/)) {
564
+ const m = line.match(/^(?:bash|sh): (?:line \d+: )?([^:\s]+): command not found$/);
565
+ if (m?.[1]) {
566
+ const rawCmd = m[1].trim();
567
+ const cmd = rawCmd.split("/").pop() ?? rawCmd;
568
+ if (SAFE_CMD.test(cmd))
569
+ return cmd;
570
+ }
571
+ }
572
+ return null;
573
+ }
574
+
536
575
  // ../../packages/core/dist/provisioning/frameworks/openclaw/index.js
537
576
  import { execFile, spawn } from "child_process";
538
577
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2, unlinkSync as unlinkSync2, chmodSync as chmodSync2, renameSync as renameSync2, symlinkSync } from "fs";
@@ -1924,6 +1963,9 @@ ${entry.content}`
1924
1963
  maxBuffer: 1024 * 1024,
1925
1964
  env: {
1926
1965
  ...process.env,
1966
+ // ENG-4510: prepend canonical brew + system bin dirs so hooks
1967
+ // resolve binaries when the manager runs under a minimal PATH.
1968
+ PATH: augmentedHookPath(process.env.PATH),
1927
1969
  AGENT_CODE_NAME: ctx.codeName,
1928
1970
  AGENT_DIR: agentDir,
1929
1971
  AGENT_PROJECT_DIR: projectDir,
@@ -2683,26 +2725,109 @@ are defined in \`CHARTER.md\`.
2683
2725
  **When in doubt, create a task.** Err on the side of tracking work rather than
2684
2726
  doing it silently. Any work that takes more than ~30 seconds should be a kanban task.
2685
2727
 
2728
+ But: **clarify before you commit.** A vague task on the board is worse than
2729
+ no task \u2014 it bakes in the wrong scope and forces a rename later. If the
2730
+ request is fuzzy, ask one or two sharp questions FIRST and create the task
2731
+ once you understand what's actually being asked for.
2732
+
2686
2733
  When you receive a request via any channel (Slack, Telegram, direct chat):
2687
2734
 
2688
2735
  1. **First, check if the request is exempt** \u2014 the following do NOT need a task:
2689
2736
  - One-line answers, yes/no questions, or simple factual lookups (under ~30 seconds)
2690
2737
  - No-action acknowledgments: "thanks", "got it", "acknowledged", "will do", or other confirmations that require no further work
2691
- 2. **If not exempt, create a kanban task** with kanban.add \u2014 don't wait to see if it's "big enough"
2692
- 3. Reply in the channel thread: "On it \u2014 tracking here: ${kanbanUrl ?? "my kanban board"}" (include the created task title)
2693
- 4. Move the task to in_progress with kanban.move
2694
- 5. Do the work
2695
- 6. Mark done with kanban.done including a result summary
2696
- 7. Reply in the channel thread with the result
2697
-
2698
- Everything that isn't exempt gets a task.
2738
+ 2. **If not exempt, check if the request is clear enough to scope a sharp task title.**
2739
+ Ask yourself: "Could I write a one-line task title right now that another
2740
+ teammate would understand without asking me anything?"
2741
+ - **If yes** \u2192 continue to step 3.
2742
+ - **If no** \u2192 reply with **at most two** clarifying questions in the channel
2743
+ thread. Do NOT create the kanban task yet \u2014 it would be wrong by the
2744
+ time you came back. When you ask, also state the default you'll
2745
+ assume if they don't reply (e.g. "If you don't say, I'll go with the
2746
+ standard VP-eyes-on overview"). Once they reply (or you've waited
2747
+ long enough to act on the default), pick up at step 3.
2748
+ 3. **Create the kanban task** with kanban.add. Title should be specific
2749
+ enough to be self-explanatory \u2014 "Pull Linear ENG sprint velocity for
2750
+ this fortnight" beats "Linear stats".
2751
+ 4. Reply in the channel thread: "On it \u2014 tracking here: ${kanbanUrl ?? "my kanban board"}" (include the created task title)
2752
+ 5. Move the task to in_progress with kanban.move
2753
+ 6. Do the work
2754
+ 7. Mark done with kanban.done including a result summary
2755
+ 8. Reply in the channel thread with the result
2756
+
2757
+ Everything that isn't exempt gets a task \u2014 but only after the request is
2758
+ clear. Don't bury a clarifying question underneath a "tracking here" reply;
2759
+ ask the question alone, no kanban link, and let the user answer before
2760
+ anything goes on the board.
2699
2761
 
2700
2762
  When asked about existing work, tasks, or what you've been doing \u2014 call kanban.list
2701
2763
  first to load your recent board state. This gives you context about completed and
2702
2764
  in-progress items so you can answer accurately.
2703
2765
 
2704
2766
  ${memorySection}
2705
- ${reportsToSection}${teamSection}${peopleSection}${integrationsSection}${knowledgeSection}## Development Workflow
2767
+ ${reportsToSection}${teamSection}${peopleSection}${integrationsSection}${knowledgeSection}## Dashboards
2768
+
2769
+ You can publish your own dashboards inside the Augmented console. They are
2770
+ **first-class platform artifacts** \u2014 KPI tiles, charts, refresh-on-demand \u2014
2771
+ and replace any urge to write static HTML and host it elsewhere (GitHub
2772
+ Pages, public buckets, screenshots in chat).
2773
+
2774
+ **When the user asks for a dashboard, do this \u2014 never anything else:**
2775
+
2776
+ 1. Plan a small set of widgets (KPI tiles for headlines, area/line for
2777
+ trends, bar for comparisons, donut for proportions).
2778
+ 2. For each widget write \`{id, kind, title, prompt, schema}\`. The
2779
+ \`prompt\` is what future-you reads on every refresh; the \`schema\` is
2780
+ the JSON Schema your output must match.
2781
+ 3. Call **\`dashboards.upsert\`** to register the dashboard. Set
2782
+ \`title\` and \`description\` so a teammate can find it later.
2783
+ 4. Optionally call **\`dashboards.request_refresh\`** to populate the
2784
+ first snapshot. Otherwise widgets render "never refreshed" until cron
2785
+ fires or a user clicks \u21BB.
2786
+
2787
+ **Refresh loop \u2014 run whenever invoked:**
2788
+
2789
+ 1. Call **\`dashboards.pending_refreshes\`**. Returns widgets queued for
2790
+ refresh with \`{slug, widget_id, kind, prompt, schema}\`.
2791
+ 2. For each: read the prompt \u2192 use your tools (kanban, knowledge, your
2792
+ integrations) to gather data \u2192 format to match the schema exactly \u2192
2793
+ call **\`dashboards.persist_widget\`** with the result.
2794
+ 3. Server validates against the schema; invalid output is rejected.
2795
+
2796
+ **If you don't see \`dashboards.upsert\` in your tool list, STOP and ask
2797
+ the user.** The console dashboards system is the canonical surface, but
2798
+ the tool may not yet be deployed in your environment. In that case:
2799
+
2800
+ > "I don't see the dashboards platform tool in my session. Do you want me
2801
+ > to wait until it's deployed, or build a one-off (static HTML, screenshot,
2802
+ > CSV) for now?"
2803
+
2804
+ Do NOT silently fall back to writing Python pipelines, Chart.js HTML,
2805
+ headless-Chrome screenshots, or any other bespoke rendering path. Those
2806
+ are dead-ends \u2014 they live on disk for one session, can't be refreshed,
2807
+ and don't show up in the console where teammates look. Ask first; let
2808
+ the user decide whether the gap is worth a workaround.
2809
+
2810
+ **Rules:**
2811
+
2812
+ - **Always quote the full URL when you tell the user a dashboard is live.**
2813
+ \`dashboards.upsert\` returns the absolute URL \u2014 paste that link verbatim,
2814
+ never a relative path like "/dashboards" or "in the console". Bad:
2815
+ "live in the console under /dashboards". Good:
2816
+ "live at ${consoleUrl ? consoleUrl + "/dashboards/<id>" : "<console>/dashboards/<id>"}".
2817
+ The same rule applies to \`dashboards.show\` and \`dashboards.list\` \u2014
2818
+ surface the URL they returned so a teammate can click straight through.
2819
+ - Never invent figures. If a tool returned nothing, persist zeros / empty
2820
+ arrays \u2014 don't fabricate plausible-looking numbers.
2821
+ - Don't write a dashboard to any other destination (GitHub Pages, S3, a
2822
+ shared markdown doc, a Telegram \`sendPhoto\`, a one-off /tmp file)
2823
+ unless the user explicitly asks for one of those formats. The console
2824
+ is the answer.
2825
+ - One LLM call per widget on refresh \u2014 don't bundle widgets into a
2826
+ single prompt; you'll lose schema strictness.
2827
+ - See \`.claude/skills/dashboards/SKILL.md\` (if installed) for the
2828
+ canonical kpi/area/line/bar/donut JSON Schemas you can copy.
2829
+
2830
+ ## Development Workflow
2706
2831
 
2707
2832
  ### Repository Management
2708
2833
 
@@ -3136,6 +3261,10 @@ function buildMcpJson(input) {
3136
3261
  AGT_API_KEY: process.env["AGT_API_KEY"] ?? "",
3137
3262
  AGT_AGENT_ID: input.agent.agent_id,
3138
3263
  AGT_AGENT_CODE_NAME: input.agent.code_name,
3264
+ // Console origin so the MCP bridge can build absolute URLs (e.g.
3265
+ // dashboard links) in tool replies. Falls back to NEXT_PUBLIC_APP_URL
3266
+ // / AGT_CONSOLE_URL — same chain consoleUrl uses for kanban links.
3267
+ AGT_APP_URL: process.env["AGT_APP_URL"] ?? process.env["NEXT_PUBLIC_APP_URL"] ?? process.env["AGT_CONSOLE_URL"] ?? "",
3139
3268
  // Include PATH/HOME so the MCP subprocess can resolve binaries
3140
3269
  PATH: process.env["PATH"] ?? "",
3141
3270
  HOME: process.env["HOME"] ?? ""
@@ -3862,6 +3991,11 @@ ${sections}`
3862
3991
  maxBuffer: 1024 * 1024,
3863
3992
  env: {
3864
3993
  ...process.env,
3994
+ // ENG-4510: prepend canonical brew + system bin dirs so hooks
3995
+ // resolve binaries (npm, npx, qmd, xurl, …) when the manager is
3996
+ // spawned from cloud-init with a minimal PATH. Otherwise hooks
3997
+ // exit 127 ("command not found") on fresh prod EC2 hosts.
3998
+ PATH: augmentedHookPath(process.env.PATH),
3865
3999
  AGENT_CODE_NAME: ctx.codeName,
3866
4000
  AGENT_DIR: agentRootDir,
3867
4001
  AGENT_PROJECT_DIR: projectDir,
@@ -3976,7 +4110,16 @@ These credentials are pre-loaded. Reference them by their environment variable n
3976
4110
 
3977
4111
  The only things that don't need a task: one-line answers, yes/no questions, simple factual lookups you can answer in under 30 seconds, or no-action acknowledgments ("thanks", "got it", "acknowledged", "will do") that require no further work. Everything else gets a task.
3978
4112
 
3979
- The cost of an unnecessary task is near zero. The cost of invisible work is confusion, duplication, and lost context.`);
4113
+ The cost of an unnecessary task is near zero. The cost of invisible work is confusion, duplication, and lost context.
4114
+
4115
+ **Always confirm task creation back to the requester via the same channel they reached you on.** When you create a kanban task in response to a Slack/direct-chat/email/etc. message, your *next* action MUST be to call that channel's send/reply tool with:
4116
+
4117
+ (a) a one-line acknowledgment of what you'll do, and
4118
+ (b) **the full kanban deep link URL** \u2014 quote it verbatim from the kanban tool's response, including the \`https://\` prefix and the full path (use the exact \`https://...\` URL the tool emits \u2014 do not invent or rewrite it). Identifiers, short slugs, or "see kanban" references are not acceptable substitutes \u2014 the user must be able to click straight through.
4119
+
4120
+ The kanban tools include the deep-link URL in their response. Locate the full URL in the tool result text (or in its \`details\` payload) and copy it verbatim into your channel reply, regardless of the surrounding sentence shape. The user has no way to see your kanban unless you give them the link \u2014 silent task creation feels like you ignored them.
4121
+
4122
+ **Your turn is not finished until you reply on the channel.** If a user contacted you via a channel tool, you must end the turn by calling that channel's reply tool. Do not just emit assistant text and stop \u2014 text emitted without a channel-reply tool call is invisible to the user. This applies to every reply, not only kanban acknowledgments: confirmation questions, status updates, results, and final answers all need to go through the channel tool.`);
3980
4123
  return sections.join("\n\n");
3981
4124
  }
3982
4125
  function stripFrontmatter(content) {
@@ -4933,6 +5076,14 @@ function looksLikeNotesOnly(remainder) {
4933
5076
  return lines.every((line) => NON_DELIVERABLE_REMAINDER_PATTERNS.some((pattern) => pattern.test(line)));
4934
5077
  }
4935
5078
 
5079
+ // ../../packages/core/dist/types/kanban.js
5080
+ function formatActorId(kind, id) {
5081
+ return `${kind}:${id}`;
5082
+ }
5083
+ function isSelfCompletion(event) {
5084
+ return event.last_actor_id === formatActorId("agent", event.agent_id);
5085
+ }
5086
+
4936
5087
  // ../../packages/core/dist/schemas/validators.js
4937
5088
  import Ajv2020 from "ajv/dist/2020.js";
4938
5089
  import addFormats from "ajv-formats";
@@ -6893,6 +7044,7 @@ export {
6893
7044
  getChannel,
6894
7045
  getAllChannelIds,
6895
7046
  getIntegration,
7047
+ extractCommandNotFound,
6896
7048
  provisionStopHook,
6897
7049
  provisionIsolationHook,
6898
7050
  setJsonMode,
@@ -6912,6 +7064,8 @@ export {
6912
7064
  warn,
6913
7065
  info,
6914
7066
  table,
7067
+ formatActorId,
7068
+ isSelfCompletion,
6915
7069
  resolveChannels,
6916
7070
  SLACK_SCOPE_CATEGORY_LABELS,
6917
7071
  getDefaultSlackScopes,
@@ -6939,4 +7093,4 @@ export {
6939
7093
  managerStopCommand,
6940
7094
  managerStatusCommand
6941
7095
  };
6942
- //# sourceMappingURL=chunk-WB3T6XIV.js.map
7096
+ //# sourceMappingURL=chunk-7QE6SJQB.js.map