@holon-run/agentinbox 1.0.3 → 1.0.4

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/src/cli.js CHANGED
@@ -57,7 +57,7 @@ async function main() {
57
57
  printHelp([command]);
58
58
  return;
59
59
  }
60
- const client = await createClient(normalized);
60
+ const client = await createClient(clientArgsForCommand(normalized));
61
61
  if (command === "host" && normalized[1] === "add") {
62
62
  const [hostType, hostKey] = normalized.slice(2, 4);
63
63
  if (!hostType || !hostKey) {
@@ -72,7 +72,10 @@ async function main() {
72
72
  return;
73
73
  }
74
74
  if (command === "host" && normalized[1] === "list") {
75
- await printRemote(client, "/hosts", undefined, "GET");
75
+ const query = buildQuery({
76
+ limit: parseOptionalLimitArg(normalized),
77
+ });
78
+ await printRemote(client, `/hosts${query}`, undefined, "GET");
76
79
  return;
77
80
  }
78
81
  if (command === "host" && normalized[1] === "show") {
@@ -106,7 +109,10 @@ async function main() {
106
109
  return;
107
110
  }
108
111
  if (command === "stream" && normalized[1] === "list") {
109
- await printRemote(client, "/streams", undefined, "GET");
112
+ const query = buildQuery({
113
+ limit: parseOptionalLimitArg(normalized),
114
+ });
115
+ await printRemote(client, `/streams${query}`, undefined, "GET");
110
116
  return;
111
117
  }
112
118
  if (command === "stream" && normalized[1] === "show") {
@@ -266,7 +272,10 @@ async function main() {
266
272
  return;
267
273
  }
268
274
  if (command === "source" && normalized[1] === "list") {
269
- await printRemote(client, "/sources", undefined, "GET");
275
+ const query = buildQuery({
276
+ limit: parseOptionalLimitArg(normalized),
277
+ });
278
+ await printRemote(client, `/sources${query}`, undefined, "GET");
270
279
  return;
271
280
  }
272
281
  if (command === "source" && normalized[1] === "show") {
@@ -363,15 +372,18 @@ async function main() {
363
372
  const notifyLeaseMs = parseOptionalNumber(takeFlagValue(normalized, "--notify-lease-ms")) ?? undefined;
364
373
  const minUnackedItems = parseOptionalNumber(takeFlagValue(normalized, "--min-unacked-items")) ?? undefined;
365
374
  const webhookUrl = takeFlagValue(normalized, "--webhook-url");
375
+ const holonContext = (0, current_agent_1.detectHolonRuntimeContext)(process.env);
366
376
  if (webhookUrl) {
367
- if (!agentId) {
368
- throw new Error("usage: agentinbox agent register --agent-id ID --webhook-url URL [--webhook-activation-mode MODE] [--webhook-notify-lease-ms N] [--webhook-min-unacked-items N]");
377
+ const resolvedAgentId = agentId ?? holonContext?.agentId;
378
+ if (!resolvedAgentId) {
379
+ throw new Error("usage: agentinbox agent register --agent-id ID --webhook-url URL [--webhook-activation-mode MODE] [--webhook-notify-lease-ms N] [--webhook-min-unacked-items N] (or set HOLON_AGENT_ID in Holon)");
369
380
  }
370
381
  const webhookNotifyLeaseMs = parseOptionalNumber(takeFlagValue(normalized, "--webhook-notify-lease-ms")) ?? notifyLeaseMs;
371
382
  const webhookMinUnackedItems = parseOptionalNumber(takeFlagValue(normalized, "--webhook-min-unacked-items")) ?? minUnackedItems;
372
383
  await printRemote(client, "/agents", {
373
- agentId,
384
+ agentId: resolvedAgentId,
374
385
  forceRebind: normalized.includes("--force-rebind"),
386
+ ...(holonContext ? { runtimeKind: holonContext.runtimeKind } : {}),
375
387
  webhook: {
376
388
  url: webhookUrl,
377
389
  activationMode: takeFlagValue(normalized, "--webhook-activation-mode") ?? undefined,
@@ -381,6 +393,28 @@ async function main() {
381
393
  });
382
394
  return;
383
395
  }
396
+ if ((0, current_agent_1.isHolonRuntimeEnv)(process.env)) {
397
+ if (!holonContext) {
398
+ throw new Error("agent register in Holon requires HOLON_AGENT_ID");
399
+ }
400
+ if (!holonContext.externalTriggerUrl) {
401
+ throw new Error("agent register in Holon requires --webhook-url or HOLON_EXTERNAL_TRIGGER_URL");
402
+ }
403
+ const webhookNotifyLeaseMs = parseOptionalNumber(takeFlagValue(normalized, "--webhook-notify-lease-ms")) ?? notifyLeaseMs;
404
+ const webhookMinUnackedItems = parseOptionalNumber(takeFlagValue(normalized, "--webhook-min-unacked-items")) ?? minUnackedItems;
405
+ await printRemote(client, "/agents", {
406
+ agentId: agentId ?? holonContext.agentId,
407
+ forceRebind: normalized.includes("--force-rebind"),
408
+ runtimeKind: holonContext.runtimeKind,
409
+ webhook: {
410
+ url: holonContext.externalTriggerUrl,
411
+ activationMode: takeFlagValue(normalized, "--webhook-activation-mode") ?? undefined,
412
+ notifyLeaseMs: webhookNotifyLeaseMs,
413
+ minUnackedItems: webhookMinUnackedItems,
414
+ },
415
+ });
416
+ return;
417
+ }
384
418
  const detected = (0, terminal_1.detectTerminalContext)(process.env);
385
419
  await printRemote(client, "/agents", {
386
420
  agentId,
@@ -399,7 +433,7 @@ async function main() {
399
433
  return;
400
434
  }
401
435
  if (command === "agent" && normalized[1] === "list") {
402
- await printAgentList(client);
436
+ await printAgentList(client, parseOptionalLimitArg(normalized));
403
437
  return;
404
438
  }
405
439
  if (command === "agent" && normalized[1] === "current") {
@@ -448,9 +482,12 @@ async function main() {
448
482
  if (command === "agent" && normalized[1] === "target" && normalized[2] === "list") {
449
483
  const agentId = normalized[3];
450
484
  if (!agentId) {
451
- throw new Error("usage: agentinbox agent target list <agentId>");
485
+ throw new Error("usage: agentinbox agent target list <agentId> [--limit N]");
452
486
  }
453
- await printRemote(client, `/agents/${encodeURIComponent(agentId)}/targets`, undefined, "GET");
487
+ const query = buildQuery({
488
+ limit: parseOptionalLimitArg(normalized),
489
+ });
490
+ await printRemote(client, `/agents/${encodeURIComponent(agentId)}/targets${query}`, undefined, "GET");
454
491
  return;
455
492
  }
456
493
  if (command === "agent" && normalized[1] === "target" && normalized[2] === "remove") {
@@ -522,6 +559,7 @@ async function main() {
522
559
  const query = buildQuery({
523
560
  source_id: takeFlagValue(normalized, "--source-id"),
524
561
  agent_id: takeFlagValue(normalized, "--agent-id"),
562
+ limit: parseOptionalLimitArg(normalized),
525
563
  });
526
564
  await printRemote(client, `/subscriptions${query}`, undefined, "GET");
527
565
  return;
@@ -599,6 +637,7 @@ async function main() {
599
637
  if (command === "timer" && normalized[1] === "list") {
600
638
  const query = buildQuery({
601
639
  agent_id: takeFlagValue(normalized, "--agent-id"),
640
+ limit: parseOptionalLimitArg(normalized),
602
641
  });
603
642
  await printRemote(client, `/timers${query}`, undefined, "GET");
604
643
  return;
@@ -628,7 +667,10 @@ async function main() {
628
667
  return;
629
668
  }
630
669
  if (command === "inbox" && normalized[1] === "list") {
631
- await printRemote(client, "/agents", undefined, "GET");
670
+ const query = buildQuery({
671
+ limit: parseOptionalLimitArg(normalized),
672
+ });
673
+ await printRemote(client, `/agents${query}`, undefined, "GET");
632
674
  return;
633
675
  }
634
676
  if (command === "inbox" && normalized[1] === "show") {
@@ -641,9 +683,9 @@ async function main() {
641
683
  }
642
684
  if (command === "inbox" && normalized[1] === "read") {
643
685
  const args = normalized.slice(2);
644
- const allowedFlags = ["--agent-id", "--after-entry", "--include-acked"];
645
- if (positionalArgs(args, ["--agent-id", "--after-entry"]).length > 0 || unexpectedFlags(args, allowedFlags).length > 0) {
646
- throw new Error("usage: agentinbox inbox read [--agent-id ID] [--after-entry ID] [--include-acked]");
686
+ const allowedFlags = ["--agent-id", "--after-entry", "--include-acked", "--limit"];
687
+ if (positionalArgs(args, ["--agent-id", "--after-entry", "--limit"]).length > 0 || unexpectedFlags(args, allowedFlags).length > 0) {
688
+ throw new Error("usage: agentinbox inbox read [--agent-id ID] [--after-entry ID] [--include-acked] [--limit N]");
647
689
  }
648
690
  const selection = await selectAgentForCommand(client, {
649
691
  explicitAgentId: takeFlagValue(normalized, "--agent-id"),
@@ -652,6 +694,7 @@ async function main() {
652
694
  const query = buildQuery({
653
695
  after_entry_id: takeFlagValue(normalized, "--after-entry"),
654
696
  include_acked: hasFlag(normalized, "--include-acked") ? "true" : undefined,
697
+ limit: parseOptionalLimitArg(normalized),
655
698
  });
656
699
  const response = await requestRemote(client, `/agents/${encodeURIComponent(selection.agentId)}/inbox/entries${query}`, undefined, "GET");
657
700
  console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
@@ -925,12 +968,12 @@ async function createClient(args) {
925
968
  });
926
969
  return new client_1.AgentInboxClient(transport);
927
970
  }
928
- async function printAgentList(client) {
929
- const records = await listAgentsWithTargets(client);
930
- console.log((0, util_1.jsonResponse)((0, current_agent_1.annotateAgents)(records, tryDetectTerminalContext())));
971
+ async function printAgentList(client, limit) {
972
+ const records = await listAgentsWithTargets(client, limit);
973
+ console.log((0, util_1.jsonResponse)((0, current_agent_1.annotateAgents)(records, tryDetectCurrentAgentContext())));
931
974
  }
932
975
  async function printCurrentAgent(client) {
933
- const context = getRequiredTerminalContext();
976
+ const context = getRequiredCurrentAgentContext();
934
977
  const records = await listAgentsWithTargets(client);
935
978
  const current = (0, current_agent_1.resolveCurrentAgent)(records, context);
936
979
  if (!current) {
@@ -940,7 +983,7 @@ async function printCurrentAgent(client) {
940
983
  }
941
984
  async function selectAgentForCommand(client, options) {
942
985
  const records = await listAgentsWithTargets(client);
943
- const context = tryDetectTerminalContext();
986
+ const context = tryDetectCurrentAgentContext();
944
987
  if (options.explicitAgentId) {
945
988
  const current = context ? (0, current_agent_1.resolveCurrentAgent)(records, context) : null;
946
989
  const requested = records.find((entry) => entry.agent.agentId === options.explicitAgentId);
@@ -960,7 +1003,7 @@ async function selectAgentForCommand(client, options) {
960
1003
  warnings,
961
1004
  };
962
1005
  }
963
- const contextForCurrent = getRequiredTerminalContext();
1006
+ const contextForCurrent = getRequiredCurrentAgentContext();
964
1007
  const current = (0, current_agent_1.resolveCurrentAgent)(records, contextForCurrent);
965
1008
  if (current) {
966
1009
  return {
@@ -972,17 +1015,7 @@ async function selectAgentForCommand(client, options) {
972
1015
  if (!options.autoRegister) {
973
1016
  throw new Error(noCurrentAgentMessage());
974
1017
  }
975
- await requestRemote(client, "/agents", {
976
- backend: contextForCurrent.backend,
977
- runtimeKind: contextForCurrent.runtimeKind,
978
- runtimeSessionId: contextForCurrent.runtimeSessionId ?? undefined,
979
- runtimePid: contextForCurrent.runtimePid ?? undefined,
980
- tmuxPaneId: contextForCurrent.tmuxPaneId ?? undefined,
981
- tty: contextForCurrent.tty ?? undefined,
982
- termProgram: contextForCurrent.termProgram ?? undefined,
983
- itermSessionId: contextForCurrent.itermSessionId ?? undefined,
984
- notifyLeaseMs: undefined,
985
- });
1018
+ await requestRemote(client, "/agents", registrationInputForCurrentContext(contextForCurrent));
986
1019
  const refreshed = await listAgentsWithTargets(client);
987
1020
  const registered = (0, current_agent_1.resolveCurrentAgent)(refreshed, contextForCurrent);
988
1021
  if (!registered) {
@@ -994,8 +1027,38 @@ async function selectAgentForCommand(client, options) {
994
1027
  warnings: [],
995
1028
  };
996
1029
  }
997
- async function listAgentsWithTargets(client) {
998
- const response = await requestRemote(client, "/agents?include_targets=true", undefined, "GET");
1030
+ function registrationInputForCurrentContext(context) {
1031
+ if ((0, current_agent_1.isHolonRuntimeContext)(context)) {
1032
+ if (!context.externalTriggerUrl) {
1033
+ throw new Error("unable to auto-register current Holon agent: HOLON_EXTERNAL_TRIGGER_URL is not set");
1034
+ }
1035
+ return {
1036
+ agentId: context.agentId,
1037
+ runtimeKind: context.runtimeKind,
1038
+ webhook: {
1039
+ url: context.externalTriggerUrl,
1040
+ notifyLeaseMs: undefined,
1041
+ },
1042
+ };
1043
+ }
1044
+ return {
1045
+ backend: context.backend,
1046
+ runtimeKind: context.runtimeKind,
1047
+ runtimeSessionId: context.runtimeSessionId ?? undefined,
1048
+ runtimePid: context.runtimePid ?? undefined,
1049
+ tmuxPaneId: context.tmuxPaneId ?? undefined,
1050
+ tty: context.tty ?? undefined,
1051
+ termProgram: context.termProgram ?? undefined,
1052
+ itermSessionId: context.itermSessionId ?? undefined,
1053
+ notifyLeaseMs: undefined,
1054
+ };
1055
+ }
1056
+ async function listAgentsWithTargets(client, limit) {
1057
+ const query = buildQuery({
1058
+ include_targets: "true",
1059
+ limit,
1060
+ });
1061
+ const response = await requestRemote(client, `/agents${query}`, undefined, "GET");
999
1062
  return response.data.agents;
1000
1063
  }
1001
1064
  async function printRemote(client, endpoint, body, method = "POST") {
@@ -1005,13 +1068,38 @@ async function printRemote(client, endpoint, body, method = "POST") {
1005
1068
  async function requestRemote(client, endpoint, body, method = "POST") {
1006
1069
  const response = await client.request(endpoint, body, method);
1007
1070
  if (response.statusCode < 200 || response.statusCode >= 300) {
1008
- throw new Error((0, util_1.jsonResponse)(response.data));
1071
+ const bodyText = (0, util_1.jsonResponse)(response.data);
1072
+ throw new Error(`request ${method} ${endpoint} failed with HTTP ${response.statusCode}: ${bodyText}`);
1009
1073
  }
1010
1074
  return { data: response.data };
1011
1075
  }
1012
1076
  function noCurrentAgentMessage() {
1013
1077
  return "no current agent is registered for this terminal/runtime context; run `agentinbox agent list` to inspect offline agents, then `agentinbox agent register` or `agentinbox agent register --force-rebind --agent-id <agentId>` to rebind one";
1014
1078
  }
1079
+ function clientArgsForCommand(args) {
1080
+ if (isAgentTargetAddWebhookCommand(args)) {
1081
+ return withoutFlagValues(args, "--url");
1082
+ }
1083
+ return args;
1084
+ }
1085
+ function isAgentTargetAddWebhookCommand(args) {
1086
+ return args[0] === "agent" && args[1] === "target" && args[2] === "add" && args[3] === "webhook";
1087
+ }
1088
+ function withoutFlagValues(args, flag) {
1089
+ const filtered = [];
1090
+ for (let index = 0; index < args.length; index += 1) {
1091
+ const value = args[index];
1092
+ if (value !== flag) {
1093
+ filtered.push(value);
1094
+ continue;
1095
+ }
1096
+ const nextIndex = index + 1;
1097
+ if (nextIndex < args.length && !args[nextIndex].startsWith("--")) {
1098
+ index = nextIndex;
1099
+ }
1100
+ }
1101
+ return filtered;
1102
+ }
1015
1103
  function takeFlagValue(args, flag) {
1016
1104
  const index = args.indexOf(flag);
1017
1105
  if (index === -1) {
@@ -1102,6 +1190,17 @@ function buildQuery(params) {
1102
1190
  const query = search.toString();
1103
1191
  return query ? `?${query}` : "";
1104
1192
  }
1193
+ function parseOptionalLimitArg(args) {
1194
+ const raw = takeFlagValue(args, "--limit");
1195
+ if (raw === undefined) {
1196
+ return undefined;
1197
+ }
1198
+ const parsed = Number.parseInt(raw, 10);
1199
+ if (!Number.isFinite(parsed) || parsed < 1 || String(parsed) !== raw) {
1200
+ throw new Error("`--limit` must be a positive integer");
1201
+ }
1202
+ return String(parsed);
1203
+ }
1105
1204
  function readSubscriptionFilter(args) {
1106
1205
  const filterJson = takeFlagValue(args, "--filter-json");
1107
1206
  const filterFile = takeFlagValue(args, "--filter-file");
@@ -1193,7 +1292,14 @@ function normalizeSubscriptionAddOutput(data, shortcutUsed) {
1193
1292
  }
1194
1293
  return data;
1195
1294
  }
1196
- function getRequiredTerminalContext() {
1295
+ function getRequiredCurrentAgentContext() {
1296
+ const holonContext = (0, current_agent_1.detectHolonRuntimeContext)(process.env);
1297
+ if (holonContext) {
1298
+ return holonContext;
1299
+ }
1300
+ if ((0, current_agent_1.isHolonRuntimeEnv)(process.env)) {
1301
+ throw new Error("unable to detect current Holon agent: HOLON_AGENT_ID is not set");
1302
+ }
1197
1303
  try {
1198
1304
  return (0, terminal_1.detectTerminalContext)(process.env);
1199
1305
  }
@@ -1202,7 +1308,11 @@ function getRequiredTerminalContext() {
1202
1308
  throw new Error(`unable to resolve current agent: ${message}`);
1203
1309
  }
1204
1310
  }
1205
- function tryDetectTerminalContext() {
1311
+ function tryDetectCurrentAgentContext() {
1312
+ const holonContext = (0, current_agent_1.detectHolonRuntimeContext)(process.env);
1313
+ if (holonContext || (0, current_agent_1.isHolonRuntimeEnv)(process.env)) {
1314
+ return holonContext;
1315
+ }
1206
1316
  try {
1207
1317
  return (0, terminal_1.detectTerminalContext)(process.env);
1208
1318
  }
@@ -1277,7 +1387,7 @@ Usage:
1277
1387
 
1278
1388
  Usage:
1279
1389
  agentinbox host add <hostType> <hostKey> [--config-json JSON] [--config-ref REF]
1280
- agentinbox host list
1390
+ agentinbox host list [--limit N]
1281
1391
  agentinbox host show <hostId>
1282
1392
  agentinbox host schema <hostId>
1283
1393
  `,
@@ -1285,7 +1395,7 @@ Usage:
1285
1395
 
1286
1396
  Usage:
1287
1397
  agentinbox stream add <hostId> <streamKind> <streamKey> [--config-json JSON] [--config-ref REF]
1288
- agentinbox stream list
1398
+ agentinbox stream list [--limit N]
1289
1399
  agentinbox stream show <streamId>
1290
1400
  agentinbox stream update <streamId> [--config-json JSON] [--config-ref REF | --clear-config-ref]
1291
1401
  agentinbox stream remove <streamId> [--with-subscriptions]
@@ -1310,7 +1420,7 @@ Examples:
1310
1420
 
1311
1421
  Usage:
1312
1422
  agentinbox source add <hostId> <streamKind> <streamKey> [--config-json JSON] [--config-ref REF]
1313
- agentinbox source list
1423
+ agentinbox source list [--limit N]
1314
1424
  agentinbox source show <sourceId>
1315
1425
  agentinbox source update <sourceId> [--config-json JSON] [--config-ref REF | --clear-config-ref]
1316
1426
  agentinbox source remove <sourceId> [--with-subscriptions]
@@ -1325,13 +1435,13 @@ Usage:
1325
1435
  Usage:
1326
1436
  agentinbox agent register [--agent-id ID] [--force-rebind] [--notify-lease-ms N] [--min-unacked-items N]
1327
1437
  agentinbox agent register --agent-id ID --webhook-url URL [--webhook-activation-mode MODE] [--webhook-notify-lease-ms N] [--webhook-min-unacked-items N]
1328
- agentinbox agent list
1438
+ agentinbox agent list [--limit N]
1329
1439
  agentinbox agent current
1330
1440
  agentinbox agent show <agentId>
1331
1441
  agentinbox agent remove <agentId>
1332
1442
  agentinbox agent resume <agentId>
1333
1443
  agentinbox agent target add webhook <agentId> --url URL [--activation-mode MODE] [--notify-lease-ms N] [--min-unacked-items N]
1334
- agentinbox agent target list <agentId>
1444
+ agentinbox agent target list <agentId> [--limit N]
1335
1445
  agentinbox agent target remove <agentId> <targetId>
1336
1446
  agentinbox agent target resume <agentId> <targetId>
1337
1447
  `,
@@ -1339,7 +1449,7 @@ Usage:
1339
1449
 
1340
1450
  Usage:
1341
1451
  agentinbox timer add --agent-id ID (--at ISO8601 | --every DURATION | --cron EXPR) --message TEXT [--timezone TZ] [--sender SENDER]
1342
- agentinbox timer list [--agent-id ID]
1452
+ agentinbox timer list [--agent-id ID] [--limit N]
1343
1453
  agentinbox timer pause <scheduleId>
1344
1454
  agentinbox timer resume <scheduleId>
1345
1455
  agentinbox timer remove <scheduleId>
@@ -1348,7 +1458,7 @@ Usage:
1348
1458
 
1349
1459
  Usage:
1350
1460
  agentinbox subscription add <sourceId> [--agent-id ID] [--shortcut NAME --shortcut-args-json JSON] [--filter-json JSON | --filter-file PATH | --filter-stdin] [--tracked-resource-ref REF] [--cleanup-policy-json JSON] [--start-policy POLICY] [--start-offset N] [--start-time ISO8601]
1351
- agentinbox subscription list [--source-id ID] [--agent-id ID]
1461
+ agentinbox subscription list [--source-id ID] [--agent-id ID] [--limit N]
1352
1462
  agentinbox subscription show <subscriptionId>
1353
1463
  agentinbox subscription remove <subscriptionId>
1354
1464
  agentinbox subscription poll <subscriptionId>
@@ -1358,9 +1468,9 @@ Usage:
1358
1468
  inbox: `agentinbox inbox
1359
1469
 
1360
1470
  Usage:
1361
- agentinbox inbox list
1471
+ agentinbox inbox list [--limit N]
1362
1472
  agentinbox inbox show <agentId>
1363
- agentinbox inbox read [--agent-id ID] [--after-entry ID] [--include-acked]
1473
+ agentinbox inbox read [--agent-id ID] [--after-entry ID] [--include-acked] [--limit N]
1364
1474
  agentinbox inbox send --agent-id ID --message TEXT [--sender SENDER]
1365
1475
  agentinbox inbox watch [--agent-id ID] [--after-entry ID] [--include-acked] [--heartbeat-ms N]
1366
1476
  agentinbox inbox ack [--agent-id ID] (--through <entryId> | --entry <entryId> | --all)
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.summarizeActivationTarget = summarizeActivationTarget;
4
+ exports.isHolonRuntimeEnv = isHolonRuntimeEnv;
5
+ exports.detectHolonRuntimeContext = detectHolonRuntimeContext;
4
6
  exports.resolveCurrentAgent = resolveCurrentAgent;
5
7
  exports.annotateAgents = annotateAgents;
8
+ exports.isHolonRuntimeContext = isHolonRuntimeContext;
6
9
  function summarizeActivationTarget(target) {
7
10
  if (target.kind === "terminal") {
8
11
  return {
@@ -25,6 +28,19 @@ function summarizeActivationTarget(target) {
25
28
  status: target.status,
26
29
  };
27
30
  }
31
+ function isHolonRuntimeEnv(env = process.env) {
32
+ return normalizeOptionalString(env.HOLON_RUNTIME) === "1";
33
+ }
34
+ function detectHolonRuntimeContext(env = process.env) {
35
+ if (!isHolonRuntimeEnv(env)) {
36
+ return null;
37
+ }
38
+ const agentId = normalizeOptionalString(env.HOLON_AGENT_ID);
39
+ if (!agentId) {
40
+ return null;
41
+ }
42
+ return { runtimeKind: "holon", agentId, externalTriggerUrl: normalizeOptionalString(env.HOLON_EXTERNAL_TRIGGER_URL) };
43
+ }
28
44
  function resolveCurrentAgent(agents, context) {
29
45
  if (!context) {
30
46
  return null;
@@ -62,6 +78,9 @@ function annotateAgents(agents, context) {
62
78
  };
63
79
  }
64
80
  function resolveAgentRecord(agents, context) {
81
+ if (isHolonRuntimeContext(context)) {
82
+ return agents.find((agent) => agent.agent.status === "active" && agent.agent.agentId === context.agentId) ?? null;
83
+ }
65
84
  if (context.tmuxPaneId) {
66
85
  const match = agents.find((agent) => terminalTargetsForCurrentMatch(agent).some((target) => target.backend === "tmux" && target.tmuxPaneId === context.tmuxPaneId));
67
86
  if (match) {
@@ -129,6 +148,9 @@ function terminalIdentityForAgent(agent) {
129
148
  return null;
130
149
  }
131
150
  function matchesCurrentTerminal(agent, context) {
151
+ if (isHolonRuntimeContext(context)) {
152
+ return false;
153
+ }
132
154
  return terminalTargetsForCurrentMatch(agent).some((target) => (context.tmuxPaneId != null && target.tmuxPaneId === context.tmuxPaneId)
133
155
  || (context.itermSessionId != null && target.itermSessionId === context.itermSessionId)
134
156
  || (context.tty != null && target.tty === context.tty));
@@ -137,9 +159,18 @@ function matchesCurrentRuntime(agent, context) {
137
159
  if (agent.agent.status !== "active") {
138
160
  return false;
139
161
  }
162
+ if (isHolonRuntimeContext(context)) {
163
+ return agent.agent.agentId === context.agentId;
164
+ }
140
165
  if (!context.runtimeSessionId) {
141
166
  return false;
142
167
  }
143
168
  return activeTerminalTargets(agent).some((target) => target.runtimeKind === context.runtimeKind && target.runtimeSessionId === context.runtimeSessionId) || (agent.agent.runtimeKind === context.runtimeKind
144
169
  && agent.agent.runtimeSessionId === context.runtimeSessionId);
145
170
  }
171
+ function isHolonRuntimeContext(context) {
172
+ return context.runtimeKind === "holon" && "agentId" in context;
173
+ }
174
+ function normalizeOptionalString(value) {
175
+ return value?.trim() || null;
176
+ }
package/dist/src/http.js CHANGED
@@ -133,6 +133,13 @@ function buildFastifyServer(service) {
133
133
  app.get("/hosts", {
134
134
  schema: {
135
135
  tags: ["sources"],
136
+ querystring: {
137
+ type: "object",
138
+ additionalProperties: false,
139
+ properties: {
140
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
141
+ },
142
+ },
136
143
  response: {
137
144
  200: {
138
145
  type: "object",
@@ -143,7 +150,10 @@ function buildFastifyServer(service) {
143
150
  },
144
151
  },
145
152
  },
146
- }, async () => ({ hosts: service.listHosts() }));
153
+ }, async (request) => {
154
+ const query = request.query;
155
+ return { hosts: service.listHosts(parseOptionalPositiveInteger(query.limit)) };
156
+ });
147
157
  app.post("/hosts", {
148
158
  schema: {
149
159
  tags: ["sources"],
@@ -206,6 +216,13 @@ function buildFastifyServer(service) {
206
216
  app.get("/streams", {
207
217
  schema: {
208
218
  tags: ["sources"],
219
+ querystring: {
220
+ type: "object",
221
+ additionalProperties: false,
222
+ properties: {
223
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
224
+ },
225
+ },
209
226
  response: {
210
227
  200: {
211
228
  type: "object",
@@ -216,7 +233,10 @@ function buildFastifyServer(service) {
216
233
  },
217
234
  },
218
235
  },
219
- }, async () => ({ streams: service.listStreams() }));
236
+ }, async (request) => {
237
+ const query = request.query;
238
+ return { streams: service.listStreams(parseOptionalPositiveInteger(query.limit)) };
239
+ });
220
240
  app.post("/streams", {
221
241
  schema: {
222
242
  tags: ["sources"],
@@ -280,6 +300,13 @@ function buildFastifyServer(service) {
280
300
  app.get("/sources", {
281
301
  schema: {
282
302
  tags: ["sources"],
303
+ querystring: {
304
+ type: "object",
305
+ additionalProperties: false,
306
+ properties: {
307
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
308
+ },
309
+ },
283
310
  response: {
284
311
  200: {
285
312
  type: "object",
@@ -290,7 +317,10 @@ function buildFastifyServer(service) {
290
317
  },
291
318
  },
292
319
  },
293
- }, async () => ({ sources: await service.listSourceViews() }));
320
+ }, async (request) => {
321
+ const query = request.query;
322
+ return { sources: await service.listSourceViews(parseOptionalPositiveInteger(query.limit)) };
323
+ });
294
324
  app.post("/sources", {
295
325
  schema: {
296
326
  tags: ["sources"],
@@ -548,6 +578,7 @@ function buildFastifyServer(service) {
548
578
  occurredAt: { type: "string", minLength: 1 },
549
579
  metadata: jsonObjectSchema,
550
580
  rawPayload: jsonObjectSchema,
581
+ providerRawPayload: jsonObjectSchema,
551
582
  },
552
583
  },
553
584
  response: {
@@ -564,6 +595,7 @@ function buildFastifyServer(service) {
564
595
  occurredAt: body.occurredAt,
565
596
  metadata: body.metadata ?? {},
566
597
  rawPayload: body.rawPayload ?? {},
598
+ providerRawPayload: body.providerRawPayload,
567
599
  });
568
600
  });
569
601
  app.delete("/sources/:sourceId", {
@@ -702,6 +734,7 @@ function buildFastifyServer(service) {
702
734
  occurredAt: { type: "string", minLength: 1 },
703
735
  metadata: jsonObjectSchema,
704
736
  rawPayload: jsonObjectSchema,
737
+ providerRawPayload: jsonObjectSchema,
705
738
  deliveryHandle: deliveryHandleSchema,
706
739
  },
707
740
  },
@@ -719,6 +752,7 @@ function buildFastifyServer(service) {
719
752
  occurredAt: optionalString(body.occurredAt),
720
753
  metadata: body.metadata ?? {},
721
754
  rawPayload: body.rawPayload ?? {},
755
+ providerRawPayload: body.providerRawPayload,
722
756
  deliveryHandle: body.deliveryHandle ?? null,
723
757
  });
724
758
  });
@@ -730,6 +764,7 @@ function buildFastifyServer(service) {
730
764
  additionalProperties: false,
731
765
  properties: {
732
766
  include_targets: { type: "string", enum: ["true", "false"] },
767
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
733
768
  },
734
769
  },
735
770
  response: {
@@ -744,17 +779,10 @@ function buildFastifyServer(service) {
744
779
  },
745
780
  }, async (request) => {
746
781
  const query = request.query;
747
- const agents = service.listAgents();
782
+ const agents = service.listAgents(parseOptionalPositiveInteger(query.limit));
748
783
  if (query.include_targets === "true") {
749
- const activationTargetsByAgentId = service.listActivationTargets().reduce((grouped, target) => {
750
- const targets = grouped.get(target.agentId);
751
- const summarized = (0, current_agent_1.summarizeActivationTarget)(target);
752
- if (targets) {
753
- targets.push(summarized);
754
- }
755
- else {
756
- grouped.set(target.agentId, [summarized]);
757
- }
784
+ const activationTargetsByAgentId = agents.reduce((grouped, agent) => {
785
+ grouped.set(agent.agentId, service.listActivationTargets(agent.agentId).map((target) => (0, current_agent_1.summarizeActivationTarget)(target)));
758
786
  return grouped;
759
787
  }, new Map());
760
788
  return {
@@ -920,6 +948,13 @@ function buildFastifyServer(service) {
920
948
  agentId: { type: "string", minLength: 1 },
921
949
  },
922
950
  },
951
+ querystring: {
952
+ type: "object",
953
+ additionalProperties: false,
954
+ properties: {
955
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
956
+ },
957
+ },
923
958
  response: {
924
959
  200: {
925
960
  type: "object",
@@ -932,7 +967,8 @@ function buildFastifyServer(service) {
932
967
  },
933
968
  }, async (request) => {
934
969
  const params = request.params;
935
- return { targets: service.listActivationTargets(decodeURIComponent(params.agentId)) };
970
+ const query = request.query;
971
+ return { targets: service.listActivationTargets(decodeURIComponent(params.agentId), parseOptionalPositiveInteger(query.limit)) };
936
972
  });
937
973
  app.post("/agents/:agentId/targets", {
938
974
  schema: {
@@ -1017,6 +1053,7 @@ function buildFastifyServer(service) {
1017
1053
  additionalProperties: false,
1018
1054
  properties: {
1019
1055
  agent_id: { type: "string" },
1056
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
1020
1057
  },
1021
1058
  },
1022
1059
  response: {
@@ -1031,7 +1068,7 @@ function buildFastifyServer(service) {
1031
1068
  },
1032
1069
  }, async (request) => {
1033
1070
  const query = request.query;
1034
- return { timers: service.listTimers(query.agent_id) };
1071
+ return { timers: service.listTimers(query.agent_id, parseOptionalPositiveInteger(query.limit)) };
1035
1072
  });
1036
1073
  app.post("/timers", {
1037
1074
  schema: {
@@ -1135,6 +1172,7 @@ function buildFastifyServer(service) {
1135
1172
  properties: {
1136
1173
  source_id: { type: "string" },
1137
1174
  agent_id: { type: "string" },
1175
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
1138
1176
  },
1139
1177
  },
1140
1178
  response: {
@@ -1147,6 +1185,7 @@ function buildFastifyServer(service) {
1147
1185
  subscriptions: service.listSubscriptions({
1148
1186
  sourceId: query.source_id,
1149
1187
  agentId: query.agent_id,
1188
+ limit: parseOptionalPositiveInteger(query.limit),
1150
1189
  }),
1151
1190
  };
1152
1191
  });
@@ -1348,6 +1387,7 @@ function buildFastifyServer(service) {
1348
1387
  properties: {
1349
1388
  after_entry_id: { type: "string" },
1350
1389
  include_acked: { type: "string", enum: ["true", "false"] },
1390
+ limit: { type: "string", pattern: "^[1-9][0-9]*$" },
1351
1391
  },
1352
1392
  },
1353
1393
  response: {
@@ -1367,6 +1407,7 @@ function buildFastifyServer(service) {
1367
1407
  entries: service.listInboxItems(decodeURIComponent(params.agentId), {
1368
1408
  afterEntryId: query.after_entry_id,
1369
1409
  includeAcked: query.include_acked ? query.include_acked === "true" : undefined,
1410
+ limit: parseOptionalPositiveInteger(query.limit),
1370
1411
  }),
1371
1412
  };
1372
1413
  });
@@ -1738,6 +1779,19 @@ function optionalString(value) {
1738
1779
  const trimmed = value.trim();
1739
1780
  return trimmed.length > 0 ? trimmed : undefined;
1740
1781
  }
1782
+ function parseOptionalPositiveInteger(value) {
1783
+ if (value === undefined) {
1784
+ return undefined;
1785
+ }
1786
+ if (!/^[1-9]\d*$/.test(value)) {
1787
+ throw new Error("expected positive integer");
1788
+ }
1789
+ const parsed = Number.parseInt(value, 10);
1790
+ if (!Number.isSafeInteger(parsed)) {
1791
+ throw new Error("expected positive integer within safe range");
1792
+ }
1793
+ return parsed;
1794
+ }
1741
1795
  function normalizeValidationMessage(message) {
1742
1796
  if (message.includes("must be boolean")) {
1743
1797
  return "expected boolean";
@@ -144,14 +144,14 @@ class AgentInboxService {
144
144
  await this.adapters.sourceAdapterFor(source.sourceType).ensureSource(source);
145
145
  return source;
146
146
  }
147
- listSources() {
148
- return this.store.listSources();
147
+ listSources(limit) {
148
+ return this.store.listSources(limit);
149
149
  }
150
- async listSourceViews() {
151
- return this.attachSourceRuntimes(this.store.listSources());
150
+ async listSourceViews(limit) {
151
+ return this.attachSourceRuntimes(this.store.listSources(limit));
152
152
  }
153
- listHosts() {
154
- return this.store.listSourceHosts();
153
+ listHosts(limit) {
154
+ return this.store.listSourceHosts(limit);
155
155
  }
156
156
  getHost(hostId) {
157
157
  const host = this.store.getSourceHost(hostId);
@@ -269,8 +269,8 @@ class AgentInboxService {
269
269
  return this.getStream(stream.sourceId);
270
270
  });
271
271
  }
272
- listStreams() {
273
- return this.listSources();
272
+ listStreams(limit) {
273
+ return this.listSources(limit);
274
274
  }
275
275
  getStream(streamId) {
276
276
  return this.getSource(streamId);
@@ -590,8 +590,8 @@ class AgentInboxService {
590
590
  notifyLeaseMs: notifyLeaseMs ?? null,
591
591
  });
592
592
  }
593
- listAgents() {
594
- return this.store.listAgents();
593
+ listAgents(limit) {
594
+ return this.store.listAgents(limit);
595
595
  }
596
596
  getAgent(agentId) {
597
597
  const agent = this.store.getAgent(agentId);
@@ -666,12 +666,12 @@ class AgentInboxService {
666
666
  this.rescheduleTimerSync();
667
667
  return timer;
668
668
  }
669
- listTimers(agentId) {
669
+ listTimers(agentId, limit) {
670
670
  if (agentId) {
671
671
  this.getAgent(agentId);
672
- return this.store.listTimersForAgent(agentId);
672
+ return this.store.listTimersForAgent(agentId, limit);
673
673
  }
674
- return this.store.listTimers();
674
+ return this.store.listTimers(limit);
675
675
  }
676
676
  getTimer(scheduleId) {
677
677
  const timer = this.store.getTimer(scheduleId);
@@ -758,12 +758,12 @@ class AgentInboxService {
758
758
  this.markAgentActive(agentId);
759
759
  return target;
760
760
  }
761
- listActivationTargets(agentId) {
761
+ listActivationTargets(agentId, limit) {
762
762
  if (agentId) {
763
763
  this.getAgent(agentId);
764
- return this.store.listActivationTargetsForAgent(agentId);
764
+ return this.store.listActivationTargetsForAgent(agentId, limit);
765
765
  }
766
- return this.store.listActivationTargets();
766
+ return this.store.listActivationTargets(limit);
767
767
  }
768
768
  getActivationTarget(targetId) {
769
769
  const target = this.store.getActivationTarget(targetId);
@@ -1024,15 +1024,7 @@ class AgentInboxService {
1024
1024
  return { removed: true, subscriptionId };
1025
1025
  }
1026
1026
  listSubscriptions(filters) {
1027
- return this.store.listSubscriptions().filter((subscription) => {
1028
- if (filters?.sourceId && subscription.sourceId !== filters.sourceId) {
1029
- return false;
1030
- }
1031
- if (filters?.agentId && subscription.agentId !== filters.agentId) {
1032
- return false;
1033
- }
1034
- return true;
1035
- });
1027
+ return this.store.listSubscriptionsFiltered(filters);
1036
1028
  }
1037
1029
  getSubscription(subscriptionId) {
1038
1030
  const subscription = this.store.getSubscription(subscriptionId);
@@ -1098,8 +1090,8 @@ class AgentInboxService {
1098
1090
  }
1099
1091
  return this.appendSourceEvent({ ...input, sourceId });
1100
1092
  }
1101
- listInboxAgentIds() {
1102
- return this.store.listInboxes().map((inbox) => inbox.ownerAgentId);
1093
+ listInboxAgentIds(limit) {
1094
+ return this.store.listInboxes(limit).map((inbox) => inbox.ownerAgentId);
1103
1095
  }
1104
1096
  getInboxDetailsByAgent(agentId) {
1105
1097
  const inbox = this.ensureInboxForAgent(agentId);
@@ -1193,6 +1185,7 @@ class AgentInboxService {
1193
1185
  occurredAt,
1194
1186
  metadata: {},
1195
1187
  rawPayload: input.rawPayload,
1188
+ providerRawPayload: undefined,
1196
1189
  deliveryHandle: null,
1197
1190
  ackedAt: null,
1198
1191
  };
@@ -1516,6 +1509,7 @@ class AgentInboxService {
1516
1509
  subscriptionId: subscription.subscriptionId,
1517
1510
  },
1518
1511
  rawPayload: event.rawPayload,
1512
+ providerRawPayload: event.providerRawPayload,
1519
1513
  deliveryHandle: event.deliveryHandle,
1520
1514
  ackedAt: null,
1521
1515
  };
@@ -3406,6 +3400,7 @@ function activationItemFromInboxItem(item) {
3406
3400
  occurredAt: item.occurredAt,
3407
3401
  metadata: item.metadata,
3408
3402
  rawPayload: item.rawPayload,
3403
+ providerRawPayload: item.providerRawPayload,
3409
3404
  deliveryHandle: item.deliveryHandle,
3410
3405
  };
3411
3406
  }
@@ -46,7 +46,7 @@ class GithubUxcClient {
46
46
  issue_number: input.issueNumber,
47
47
  body: input.body,
48
48
  },
49
- options: { auth: input.auth },
49
+ options: githubAuthOptions(input.auth),
50
50
  });
51
51
  }
52
52
  async replyToReviewComment(input) {
@@ -60,7 +60,7 @@ class GithubUxcClient {
60
60
  comment_id: input.commentId,
61
61
  body: input.body,
62
62
  },
63
- options: { auth: input.auth },
63
+ options: githubAuthOptions(input.auth),
64
64
  });
65
65
  }
66
66
  async updateIssueState(input) {
@@ -73,7 +73,7 @@ class GithubUxcClient {
73
73
  issue_number: input.issueNumber,
74
74
  state: input.state,
75
75
  },
76
- options: { auth: input.auth },
76
+ options: githubAuthOptions(input.auth),
77
77
  });
78
78
  }
79
79
  async mergePullRequest(input) {
@@ -88,7 +88,7 @@ class GithubUxcClient {
88
88
  commit_title: input.commitTitle ?? null,
89
89
  commit_message: input.commitMessage ?? null,
90
90
  },
91
- options: { auth: input.auth },
91
+ options: githubAuthOptions(input.auth),
92
92
  });
93
93
  }
94
94
  async getPullRequestDetails(input) {
@@ -100,7 +100,7 @@ class GithubUxcClient {
100
100
  repo: input.repo,
101
101
  pull_number: input.pullNumber,
102
102
  },
103
- options: { auth: input.auth },
103
+ options: githubReadOptions(input.auth),
104
104
  });
105
105
  const data = asRecord(response.data);
106
106
  const head = asRecord(data.head);
@@ -333,7 +333,7 @@ async function hydrateGithubRepoEventIfNeeded(config, raw, client = DEFAULT_GITH
333
333
  per_page: perPage,
334
334
  page,
335
335
  },
336
- options: { auth: config.uxcAuth },
336
+ options: githubReadOptions(config.uxcAuth),
337
337
  });
338
338
  }
339
339
  catch {
@@ -705,6 +705,15 @@ function computeGithubHydrationPerPage(perPage) {
705
705
  : GITHUB_EVENT_HYDRATION_MIN_PER_PAGE;
706
706
  return Math.min(GITHUB_EVENT_HYDRATION_MAX_PER_PAGE, Math.max(GITHUB_EVENT_HYDRATION_MIN_PER_PAGE, configured));
707
707
  }
708
+ function githubAuthOptions(auth) {
709
+ return { auth };
710
+ }
711
+ function githubReadOptions(auth) {
712
+ return {
713
+ auth,
714
+ artifact_compaction: false,
715
+ };
716
+ }
708
717
  function extractGithubRepoEventUrl(event, issue, pullRequest, review, comment) {
709
718
  return (asString(comment.html_url)
710
719
  ?? asString(review.html_url)
@@ -391,6 +391,7 @@ class RemoteSourceRuntime {
391
391
  occurredAt: mapped.occurredAt,
392
392
  metadata: mapped.metadata,
393
393
  rawPayload: mapped.rawPayload,
394
+ providerRawPayload: mapped.providerRawPayload,
394
395
  deliveryHandle: mapped.deliveryHandle ?? null,
395
396
  });
396
397
  appended += result.appended;
@@ -297,7 +297,10 @@ function createGithubRepoRemoteModule(options) {
297
297
  seen_window: 1024,
298
298
  },
299
299
  },
300
- options: { auth: config.uxcAuth },
300
+ options: {
301
+ auth: config.uxcAuth,
302
+ artifact_compaction: false,
303
+ },
301
304
  };
302
305
  },
303
306
  async mapRawEvent(rawPayload, source) {
@@ -312,6 +315,7 @@ function createGithubRepoRemoteModule(options) {
312
315
  eventVariant: normalized.eventVariant,
313
316
  metadata: normalized.metadata ?? {},
314
317
  rawPayload: normalized.rawPayload ?? hydratedPayload,
318
+ providerRawPayload: hydratedPayload,
315
319
  occurredAt: normalized.occurredAt,
316
320
  deliveryHandle: normalized.deliveryHandle,
317
321
  };
@@ -434,7 +438,10 @@ const GITHUB_REPO_CI_MODULE = {
434
438
  seen_window: 1024,
435
439
  },
436
440
  },
437
- options: { auth: config.uxcAuth },
441
+ options: {
442
+ auth: config.uxcAuth,
443
+ artifact_compaction: false,
444
+ },
438
445
  };
439
446
  },
440
447
  mapRawEvent(rawPayload, source) {
@@ -448,6 +455,7 @@ const GITHUB_REPO_CI_MODULE = {
448
455
  eventVariant: normalized.eventVariant,
449
456
  metadata: normalized.metadata ?? {},
450
457
  rawPayload: normalized.rawPayload ?? rawPayload,
458
+ providerRawPayload: rawPayload,
451
459
  occurredAt: normalized.occurredAt,
452
460
  deliveryHandle: normalized.deliveryHandle,
453
461
  };
@@ -500,7 +508,10 @@ const FEISHU_BOT_MODULE = {
500
508
  endpoint: config.endpoint ?? feishu_1.FEISHU_OPENAPI_ENDPOINT,
501
509
  mode: "stream",
502
510
  transport_hint: "feishu_long_connection",
503
- options: { auth: config.uxcAuth },
511
+ options: {
512
+ auth: config.uxcAuth,
513
+ artifact_compaction: false,
514
+ },
504
515
  };
505
516
  },
506
517
  mapRawEvent(rawPayload, source) {
@@ -514,6 +525,7 @@ const FEISHU_BOT_MODULE = {
514
525
  eventVariant: normalized.eventVariant,
515
526
  metadata: normalized.metadata ?? {},
516
527
  rawPayload: normalized.rawPayload ?? rawPayload,
528
+ providerRawPayload: rawPayload,
517
529
  occurredAt: normalized.occurredAt,
518
530
  deliveryHandle: normalized.deliveryHandle,
519
531
  };
package/dist/src/store.js CHANGED
@@ -288,8 +288,10 @@ class AgentInboxStore {
288
288
  ]);
289
289
  this.persist();
290
290
  }
291
- listSourceHosts() {
292
- const rows = this.getAll("select * from source_hosts order by created_at asc");
291
+ listSourceHosts(limit) {
292
+ const rows = typeof limit === "number"
293
+ ? this.getAll("select * from source_hosts order by created_at asc, host_id asc limit ?", [limit])
294
+ : this.getAll("select * from source_hosts order by created_at asc, host_id asc");
293
295
  return rows.map((row) => this.mapSourceHost(row));
294
296
  }
295
297
  updateSourceHostDefinition(hostId, input) {
@@ -362,8 +364,10 @@ class AgentInboxStore {
362
364
  });
363
365
  this.persist();
364
366
  }
365
- listSources() {
366
- const rows = this.getAll("select * from sources order by created_at asc");
367
+ listSources(limit) {
368
+ const rows = typeof limit === "number"
369
+ ? this.getAll("select * from sources order by created_at asc, source_id asc limit ?", [limit])
370
+ : this.getAll("select * from sources order by created_at asc, source_id asc");
367
371
  return rows.map((row) => this.mapSource(row));
368
372
  }
369
373
  getSourceIdleState(sourceId) {
@@ -505,8 +509,10 @@ class AgentInboxStore {
505
509
  this.persist();
506
510
  return this.getAgent(agentId);
507
511
  }
508
- listAgents() {
509
- const rows = this.getAll("select * from agents order by created_at asc");
512
+ listAgents(limit) {
513
+ const rows = typeof limit === "number"
514
+ ? this.getAll("select * from agents order by created_at asc, agent_id asc limit ?", [limit])
515
+ : this.getAll("select * from agents order by created_at asc, agent_id asc");
510
516
  return rows.map((row) => this.mapAgent(row));
511
517
  }
512
518
  getInbox(inboxId) {
@@ -556,8 +562,10 @@ class AgentInboxStore {
556
562
  this.persist();
557
563
  return this.getInbox(inboxId);
558
564
  }
559
- listInboxes() {
560
- const rows = this.getAll("select * from inboxes order by created_at asc");
565
+ listInboxes(limit) {
566
+ const rows = typeof limit === "number"
567
+ ? this.getAll("select * from inboxes order by created_at asc, inbox_id asc limit ?", [limit])
568
+ : this.getAll("select * from inboxes order by created_at asc, inbox_id asc");
561
569
  return rows.map((row) => this.mapInbox(row));
562
570
  }
563
571
  getSubscription(subscriptionId) {
@@ -583,16 +591,41 @@ class AgentInboxStore {
583
591
  ]);
584
592
  this.persist();
585
593
  }
586
- listSubscriptions() {
587
- const rows = this.getAll("select * from subscriptions order by created_at asc");
594
+ listSubscriptions(limit) {
595
+ const rows = typeof limit === "number"
596
+ ? this.getAll("select * from subscriptions order by created_at asc, subscription_id asc limit ?", [limit])
597
+ : this.getAll("select * from subscriptions order by created_at asc, subscription_id asc");
588
598
  return rows.map((row) => this.mapSubscription(row));
589
599
  }
590
- listSubscriptionsForSource(sourceId) {
591
- const rows = this.getAll("select * from subscriptions where source_id = ? order by created_at asc", [sourceId]);
600
+ listSubscriptionsFiltered(filters) {
601
+ const clauses = [];
602
+ const params = [];
603
+ if (filters?.sourceId) {
604
+ clauses.push("source_id = ?");
605
+ params.push(filters.sourceId);
606
+ }
607
+ if (filters?.agentId) {
608
+ clauses.push("agent_id = ?");
609
+ params.push(filters.agentId);
610
+ }
611
+ const where = clauses.length > 0 ? ` where ${clauses.join(" and ")}` : "";
612
+ const limitClause = typeof filters?.limit === "number" ? " limit ?" : "";
613
+ if (typeof filters?.limit === "number") {
614
+ params.push(filters.limit);
615
+ }
616
+ const rows = this.getAll(`select * from subscriptions${where} order by created_at asc, subscription_id asc${limitClause}`, params);
617
+ return rows.map((row) => this.mapSubscription(row));
618
+ }
619
+ listSubscriptionsForSource(sourceId, limit) {
620
+ const rows = typeof limit === "number"
621
+ ? this.getAll("select * from subscriptions where source_id = ? order by created_at asc, subscription_id asc limit ?", [sourceId, limit])
622
+ : this.getAll("select * from subscriptions where source_id = ? order by created_at asc, subscription_id asc", [sourceId]);
592
623
  return rows.map((row) => this.mapSubscription(row));
593
624
  }
594
- listSubscriptionsForAgent(agentId) {
595
- const rows = this.getAll("select * from subscriptions where agent_id = ? order by created_at asc", [agentId]);
625
+ listSubscriptionsForAgent(agentId, limit) {
626
+ const rows = typeof limit === "number"
627
+ ? this.getAll("select * from subscriptions where agent_id = ? order by created_at asc, subscription_id asc limit ?", [agentId, limit])
628
+ : this.getAll("select * from subscriptions where agent_id = ? order by created_at asc, subscription_id asc", [agentId]);
596
629
  return rows.map((row) => this.mapSubscription(row));
597
630
  }
598
631
  listSubscriptionsForHostTrackedResourceRef(hostId, trackedResourceRef) {
@@ -821,12 +854,16 @@ class AgentInboxStore {
821
854
  this.persist();
822
855
  return this.getActivationTarget(targetId);
823
856
  }
824
- listActivationTargets() {
825
- const rows = this.getAll("select * from activation_targets order by created_at asc");
857
+ listActivationTargets(limit) {
858
+ const rows = typeof limit === "number"
859
+ ? this.getAll("select * from activation_targets order by created_at asc, target_id asc limit ?", [limit])
860
+ : this.getAll("select * from activation_targets order by created_at asc, target_id asc");
826
861
  return rows.map((row) => this.mapActivationTarget(row));
827
862
  }
828
- listActivationTargetsForAgent(agentId) {
829
- const rows = this.getAll("select * from activation_targets where agent_id = ? order by created_at asc", [agentId]);
863
+ listActivationTargetsForAgent(agentId, limit) {
864
+ const rows = typeof limit === "number"
865
+ ? this.getAll("select * from activation_targets where agent_id = ? order by created_at asc, target_id asc limit ?", [agentId, limit])
866
+ : this.getAll("select * from activation_targets where agent_id = ? order by created_at asc, target_id asc", [agentId]);
830
867
  return rows.map((row) => this.mapActivationTarget(row));
831
868
  }
832
869
  deleteActivationTarget(agentId, targetId) {
@@ -902,12 +939,16 @@ class AgentInboxStore {
902
939
  const row = this.getOne("select * from timers where schedule_id = ?", [scheduleId]);
903
940
  return row ? this.mapTimer(row) : null;
904
941
  }
905
- listTimers() {
906
- const rows = this.getAll("select * from timers order by created_at asc");
942
+ listTimers(limit) {
943
+ const rows = typeof limit === "number"
944
+ ? this.getAll("select * from timers order by created_at asc, schedule_id asc limit ?", [limit])
945
+ : this.getAll("select * from timers order by created_at asc, schedule_id asc");
907
946
  return rows.map((row) => this.mapTimer(row));
908
947
  }
909
- listTimersForAgent(agentId) {
910
- const rows = this.getAll("select * from timers where agent_id = ? order by created_at asc", [agentId]);
948
+ listTimersForAgent(agentId, limit) {
949
+ const rows = typeof limit === "number"
950
+ ? this.getAll("select * from timers where agent_id = ? order by created_at asc, schedule_id asc limit ?", [agentId, limit])
951
+ : this.getAll("select * from timers where agent_id = ? order by created_at asc, schedule_id asc", [agentId]);
911
952
  return rows.map((row) => this.mapTimer(row));
912
953
  }
913
954
  listDueTimers(cutoffIso) {
@@ -1015,8 +1056,8 @@ class AgentInboxStore {
1015
1056
  this.db.run(`
1016
1057
  insert or ignore into inbox_items (
1017
1058
  item_id, source_id, source_native_id, event_variant, inbox_id, occurred_at,
1018
- metadata_json, raw_payload_json, delivery_handle_json, acked_at
1019
- ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1059
+ metadata_json, raw_payload_json, provider_raw_payload_json, delivery_handle_json, acked_at
1060
+ ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1020
1061
  `, [
1021
1062
  item.itemId,
1022
1063
  item.sourceId,
@@ -1026,6 +1067,7 @@ class AgentInboxStore {
1026
1067
  item.occurredAt,
1027
1068
  JSON.stringify(item.metadata),
1028
1069
  JSON.stringify(item.rawPayload),
1070
+ item.providerRawPayload ? JSON.stringify(item.providerRawPayload) : null,
1029
1071
  item.deliveryHandle ? JSON.stringify(item.deliveryHandle) : null,
1030
1072
  item.ackedAt ?? null,
1031
1073
  ]);
@@ -1059,6 +1101,7 @@ class AgentInboxStore {
1059
1101
  occurredAt: item.occurredAt,
1060
1102
  metadata: item.metadata,
1061
1103
  rawPayload: item.rawPayload,
1104
+ providerRawPayload: item.providerRawPayload,
1062
1105
  deliveryHandle: item.deliveryHandle ?? null,
1063
1106
  }),
1064
1107
  count: 1,
@@ -1092,7 +1135,11 @@ class AgentInboxStore {
1092
1135
  filters.push("sequence > ?");
1093
1136
  params.push(Number(anchor.sequence));
1094
1137
  }
1095
- const rows = this.getAll(`select * from inbox_entries where ${filters.join(" and ")} order by sequence asc`, params);
1138
+ const sql = `select * from inbox_entries where ${filters.join(" and ")} order by sequence asc${typeof options?.limit === "number" ? " limit ?" : ""}`;
1139
+ if (typeof options?.limit === "number") {
1140
+ params.push(options.limit);
1141
+ }
1142
+ const rows = this.getAll(sql, params);
1096
1143
  return this.mapInboxEntries(rows);
1097
1144
  }
1098
1145
  getInboxEntry(entryId) {
@@ -1273,7 +1320,11 @@ class AgentInboxStore {
1273
1320
  if (!includeAcked) {
1274
1321
  filters.push("acked_at is null");
1275
1322
  }
1276
- const rows = this.getAll(`select * from inbox_items where ${filters.join(" and ")} order by coalesce(inbox_sequence, rowid) asc`, params);
1323
+ const sql = `select * from inbox_items where ${filters.join(" and ")} order by coalesce(inbox_sequence, rowid) asc${typeof options?.limit === "number" ? " limit ?" : ""}`;
1324
+ if (typeof options?.limit === "number") {
1325
+ params.push(options.limit);
1326
+ }
1327
+ const rows = this.getAll(sql, params);
1277
1328
  return rows.map((row) => this.mapInboxItem(row));
1278
1329
  }
1279
1330
  ackItems(inboxId, itemIds, ackedAt) {
@@ -1406,8 +1457,10 @@ class AgentInboxStore {
1406
1457
  const row = this.getOne("select * from streams where stream_id = ?", [streamId]);
1407
1458
  return row ? this.mapStream(row) : null;
1408
1459
  }
1409
- listStreams() {
1410
- const rows = this.getAll("select * from streams order by created_at asc");
1460
+ listStreams(limit) {
1461
+ const rows = typeof limit === "number"
1462
+ ? this.getAll("select * from streams order by created_at asc, stream_id asc limit ?", [limit])
1463
+ : this.getAll("select * from streams order by created_at asc, stream_id asc");
1411
1464
  return rows.map((row) => this.mapStream(row));
1412
1465
  }
1413
1466
  getStreamBySourceId(sourceId) {
@@ -1418,14 +1471,15 @@ class AgentInboxStore {
1418
1471
  const occurredAt = event.occurredAt ?? (0, util_1.nowIso)();
1419
1472
  const metadataJson = JSON.stringify(event.metadata ?? {});
1420
1473
  const rawPayloadJson = JSON.stringify(event.rawPayload ?? {});
1474
+ const providerRawPayloadJson = event.providerRawPayload ? JSON.stringify(event.providerRawPayload) : null;
1421
1475
  const deliveryHandleJson = event.deliveryHandle ? JSON.stringify(event.deliveryHandle) : null;
1422
1476
  for (let attempt = 0; attempt < 5; attempt += 1) {
1423
1477
  const before = this.changes();
1424
1478
  this.db.run(`
1425
1479
  insert or ignore into stream_events (
1426
1480
  stream_event_id, stream_id, source_id, source_native_id, event_variant,
1427
- occurred_at, metadata_json, raw_payload_json, delivery_handle_json, created_at
1428
- ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1481
+ occurred_at, metadata_json, raw_payload_json, provider_raw_payload_json, delivery_handle_json, created_at
1482
+ ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1429
1483
  `, [
1430
1484
  (0, util_1.generateCanonicalId)("evt"),
1431
1485
  streamId,
@@ -1435,6 +1489,7 @@ class AgentInboxStore {
1435
1489
  occurredAt,
1436
1490
  metadataJson,
1437
1491
  rawPayloadJson,
1492
+ providerRawPayloadJson,
1438
1493
  deliveryHandleJson,
1439
1494
  (0, util_1.nowIso)(),
1440
1495
  ]);
@@ -1821,6 +1876,9 @@ class AgentInboxStore {
1821
1876
  occurredAt: String(row.occurred_at),
1822
1877
  metadata: parseJson(row.metadata_json),
1823
1878
  rawPayload: parseJson(row.raw_payload_json),
1879
+ providerRawPayload: row.provider_raw_payload_json
1880
+ ? parseJson(row.provider_raw_payload_json)
1881
+ : undefined,
1824
1882
  deliveryHandle: row.delivery_handle_json
1825
1883
  ? parseJson(row.delivery_handle_json)
1826
1884
  : null,
@@ -1858,6 +1916,7 @@ class AgentInboxStore {
1858
1916
  occurredAt: item.occurredAt,
1859
1917
  metadata: item.metadata,
1860
1918
  rawPayload: item.rawPayload,
1919
+ providerRawPayload: item.providerRawPayload,
1861
1920
  item,
1862
1921
  };
1863
1922
  }
@@ -2130,6 +2189,9 @@ class AgentInboxStore {
2130
2189
  occurredAt: String(row.occurred_at),
2131
2190
  metadata: parseJson(row.metadata_json),
2132
2191
  rawPayload: parseJson(row.raw_payload_json),
2192
+ providerRawPayload: row.provider_raw_payload_json
2193
+ ? parseJson(row.provider_raw_payload_json)
2194
+ : undefined,
2133
2195
  deliveryHandle: row.delivery_handle_json
2134
2196
  ? parseJson(row.delivery_handle_json)
2135
2197
  : null,
@@ -0,0 +1,3 @@
1
+ alter table inbox_items add column provider_raw_payload_json text;
2
+
3
+ alter table stream_events add column provider_raw_payload_json text;
package/drizzle/schema.ts CHANGED
@@ -173,6 +173,7 @@ export const inboxItems = sqliteTable("inbox_items", {
173
173
  occurredAt: text("occurred_at").notNull(),
174
174
  metadataJson: text("metadata_json").notNull(),
175
175
  rawPayloadJson: text("raw_payload_json").notNull(),
176
+ providerRawPayloadJson: text("provider_raw_payload_json"),
176
177
  deliveryHandleJson: text("delivery_handle_json"),
177
178
  ackedAt: text("acked_at"),
178
179
  }, (table) => ({
@@ -302,6 +303,7 @@ export const streamEvents = sqliteTable("stream_events", {
302
303
  occurredAt: text("occurred_at").notNull(),
303
304
  metadataJson: text("metadata_json").notNull(),
304
305
  rawPayloadJson: text("raw_payload_json").notNull(),
306
+ providerRawPayloadJson: text("provider_raw_payload_json"),
305
307
  deliveryHandleJson: text("delivery_handle_json"),
306
308
  createdAt: text("created_at").notNull(),
307
309
  }, (table) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holon-run/agentinbox",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Local event subscription and delivery service for agents.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@fastify/swagger": "^9.5.2",
47
- "@holon-run/uxc-daemon-client": "^0.15.3",
47
+ "@holon-run/uxc-daemon-client": "^0.15.4",
48
48
  "fastify": "^5.6.1",
49
49
  "jexl": "^2.3.0",
50
50
  "sql.js": "^1.13.0"