appduct 0.11.1 → 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 (74) hide show
  1. package/README.md +43 -38
  2. package/dist/bin.js +50 -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 +216 -46
  7. package/dist/cli/routes/daemon/start.js +18 -16
  8. package/dist/cli/routes/daemon/status.js +18 -16
  9. package/dist/cli/routes/daemon/stop.js +18 -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} +184 -162
  19. package/dist/cli/routes/init.js +14 -18
  20. package/dist/cli/routes/keygen.js +13 -16
  21. package/dist/cli/routes/mcp.js +193 -175
  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} +19 -17
  26. package/dist/cli/routes/sessions/ls.d.ts +4 -0
  27. package/dist/cli/routes/{ls.js → sessions/ls.js} +19 -17
  28. package/dist/cli/routes/sessions/revoke.d.ts +4 -0
  29. package/dist/cli/routes/{revoke.js → sessions/revoke.js} +20 -18
  30. package/dist/cli/routes/tools/call.d.ts +4 -0
  31. package/dist/cli/routes/{invoke.js → tools/call.js} +21 -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} +46 -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 +183 -139
  43. package/dist/commands/events.d.ts +31 -13
  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 +5 -2
  50. package/dist/daemon/daemon.d.ts +3 -0
  51. package/dist/daemon/event-bus.d.ts +36 -4
  52. package/dist/daemon/events-log.d.ts +31 -0
  53. package/dist/daemon/memory-append-only-file.d.ts +17 -0
  54. package/dist/daemon/node-append-only-file.d.ts +9 -0
  55. package/dist/daemon/rpc-errors.d.ts +1 -1
  56. package/dist/daemon/state-dir.d.ts +2 -0
  57. package/dist/errors.d.ts +1 -1
  58. package/dist/events/index.d.ts +60 -0
  59. package/dist/index.js +62 -39
  60. package/dist/link.d.ts +1 -1
  61. package/dist/mcp/app-tools.d.ts +3 -2
  62. package/dist/mcp/connect-tool.d.ts +1 -1
  63. package/dist/mcp/events-tool.d.ts +28 -34
  64. package/dist/native-scheme.d.ts +1 -1
  65. package/dist/output.d.ts +29 -6
  66. package/dist/rpc/client.d.ts +1 -1
  67. package/dist/scheme.d.ts +4 -4
  68. package/package.json +2 -2
  69. package/dist/cli/routes/events.d.ts +0 -3
  70. package/dist/cli/routes/invoke.d.ts +0 -3
  71. package/dist/cli/routes/link.d.ts +0 -3
  72. package/dist/cli/routes/ls.d.ts +0 -3
  73. package/dist/cli/routes/revoke.d.ts +0 -3
  74. 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;
@@ -25,6 +25,7 @@ var KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
25
25
  "eventBufferSize",
26
26
  "auditRetentionDays",
27
27
  "daemonLogMaxBytes",
28
+ "eventsLogMaxBytes",
28
29
  "policy",
29
30
  "advertisedIp",
30
31
  "scheme",
@@ -84,6 +85,7 @@ var defaultConfig = (paths) => {
84
85
  eventBufferSize: 256,
85
86
  auditRetentionDays: DEFAULT_AUDIT_RETENTION_DAYS,
86
87
  daemonLogMaxBytes: DEFAULT_DAEMON_LOG_MAX_BYTES,
88
+ eventsLogMaxBytes: 10 * 1024 * 1024,
87
89
  restartDaemonOnVersionMismatch: false,
88
90
  policy: {
89
91
  default: "allow",
@@ -146,6 +148,9 @@ var loadConfig = async (paths, options = {}) => {
146
148
  if (parsed.daemonLogMaxBytes !== void 0) {
147
149
  config.daemonLogMaxBytes = requirePositiveInteger(parsed.daemonLogMaxBytes, "daemonLogMaxBytes");
148
150
  }
151
+ if (parsed.eventsLogMaxBytes !== void 0) {
152
+ config.eventsLogMaxBytes = requirePositiveInteger(parsed.eventsLogMaxBytes, "eventsLogMaxBytes");
153
+ }
149
154
  if (parsed.restartDaemonOnVersionMismatch !== void 0) {
150
155
  config.restartDaemonOnVersionMismatch = requireBoolean(
151
156
  parsed.restartDaemonOnVersionMismatch,
@@ -246,6 +251,7 @@ var getStateDirPaths = (stateDir) => {
246
251
  socketPath: join(stateDir, "daemon.sock"),
247
252
  pidFilePath: join(stateDir, "daemon.pid"),
248
253
  logFilePath: join(stateDir, "daemon.log"),
254
+ eventsLogPath: join(stateDir, "events.log"),
249
255
  keyPath: join(stateDir, "key.pem"),
250
256
  configPath: join(stateDir, "config.json"),
251
257
  auditDir: join(stateDir, "audit"),
@@ -2179,9 +2185,6 @@ var renderLsData = (colors, data, now) => {
2179
2185
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
2180
2186
  ];
2181
2187
  };
2182
- var isToolsListing = (data) => {
2183
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
2184
- };
2185
2188
  var isToolGroupsListing = (data) => {
2186
2189
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
2187
2190
  };
@@ -2199,7 +2202,7 @@ var renderEmptyToolsLine = (data) => {
2199
2202
  }
2200
2203
  if (data.group !== void 0) {
2201
2204
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
2202
- 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.`;
2203
2206
  }
2204
2207
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
2205
2208
  };
@@ -2281,7 +2284,7 @@ var renderToolSummaryTable = (colors, data) => {
2281
2284
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
2282
2285
  ...renderTruncationLine(data),
2283
2286
  "",
2284
- "Run `appduct tools <name>` for a tool's full schema."
2287
+ "Run `appduct tools describe <name>` for a tool's full schema."
2285
2288
  ];
2286
2289
  };
2287
2290
  var renderToolDetail = (colors, tool, flags) => {
@@ -2333,16 +2336,13 @@ var renderToolGroups = (colors, data) => {
2333
2336
  colors.green("Groups"),
2334
2337
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
2335
2338
  "",
2336
- `${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.")
2337
2340
  ];
2338
2341
  };
2339
- var renderToolsData = (colors, data, flags, full) => {
2342
+ var renderToolsListData = (colors, data, flags, full) => {
2340
2343
  if (isToolGroupsListing(data)) {
2341
2344
  return renderToolGroups(colors, data);
2342
2345
  }
2343
- if (!isToolsListing(data)) {
2344
- return renderToolDetail(colors, data, flags);
2345
- }
2346
2346
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
2347
2347
  };
2348
2348
  var renderInvokeData = (colors, data, flags) => {
@@ -2528,15 +2528,17 @@ var renderSuccessData = (colors, command, data, options) => {
2528
2528
  return renderInitData(colors, data, flags);
2529
2529
  case "keygen":
2530
2530
  return renderKeygenData(colors, data, flags);
2531
- case "link":
2531
+ case "sessions link":
2532
2532
  return renderLinkData(colors, data, flags, options.qr);
2533
- case "ls":
2533
+ case "sessions ls":
2534
2534
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
2535
- case "tools":
2536
- return renderToolsData(colors, data, flags, options.full);
2537
- 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":
2538
2540
  return renderInvokeData(colors, data, flags);
2539
- case "revoke":
2541
+ case "sessions revoke":
2540
2542
  return renderRevokeData(colors, data);
2541
2543
  case "daemon run":
2542
2544
  return renderDaemonRunData(colors, data, flags);
@@ -2682,7 +2684,7 @@ var guarded = (context) => {
2682
2684
  };
2683
2685
  };
2684
2686
 
2685
- // src/cli/routes/link.ts
2687
+ // src/cli/routes/sessions/link.ts
2686
2688
  var route = async (context) => {
2687
2689
  const { options, stateDir } = context;
2688
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;
@@ -22,6 +22,7 @@ var KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
22
22
  "eventBufferSize",
23
23
  "auditRetentionDays",
24
24
  "daemonLogMaxBytes",
25
+ "eventsLogMaxBytes",
25
26
  "policy",
26
27
  "advertisedIp",
27
28
  "scheme",
@@ -81,6 +82,7 @@ var defaultConfig = (paths) => {
81
82
  eventBufferSize: 256,
82
83
  auditRetentionDays: DEFAULT_AUDIT_RETENTION_DAYS,
83
84
  daemonLogMaxBytes: DEFAULT_DAEMON_LOG_MAX_BYTES,
85
+ eventsLogMaxBytes: 10 * 1024 * 1024,
84
86
  restartDaemonOnVersionMismatch: false,
85
87
  policy: {
86
88
  default: "allow",
@@ -143,6 +145,9 @@ var loadConfig = async (paths, options = {}) => {
143
145
  if (parsed.daemonLogMaxBytes !== void 0) {
144
146
  config.daemonLogMaxBytes = requirePositiveInteger(parsed.daemonLogMaxBytes, "daemonLogMaxBytes");
145
147
  }
148
+ if (parsed.eventsLogMaxBytes !== void 0) {
149
+ config.eventsLogMaxBytes = requirePositiveInteger(parsed.eventsLogMaxBytes, "eventsLogMaxBytes");
150
+ }
146
151
  if (parsed.restartDaemonOnVersionMismatch !== void 0) {
147
152
  config.restartDaemonOnVersionMismatch = requireBoolean(
148
153
  parsed.restartDaemonOnVersionMismatch,
@@ -243,6 +248,7 @@ var getStateDirPaths = (stateDir) => {
243
248
  socketPath: join(stateDir, "daemon.sock"),
244
249
  pidFilePath: join(stateDir, "daemon.pid"),
245
250
  logFilePath: join(stateDir, "daemon.log"),
251
+ eventsLogPath: join(stateDir, "events.log"),
246
252
  keyPath: join(stateDir, "key.pem"),
247
253
  configPath: join(stateDir, "config.json"),
248
254
  auditDir: join(stateDir, "audit"),
@@ -1151,9 +1157,6 @@ var renderLsData = (colors, data, now) => {
1151
1157
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
1152
1158
  ];
1153
1159
  };
1154
- var isToolsListing = (data) => {
1155
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
1156
- };
1157
1160
  var isToolGroupsListing = (data) => {
1158
1161
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
1159
1162
  };
@@ -1171,7 +1174,7 @@ var renderEmptyToolsLine = (data) => {
1171
1174
  }
1172
1175
  if (data.group !== void 0) {
1173
1176
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
1174
- 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.`;
1175
1178
  }
1176
1179
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
1177
1180
  };
@@ -1253,7 +1256,7 @@ var renderToolSummaryTable = (colors, data) => {
1253
1256
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
1254
1257
  ...renderTruncationLine(data),
1255
1258
  "",
1256
- "Run `appduct tools <name>` for a tool's full schema."
1259
+ "Run `appduct tools describe <name>` for a tool's full schema."
1257
1260
  ];
1258
1261
  };
1259
1262
  var renderToolDetail = (colors, tool, flags) => {
@@ -1305,16 +1308,13 @@ var renderToolGroups = (colors, data) => {
1305
1308
  colors.green("Groups"),
1306
1309
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
1307
1310
  "",
1308
- `${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.")
1309
1312
  ];
1310
1313
  };
1311
- var renderToolsData = (colors, data, flags, full) => {
1314
+ var renderToolsListData = (colors, data, flags, full) => {
1312
1315
  if (isToolGroupsListing(data)) {
1313
1316
  return renderToolGroups(colors, data);
1314
1317
  }
1315
- if (!isToolsListing(data)) {
1316
- return renderToolDetail(colors, data, flags);
1317
- }
1318
1318
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1319
1319
  };
1320
1320
  var renderInvokeData = (colors, data, flags) => {
@@ -1500,15 +1500,17 @@ var renderSuccessData = (colors, command, data, options) => {
1500
1500
  return renderInitData(colors, data, flags);
1501
1501
  case "keygen":
1502
1502
  return renderKeygenData(colors, data, flags);
1503
- case "link":
1503
+ case "sessions link":
1504
1504
  return renderLinkData(colors, data, flags, options.qr);
1505
- case "ls":
1505
+ case "sessions ls":
1506
1506
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
1507
- case "tools":
1508
- return renderToolsData(colors, data, flags, options.full);
1509
- 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":
1510
1512
  return renderInvokeData(colors, data, flags);
1511
- case "revoke":
1513
+ case "sessions revoke":
1512
1514
  return renderRevokeData(colors, data);
1513
1515
  case "daemon run":
1514
1516
  return renderDaemonRunData(colors, data, flags);
@@ -1654,7 +1656,7 @@ var guarded = (context) => {
1654
1656
  };
1655
1657
  };
1656
1658
 
1657
- // src/cli/routes/ls.ts
1659
+ // src/cli/routes/sessions/ls.ts
1658
1660
  var route = async (context) => {
1659
1661
  const { stateDir } = context;
1660
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;
@@ -22,6 +22,7 @@ var KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
22
22
  "eventBufferSize",
23
23
  "auditRetentionDays",
24
24
  "daemonLogMaxBytes",
25
+ "eventsLogMaxBytes",
25
26
  "policy",
26
27
  "advertisedIp",
27
28
  "scheme",
@@ -81,6 +82,7 @@ var defaultConfig = (paths) => {
81
82
  eventBufferSize: 256,
82
83
  auditRetentionDays: DEFAULT_AUDIT_RETENTION_DAYS,
83
84
  daemonLogMaxBytes: DEFAULT_DAEMON_LOG_MAX_BYTES,
85
+ eventsLogMaxBytes: 10 * 1024 * 1024,
84
86
  restartDaemonOnVersionMismatch: false,
85
87
  policy: {
86
88
  default: "allow",
@@ -143,6 +145,9 @@ var loadConfig = async (paths, options = {}) => {
143
145
  if (parsed.daemonLogMaxBytes !== void 0) {
144
146
  config.daemonLogMaxBytes = requirePositiveInteger(parsed.daemonLogMaxBytes, "daemonLogMaxBytes");
145
147
  }
148
+ if (parsed.eventsLogMaxBytes !== void 0) {
149
+ config.eventsLogMaxBytes = requirePositiveInteger(parsed.eventsLogMaxBytes, "eventsLogMaxBytes");
150
+ }
146
151
  if (parsed.restartDaemonOnVersionMismatch !== void 0) {
147
152
  config.restartDaemonOnVersionMismatch = requireBoolean(
148
153
  parsed.restartDaemonOnVersionMismatch,
@@ -243,6 +248,7 @@ var getStateDirPaths = (stateDir) => {
243
248
  socketPath: join(stateDir, "daemon.sock"),
244
249
  pidFilePath: join(stateDir, "daemon.pid"),
245
250
  logFilePath: join(stateDir, "daemon.log"),
251
+ eventsLogPath: join(stateDir, "events.log"),
246
252
  keyPath: join(stateDir, "key.pem"),
247
253
  configPath: join(stateDir, "config.json"),
248
254
  auditDir: join(stateDir, "audit"),
@@ -1162,9 +1168,6 @@ var renderLsData = (colors, data, now) => {
1162
1168
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
1163
1169
  ];
1164
1170
  };
1165
- var isToolsListing = (data) => {
1166
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
1167
- };
1168
1171
  var isToolGroupsListing = (data) => {
1169
1172
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
1170
1173
  };
@@ -1182,7 +1185,7 @@ var renderEmptyToolsLine = (data) => {
1182
1185
  }
1183
1186
  if (data.group !== void 0) {
1184
1187
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
1185
- 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.`;
1186
1189
  }
1187
1190
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
1188
1191
  };
@@ -1264,7 +1267,7 @@ var renderToolSummaryTable = (colors, data) => {
1264
1267
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
1265
1268
  ...renderTruncationLine(data),
1266
1269
  "",
1267
- "Run `appduct tools <name>` for a tool's full schema."
1270
+ "Run `appduct tools describe <name>` for a tool's full schema."
1268
1271
  ];
1269
1272
  };
1270
1273
  var renderToolDetail = (colors, tool, flags) => {
@@ -1316,16 +1319,13 @@ var renderToolGroups = (colors, data) => {
1316
1319
  colors.green("Groups"),
1317
1320
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
1318
1321
  "",
1319
- `${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.")
1320
1323
  ];
1321
1324
  };
1322
- var renderToolsData = (colors, data, flags, full) => {
1325
+ var renderToolsListData = (colors, data, flags, full) => {
1323
1326
  if (isToolGroupsListing(data)) {
1324
1327
  return renderToolGroups(colors, data);
1325
1328
  }
1326
- if (!isToolsListing(data)) {
1327
- return renderToolDetail(colors, data, flags);
1328
- }
1329
1329
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1330
1330
  };
1331
1331
  var renderInvokeData = (colors, data, flags) => {
@@ -1511,15 +1511,17 @@ var renderSuccessData = (colors, command, data, options) => {
1511
1511
  return renderInitData(colors, data, flags);
1512
1512
  case "keygen":
1513
1513
  return renderKeygenData(colors, data, flags);
1514
- case "link":
1514
+ case "sessions link":
1515
1515
  return renderLinkData(colors, data, flags, options.qr);
1516
- case "ls":
1516
+ case "sessions ls":
1517
1517
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
1518
- case "tools":
1519
- return renderToolsData(colors, data, flags, options.full);
1520
- 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":
1521
1523
  return renderInvokeData(colors, data, flags);
1522
- case "revoke":
1524
+ case "sessions revoke":
1523
1525
  return renderRevokeData(colors, data);
1524
1526
  case "daemon run":
1525
1527
  return renderDaemonRunData(colors, data, flags);
@@ -1665,7 +1667,7 @@ var guarded = (context) => {
1665
1667
  };
1666
1668
  };
1667
1669
 
1668
- // src/cli/routes/revoke.ts
1670
+ // src/cli/routes/sessions/revoke.ts
1669
1671
  var route = async (context) => {
1670
1672
  const { stateDir } = context;
1671
1673
  return executeCommand(
@@ -1673,7 +1675,7 @@ var route = async (context) => {
1673
1675
  // Parsed inside the handler so a usage error renders through the runner instead of escaping
1674
1676
  // the route as an uncaught rejection.
1675
1677
  () => {
1676
- const { selector } = splitOptionalSelector(context.args, "revoke [selector]");
1678
+ const { selector } = splitOptionalSelector(context.args, "sessions revoke [selector]");
1677
1679
  return guarded(context)(() => handleRevokeCommand({ selector }, { stateDir }))();
1678
1680
  },
1679
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;
@@ -42,6 +42,7 @@ var KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
42
42
  "eventBufferSize",
43
43
  "auditRetentionDays",
44
44
  "daemonLogMaxBytes",
45
+ "eventsLogMaxBytes",
45
46
  "policy",
46
47
  "advertisedIp",
47
48
  "scheme",
@@ -101,6 +102,7 @@ var defaultConfig = (paths) => {
101
102
  eventBufferSize: 256,
102
103
  auditRetentionDays: DEFAULT_AUDIT_RETENTION_DAYS,
103
104
  daemonLogMaxBytes: DEFAULT_DAEMON_LOG_MAX_BYTES,
105
+ eventsLogMaxBytes: 10 * 1024 * 1024,
104
106
  restartDaemonOnVersionMismatch: false,
105
107
  policy: {
106
108
  default: "allow",
@@ -163,6 +165,9 @@ var loadConfig = async (paths, options = {}) => {
163
165
  if (parsed.daemonLogMaxBytes !== void 0) {
164
166
  config.daemonLogMaxBytes = requirePositiveInteger(parsed.daemonLogMaxBytes, "daemonLogMaxBytes");
165
167
  }
168
+ if (parsed.eventsLogMaxBytes !== void 0) {
169
+ config.eventsLogMaxBytes = requirePositiveInteger(parsed.eventsLogMaxBytes, "eventsLogMaxBytes");
170
+ }
166
171
  if (parsed.restartDaemonOnVersionMismatch !== void 0) {
167
172
  config.restartDaemonOnVersionMismatch = requireBoolean(
168
173
  parsed.restartDaemonOnVersionMismatch,
@@ -263,6 +268,7 @@ var getStateDirPaths = (stateDir) => {
263
268
  socketPath: join(stateDir, "daemon.sock"),
264
269
  pidFilePath: join(stateDir, "daemon.pid"),
265
270
  logFilePath: join(stateDir, "daemon.log"),
271
+ eventsLogPath: join(stateDir, "events.log"),
266
272
  keyPath: join(stateDir, "key.pem"),
267
273
  configPath: join(stateDir, "config.json"),
268
274
  auditDir: join(stateDir, "audit"),
@@ -1350,9 +1356,6 @@ var renderLsData = (colors, data, now) => {
1350
1356
  ...rows.map((row) => ` ${row.map((cell, index) => cell.padEnd(widths[index])).join(" ")}`)
1351
1357
  ];
1352
1358
  };
1353
- var isToolsListing = (data) => {
1354
- return typeof data === "object" && data !== null && Array.isArray(data.tools);
1355
- };
1356
1359
  var isToolGroupsListing = (data) => {
1357
1360
  return typeof data === "object" && data !== null && Array.isArray(data.groups) && !Array.isArray(data.tools);
1358
1361
  };
@@ -1370,7 +1373,7 @@ var renderEmptyToolsLine = (data) => {
1370
1373
  }
1371
1374
  if (data.group !== void 0) {
1372
1375
  const match = data.filter === void 0 ? "" : ` match ${JSON.stringify(data.filter)}`;
1373
- 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.`;
1374
1377
  }
1375
1378
  return data.filter === void 0 ? " No tools registered." : ` No tools match ${JSON.stringify(data.filter)}.`;
1376
1379
  };
@@ -1452,7 +1455,7 @@ var renderToolSummaryTable = (colors, data) => {
1452
1455
  ...grouped ? renderGroupedToolLines(colors, data.tools) : data.tools.flatMap((tool) => renderToolSummaryLines(tool, " ")),
1453
1456
  ...renderTruncationLine(data),
1454
1457
  "",
1455
- "Run `appduct tools <name>` for a tool's full schema."
1458
+ "Run `appduct tools describe <name>` for a tool's full schema."
1456
1459
  ];
1457
1460
  };
1458
1461
  var renderToolDetail = (colors, tool, flags) => {
@@ -1504,16 +1507,13 @@ var renderToolGroups = (colors, data) => {
1504
1507
  colors.green("Groups"),
1505
1508
  ...data.groups.map((entry) => ` ${label(entry).padEnd(width)} ${String(entry.total).padStart(countWidth)}`),
1506
1509
  "",
1507
- `${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.")
1508
1511
  ];
1509
1512
  };
1510
- var renderToolsData = (colors, data, flags, full) => {
1513
+ var renderToolsListData = (colors, data, flags, full) => {
1511
1514
  if (isToolGroupsListing(data)) {
1512
1515
  return renderToolGroups(colors, data);
1513
1516
  }
1514
- if (!isToolsListing(data)) {
1515
- return renderToolDetail(colors, data, flags);
1516
- }
1517
1517
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1518
1518
  };
1519
1519
  var renderInvokeData = (colors, data, flags) => {
@@ -1699,15 +1699,17 @@ var renderSuccessData = (colors, command, data, options) => {
1699
1699
  return renderInitData(colors, data, flags);
1700
1700
  case "keygen":
1701
1701
  return renderKeygenData(colors, data, flags);
1702
- case "link":
1702
+ case "sessions link":
1703
1703
  return renderLinkData(colors, data, flags, options.qr);
1704
- case "ls":
1704
+ case "sessions ls":
1705
1705
  return renderLsData(colors, data, options.now ?? /* @__PURE__ */ new Date());
1706
- case "tools":
1707
- return renderToolsData(colors, data, flags, options.full);
1708
- 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":
1709
1711
  return renderInvokeData(colors, data, flags);
1710
- case "revoke":
1712
+ case "sessions revoke":
1711
1713
  return renderRevokeData(colors, data);
1712
1714
  case "daemon run":
1713
1715
  return renderDaemonRunData(colors, data, flags);
@@ -1853,7 +1855,7 @@ var guarded = (context) => {
1853
1855
  };
1854
1856
  };
1855
1857
 
1856
- // src/cli/routes/invoke.ts
1858
+ // src/cli/routes/tools/call.ts
1857
1859
  var route = async (context) => {
1858
1860
  const { options, stateDir } = context;
1859
1861
  const cancelController = new AbortController();
@@ -1862,12 +1864,12 @@ var route = async (context) => {
1862
1864
  try {
1863
1865
  return await executeCommand(
1864
1866
  commandName(context),
1865
- // 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
1866
1868
  // as a usage error instead of escaping the route as an uncaught rejection.
1867
1869
  () => {
1868
1870
  const { selector, target: tool } = splitSelectorAndRequiredTarget(
1869
1871
  context.args,
1870
- "invoke [selector] <tool> --input '<json>'"
1872
+ "tools call [selector] <name> --input '<json>'"
1871
1873
  );
1872
1874
  return guarded(context)(
1873
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;