appduct 0.12.0 → 0.13.0

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 (69) hide show
  1. package/README.md +41 -36
  2. package/dist/bin.js +44 -36
  3. package/dist/cli/command-options.d.ts +7 -17
  4. package/dist/cli/result-types.d.ts +11 -8
  5. package/dist/cli/routes/daemon/index.js +12 -16
  6. package/dist/cli/routes/daemon/run.js +136 -28
  7. package/dist/cli/routes/daemon/start.js +12 -16
  8. package/dist/cli/routes/daemon/status.js +12 -16
  9. package/dist/cli/routes/daemon/stop.js +12 -16
  10. package/dist/cli/routes/doctor.js +12 -16
  11. package/dist/cli/routes/events/index.d.ts +9 -0
  12. package/dist/cli/routes/events/index.js +842 -0
  13. package/dist/cli/routes/events/shared-options.d.ts +12 -0
  14. package/dist/cli/routes/events/shared-options.js +102 -0
  15. package/dist/cli/routes/events/since.d.ts +6 -0
  16. package/dist/cli/routes/events/since.js +1977 -0
  17. package/dist/cli/routes/events/tail.d.ts +6 -0
  18. package/dist/cli/routes/{events.js → events/tail.js} +177 -162
  19. package/dist/cli/routes/init.js +14 -18
  20. package/dist/cli/routes/keygen.js +12 -16
  21. package/dist/cli/routes/mcp.js +181 -165
  22. package/dist/cli/routes/sessions/index.d.ts +7 -0
  23. package/dist/cli/routes/sessions/index.js +843 -0
  24. package/dist/cli/routes/sessions/link.d.ts +4 -0
  25. package/dist/cli/routes/{link.js → sessions/link.js} +13 -17
  26. package/dist/cli/routes/sessions/ls.d.ts +4 -0
  27. package/dist/cli/routes/{ls.js → sessions/ls.js} +13 -17
  28. package/dist/cli/routes/sessions/revoke.d.ts +4 -0
  29. package/dist/cli/routes/{revoke.js → sessions/revoke.js} +14 -18
  30. package/dist/cli/routes/tools/call.d.ts +4 -0
  31. package/dist/cli/routes/{invoke.js → tools/call.js} +15 -19
  32. package/dist/cli/routes/tools/describe.d.ts +6 -0
  33. package/dist/cli/routes/tools/describe.js +1837 -0
  34. package/dist/cli/routes/tools/index.d.ts +6 -0
  35. package/dist/cli/routes/tools/index.js +843 -0
  36. package/dist/cli/routes/tools/ls.d.ts +4 -0
  37. package/dist/cli/routes/{tools.js → tools/ls.js} +40 -73
  38. package/dist/cli/routes/tools/shared-options.d.ts +16 -0
  39. package/dist/cli/routes/tools/shared-options.js +122 -0
  40. package/dist/client/app-client.d.ts +96 -37
  41. package/dist/client/index.d.ts +3 -2
  42. package/dist/client/index.js +178 -138
  43. package/dist/commands/events.d.ts +31 -14
  44. package/dist/commands/invoke.d.ts +1 -1
  45. package/dist/commands/link.d.ts +1 -1
  46. package/dist/commands/ls.d.ts +1 -1
  47. package/dist/commands/revoke.d.ts +1 -1
  48. package/dist/commands/tools.d.ts +12 -13
  49. package/dist/daemon/config.d.ts +1 -1
  50. package/dist/daemon/event-bus.d.ts +32 -0
  51. package/dist/daemon/rpc-errors.d.ts +1 -1
  52. package/dist/errors.d.ts +1 -1
  53. package/dist/events/index.d.ts +60 -0
  54. package/dist/index.js +56 -39
  55. package/dist/link.d.ts +1 -1
  56. package/dist/mcp/app-tools.d.ts +3 -2
  57. package/dist/mcp/connect-tool.d.ts +1 -1
  58. package/dist/mcp/events-tool.d.ts +28 -27
  59. package/dist/native-scheme.d.ts +1 -1
  60. package/dist/output.d.ts +29 -6
  61. package/dist/rpc/client.d.ts +1 -1
  62. package/dist/scheme.d.ts +4 -4
  63. package/package.json +2 -2
  64. package/dist/cli/routes/events.d.ts +0 -3
  65. package/dist/cli/routes/invoke.d.ts +0 -3
  66. package/dist/cli/routes/link.d.ts +0 -3
  67. package/dist/cli/routes/ls.d.ts +0 -3
  68. package/dist/cli/routes/revoke.d.ts +0 -3
  69. package/dist/cli/routes/tools.d.ts +0 -3
@@ -0,0 +1,4 @@
1
+ /** Route for `appduct sessions link` — loaded by `routes/sessions/index.ts`'s router only when it
2
+ * runs (issue #96; replaces the removed `appduct link`). */
3
+ import type { Route } from "../../router.js";
4
+ export declare const route: Route;
@@ -2185,9 +2185,6 @@ var renderLsData = (colors, data, now) => {
2185
2185
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
2186
2186
  ];
2187
2187
  };
2188
- var isToolsListing = (data) => {
2189
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
2190
- };
2191
2188
  var isToolGroupsListing = (data) => {
2192
2189
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
2193
2190
  };
@@ -2205,7 +2202,7 @@ var renderEmptyToolsLine = (data) => {
2205
2202
  }
2206
2203
  if (data.group !== void 0) {
2207
2204
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
2208
- return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools --groups\` to see the session's groups.`;
2205
+ return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools ls --groups\` to see the session's groups.`;
2209
2206
  }
2210
2207
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
2211
2208
  };
@@ -2287,7 +2284,7 @@ var renderToolSummaryTable = (colors, data) => {
2287
2284
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
2288
2285
  ...renderTruncationLine(data),
2289
2286
  "",
2290
- "Run `appduct tools <name>` for a tool's full schema."
2287
+ "Run `appduct tools describe <name>` for a tool's full schema."
2291
2288
  ];
2292
2289
  };
2293
2290
  var renderToolDetail = (colors, tool, flags) => {
@@ -2339,16 +2336,13 @@ var renderToolGroups = (colors, data) => {
2339
2336
  colors.green("Groups"),
2340
2337
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
2341
2338
  "",
2342
- `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools --group <name>` to list one group's tools." : "No tool declares a group.")
2339
+ `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools ls --group <name>` to list one group's tools." : "No tool declares a group.")
2343
2340
  ];
2344
2341
  };
2345
- var renderToolsData = (colors, data, flags, full) => {
2342
+ var renderToolsListData = (colors, data, flags, full) => {
2346
2343
  if (isToolGroupsListing(data)) {
2347
2344
  return renderToolGroups(colors, data);
2348
2345
  }
2349
- if (!isToolsListing(data)) {
2350
- return renderToolDetail(colors, data, flags);
2351
- }
2352
2346
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
2353
2347
  };
2354
2348
  var renderInvokeData = (colors, data, flags) => {
@@ -2534,15 +2528,17 @@ var renderSuccessData = (colors, command, data, options) => {
2534
2528
  return renderInitData(colors, data, flags);
2535
2529
  case "keygen":
2536
2530
  return renderKeygenData(colors, data, flags);
2537
- case "link":
2531
+ case "sessions link":
2538
2532
  return renderLinkData(colors, data, flags, options.qr);
2539
- case "ls":
2533
+ case "sessions ls":
2540
2534
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
2541
- case "tools":
2542
- return renderToolsData(colors, data, flags, options.full);
2543
- case "invoke":
2535
+ case "tools ls":
2536
+ return renderToolsListData(colors, data, flags, options.full);
2537
+ case "tools describe":
2538
+ return renderToolDetail(colors, data, flags);
2539
+ case "tools call":
2544
2540
  return renderInvokeData(colors, data, flags);
2545
- case "revoke":
2541
+ case "sessions revoke":
2546
2542
  return renderRevokeData(colors, data);
2547
2543
  case "daemon run":
2548
2544
  return renderDaemonRunData(colors, data, flags);
@@ -2688,7 +2684,7 @@ var guarded = (context) => {
2688
2684
  };
2689
2685
  };
2690
2686
 
2691
- // src/cli/routes/link.ts
2687
+ // src/cli/routes/sessions/link.ts
2692
2688
  var route = async (context) => {
2693
2689
  const { options, stateDir } = context;
2694
2690
  return executeCommand(
@@ -0,0 +1,4 @@
1
+ /** Route for `appduct sessions ls` — loaded by `routes/sessions/index.ts`'s router only when it
2
+ * runs (issue #96; replaces the removed `appduct ls`). */
3
+ import type { Route } from "../../router.js";
4
+ export declare const route: Route;
@@ -1157,9 +1157,6 @@ var renderLsData = (colors, data, now) => {
1157
1157
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
1158
1158
  ];
1159
1159
  };
1160
- var isToolsListing = (data) => {
1161
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
1162
- };
1163
1160
  var isToolGroupsListing = (data) => {
1164
1161
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
1165
1162
  };
@@ -1177,7 +1174,7 @@ var renderEmptyToolsLine = (data) => {
1177
1174
  }
1178
1175
  if (data.group !== void 0) {
1179
1176
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
1180
- return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools --groups\` to see the session's groups.`;
1177
+ return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools ls --groups\` to see the session's groups.`;
1181
1178
  }
1182
1179
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
1183
1180
  };
@@ -1259,7 +1256,7 @@ var renderToolSummaryTable = (colors, data) => {
1259
1256
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
1260
1257
  ...renderTruncationLine(data),
1261
1258
  "",
1262
- "Run `appduct tools <name>` for a tool's full schema."
1259
+ "Run `appduct tools describe <name>` for a tool's full schema."
1263
1260
  ];
1264
1261
  };
1265
1262
  var renderToolDetail = (colors, tool, flags) => {
@@ -1311,16 +1308,13 @@ var renderToolGroups = (colors, data) => {
1311
1308
  colors.green("Groups"),
1312
1309
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
1313
1310
  "",
1314
- `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools --group <name>` to list one group's tools." : "No tool declares a group.")
1311
+ `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools ls --group <name>` to list one group's tools." : "No tool declares a group.")
1315
1312
  ];
1316
1313
  };
1317
- var renderToolsData = (colors, data, flags, full) => {
1314
+ var renderToolsListData = (colors, data, flags, full) => {
1318
1315
  if (isToolGroupsListing(data)) {
1319
1316
  return renderToolGroups(colors, data);
1320
1317
  }
1321
- if (!isToolsListing(data)) {
1322
- return renderToolDetail(colors, data, flags);
1323
- }
1324
1318
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1325
1319
  };
1326
1320
  var renderInvokeData = (colors, data, flags) => {
@@ -1506,15 +1500,17 @@ var renderSuccessData = (colors, command, data, options) => {
1506
1500
  return renderInitData(colors, data, flags);
1507
1501
  case "keygen":
1508
1502
  return renderKeygenData(colors, data, flags);
1509
- case "link":
1503
+ case "sessions link":
1510
1504
  return renderLinkData(colors, data, flags, options.qr);
1511
- case "ls":
1505
+ case "sessions ls":
1512
1506
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
1513
- case "tools":
1514
- return renderToolsData(colors, data, flags, options.full);
1515
- case "invoke":
1507
+ case "tools ls":
1508
+ return renderToolsListData(colors, data, flags, options.full);
1509
+ case "tools describe":
1510
+ return renderToolDetail(colors, data, flags);
1511
+ case "tools call":
1516
1512
  return renderInvokeData(colors, data, flags);
1517
- case "revoke":
1513
+ case "sessions revoke":
1518
1514
  return renderRevokeData(colors, data);
1519
1515
  case "daemon run":
1520
1516
  return renderDaemonRunData(colors, data, flags);
@@ -1660,7 +1656,7 @@ var guarded = (context) => {
1660
1656
  };
1661
1657
  };
1662
1658
 
1663
- // src/cli/routes/ls.ts
1659
+ // src/cli/routes/sessions/ls.ts
1664
1660
  var route = async (context) => {
1665
1661
  const { stateDir } = context;
1666
1662
  return executeCommand(
@@ -0,0 +1,4 @@
1
+ /** Route for `appduct sessions revoke` — loaded by `routes/sessions/index.ts`'s router only when
2
+ * it runs (issue #96; replaces the removed `appduct revoke`). */
3
+ import type { Route } from "../../router.js";
4
+ export declare const route: Route;
@@ -1168,9 +1168,6 @@ var renderLsData = (colors, data, now) => {
1168
1168
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
1169
1169
  ];
1170
1170
  };
1171
- var isToolsListing = (data) => {
1172
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
1173
- };
1174
1171
  var isToolGroupsListing = (data) => {
1175
1172
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
1176
1173
  };
@@ -1188,7 +1185,7 @@ var renderEmptyToolsLine = (data) => {
1188
1185
  }
1189
1186
  if (data.group !== void 0) {
1190
1187
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
1191
- return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools --groups\` to see the session's groups.`;
1188
+ return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools ls --groups\` to see the session's groups.`;
1192
1189
  }
1193
1190
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
1194
1191
  };
@@ -1270,7 +1267,7 @@ var renderToolSummaryTable = (colors, data) => {
1270
1267
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
1271
1268
  ...renderTruncationLine(data),
1272
1269
  "",
1273
- "Run `appduct tools <name>` for a tool's full schema."
1270
+ "Run `appduct tools describe <name>` for a tool's full schema."
1274
1271
  ];
1275
1272
  };
1276
1273
  var renderToolDetail = (colors, tool, flags) => {
@@ -1322,16 +1319,13 @@ var renderToolGroups = (colors, data) => {
1322
1319
  colors.green("Groups"),
1323
1320
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
1324
1321
  "",
1325
- `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools --group <name>` to list one group's tools." : "No tool declares a group.")
1322
+ `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools ls --group <name>` to list one group's tools." : "No tool declares a group.")
1326
1323
  ];
1327
1324
  };
1328
- var renderToolsData = (colors, data, flags, full) => {
1325
+ var renderToolsListData = (colors, data, flags, full) => {
1329
1326
  if (isToolGroupsListing(data)) {
1330
1327
  return renderToolGroups(colors, data);
1331
1328
  }
1332
- if (!isToolsListing(data)) {
1333
- return renderToolDetail(colors, data, flags);
1334
- }
1335
1329
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1336
1330
  };
1337
1331
  var renderInvokeData = (colors, data, flags) => {
@@ -1517,15 +1511,17 @@ var renderSuccessData = (colors, command, data, options) => {
1517
1511
  return renderInitData(colors, data, flags);
1518
1512
  case "keygen":
1519
1513
  return renderKeygenData(colors, data, flags);
1520
- case "link":
1514
+ case "sessions link":
1521
1515
  return renderLinkData(colors, data, flags, options.qr);
1522
- case "ls":
1516
+ case "sessions ls":
1523
1517
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
1524
- case "tools":
1525
- return renderToolsData(colors, data, flags, options.full);
1526
- case "invoke":
1518
+ case "tools ls":
1519
+ return renderToolsListData(colors, data, flags, options.full);
1520
+ case "tools describe":
1521
+ return renderToolDetail(colors, data, flags);
1522
+ case "tools call":
1527
1523
  return renderInvokeData(colors, data, flags);
1528
- case "revoke":
1524
+ case "sessions revoke":
1529
1525
  return renderRevokeData(colors, data);
1530
1526
  case "daemon run":
1531
1527
  return renderDaemonRunData(colors, data, flags);
@@ -1671,7 +1667,7 @@ var guarded = (context) => {
1671
1667
  };
1672
1668
  };
1673
1669
 
1674
- // src/cli/routes/revoke.ts
1670
+ // src/cli/routes/sessions/revoke.ts
1675
1671
  var route = async (context) => {
1676
1672
  const { stateDir } = context;
1677
1673
  return executeCommand(
@@ -1679,7 +1675,7 @@ var route = async (context) => {
1679
1675
  // Parsed inside the handler so a usage error renders through the runner instead of escaping
1680
1676
  // the route as an uncaught rejection.
1681
1677
  () => {
1682
- const { selector } = splitOptionalSelector(context.args, "revoke [selector]");
1678
+ const { selector } = splitOptionalSelector(context.args, "sessions revoke [selector]");
1683
1679
  return guarded(context)(() => handleRevokeCommand({ selector }, { stateDir }))();
1684
1680
  },
1685
1681
  context.env
@@ -0,0 +1,4 @@
1
+ /** Route for `appduct tools call` — loaded by `routes/tools/index.ts`'s router only when it runs
2
+ * (issue #96; replaces the removed `appduct invoke`). */
3
+ import type { Route } from "../../router.js";
4
+ export declare const route: Route;
@@ -1356,9 +1356,6 @@ var renderLsData = (colors, data, now) => {
1356
1356
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
1357
1357
  ];
1358
1358
  };
1359
- var isToolsListing = (data) => {
1360
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
1361
- };
1362
1359
  var isToolGroupsListing = (data) => {
1363
1360
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
1364
1361
  };
@@ -1376,7 +1373,7 @@ var renderEmptyToolsLine = (data) => {
1376
1373
  }
1377
1374
  if (data.group !== void 0) {
1378
1375
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
1379
- return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools --groups\` to see the session's groups.`;
1376
+ return ` No tools in group ${JSON.stringify(data.group)}${match}. Run \`appduct tools ls --groups\` to see the session's groups.`;
1380
1377
  }
1381
1378
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
1382
1379
  };
@@ -1458,7 +1455,7 @@ var renderToolSummaryTable = (colors, data) => {
1458
1455
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
1459
1456
  ...renderTruncationLine(data),
1460
1457
  "",
1461
- "Run `appduct tools <name>` for a tool's full schema."
1458
+ "Run `appduct tools describe <name>` for a tool's full schema."
1462
1459
  ];
1463
1460
  };
1464
1461
  var renderToolDetail = (colors, tool, flags) => {
@@ -1510,16 +1507,13 @@ var renderToolGroups = (colors, data) => {
1510
1507
  colors.green("Groups"),
1511
1508
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
1512
1509
  "",
1513
- `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools --group <name>` to list one group's tools." : "No tool declares a group.")
1510
+ `${data.total} tool${data.total === 1 ? "" : "s"} in total. ` + (hasAnyGroup(data.groups) ? "Run `appduct tools ls --group <name>` to list one group's tools." : "No tool declares a group.")
1514
1511
  ];
1515
1512
  };
1516
- var renderToolsData = (colors, data, flags, full) => {
1513
+ var renderToolsListData = (colors, data, flags, full) => {
1517
1514
  if (isToolGroupsListing(data)) {
1518
1515
  return renderToolGroups(colors, data);
1519
1516
  }
1520
- if (!isToolsListing(data)) {
1521
- return renderToolDetail(colors, data, flags);
1522
- }
1523
1517
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1524
1518
  };
1525
1519
  var renderInvokeData = (colors, data, flags) => {
@@ -1705,15 +1699,17 @@ var renderSuccessData = (colors, command, data, options) => {
1705
1699
  return renderInitData(colors, data, flags);
1706
1700
  case "keygen":
1707
1701
  return renderKeygenData(colors, data, flags);
1708
- case "link":
1702
+ case "sessions link":
1709
1703
  return renderLinkData(colors, data, flags, options.qr);
1710
- case "ls":
1704
+ case "sessions ls":
1711
1705
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
1712
- case "tools":
1713
- return renderToolsData(colors, data, flags, options.full);
1714
- case "invoke":
1706
+ case "tools ls":
1707
+ return renderToolsListData(colors, data, flags, options.full);
1708
+ case "tools describe":
1709
+ return renderToolDetail(colors, data, flags);
1710
+ case "tools call":
1715
1711
  return renderInvokeData(colors, data, flags);
1716
- case "revoke":
1712
+ case "sessions revoke":
1717
1713
  return renderRevokeData(colors, data);
1718
1714
  case "daemon run":
1719
1715
  return renderDaemonRunData(colors, data, flags);
@@ -1859,7 +1855,7 @@ var guarded = (context) => {
1859
1855
  };
1860
1856
  };
1861
1857
 
1862
- // src/cli/routes/invoke.ts
1858
+ // src/cli/routes/tools/call.ts
1863
1859
  var route = async (context) => {
1864
1860
  const { options, stateDir } = context;
1865
1861
  const cancelController = new AbortController();
@@ -1868,12 +1864,12 @@ var route = async (context) => {
1868
1864
  try {
1869
1865
  return await executeCommand(
1870
1866
  commandName(context),
1871
- // Positionals are split inside the handler so a missing `<tool>` renders through the runner
1867
+ // Positionals are split inside the handler so a missing `<name>` renders through the runner
1872
1868
  // as a usage error instead of escaping the route as an uncaught rejection.
1873
1869
  () => {
1874
1870
  const { selector, target: tool } = splitSelectorAndRequiredTarget(
1875
1871
  context.args,
1876
- "invoke [selector] <tool> --input '<json>'"
1872
+ "tools call [selector] <name> --input '<json>'"
1877
1873
  );
1878
1874
  return guarded(context)(
1879
1875
  () => handleInvokeCommand(
@@ -0,0 +1,6 @@
1
+ /** Route for `appduct tools describe` — loaded by `routes/tools/index.ts`'s router only when it
2
+ * runs (issue #96; replaces the removed `appduct tools <name>` / `appduct tools [selector] <name>`
3
+ * detail form). Unlike the old single-positional form, `<name>` is never ambiguous with a
4
+ * selector: `splitSelectorAndRequiredTarget` always takes the last positional as the name. */
5
+ import type { Route } from "../../router.js";
6
+ export declare const route: Route;