appduct 0.13.0 → 0.14.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 (36) hide show
  1. package/README.md +3 -2
  2. package/dist/bin.js +61 -4
  3. package/dist/cli/result-types.d.ts +8 -1
  4. package/dist/cli/routes/daemon/index.js +58 -1
  5. package/dist/cli/routes/daemon/run.js +152 -22
  6. package/dist/cli/routes/daemon/start.js +58 -1
  7. package/dist/cli/routes/daemon/status.js +58 -1
  8. package/dist/cli/routes/daemon/stop.js +58 -1
  9. package/dist/cli/routes/doctor.js +58 -1
  10. package/dist/cli/routes/events/index.d.ts +0 -3
  11. package/dist/cli/routes/events/index.js +60 -2
  12. package/dist/cli/routes/events/ls.d.ts +5 -0
  13. package/dist/cli/routes/events/ls.js +1798 -0
  14. package/dist/cli/routes/events/since.js +58 -1
  15. package/dist/cli/routes/events/tail.js +58 -1
  16. package/dist/cli/routes/init.js +58 -1
  17. package/dist/cli/routes/keygen.js +58 -1
  18. package/dist/cli/routes/mcp.js +108 -1
  19. package/dist/cli/routes/sessions/index.js +58 -1
  20. package/dist/cli/routes/sessions/link.js +58 -1
  21. package/dist/cli/routes/sessions/ls.js +58 -1
  22. package/dist/cli/routes/sessions/revoke.js +58 -1
  23. package/dist/cli/routes/tools/call.js +58 -1
  24. package/dist/cli/routes/tools/describe.js +58 -1
  25. package/dist/cli/routes/tools/index.js +58 -1
  26. package/dist/cli/routes/tools/ls.js +58 -1
  27. package/dist/commands/events-ls.d.ts +21 -0
  28. package/dist/daemon/calls.d.ts +3 -1
  29. package/dist/daemon/event-bus.d.ts +10 -0
  30. package/dist/daemon/registry.d.ts +20 -12
  31. package/dist/daemon/rpc-errors.d.ts +3 -0
  32. package/dist/daemon/sessions.d.ts +4 -2
  33. package/dist/index.js +61 -4
  34. package/dist/mcp/app-tools.d.ts +19 -0
  35. package/dist/mcp/events-tool.d.ts +39 -0
  36. package/package.json +2 -2
@@ -2068,6 +2068,7 @@ var formatJson = (value, flags) => {
2068
2068
  import pc from "picocolors";
2069
2069
  import {
2070
2070
  formatAgentWebSocketUrl,
2071
+ renderEventSignature,
2071
2072
  renderToolSignature,
2072
2073
  summarizeToolDescription
2073
2074
  } from "@appduct/shared";
@@ -2163,6 +2164,13 @@ var formatDevice = (device) => {
2163
2164
  const label = parts.length > 0 ? parts.join(" ") : "unknown device";
2164
2165
  return device.os ? `${label} (${device.os})` : label;
2165
2166
  };
2167
+ var SUSPEND_REASON_LABELS = {
2168
+ app_backgrounded: "app in background",
2169
+ connection_lost: "connection lost"
2170
+ };
2171
+ var formatSessionState = (session) => {
2172
+ return session.suspendReason ? `${session.state} (${SUSPEND_REASON_LABELS[session.suspendReason]})` : session.state;
2173
+ };
2166
2174
  var renderLsData = (colors, data, now) => {
2167
2175
  if (data.length === 0) {
2168
2176
  return [colors.dim("Sessions"), " No Appduct sessions are registered."];
@@ -2171,7 +2179,7 @@ var renderLsData = (colors, data, now) => {
2171
2179
  const headers = ["Alias", "State", "Device", "Tools", "Age"];
2172
2180
  const rows = data.map((session) => [
2173
2181
  session.alias,
2174
- session.state,
2182
+ formatSessionState(session),
2175
2183
  formatDevice(session.device),
2176
2184
  String(session.toolCount),
2177
2185
  formatAge(session.claimedAt ?? session.createdAt, nowIso)
@@ -2345,6 +2353,53 @@ var renderToolsListData = (colors, data, flags, full) => {
2345
2353
  }
2346
2354
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
2347
2355
  };
2356
+ var renderEventsTruncationLine = (data) => {
2357
+ const offset = data.offset ?? 0;
2358
+ if (data.events.length >= data.total) {
2359
+ return [];
2360
+ }
2361
+ return [
2362
+ "",
2363
+ `Showing ${data.events.length} of ${data.total} events (offset ${offset}). Narrow with --name <glob> or page with --offset <n>.`
2364
+ ];
2365
+ };
2366
+ var renderEventsListData = (colors, data, flags) => {
2367
+ const [only] = data.events;
2368
+ if (data.name !== void 0 && !data.name.includes("*") && only !== void 0) {
2369
+ return renderFields(
2370
+ colors.green(`Event: ${only.name}`),
2371
+ [
2372
+ ["Signature", renderEventSignature(only)],
2373
+ ["Description", only.description],
2374
+ ["Payload schema", only.payload_schema]
2375
+ ],
2376
+ flags
2377
+ );
2378
+ }
2379
+ if (data.events.length === 0 && data.total > 0) {
2380
+ return [
2381
+ colors.green("Events"),
2382
+ ` No events at offset ${data.offset ?? 0}; ${data.total} matching event${data.total === 1 ? "" : "s"} in total.`
2383
+ ];
2384
+ }
2385
+ if (data.events.length === 0) {
2386
+ return [
2387
+ colors.green("Events"),
2388
+ data.name === void 0 ? " No events declared." : ` No events match ${JSON.stringify(data.name)}.`
2389
+ ];
2390
+ }
2391
+ const lines = data.events.flatMap((event) => [
2392
+ ` ${renderEventSignature(event)}`,
2393
+ ` ${summarizeToolDescription(event.description)}`
2394
+ ]);
2395
+ return [
2396
+ colors.green("Events"),
2397
+ ...lines,
2398
+ ...renderEventsTruncationLine(data),
2399
+ "",
2400
+ "Run `appduct events ls --name <name>` for an event's full payload schema."
2401
+ ];
2402
+ };
2348
2403
  var renderInvokeData = (colors, data, flags) => {
2349
2404
  return [colors.green("Result"), formatScalar(data, flags)];
2350
2405
  };
@@ -2536,6 +2591,8 @@ var renderSuccessData = (colors, command, data, options) => {
2536
2591
  return renderToolsListData(colors, data, flags, options.full);
2537
2592
  case "tools describe":
2538
2593
  return renderToolDetail(colors, data, flags);
2594
+ case "events ls":
2595
+ return renderEventsListData(colors, data, flags);
2539
2596
  case "tools call":
2540
2597
  return renderInvokeData(colors, data, flags);
2541
2598
  case "sessions revoke":
@@ -1040,6 +1040,7 @@ var formatJson = (value, flags) => {
1040
1040
  import pc from "picocolors";
1041
1041
  import {
1042
1042
  formatAgentWebSocketUrl,
1043
+ renderEventSignature,
1043
1044
  renderToolSignature,
1044
1045
  summarizeToolDescription
1045
1046
  } from "@appduct/shared";
@@ -1135,6 +1136,13 @@ var formatDevice = (device) => {
1135
1136
  const label = parts.length > 0 ? parts.join(" ") : "unknown device";
1136
1137
  return device.os ? `${label} (${device.os})` : label;
1137
1138
  };
1139
+ var SUSPEND_REASON_LABELS = {
1140
+ app_backgrounded: "app in background",
1141
+ connection_lost: "connection lost"
1142
+ };
1143
+ var formatSessionState = (session) => {
1144
+ return session.suspendReason ? `${session.state} (${SUSPEND_REASON_LABELS[session.suspendReason]})` : session.state;
1145
+ };
1138
1146
  var renderLsData = (colors, data, now) => {
1139
1147
  if (data.length === 0) {
1140
1148
  return [colors.dim("Sessions"), " No Appduct sessions are registered."];
@@ -1143,7 +1151,7 @@ var renderLsData = (colors, data, now) => {
1143
1151
  const headers = ["Alias", "State", "Device", "Tools", "Age"];
1144
1152
  const rows = data.map((session) => [
1145
1153
  session.alias,
1146
- session.state,
1154
+ formatSessionState(session),
1147
1155
  formatDevice(session.device),
1148
1156
  String(session.toolCount),
1149
1157
  formatAge(session.claimedAt ?? session.createdAt, nowIso)
@@ -1317,6 +1325,53 @@ var renderToolsListData = (colors, data, flags, full) => {
1317
1325
  }
1318
1326
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1319
1327
  };
1328
+ var renderEventsTruncationLine = (data) => {
1329
+ const offset = data.offset ?? 0;
1330
+ if (data.events.length >= data.total) {
1331
+ return [];
1332
+ }
1333
+ return [
1334
+ "",
1335
+ `Showing ${data.events.length} of ${data.total} events (offset ${offset}). Narrow with --name <glob> or page with --offset <n>.`
1336
+ ];
1337
+ };
1338
+ var renderEventsListData = (colors, data, flags) => {
1339
+ const [only] = data.events;
1340
+ if (data.name !== void 0 && !data.name.includes("*") && only !== void 0) {
1341
+ return renderFields(
1342
+ colors.green(`Event: ${only.name}`),
1343
+ [
1344
+ ["Signature", renderEventSignature(only)],
1345
+ ["Description", only.description],
1346
+ ["Payload schema", only.payload_schema]
1347
+ ],
1348
+ flags
1349
+ );
1350
+ }
1351
+ if (data.events.length === 0 && data.total > 0) {
1352
+ return [
1353
+ colors.green("Events"),
1354
+ ` No events at offset ${data.offset ?? 0}; ${data.total} matching event${data.total === 1 ? "" : "s"} in total.`
1355
+ ];
1356
+ }
1357
+ if (data.events.length === 0) {
1358
+ return [
1359
+ colors.green("Events"),
1360
+ data.name === void 0 ? " No events declared." : ` No events match ${JSON.stringify(data.name)}.`
1361
+ ];
1362
+ }
1363
+ const lines = data.events.flatMap((event) => [
1364
+ ` ${renderEventSignature(event)}`,
1365
+ ` ${summarizeToolDescription(event.description)}`
1366
+ ]);
1367
+ return [
1368
+ colors.green("Events"),
1369
+ ...lines,
1370
+ ...renderEventsTruncationLine(data),
1371
+ "",
1372
+ "Run `appduct events ls --name <name>` for an event's full payload schema."
1373
+ ];
1374
+ };
1320
1375
  var renderInvokeData = (colors, data, flags) => {
1321
1376
  return [colors.green("Result"), formatScalar(data, flags)];
1322
1377
  };
@@ -1508,6 +1563,8 @@ var renderSuccessData = (colors, command, data, options) => {
1508
1563
  return renderToolsListData(colors, data, flags, options.full);
1509
1564
  case "tools describe":
1510
1565
  return renderToolDetail(colors, data, flags);
1566
+ case "events ls":
1567
+ return renderEventsListData(colors, data, flags);
1511
1568
  case "tools call":
1512
1569
  return renderInvokeData(colors, data, flags);
1513
1570
  case "sessions revoke":
@@ -1051,6 +1051,7 @@ var formatJson = (value, flags) => {
1051
1051
  import pc from "picocolors";
1052
1052
  import {
1053
1053
  formatAgentWebSocketUrl,
1054
+ renderEventSignature,
1054
1055
  renderToolSignature,
1055
1056
  summarizeToolDescription
1056
1057
  } from "@appduct/shared";
@@ -1146,6 +1147,13 @@ var formatDevice = (device) => {
1146
1147
  const label = parts.length > 0 ? parts.join(" ") : "unknown device";
1147
1148
  return device.os ? `${label} (${device.os})` : label;
1148
1149
  };
1150
+ var SUSPEND_REASON_LABELS = {
1151
+ app_backgrounded: "app in background",
1152
+ connection_lost: "connection lost"
1153
+ };
1154
+ var formatSessionState = (session) => {
1155
+ return session.suspendReason ? `${session.state} (${SUSPEND_REASON_LABELS[session.suspendReason]})` : session.state;
1156
+ };
1149
1157
  var renderLsData = (colors, data, now) => {
1150
1158
  if (data.length === 0) {
1151
1159
  return [colors.dim("Sessions"), " No Appduct sessions are registered."];
@@ -1154,7 +1162,7 @@ var renderLsData = (colors, data, now) => {
1154
1162
  const headers = ["Alias", "State", "Device", "Tools", "Age"];
1155
1163
  const rows = data.map((session) => [
1156
1164
  session.alias,
1157
- session.state,
1165
+ formatSessionState(session),
1158
1166
  formatDevice(session.device),
1159
1167
  String(session.toolCount),
1160
1168
  formatAge(session.claimedAt ?? session.createdAt, nowIso)
@@ -1328,6 +1336,53 @@ var renderToolsListData = (colors, data, flags, full) => {
1328
1336
  }
1329
1337
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1330
1338
  };
1339
+ var renderEventsTruncationLine = (data) => {
1340
+ const offset = data.offset ?? 0;
1341
+ if (data.events.length >= data.total) {
1342
+ return [];
1343
+ }
1344
+ return [
1345
+ "",
1346
+ `Showing ${data.events.length} of ${data.total} events (offset ${offset}). Narrow with --name <glob> or page with --offset <n>.`
1347
+ ];
1348
+ };
1349
+ var renderEventsListData = (colors, data, flags) => {
1350
+ const [only] = data.events;
1351
+ if (data.name !== void 0 && !data.name.includes("*") && only !== void 0) {
1352
+ return renderFields(
1353
+ colors.green(`Event: ${only.name}`),
1354
+ [
1355
+ ["Signature", renderEventSignature(only)],
1356
+ ["Description", only.description],
1357
+ ["Payload schema", only.payload_schema]
1358
+ ],
1359
+ flags
1360
+ );
1361
+ }
1362
+ if (data.events.length === 0 && data.total > 0) {
1363
+ return [
1364
+ colors.green("Events"),
1365
+ ` No events at offset ${data.offset ?? 0}; ${data.total} matching event${data.total === 1 ? "" : "s"} in total.`
1366
+ ];
1367
+ }
1368
+ if (data.events.length === 0) {
1369
+ return [
1370
+ colors.green("Events"),
1371
+ data.name === void 0 ? " No events declared." : ` No events match ${JSON.stringify(data.name)}.`
1372
+ ];
1373
+ }
1374
+ const lines = data.events.flatMap((event) => [
1375
+ ` ${renderEventSignature(event)}`,
1376
+ ` ${summarizeToolDescription(event.description)}`
1377
+ ]);
1378
+ return [
1379
+ colors.green("Events"),
1380
+ ...lines,
1381
+ ...renderEventsTruncationLine(data),
1382
+ "",
1383
+ "Run `appduct events ls --name <name>` for an event's full payload schema."
1384
+ ];
1385
+ };
1331
1386
  var renderInvokeData = (colors, data, flags) => {
1332
1387
  return [colors.green("Result"), formatScalar(data, flags)];
1333
1388
  };
@@ -1519,6 +1574,8 @@ var renderSuccessData = (colors, command, data, options) => {
1519
1574
  return renderToolsListData(colors, data, flags, options.full);
1520
1575
  case "tools describe":
1521
1576
  return renderToolDetail(colors, data, flags);
1577
+ case "events ls":
1578
+ return renderEventsListData(colors, data, flags);
1522
1579
  case "tools call":
1523
1580
  return renderInvokeData(colors, data, flags);
1524
1581
  case "sessions revoke":
@@ -1239,6 +1239,7 @@ var formatJson = (value, flags) => {
1239
1239
  import pc from "picocolors";
1240
1240
  import {
1241
1241
  formatAgentWebSocketUrl,
1242
+ renderEventSignature,
1242
1243
  renderToolSignature,
1243
1244
  summarizeToolDescription
1244
1245
  } from "@appduct/shared";
@@ -1334,6 +1335,13 @@ var formatDevice = (device) => {
1334
1335
  const label = parts.length > 0 ? parts.join(" ") : "unknown device";
1335
1336
  return device.os ? `${label} (${device.os})` : label;
1336
1337
  };
1338
+ var SUSPEND_REASON_LABELS = {
1339
+ app_backgrounded: "app in background",
1340
+ connection_lost: "connection lost"
1341
+ };
1342
+ var formatSessionState = (session) => {
1343
+ return session.suspendReason ? `${session.state} (${SUSPEND_REASON_LABELS[session.suspendReason]})` : session.state;
1344
+ };
1337
1345
  var renderLsData = (colors, data, now) => {
1338
1346
  if (data.length === 0) {
1339
1347
  return [colors.dim("Sessions"), " No Appduct sessions are registered."];
@@ -1342,7 +1350,7 @@ var renderLsData = (colors, data, now) => {
1342
1350
  const headers = ["Alias", "State", "Device", "Tools", "Age"];
1343
1351
  const rows = data.map((session) => [
1344
1352
  session.alias,
1345
- session.state,
1353
+ formatSessionState(session),
1346
1354
  formatDevice(session.device),
1347
1355
  String(session.toolCount),
1348
1356
  formatAge(session.claimedAt ?? session.createdAt, nowIso)
@@ -1516,6 +1524,53 @@ var renderToolsListData = (colors, data, flags, full) => {
1516
1524
  }
1517
1525
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1518
1526
  };
1527
+ var renderEventsTruncationLine = (data) => {
1528
+ const offset = data.offset ?? 0;
1529
+ if (data.events.length >= data.total) {
1530
+ return [];
1531
+ }
1532
+ return [
1533
+ "",
1534
+ `Showing ${data.events.length} of ${data.total} events (offset ${offset}). Narrow with --name <glob> or page with --offset <n>.`
1535
+ ];
1536
+ };
1537
+ var renderEventsListData = (colors, data, flags) => {
1538
+ const [only] = data.events;
1539
+ if (data.name !== void 0 && !data.name.includes("*") && only !== void 0) {
1540
+ return renderFields(
1541
+ colors.green(`Event: ${only.name}`),
1542
+ [
1543
+ ["Signature", renderEventSignature(only)],
1544
+ ["Description", only.description],
1545
+ ["Payload schema", only.payload_schema]
1546
+ ],
1547
+ flags
1548
+ );
1549
+ }
1550
+ if (data.events.length === 0 && data.total > 0) {
1551
+ return [
1552
+ colors.green("Events"),
1553
+ ` No events at offset ${data.offset ?? 0}; ${data.total} matching event${data.total === 1 ? "" : "s"} in total.`
1554
+ ];
1555
+ }
1556
+ if (data.events.length === 0) {
1557
+ return [
1558
+ colors.green("Events"),
1559
+ data.name === void 0 ? " No events declared." : ` No events match ${JSON.stringify(data.name)}.`
1560
+ ];
1561
+ }
1562
+ const lines = data.events.flatMap((event) => [
1563
+ ` ${renderEventSignature(event)}`,
1564
+ ` ${summarizeToolDescription(event.description)}`
1565
+ ]);
1566
+ return [
1567
+ colors.green("Events"),
1568
+ ...lines,
1569
+ ...renderEventsTruncationLine(data),
1570
+ "",
1571
+ "Run `appduct events ls --name <name>` for an event's full payload schema."
1572
+ ];
1573
+ };
1519
1574
  var renderInvokeData = (colors, data, flags) => {
1520
1575
  return [colors.green("Result"), formatScalar(data, flags)];
1521
1576
  };
@@ -1707,6 +1762,8 @@ var renderSuccessData = (colors, command, data, options) => {
1707
1762
  return renderToolsListData(colors, data, flags, options.full);
1708
1763
  case "tools describe":
1709
1764
  return renderToolDetail(colors, data, flags);
1765
+ case "events ls":
1766
+ return renderEventsListData(colors, data, flags);
1710
1767
  case "tools call":
1711
1768
  return renderInvokeData(colors, data, flags);
1712
1769
  case "sessions revoke":
@@ -1181,6 +1181,7 @@ var formatJson = (value, flags) => {
1181
1181
  import pc from "picocolors";
1182
1182
  import {
1183
1183
  formatAgentWebSocketUrl,
1184
+ renderEventSignature,
1184
1185
  renderToolSignature,
1185
1186
  summarizeToolDescription
1186
1187
  } from "@appduct/shared";
@@ -1276,6 +1277,13 @@ var formatDevice = (device) => {
1276
1277
  const label = parts.length > 0 ? parts.join(" ") : "unknown device";
1277
1278
  return device.os ? `${label} (${device.os})` : label;
1278
1279
  };
1280
+ var SUSPEND_REASON_LABELS = {
1281
+ app_backgrounded: "app in background",
1282
+ connection_lost: "connection lost"
1283
+ };
1284
+ var formatSessionState = (session) => {
1285
+ return session.suspendReason ? `${session.state} (${SUSPEND_REASON_LABELS[session.suspendReason]})` : session.state;
1286
+ };
1279
1287
  var renderLsData = (colors, data, now) => {
1280
1288
  if (data.length === 0) {
1281
1289
  return [colors.dim("Sessions"), " No Appduct sessions are registered."];
@@ -1284,7 +1292,7 @@ var renderLsData = (colors, data, now) => {
1284
1292
  const headers = ["Alias", "State", "Device", "Tools", "Age"];
1285
1293
  const rows = data.map((session) => [
1286
1294
  session.alias,
1287
- session.state,
1295
+ formatSessionState(session),
1288
1296
  formatDevice(session.device),
1289
1297
  String(session.toolCount),
1290
1298
  formatAge(session.claimedAt ?? session.createdAt, nowIso)
@@ -1458,6 +1466,53 @@ var renderToolsListData = (colors, data, flags, full) => {
1458
1466
  }
1459
1467
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1460
1468
  };
1469
+ var renderEventsTruncationLine = (data) => {
1470
+ const offset = data.offset ?? 0;
1471
+ if (data.events.length >= data.total) {
1472
+ return [];
1473
+ }
1474
+ return [
1475
+ "",
1476
+ `Showing ${data.events.length} of ${data.total} events (offset ${offset}). Narrow with --name <glob> or page with --offset <n>.`
1477
+ ];
1478
+ };
1479
+ var renderEventsListData = (colors, data, flags) => {
1480
+ const [only] = data.events;
1481
+ if (data.name !== void 0 && !data.name.includes("*") && only !== void 0) {
1482
+ return renderFields(
1483
+ colors.green(`Event: ${only.name}`),
1484
+ [
1485
+ ["Signature", renderEventSignature(only)],
1486
+ ["Description", only.description],
1487
+ ["Payload schema", only.payload_schema]
1488
+ ],
1489
+ flags
1490
+ );
1491
+ }
1492
+ if (data.events.length === 0 && data.total > 0) {
1493
+ return [
1494
+ colors.green("Events"),
1495
+ ` No events at offset ${data.offset ?? 0}; ${data.total} matching event${data.total === 1 ? "" : "s"} in total.`
1496
+ ];
1497
+ }
1498
+ if (data.events.length === 0) {
1499
+ return [
1500
+ colors.green("Events"),
1501
+ data.name === void 0 ? " No events declared." : ` No events match ${JSON.stringify(data.name)}.`
1502
+ ];
1503
+ }
1504
+ const lines = data.events.flatMap((event) => [
1505
+ ` ${renderEventSignature(event)}`,
1506
+ ` ${summarizeToolDescription(event.description)}`
1507
+ ]);
1508
+ return [
1509
+ colors.green("Events"),
1510
+ ...lines,
1511
+ ...renderEventsTruncationLine(data),
1512
+ "",
1513
+ "Run `appduct events ls --name <name>` for an event's full payload schema."
1514
+ ];
1515
+ };
1461
1516
  var renderInvokeData = (colors, data, flags) => {
1462
1517
  return [colors.green("Result"), formatScalar(data, flags)];
1463
1518
  };
@@ -1649,6 +1704,8 @@ var renderSuccessData = (colors, command, data, options) => {
1649
1704
  return renderToolsListData(colors, data, flags, options.full);
1650
1705
  case "tools describe":
1651
1706
  return renderToolDetail(colors, data, flags);
1707
+ case "events ls":
1708
+ return renderEventsListData(colors, data, flags);
1652
1709
  case "tools call":
1653
1710
  return renderInvokeData(colors, data, flags);
1654
1711
  case "sessions revoke":
@@ -213,6 +213,7 @@ var formatJson = (value, flags) => {
213
213
  import pc from "picocolors";
214
214
  import {
215
215
  formatAgentWebSocketUrl,
216
+ renderEventSignature,
216
217
  renderToolSignature,
217
218
  summarizeToolDescription
218
219
  } from "@appduct/shared";
@@ -308,6 +309,13 @@ var formatDevice = (device) => {
308
309
  const label = parts.length > 0 ? parts.join(" ") : "unknown device";
309
310
  return device.os ? `${label} (${device.os})` : label;
310
311
  };
312
+ var SUSPEND_REASON_LABELS = {
313
+ app_backgrounded: "app in background",
314
+ connection_lost: "connection lost"
315
+ };
316
+ var formatSessionState = (session) => {
317
+ return session.suspendReason ? `${session.state} (${SUSPEND_REASON_LABELS[session.suspendReason]})` : session.state;
318
+ };
311
319
  var renderLsData = (colors, data, now) => {
312
320
  if (data.length === 0) {
313
321
  return [colors.dim("Sessions"), " No Appduct sessions are registered."];
@@ -316,7 +324,7 @@ var renderLsData = (colors, data, now) => {
316
324
  const headers = ["Alias", "State", "Device", "Tools", "Age"];
317
325
  const rows = data.map((session) => [
318
326
  session.alias,
319
- session.state,
327
+ formatSessionState(session),
320
328
  formatDevice(session.device),
321
329
  String(session.toolCount),
322
330
  formatAge(session.claimedAt ?? session.createdAt, nowIso)
@@ -490,6 +498,53 @@ var renderToolsListData = (colors, data, flags, full) => {
490
498
  }
491
499
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
492
500
  };
501
+ var renderEventsTruncationLine = (data) => {
502
+ const offset = data.offset ?? 0;
503
+ if (data.events.length >= data.total) {
504
+ return [];
505
+ }
506
+ return [
507
+ "",
508
+ `Showing ${data.events.length} of ${data.total} events (offset ${offset}). Narrow with --name <glob> or page with --offset <n>.`
509
+ ];
510
+ };
511
+ var renderEventsListData = (colors, data, flags) => {
512
+ const [only] = data.events;
513
+ if (data.name !== void 0 && !data.name.includes("*") && only !== void 0) {
514
+ return renderFields(
515
+ colors.green(`Event: ${only.name}`),
516
+ [
517
+ ["Signature", renderEventSignature(only)],
518
+ ["Description", only.description],
519
+ ["Payload schema", only.payload_schema]
520
+ ],
521
+ flags
522
+ );
523
+ }
524
+ if (data.events.length === 0 && data.total > 0) {
525
+ return [
526
+ colors.green("Events"),
527
+ ` No events at offset ${data.offset ?? 0}; ${data.total} matching event${data.total === 1 ? "" : "s"} in total.`
528
+ ];
529
+ }
530
+ if (data.events.length === 0) {
531
+ return [
532
+ colors.green("Events"),
533
+ data.name === void 0 ? " No events declared." : ` No events match ${JSON.stringify(data.name)}.`
534
+ ];
535
+ }
536
+ const lines = data.events.flatMap((event) => [
537
+ ` ${renderEventSignature(event)}`,
538
+ ` ${summarizeToolDescription(event.description)}`
539
+ ]);
540
+ return [
541
+ colors.green("Events"),
542
+ ...lines,
543
+ ...renderEventsTruncationLine(data),
544
+ "",
545
+ "Run `appduct events ls --name <name>` for an event's full payload schema."
546
+ ];
547
+ };
493
548
  var renderInvokeData = (colors, data, flags) => {
494
549
  return [colors.green("Result"), formatScalar(data, flags)];
495
550
  };
@@ -681,6 +736,8 @@ var renderSuccessData = (colors, command, data, options) => {
681
736
  return renderToolsListData(colors, data, flags, options.full);
682
737
  case "tools describe":
683
738
  return renderToolDetail(colors, data, flags);
739
+ case "events ls":
740
+ return renderEventsListData(colors, data, flags);
684
741
  case "tools call":
685
742
  return renderInvokeData(colors, data, flags);
686
743
  case "sessions revoke":
@@ -1175,6 +1175,7 @@ var formatJson = (value, flags) => {
1175
1175
  import pc from "picocolors";
1176
1176
  import {
1177
1177
  formatAgentWebSocketUrl,
1178
+ renderEventSignature,
1178
1179
  renderToolSignature,
1179
1180
  summarizeToolDescription
1180
1181
  } from "@appduct/shared";
@@ -1270,6 +1271,13 @@ var formatDevice = (device) => {
1270
1271
  const label = parts.length > 0 ? parts.join(" ") : "unknown device";
1271
1272
  return device.os ? `${label} (${device.os})` : label;
1272
1273
  };
1274
+ var SUSPEND_REASON_LABELS = {
1275
+ app_backgrounded: "app in background",
1276
+ connection_lost: "connection lost"
1277
+ };
1278
+ var formatSessionState = (session) => {
1279
+ return session.suspendReason ? `${session.state} (${SUSPEND_REASON_LABELS[session.suspendReason]})` : session.state;
1280
+ };
1273
1281
  var renderLsData = (colors, data, now) => {
1274
1282
  if (data.length === 0) {
1275
1283
  return [colors.dim("Sessions"), " No Appduct sessions are registered."];
@@ -1278,7 +1286,7 @@ var renderLsData = (colors, data, now) => {
1278
1286
  const headers = ["Alias", "State", "Device", "Tools", "Age"];
1279
1287
  const rows = data.map((session) => [
1280
1288
  session.alias,
1281
- session.state,
1289
+ formatSessionState(session),
1282
1290
  formatDevice(session.device),
1283
1291
  String(session.toolCount),
1284
1292
  formatAge(session.claimedAt ?? session.createdAt, nowIso)
@@ -1452,6 +1460,53 @@ var renderToolsListData = (colors, data, flags, full) => {
1452
1460
  }
1453
1461
  return full ? renderToolsFullListing(colors, data, flags) : renderToolSummaryTable(colors, data);
1454
1462
  };
1463
+ var renderEventsTruncationLine = (data) => {
1464
+ const offset = data.offset ?? 0;
1465
+ if (data.events.length >= data.total) {
1466
+ return [];
1467
+ }
1468
+ return [
1469
+ "",
1470
+ `Showing ${data.events.length} of ${data.total} events (offset ${offset}). Narrow with --name <glob> or page with --offset <n>.`
1471
+ ];
1472
+ };
1473
+ var renderEventsListData = (colors, data, flags) => {
1474
+ const [only] = data.events;
1475
+ if (data.name !== void 0 && !data.name.includes("*") && only !== void 0) {
1476
+ return renderFields(
1477
+ colors.green(`Event: ${only.name}`),
1478
+ [
1479
+ ["Signature", renderEventSignature(only)],
1480
+ ["Description", only.description],
1481
+ ["Payload schema", only.payload_schema]
1482
+ ],
1483
+ flags
1484
+ );
1485
+ }
1486
+ if (data.events.length === 0 && data.total > 0) {
1487
+ return [
1488
+ colors.green("Events"),
1489
+ ` No events at offset ${data.offset ?? 0}; ${data.total} matching event${data.total === 1 ? "" : "s"} in total.`
1490
+ ];
1491
+ }
1492
+ if (data.events.length === 0) {
1493
+ return [
1494
+ colors.green("Events"),
1495
+ data.name === void 0 ? " No events declared." : ` No events match ${JSON.stringify(data.name)}.`
1496
+ ];
1497
+ }
1498
+ const lines = data.events.flatMap((event) => [
1499
+ ` ${renderEventSignature(event)}`,
1500
+ ` ${summarizeToolDescription(event.description)}`
1501
+ ]);
1502
+ return [
1503
+ colors.green("Events"),
1504
+ ...lines,
1505
+ ...renderEventsTruncationLine(data),
1506
+ "",
1507
+ "Run `appduct events ls --name <name>` for an event's full payload schema."
1508
+ ];
1509
+ };
1455
1510
  var renderInvokeData = (colors, data, flags) => {
1456
1511
  return [colors.green("Result"), formatScalar(data, flags)];
1457
1512
  };
@@ -1643,6 +1698,8 @@ var renderSuccessData = (colors, command, data, options) => {
1643
1698
  return renderToolsListData(colors, data, flags, options.full);
1644
1699
  case "tools describe":
1645
1700
  return renderToolDetail(colors, data, flags);
1701
+ case "events ls":
1702
+ return renderEventsListData(colors, data, flags);
1646
1703
  case "tools call":
1647
1704
  return renderInvokeData(colors, data, flags);
1648
1705
  case "sessions revoke":
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `appduct events ls [selector] [--name <glob>] [--limit <n>] [--offset <n>]` (issue #124): lists the events an app declared,
3
+ * from the daemon's `events.list`. The listing carries each event's full descriptor, so `--json`
4
+ * has the payload schemas too; the human renderer prints signature lines, and the full schema when
5
+ * `--name` is an exact name (no `*`) that matched an event.
6
+ */
7
+ import type { CliResult, EventsListing } from "../cli/result-types.js";
8
+ import { type SpawnFn } from "../rpc/client.js";
9
+ export type EventsLsOptions = {
10
+ selector?: string;
11
+ /** Whole-name, case-sensitive glob, forwarded to `events.list`. */
12
+ name?: string;
13
+ /** Page size; omitted lists everything from `offset` on. */
14
+ limit?: number;
15
+ /** Zero-based start index into the name-sorted, filtered list. */
16
+ offset?: number;
17
+ };
18
+ export declare const handleEventsLsCommand: (options: EventsLsOptions, context: {
19
+ stateDir: string;
20
+ spawn?: SpawnFn;
21
+ }) => Promise<CliResult<EventsListing>>;
@@ -66,7 +66,9 @@ export type CallsManager = {
66
66
  * session has no active socket to send the frame on right now. */
67
67
  cancel: (sessionId: string, callId: string, reason: string) => boolean;
68
68
  /** Rejects every pending call for a session immediately (suspend/revoke/expiry transitions). */
69
- rejectSession: (sessionId: string, errorType: "session_suspended" | "unknown_session") => void;
69
+ rejectSession: (sessionId: string, errorType: "session_suspended" | "unknown_session", options?: {
70
+ backgrounded?: boolean;
71
+ }) => void;
70
72
  /** Rejects and clears every pending call across every session (daemon shutdown). */
71
73
  disposeAll: () => void;
72
74
  };