@topolo/cli 0.7.1 → 0.7.3

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/index.js CHANGED
@@ -4644,6 +4644,18 @@ function emit(data, mode, pretty) {
4644
4644
  process.stdout.write(pretty() + "\n");
4645
4645
  }
4646
4646
  }
4647
+ function handleOutputStreamError(err, exit = process.exit) {
4648
+ if (err?.code === "EPIPE") {
4649
+ exit(0);
4650
+ return;
4651
+ }
4652
+ throw err;
4653
+ }
4654
+ function installOutputErrorHandlers(stdout = process.stdout, stderr = process.stderr, exit = process.exit) {
4655
+ const handler = (err) => handleOutputStreamError(err, exit);
4656
+ stdout.on("error", handler);
4657
+ stderr.on("error", handler);
4658
+ }
4647
4659
  function fail(err, mode) {
4648
4660
  const payload = normalizeError(err);
4649
4661
  if (mode === "json") {
@@ -5268,20 +5280,62 @@ function registerActionsCommand(program2) {
5268
5280
  fail(err, mode);
5269
5281
  }
5270
5282
  });
5271
- actions.command("capabilities").description("List every published action for one application (its capability contract)").option("-s, --service <service>", "App id, slug, or name").option("--detail", "Include full schemas and agent contracts").option("--json", "Output JSON").option("--no-json", "Output human-readable table").action(async (opts, command) => {
5283
+ actions.command("capabilities").description("List every published action for one application (its capability contract)").option("-s, --service <service>", "App id, slug, or name").option("--summary", "Return compact capability counts without action rows").option("--detail", "Include full schemas and agent contracts").option("--json", "Output JSON").option("--no-json", "Output human-readable table").action(async (opts, command) => {
5272
5284
  const mode = resolveOutputMode(opts.json ?? command.parent?.opts().json);
5273
5285
  try {
5274
5286
  const topolo = await requiredClient();
5275
5287
  const service = opts.service || command.parent?.opts().service;
5276
5288
  if (!service?.trim()) throw new Error("--service is required for capability discovery");
5277
- const result = await topolo.client.searchActions({ service: service.trim(), limit: 100 });
5278
- const output2 = detailRequested(opts.detail, command) ? result : { actions: result.actions.map(compactActionCatalogEntry), page: result.page };
5279
- emit(output2, mode, () => formatActionRows(result.actions, result.page.nextCursor));
5289
+ if (opts.summary && detailRequested(opts.detail, command)) {
5290
+ throw new Error("--summary cannot be combined with --detail");
5291
+ }
5292
+ const resolvedService = service.trim();
5293
+ const discovered = [];
5294
+ const seenCursors = /* @__PURE__ */ new Set();
5295
+ let cursor;
5296
+ for (; ; ) {
5297
+ const page = await topolo.client.searchActions({
5298
+ service: resolvedService,
5299
+ limit: 100,
5300
+ ...cursor ? { cursor } : {}
5301
+ });
5302
+ discovered.push(...page.actions);
5303
+ if (!page.page.hasMore) break;
5304
+ const nextCursor = page.page.nextCursor?.trim();
5305
+ if (!nextCursor || seenCursors.has(nextCursor)) {
5306
+ throw new Error("Capability discovery returned an invalid continuation cursor.");
5307
+ }
5308
+ seenCursors.add(nextCursor);
5309
+ cursor = nextCursor;
5310
+ }
5311
+ const result = { actions: discovered, page: { nextCursor: null, hasMore: false } };
5312
+ const output2 = opts.summary ? summarizeActionCapabilities(resolvedService, discovered) : detailRequested(opts.detail, command) ? result : { actions: discovered.map(compactActionCatalogEntry), page: result.page };
5313
+ emit(output2, mode, () => opts.summary ? formatActionCapabilitySummary(summarizeActionCapabilities(resolvedService, discovered)) : formatActionRows(discovered));
5280
5314
  } catch (err) {
5281
5315
  fail(err, mode);
5282
5316
  }
5283
5317
  });
5284
5318
  }
5319
+ function summarizeActionCapabilities(service, actions) {
5320
+ return {
5321
+ service,
5322
+ total: actions.length,
5323
+ readOnly: actions.filter((action) => action.readOnly).length,
5324
+ mutating: actions.filter((action) => !action.readOnly).length,
5325
+ destructive: actions.filter((action) => action.destructive).length,
5326
+ confirmationRequired: actions.filter((action) => action.requiresConfirmation).length,
5327
+ resourceTypes: [...new Set(actions.map((action) => action.agentContract?.resource?.kind).filter(Boolean))].sort()
5328
+ };
5329
+ }
5330
+ function formatActionCapabilitySummary(summary) {
5331
+ return [
5332
+ `Service: ${summary.service}`,
5333
+ `Actions: ${summary.total} (${summary.readOnly} read-only, ${summary.mutating} mutating)`,
5334
+ `Destructive: ${summary.destructive}`,
5335
+ `Confirmation required: ${summary.confirmationRequired}`,
5336
+ `Resource types: ${summary.resourceTypes.join(", ") || "-"}`
5337
+ ].join("\n");
5338
+ }
5285
5339
  function detailRequested(local, command) {
5286
5340
  return local === true || command.parent?.opts().detail === true;
5287
5341
  }
@@ -13697,6 +13751,7 @@ Workspace: ${workspace.name} (${workspace.id})${workspace.isDefault ? "\nDefault
13697
13751
  }
13698
13752
 
13699
13753
  // src/index.ts
13754
+ installOutputErrorHandlers();
13700
13755
  var program = new Command();
13701
13756
  var argv;
13702
13757
  try {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@topolo/cli",
3
- "version": "0.7.1",
4
- "topoloPublishedVersion": "0.7.1",
3
+ "version": "0.7.3",
4
+ "topoloPublishedVersion": "0.7.3",
5
5
  "description": "Command-line interface for Topolo developers, operators, and agents, with internal first-party scaffolding available under the topolo platform namespace.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -169,7 +169,7 @@ For large inputs, write one schema-valid JSON object to a file and pass it witho
169
169
 
170
170
  ```bash
171
171
  topolo actions validate <action-id> --data @payload.json --json
172
- topolo actions plan <action-id> --data @payload.json --json
172
+ topolo actions plan <action-id> --data @payload.json --confirm --json
173
173
  topolo actions call <action-id> --data @payload.json --confirm --json
174
174
  ```
175
175
 
@@ -183,7 +183,7 @@ topolo actions plan <action-id> --data '<json>' --json
183
183
 
184
184
  MCP: `topolo_plan_action`.
185
185
 
186
- The plan must be valid and must expose the resolved request, confirmation requirement, verification steps, and rollback when one is published. If `executable` is false, do not call the action.
186
+ The plan must be valid and must expose the resolved request, confirmation requirement, verification steps, and rollback when one is published. For a mutation that the user has already authorized, include `--confirm` in the plan so `executable` reflects the exact confirmed call; planning never executes the action. Before approval, omit `--confirm`, present the plan, and treat `executable: false` with `confirmationRequired: true` and `confirmationProvided: false` as awaiting approval rather than an invalid contract. Once approval is obtained, call the unchanged request with `--confirm` without planning it a second time. Any other `executable: false` result blocks the call.
187
187
 
188
188
  ### 6. Confirm mutations
189
189