@great-arrow/cli 0.1.54 → 0.1.56

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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +135 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -227,6 +227,7 @@ and MCP reachability.
227
227
  ### Agents
228
228
 
229
229
  ```bash
230
+ gad agents # who is working right now, and where
230
231
  gad agent list
231
232
  gad agent invoke research-analyst --task "Summarize Q2 metrics"
232
233
  gad ask "What did we decide about the caching layer?"
package/dist/index.js CHANGED
@@ -9402,7 +9402,7 @@ function isNodeError(value) {
9402
9402
 
9403
9403
  // src/lib/version.ts
9404
9404
  var CLI_PACKAGE_NAME = "@great-arrow/cli";
9405
- var CLI_VERSION = "0.1.54";
9405
+ var CLI_VERSION = "0.1.56";
9406
9406
  var GAD_INSTALL_VERSION = "2026.08.08";
9407
9407
  var GAD_INSTALL_MIN_VERSION = "2026.06.22";
9408
9408
  var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
@@ -10129,6 +10129,9 @@ async function confirm(message) {
10129
10129
  });
10130
10130
  });
10131
10131
  }
10132
+ function stripControlChars(s) {
10133
+ return String(s).replace(/[\u0000-\u001f\u007f-\u009f]/g, "");
10134
+ }
10132
10135
 
10133
10136
  // src/lib/formatter.ts
10134
10137
  var Formatter = class {
@@ -11180,6 +11183,68 @@ var GadClient = class {
11180
11183
  }
11181
11184
  return payload;
11182
11185
  }
11186
+ /**
11187
+ * Own one chat response through body consumption, with the normal workspace
11188
+ * attribution. A received turn is never replayed. The consumer handles either
11189
+ * the versioned local handoff or the actual frontier stream inside this scope.
11190
+ */
11191
+ async withChatResponse(body, consume, options = {}) {
11192
+ const deadlineMs = options.deadlineMs ?? 3e5;
11193
+ if (!Number.isInteger(deadlineMs) || deadlineMs < 1 || deadlineMs > 3e5) {
11194
+ throw new CliError(
11195
+ "Chat deadline must be between 1 and 300000 milliseconds.",
11196
+ 3 /* VALIDATION_ERROR */
11197
+ );
11198
+ }
11199
+ const controller = new AbortController();
11200
+ const signal = options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
11201
+ const timer = setTimeout(
11202
+ () => controller.abort(new Error("Chat response deadline exceeded.")),
11203
+ deadlineMs
11204
+ );
11205
+ let rejectAbort;
11206
+ let response;
11207
+ const aborted = new Promise((_, reject) => {
11208
+ rejectAbort = () => reject(signal.reason ?? new Error("Chat stopped."));
11209
+ if (signal.aborted) rejectAbort();
11210
+ else signal.addEventListener("abort", rejectAbort, { once: true });
11211
+ });
11212
+ try {
11213
+ return await Promise.race([
11214
+ (async () => {
11215
+ signal.throwIfAborted();
11216
+ response = await fetch(`${this.apiUrl}/api/chat`, {
11217
+ method: "POST",
11218
+ headers: {
11219
+ ...this.buildHeaders(),
11220
+ Accept: "text/event-stream, application/json"
11221
+ },
11222
+ body: JSON.stringify(body),
11223
+ redirect: "error",
11224
+ cache: "no-store",
11225
+ signal
11226
+ });
11227
+ signal.throwIfAborted();
11228
+ if (!response.ok) await this.handleResponse(response);
11229
+ return consume(response, signal);
11230
+ })(),
11231
+ aborted
11232
+ ]);
11233
+ } finally {
11234
+ clearTimeout(timer);
11235
+ if (rejectAbort) signal.removeEventListener("abort", rejectAbort);
11236
+ controller.abort();
11237
+ const body2 = response?.body;
11238
+ if (body2 && !body2.locked)
11239
+ void (async () => {
11240
+ try {
11241
+ await body2.cancel();
11242
+ } catch (error) {
11243
+ debugSwallow("chat.response.cancel", error);
11244
+ }
11245
+ })();
11246
+ }
11247
+ }
11183
11248
  /**
11184
11249
  * Make a GET request to a REST API endpoint.
11185
11250
  *
@@ -11766,7 +11831,9 @@ var TODO_COLUMNS = [
11766
11831
  if (Number.isNaN(date.getTime())) return str;
11767
11832
  return date.toLocaleDateString();
11768
11833
  }
11769
- }
11834
+ },
11835
+ // Every card the CLI lists is clickable (owner rule 2026-10-06).
11836
+ { key: "url", header: "Link" }
11770
11837
  ];
11771
11838
  var listCommand2 = new Command("list").description("List open todos sorted by priority").option(
11772
11839
  "--status <status>",
@@ -17159,6 +17226,68 @@ agentCommand.command("invoke <agent-id>").description("Execute an agent with a t
17159
17226
  }
17160
17227
  });
17161
17228
 
17229
+ // src/commands/agents.ts
17230
+ function groupTitle(where, rawMachine) {
17231
+ const machine = rawMachine ? stripControlChars(String(rawMachine)) : "";
17232
+ switch (where) {
17233
+ case "this_computer":
17234
+ return machine ? `On ${machine}` : "On your computers";
17235
+ case "remote_machine":
17236
+ return machine ? `On ${machine} (remote)` : "On a remote machine";
17237
+ case "vendor_cloud":
17238
+ return "In the cloud";
17239
+ case "great_arrow":
17240
+ return "Great Arrow agents";
17241
+ default:
17242
+ return "Location not reported";
17243
+ }
17244
+ }
17245
+ function itemLine(item) {
17246
+ const name = stripControlChars(String(item.who ?? ""));
17247
+ const who = typeof item.sessions === "number" && item.sessions > 1 ? `${name} (${item.sessions} sessions)` : name;
17248
+ const detail = item.detail ? stripControlChars(String(item.detail)) : "";
17249
+ return detail ? ` ${who} \u2014 ${detail}` : ` ${who}`;
17250
+ }
17251
+ function count(n) {
17252
+ return typeof n === "number" && Number.isFinite(n) ? n : 0;
17253
+ }
17254
+ function renderAgentsNow(payload) {
17255
+ const safe = payload && typeof payload === "object" ? payload : {};
17256
+ const groups = (Array.isArray(safe.working) ? safe.working : []).filter(
17257
+ (g) => g && Array.isArray(g.items) && g.items.length > 0
17258
+ );
17259
+ const counts = safe.counts ?? {};
17260
+ const lines = [];
17261
+ if (groups.length === 0) {
17262
+ lines.push("No agent is working right now.");
17263
+ } else {
17264
+ for (const g of groups) {
17265
+ lines.push(groupTitle(g.where, g.machine));
17266
+ for (const item of g.items) lines.push(itemLine(item));
17267
+ lines.push("");
17268
+ }
17269
+ if (lines[lines.length - 1] === "") lines.pop();
17270
+ }
17271
+ lines.push("");
17272
+ lines.push(
17273
+ `${count(counts.connected)} connected, idle \xB7 ${count(count(counts.working) + count(counts.connected) + count(counts.recent))} seen in 24h`
17274
+ );
17275
+ return lines.join("\n");
17276
+ }
17277
+ var agentsCommand = new Command("agents").description(
17278
+ "Agents working right now \u2014 this computer, the cloud and Great Arrow"
17279
+ ).option("--json", "Output as JSON").action(async (_opts, command) => {
17280
+ const g = globalOutputOpts(command);
17281
+ const auth = await resolveAuth();
17282
+ const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
17283
+ const result = await client.mcpCall("agents_now", {});
17284
+ if (g.json) {
17285
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
17286
+ return;
17287
+ }
17288
+ process.stdout.write(renderAgentsNow(result) + "\n");
17289
+ });
17290
+
17162
17291
  // src/commands/ask.ts
17163
17292
  var ORCHESTRATOR_TIMEOUT_MS = 9e4;
17164
17293
  var ANSWER_FIELDS = [
@@ -19204,7 +19333,9 @@ var NEXT_COLUMNS = [
19204
19333
  { key: "priority", header: "Priority", width: 8 },
19205
19334
  { key: "id", header: "ID", width: 36 },
19206
19335
  { key: "title", header: "Title", width: 40 },
19207
- { key: "context", header: "Next" }
19336
+ { key: "context", header: "Next" },
19337
+ // Every card the CLI lists is clickable (owner rule 2026-10-06).
19338
+ { key: "url", header: "Link" }
19208
19339
  ];
19209
19340
  function dueRank(value) {
19210
19341
  if (typeof value !== "string" || !value) return Number.POSITIVE_INFINITY;
@@ -22990,6 +23121,7 @@ program2.addCommand(doctorCommand());
22990
23121
  program2.addCommand(integrations_default);
22991
23122
  program2.addCommand(mcp_default);
22992
23123
  program2.addCommand(agentCommand);
23124
+ program2.addCommand(agentsCommand);
22993
23125
  program2.addCommand(askCommand());
22994
23126
  program2.addCommand(localCommand());
22995
23127
  program2.addCommand(smokeCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@great-arrow/cli",
3
- "version": "0.1.54",
3
+ "version": "0.1.56",
4
4
  "description": "GreatArrow.ai CLI tool",
5
5
  "type": "module",
6
6
  "bin": {