@holon-run/agentinbox 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/cli.js CHANGED
@@ -9,6 +9,7 @@ const node_path_1 = __importDefault(require("node:path"));
9
9
  const adapters_1 = require("./adapters");
10
10
  const client_1 = require("./client");
11
11
  const control_server_1 = require("./control_server");
12
+ const current_agent_1 = require("./current_agent");
12
13
  const daemon_1 = require("./daemon");
13
14
  const http_1 = require("./http");
14
15
  const paths_1 = require("./paths");
@@ -54,10 +55,10 @@ async function main() {
54
55
  if (!type || !sourceKey) {
55
56
  throw new Error("usage: agentinbox source add <type> <sourceKey> [--config-json JSON] [--config-ref REF]");
56
57
  }
57
- await printRemote(client, "/sources/register", {
58
+ await printRemote(client, "/sources", {
58
59
  sourceType: type,
59
60
  sourceKey,
60
- configRef: takeFlagValue(normalized, "--config-ref") ?? null,
61
+ configRef: takeFlagValue(normalized, "--config-ref") ?? undefined,
61
62
  config: (0, util_1.parseJsonArg)(takeFlagValue(normalized, "--config-json")),
62
63
  });
63
64
  return;
@@ -74,6 +75,50 @@ async function main() {
74
75
  await printRemote(client, `/sources/${encodeURIComponent(sourceId)}`, undefined, "GET");
75
76
  return;
76
77
  }
78
+ if (command === "source" && normalized[1] === "remove") {
79
+ const sourceId = normalized[2];
80
+ if (!sourceId) {
81
+ throw new Error("usage: agentinbox source remove <sourceId>");
82
+ }
83
+ await printRemote(client, `/sources/${encodeURIComponent(sourceId)}`, undefined, "DELETE");
84
+ return;
85
+ }
86
+ if (command === "source" && normalized[1] === "update") {
87
+ const sourceId = normalized[2];
88
+ if (!sourceId) {
89
+ throw new Error("usage: agentinbox source update <sourceId> [--config-json JSON] [--config-ref REF | --clear-config-ref]");
90
+ }
91
+ const configRef = takeFlagValue(normalized, "--config-ref");
92
+ const clearConfigRef = hasFlag(normalized, "--clear-config-ref");
93
+ const configJson = takeFlagValue(normalized, "--config-json");
94
+ if (configRef != null && clearConfigRef) {
95
+ throw new Error("source update accepts only one of --config-ref or --clear-config-ref");
96
+ }
97
+ if (!clearConfigRef && configRef == null && configJson == null) {
98
+ throw new Error("usage: agentinbox source update <sourceId> [--config-json JSON] [--config-ref REF | --clear-config-ref]");
99
+ }
100
+ await printRemote(client, `/sources/${encodeURIComponent(sourceId)}`, {
101
+ ...(clearConfigRef ? { configRef: null } : (configRef != null ? { configRef } : {})),
102
+ config: configJson != null ? (0, util_1.parseJsonArg)(configJson, "--config-json") : undefined,
103
+ }, "PATCH");
104
+ return;
105
+ }
106
+ if (command === "source" && normalized[1] === "pause") {
107
+ const sourceId = normalized[2];
108
+ if (!sourceId) {
109
+ throw new Error("usage: agentinbox source pause <remoteSourceId>");
110
+ }
111
+ await printRemote(client, `/sources/${encodeURIComponent(sourceId)}/pause`, {});
112
+ return;
113
+ }
114
+ if (command === "source" && normalized[1] === "resume") {
115
+ const sourceId = normalized[2];
116
+ if (!sourceId) {
117
+ throw new Error("usage: agentinbox source resume <remoteSourceId>");
118
+ }
119
+ await printRemote(client, `/sources/${encodeURIComponent(sourceId)}/resume`, {});
120
+ return;
121
+ }
77
122
  if (command === "source" && normalized[1] === "schema") {
78
123
  const sourceType = normalized[2];
79
124
  if (!sourceType) {
@@ -108,22 +153,26 @@ async function main() {
108
153
  }
109
154
  if (command === "agent" && normalized[1] === "register") {
110
155
  const detected = (0, terminal_1.detectTerminalContext)(process.env);
111
- await printRemote(client, "/agents/register", {
112
- agentId: takeFlagValue(normalized, "--agent-id") ?? null,
156
+ await printRemote(client, "/agents", {
157
+ agentId: takeFlagValue(normalized, "--agent-id") ?? undefined,
113
158
  forceRebind: normalized.includes("--force-rebind"),
114
159
  backend: detected.backend,
115
160
  runtimeKind: detected.runtimeKind,
116
- runtimeSessionId: detected.runtimeSessionId ?? null,
117
- tmuxPaneId: detected.tmuxPaneId ?? null,
118
- tty: detected.tty ?? null,
119
- termProgram: detected.termProgram ?? null,
120
- itermSessionId: detected.itermSessionId ?? null,
121
- notifyLeaseMs: parseOptionalNumber(takeFlagValue(normalized, "--notify-lease-ms")) ?? null,
161
+ runtimeSessionId: detected.runtimeSessionId ?? undefined,
162
+ tmuxPaneId: detected.tmuxPaneId ?? undefined,
163
+ tty: detected.tty ?? undefined,
164
+ termProgram: detected.termProgram ?? undefined,
165
+ itermSessionId: detected.itermSessionId ?? undefined,
166
+ notifyLeaseMs: parseOptionalNumber(takeFlagValue(normalized, "--notify-lease-ms")) ?? undefined,
122
167
  });
123
168
  return;
124
169
  }
125
170
  if (command === "agent" && normalized[1] === "list") {
126
- await printRemote(client, "/agents", undefined, "GET");
171
+ await printAgentList(client);
172
+ return;
173
+ }
174
+ if (command === "agent" && normalized[1] === "current") {
175
+ await printCurrentAgent(client);
127
176
  return;
128
177
  }
129
178
  if (command === "agent" && normalized[1] === "show") {
@@ -152,7 +201,7 @@ async function main() {
152
201
  kind: "webhook",
153
202
  url,
154
203
  activationMode: takeFlagValue(normalized, "--activation-mode") ?? undefined,
155
- notifyLeaseMs: parseOptionalNumber(takeFlagValue(normalized, "--notify-lease-ms")) ?? null,
204
+ notifyLeaseMs: parseOptionalNumber(takeFlagValue(normalized, "--notify-lease-ms")) ?? undefined,
156
205
  });
157
206
  return;
158
207
  }
@@ -173,18 +222,25 @@ async function main() {
173
222
  return;
174
223
  }
175
224
  if (command === "subscription" && normalized[1] === "add") {
176
- const [agentId, sourceId] = normalized.slice(2, 4);
177
- if (!agentId || !sourceId) {
178
- throw new Error("usage: agentinbox subscription add <agentId> <sourceId> [--filter-json JSON] [--start-policy POLICY] [--start-offset N] [--start-time ISO8601]");
225
+ const args = normalized.slice(2);
226
+ const positionals = positionalArgs(args, ["--agent-id", "--filter-json", "--filter-file", "--start-policy", "--start-offset", "--start-time"]);
227
+ const sourceId = positionals[0];
228
+ if (!sourceId || positionals[1]) {
229
+ throw new Error("usage: agentinbox subscription add <sourceId> [--agent-id ID] [--filter-json JSON | --filter-file PATH | --filter-stdin] [--start-policy POLICY] [--start-offset N] [--start-time ISO8601]");
179
230
  }
180
- await printRemote(client, "/subscriptions/register", {
181
- agentId,
231
+ const selection = await selectAgentForCommand(client, {
232
+ explicitAgentId: takeFlagValue(normalized, "--agent-id"),
233
+ autoRegister: true,
234
+ });
235
+ const response = await requestRemote(client, "/subscriptions", {
236
+ agentId: selection.agentId,
182
237
  sourceId,
183
- filter: (0, util_1.parseJsonArg)(takeFlagValue(normalized, "--filter-json")),
238
+ filter: readSubscriptionFilter(normalized),
184
239
  startPolicy: takeFlagValue(normalized, "--start-policy") ?? undefined,
185
240
  startOffset: parseOptionalNumber(takeFlagValue(normalized, "--start-offset")),
186
241
  startTime: takeFlagValue(normalized, "--start-time") ?? undefined,
187
242
  });
243
+ console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
188
244
  return;
189
245
  }
190
246
  if (command === "subscription" && normalized[1] === "list") {
@@ -253,23 +309,39 @@ async function main() {
253
309
  return;
254
310
  }
255
311
  if (command === "inbox" && normalized[1] === "read") {
256
- const agentId = normalized[2];
257
- if (!agentId) {
258
- throw new Error("usage: agentinbox inbox read <agentId>");
312
+ const args = normalized.slice(2);
313
+ const allowedFlags = ["--agent-id", "--after-item", "--include-acked"];
314
+ if (positionalArgs(args, ["--agent-id", "--after-item"]).length > 0 || unexpectedFlags(args, allowedFlags).length > 0) {
315
+ throw new Error("usage: agentinbox inbox read [--agent-id ID] [--after-item ID] [--include-acked]");
259
316
  }
317
+ const selection = await selectAgentForCommand(client, {
318
+ explicitAgentId: takeFlagValue(normalized, "--agent-id"),
319
+ autoRegister: true,
320
+ });
260
321
  const query = buildQuery({
261
322
  after_item_id: takeFlagValue(normalized, "--after-item"),
262
323
  include_acked: hasFlag(normalized, "--include-acked") ? "true" : undefined,
263
324
  });
264
- await printRemote(client, `/agents/${encodeURIComponent(agentId)}/inbox/items${query}`, undefined, "GET");
325
+ const response = await requestRemote(client, `/agents/${encodeURIComponent(selection.agentId)}/inbox/items${query}`, undefined, "GET");
326
+ console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
265
327
  return;
266
328
  }
267
329
  if (command === "inbox" && normalized[1] === "watch") {
268
- const agentId = normalized[2];
269
- if (!agentId) {
270
- throw new Error("usage: agentinbox inbox watch <agentId> [--after-item ID] [--include-acked] [--heartbeat-ms N]");
330
+ const args = normalized.slice(2);
331
+ if (positionalArgs(args, ["--agent-id", "--after-item", "--heartbeat-ms"]).length > 0) {
332
+ throw new Error("usage: agentinbox inbox watch [--agent-id ID] [--after-item ID] [--include-acked] [--heartbeat-ms N]");
333
+ }
334
+ const selection = await selectAgentForCommand(client, {
335
+ explicitAgentId: takeFlagValue(normalized, "--agent-id"),
336
+ autoRegister: true,
337
+ });
338
+ const metadata = withCommandMetadata({
339
+ event: "watch_notice",
340
+ }, selection);
341
+ if (selection.autoRegistered || selection.warnings.length > 0) {
342
+ console.log((0, util_1.jsonResponse)(metadata));
271
343
  }
272
- for await (const event of client.watchInbox(agentId, {
344
+ for await (const event of client.watchInbox(selection.agentId, {
273
345
  afterItemId: takeFlagValue(normalized, "--after-item"),
274
346
  includeAcked: hasFlag(normalized, "--include-acked"),
275
347
  heartbeatMs: parseOptionalNumber(takeFlagValue(normalized, "--heartbeat-ms")),
@@ -282,19 +354,20 @@ async function main() {
282
354
  return;
283
355
  }
284
356
  if (command === "inbox" && normalized[1] === "ack") {
285
- const agentId = normalized[2];
357
+ const args = normalized.slice(2);
286
358
  const itemId = takeFlagValue(normalized, "--item");
287
359
  const throughItemId = takeFlagValue(normalized, "--through");
288
360
  const ackAll = hasFlag(normalized, "--all");
289
361
  const modeCount = Number(Boolean(itemId)) + Number(Boolean(throughItemId)) + Number(ackAll);
290
- if (!agentId || modeCount !== 1) {
291
- throw new Error("usage: agentinbox inbox ack <agentId> (--through <itemId> | --item <itemId> | --all)");
292
- }
293
- if (ackAll) {
294
- await printRemote(client, `/agents/${encodeURIComponent(agentId)}/inbox/ack-all`, {});
295
- return;
362
+ if (positionalArgs(args, ["--agent-id", "--item", "--through"]).length > 0 || modeCount !== 1) {
363
+ throw new Error("usage: agentinbox inbox ack [--agent-id ID] (--through <itemId> | --item <itemId> | --all)");
296
364
  }
297
- await printRemote(client, `/agents/${encodeURIComponent(agentId)}/inbox/ack`, throughItemId ? { throughItemId } : { itemIds: [itemId] });
365
+ const selection = await selectAgentForCommand(client, {
366
+ explicitAgentId: takeFlagValue(normalized, "--agent-id"),
367
+ autoRegister: true,
368
+ });
369
+ const response = await requestRemote(client, `/agents/${encodeURIComponent(selection.agentId)}/inbox/ack`, ackAll ? { all: true } : (throughItemId ? { throughItemId } : { itemIds: [itemId] }));
370
+ console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
298
371
  return;
299
372
  }
300
373
  if (command === "inbox" && normalized[1] === "compact") {
@@ -309,22 +382,6 @@ async function main() {
309
382
  await printRemote(client, "/gc", {});
310
383
  return;
311
384
  }
312
- if (command === "fixture" && normalized[1] === "emit") {
313
- const sourceId = normalized[2];
314
- const sourceNativeId = takeFlagValue(normalized, "--native-id") ?? `fixture-${Date.now()}`;
315
- const eventVariant = takeFlagValue(normalized, "--event") ?? "message";
316
- if (!sourceId) {
317
- throw new Error("usage: agentinbox fixture emit <sourceId> [--native-id ID] [--event EVENT] [--metadata-json JSON] [--payload-json JSON]");
318
- }
319
- await printRemote(client, "/fixtures/emit", {
320
- sourceId,
321
- sourceNativeId,
322
- eventVariant,
323
- metadata: (0, util_1.parseJsonArg)(takeFlagValue(normalized, "--metadata-json")),
324
- rawPayload: (0, util_1.parseJsonArg)(takeFlagValue(normalized, "--payload-json")),
325
- });
326
- return;
327
- }
328
385
  if (command === "deliver" && normalized[1] === "send") {
329
386
  const provider = takeFlagValue(normalized, "--provider");
330
387
  const surface = takeFlagValue(normalized, "--surface");
@@ -337,8 +394,8 @@ async function main() {
337
394
  provider,
338
395
  surface,
339
396
  targetRef,
340
- threadRef: takeFlagValue(normalized, "--thread") ?? null,
341
- replyMode: takeFlagValue(normalized, "--reply-mode") ?? null,
397
+ threadRef: takeFlagValue(normalized, "--thread") ?? undefined,
398
+ replyMode: takeFlagValue(normalized, "--reply-mode") ?? undefined,
342
399
  kind,
343
400
  payload: (0, util_1.parseJsonArg)(takeFlagValue(normalized, "--payload-json")),
344
401
  });
@@ -369,7 +426,9 @@ async function runServe(args) {
369
426
  });
370
427
  const store = await store_1.AgentInboxStore.open(serveConfig.dbPath);
371
428
  let service;
372
- const adapters = new adapters_1.AdapterRegistry(store, async (input) => service.appendSourceEvent(input));
429
+ const adapters = new adapters_1.AdapterRegistry(store, async (input) => service.appendSourceEvent(input), {
430
+ homeDir: serveConfig.homeDir,
431
+ });
373
432
  service = new service_1.AgentInboxService(store, adapters);
374
433
  const server = (0, http_1.createServer)(service);
375
434
  await adapters.start();
@@ -434,19 +493,99 @@ async function createClient(args) {
434
493
  });
435
494
  return new client_1.AgentInboxClient(transport);
436
495
  }
496
+ async function printAgentList(client) {
497
+ const records = await listAgentsWithTargets(client);
498
+ console.log((0, util_1.jsonResponse)((0, current_agent_1.annotateAgents)(records, tryDetectTerminalContext())));
499
+ }
500
+ async function printCurrentAgent(client) {
501
+ const context = getRequiredTerminalContext();
502
+ const records = await listAgentsWithTargets(client);
503
+ const current = (0, current_agent_1.resolveCurrentAgent)(records, context);
504
+ if (!current) {
505
+ throw new Error("no current agent is registered for this terminal/runtime context; run `agentinbox agent register`");
506
+ }
507
+ console.log((0, util_1.jsonResponse)(current));
508
+ }
509
+ async function selectAgentForCommand(client, options) {
510
+ const records = await listAgentsWithTargets(client);
511
+ const context = tryDetectTerminalContext();
512
+ if (options.explicitAgentId) {
513
+ const current = context ? (0, current_agent_1.resolveCurrentAgent)(records, context) : null;
514
+ const requested = records.find((entry) => entry.agent.agentId === options.explicitAgentId);
515
+ const warnings = [];
516
+ if (current && requested && current.agentId !== requested.agent.agentId && current.bindingKind === "session_bound"
517
+ && bindingKindForRecord(requested) === "session_bound") {
518
+ warnings.push({
519
+ code: "cross_session_agent",
520
+ message: "Requested agent does not match the current terminal session.",
521
+ currentAgentId: current.agentId,
522
+ requestedAgentId: requested.agent.agentId,
523
+ });
524
+ }
525
+ return {
526
+ agentId: options.explicitAgentId,
527
+ autoRegistered: false,
528
+ warnings,
529
+ };
530
+ }
531
+ const contextForCurrent = getRequiredTerminalContext();
532
+ const current = (0, current_agent_1.resolveCurrentAgent)(records, contextForCurrent);
533
+ if (current) {
534
+ return {
535
+ agentId: current.agentId,
536
+ autoRegistered: false,
537
+ warnings: [],
538
+ };
539
+ }
540
+ if (!options.autoRegister) {
541
+ throw new Error("no current agent is registered for this terminal/runtime context; run `agentinbox agent register`");
542
+ }
543
+ await requestRemote(client, "/agents", {
544
+ backend: contextForCurrent.backend,
545
+ runtimeKind: contextForCurrent.runtimeKind,
546
+ runtimeSessionId: contextForCurrent.runtimeSessionId ?? undefined,
547
+ tmuxPaneId: contextForCurrent.tmuxPaneId ?? undefined,
548
+ tty: contextForCurrent.tty ?? undefined,
549
+ termProgram: contextForCurrent.termProgram ?? undefined,
550
+ itermSessionId: contextForCurrent.itermSessionId ?? undefined,
551
+ notifyLeaseMs: undefined,
552
+ });
553
+ const refreshed = await listAgentsWithTargets(client);
554
+ const registered = (0, current_agent_1.resolveCurrentAgent)(refreshed, contextForCurrent);
555
+ if (!registered) {
556
+ throw new Error("failed to resolve current agent after auto-register");
557
+ }
558
+ return {
559
+ agentId: registered.agentId,
560
+ autoRegistered: true,
561
+ warnings: [],
562
+ };
563
+ }
564
+ async function listAgentsWithTargets(client) {
565
+ const response = await requestRemote(client, "/agents?include_targets=true", undefined, "GET");
566
+ return response.data.agents;
567
+ }
437
568
  async function printRemote(client, endpoint, body, method = "POST") {
569
+ const response = await requestRemote(client, endpoint, body, method);
570
+ console.log((0, util_1.jsonResponse)(response.data));
571
+ }
572
+ async function requestRemote(client, endpoint, body, method = "POST") {
438
573
  const response = await client.request(endpoint, body, method);
439
574
  if (response.statusCode < 200 || response.statusCode >= 300) {
440
575
  throw new Error((0, util_1.jsonResponse)(response.data));
441
576
  }
442
- console.log((0, util_1.jsonResponse)(response.data));
577
+ return { data: response.data };
443
578
  }
444
579
  function takeFlagValue(args, flag) {
445
580
  const index = args.indexOf(flag);
446
581
  if (index === -1) {
447
582
  return undefined;
448
583
  }
449
- return args[index + 1];
584
+ const value = args[index + 1];
585
+ if (!value || value.startsWith("--")) {
586
+ throw new Error(`flag ${flag} requires a value`);
587
+ }
588
+ return value;
450
589
  }
451
590
  function hasFlag(args, flag) {
452
591
  return args.includes(flag);
@@ -483,6 +622,82 @@ function buildQuery(params) {
483
622
  const query = search.toString();
484
623
  return query ? `?${query}` : "";
485
624
  }
625
+ function readSubscriptionFilter(args) {
626
+ const filterJson = takeFlagValue(args, "--filter-json");
627
+ const filterFile = takeFlagValue(args, "--filter-file");
628
+ const filterStdin = hasFlag(args, "--filter-stdin");
629
+ const configured = [filterJson != null, filterFile != null, filterStdin].filter(Boolean).length;
630
+ if (configured > 1) {
631
+ throw new Error("subscription add accepts only one of --filter-json, --filter-file, or --filter-stdin");
632
+ }
633
+ if (filterJson != null) {
634
+ return (0, util_1.parseJsonArg)(filterJson, "--filter-json", {
635
+ requireNonEmptyObject: true,
636
+ });
637
+ }
638
+ if (filterFile != null) {
639
+ return (0, util_1.parseJsonArg)(node_fs_1.default.readFileSync(filterFile, "utf8"), `filter file ${filterFile}`, {
640
+ requireNonEmptyObject: true,
641
+ });
642
+ }
643
+ if (filterStdin) {
644
+ const stdin = node_fs_1.default.readFileSync(0, "utf8");
645
+ return (0, util_1.parseJsonArg)(stdin, "stdin filter", {
646
+ requireNonEmptyObject: true,
647
+ });
648
+ }
649
+ return {};
650
+ }
651
+ function withCommandMetadata(data, selection) {
652
+ return {
653
+ ...data,
654
+ agentId: selection.agentId,
655
+ ...(selection.autoRegistered ? { autoRegistered: true } : {}),
656
+ ...(selection.warnings.length > 0 ? { warnings: selection.warnings } : {}),
657
+ };
658
+ }
659
+ function getRequiredTerminalContext() {
660
+ try {
661
+ return (0, terminal_1.detectTerminalContext)(process.env);
662
+ }
663
+ catch (error) {
664
+ const message = error instanceof Error ? error.message : String(error);
665
+ throw new Error(`unable to resolve current agent: ${message}`);
666
+ }
667
+ }
668
+ function tryDetectTerminalContext() {
669
+ try {
670
+ return (0, terminal_1.detectTerminalContext)(process.env);
671
+ }
672
+ catch {
673
+ return null;
674
+ }
675
+ }
676
+ function bindingKindForRecord(record) {
677
+ return record.agent.status === "active" && record.activationTargets.some((target) => target.kind === "terminal" && target.status === "active")
678
+ ? "session_bound"
679
+ : "detached";
680
+ }
681
+ function positionalArgs(args, flagsWithValues) {
682
+ const flags = new Set(flagsWithValues);
683
+ const positionals = [];
684
+ for (let index = 0; index < args.length; index += 1) {
685
+ const token = args[index];
686
+ if (flags.has(token)) {
687
+ index += 1;
688
+ continue;
689
+ }
690
+ if (token.startsWith("--")) {
691
+ continue;
692
+ }
693
+ positionals.push(token);
694
+ }
695
+ return positionals;
696
+ }
697
+ function unexpectedFlags(args, allowedFlags) {
698
+ const allowed = new Set(allowedFlags);
699
+ return args.filter((token) => token.startsWith("--") && !allowed.has(token));
700
+ }
486
701
  function printHelp(path = []) {
487
702
  const key = path[0] ?? "root";
488
703
  const helpByKey = {
@@ -502,10 +717,8 @@ Commands:
502
717
  subscription
503
718
  inbox
504
719
  gc
505
- fixture
506
720
  deliver
507
721
  status
508
- gc
509
722
  version
510
723
  `,
511
724
  serve: `agentinbox serve
@@ -527,6 +740,10 @@ Usage:
527
740
  agentinbox source add <type> <sourceKey> [--config-json JSON] [--config-ref REF]
528
741
  agentinbox source list
529
742
  agentinbox source show <sourceId>
743
+ agentinbox source update <sourceId> [--config-json JSON] [--config-ref REF | --clear-config-ref]
744
+ agentinbox source remove <sourceId>
745
+ agentinbox source pause <remoteSourceId>
746
+ agentinbox source resume <remoteSourceId>
530
747
  agentinbox source schema <sourceType>
531
748
  agentinbox source poll <sourceId>
532
749
  agentinbox source event <sourceId> --native-id ID --event EVENT [--occurred-at ISO8601] [--metadata-json JSON] [--payload-json JSON]
@@ -536,6 +753,7 @@ Usage:
536
753
  Usage:
537
754
  agentinbox agent register [--agent-id ID] [--force-rebind] [--notify-lease-ms N]
538
755
  agentinbox agent list
756
+ agentinbox agent current
539
757
  agentinbox agent show <agentId>
540
758
  agentinbox agent remove <agentId>
541
759
  agentinbox agent target add webhook <agentId> --url URL [--activation-mode MODE] [--notify-lease-ms N]
@@ -545,7 +763,7 @@ Usage:
545
763
  subscription: `agentinbox subscription
546
764
 
547
765
  Usage:
548
- agentinbox subscription add <agentId> <sourceId> [--filter-json JSON] [--start-policy POLICY] [--start-offset N] [--start-time ISO8601]
766
+ agentinbox subscription add <sourceId> [--agent-id ID] [--filter-json JSON | --filter-file PATH | --filter-stdin] [--start-policy POLICY] [--start-offset N] [--start-time ISO8601]
549
767
  agentinbox subscription list [--source-id ID] [--agent-id ID]
550
768
  agentinbox subscription show <subscriptionId>
551
769
  agentinbox subscription remove <subscriptionId>
@@ -558,15 +776,10 @@ Usage:
558
776
  Usage:
559
777
  agentinbox inbox list
560
778
  agentinbox inbox show <agentId>
561
- agentinbox inbox read <agentId> [--after-item ID] [--include-acked]
562
- agentinbox inbox watch <agentId> [--after-item ID] [--include-acked] [--heartbeat-ms N]
563
- agentinbox inbox ack <agentId> (--through <itemId> | --item <itemId> | --all)
779
+ agentinbox inbox read [--agent-id ID] [--after-item ID] [--include-acked]
780
+ agentinbox inbox watch [--agent-id ID] [--after-item ID] [--include-acked] [--heartbeat-ms N]
781
+ agentinbox inbox ack [--agent-id ID] (--through <itemId> | --item <itemId> | --all)
564
782
  agentinbox inbox compact <agentId>
565
- `,
566
- fixture: `agentinbox fixture
567
-
568
- Usage:
569
- agentinbox fixture emit <sourceId> [--native-id ID] [--event EVENT] [--metadata-json JSON] [--payload-json JSON]
570
783
  `,
571
784
  deliver: `agentinbox deliver
572
785
 
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.summarizeActivationTarget = summarizeActivationTarget;
4
+ exports.resolveCurrentAgent = resolveCurrentAgent;
5
+ exports.annotateAgents = annotateAgents;
6
+ function summarizeActivationTarget(target) {
7
+ if (target.kind === "terminal") {
8
+ return {
9
+ targetId: target.targetId,
10
+ kind: "terminal",
11
+ status: target.status,
12
+ backend: target.backend,
13
+ tmuxPaneId: target.tmuxPaneId ?? null,
14
+ tty: target.tty ?? null,
15
+ termProgram: target.termProgram ?? null,
16
+ itermSessionId: target.itermSessionId ?? null,
17
+ runtimeKind: target.runtimeKind ?? null,
18
+ runtimeSessionId: target.runtimeSessionId ?? null,
19
+ };
20
+ }
21
+ return {
22
+ targetId: target.targetId,
23
+ kind: "webhook",
24
+ status: target.status,
25
+ };
26
+ }
27
+ function resolveCurrentAgent(agents, context) {
28
+ if (!context) {
29
+ return null;
30
+ }
31
+ const agent = resolveAgentRecord(agents, context);
32
+ if (!agent) {
33
+ return null;
34
+ }
35
+ return {
36
+ agentId: agent.agent.agentId,
37
+ bindingKind: bindingKindForAgent(agent),
38
+ matchesCurrentTerminal: matchesCurrentTerminal(agent, context),
39
+ matchesCurrentRuntime: matchesCurrentRuntime(agent, context),
40
+ terminalIdentity: terminalIdentityForAgent(agent),
41
+ };
42
+ }
43
+ function annotateAgents(agents, context) {
44
+ const current = resolveCurrentAgent(agents, context);
45
+ return {
46
+ currentAgentId: current?.agentId ?? null,
47
+ agents: agents.map((entry) => ({
48
+ ...entry.agent,
49
+ bindingKind: bindingKindForAgent(entry),
50
+ matchesCurrentTerminal: context ? matchesCurrentTerminal(entry, context) : false,
51
+ matchesCurrentRuntime: context ? matchesCurrentRuntime(entry, context) : false,
52
+ terminalIdentity: terminalIdentityForAgent(entry),
53
+ isCurrent: current?.agentId === entry.agent.agentId,
54
+ })),
55
+ };
56
+ }
57
+ function resolveAgentRecord(agents, context) {
58
+ if (context.tmuxPaneId) {
59
+ const match = agents.find((agent) => activeTerminalTargets(agent).some((target) => target.backend === "tmux" && target.tmuxPaneId === context.tmuxPaneId));
60
+ if (match) {
61
+ return match;
62
+ }
63
+ }
64
+ if (context.itermSessionId) {
65
+ const match = agents.find((agent) => activeTerminalTargets(agent).some((target) => target.backend === "iterm2" && target.itermSessionId === context.itermSessionId));
66
+ if (match) {
67
+ return match;
68
+ }
69
+ }
70
+ if (context.tty) {
71
+ const match = agents.find((agent) => activeTerminalTargets(agent).some((target) => target.tty === context.tty));
72
+ if (match) {
73
+ return match;
74
+ }
75
+ }
76
+ if (context.runtimeSessionId) {
77
+ const match = agents.find((agent) => matchesCurrentRuntime(agent, context));
78
+ if (match) {
79
+ return match;
80
+ }
81
+ }
82
+ return null;
83
+ }
84
+ function bindingKindForAgent(agent) {
85
+ return activeTerminalTargets(agent).length > 0 ? "session_bound" : "detached";
86
+ }
87
+ function terminalTargets(agent) {
88
+ return agent.activationTargets.filter((target) => target.kind === "terminal");
89
+ }
90
+ function activeTerminalTargets(agent) {
91
+ if (agent.agent.status !== "active") {
92
+ return [];
93
+ }
94
+ return terminalTargets(agent).filter((target) => target.status === "active");
95
+ }
96
+ function terminalIdentityForAgent(agent) {
97
+ const target = activeTerminalTargets(agent)[0];
98
+ if (!target) {
99
+ return null;
100
+ }
101
+ if (target.tmuxPaneId) {
102
+ return `tmux:${target.tmuxPaneId}`;
103
+ }
104
+ if (target.itermSessionId) {
105
+ return `iterm2:${target.itermSessionId}`;
106
+ }
107
+ if (target.tty) {
108
+ return `tty:${target.tty}`;
109
+ }
110
+ return null;
111
+ }
112
+ function matchesCurrentTerminal(agent, context) {
113
+ return activeTerminalTargets(agent).some((target) => (context.tmuxPaneId != null && target.tmuxPaneId === context.tmuxPaneId)
114
+ || (context.itermSessionId != null && target.itermSessionId === context.itermSessionId)
115
+ || (context.tty != null && target.tty === context.tty));
116
+ }
117
+ function matchesCurrentRuntime(agent, context) {
118
+ if (agent.agent.status !== "active") {
119
+ return false;
120
+ }
121
+ if (!context.runtimeSessionId) {
122
+ return false;
123
+ }
124
+ return activeTerminalTargets(agent).some((target) => target.runtimeKind === context.runtimeKind && target.runtimeSessionId === context.runtimeSessionId) || (agent.agent.runtimeKind === context.runtimeKind
125
+ && agent.agent.runtimeSessionId === context.runtimeSessionId);
126
+ }