@holon-run/agentinbox 0.1.4 → 0.3.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.
package/README.md CHANGED
@@ -136,6 +136,7 @@ Create a local source and publish an event:
136
136
  agentinbox source add local_event local-demo
137
137
  agentinbox subscription add <source_id>
138
138
  agentinbox subscription add <source_id> --agent-id <agent_id>
139
+ agentinbox subscription add <source_id> --tracked-resource-ref pr:373 --cleanup-policy-json '{"mode":"manual"}'
139
140
  agentinbox subscription add <source_id> --filter-file ./filter.json
140
141
  cat filter.json | agentinbox subscription add <source_id> --filter-stdin
141
142
  agentinbox source event <source_id> --native-id demo-1 --event local.demo
@@ -1,9 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AdapterRegistry = void 0;
4
+ const paths_1 = require("./paths");
4
5
  const feishu_1 = require("./sources/feishu");
5
6
  const github_1 = require("./sources/github");
6
7
  const remote_1 = require("./sources/remote");
8
+ const remote_profiles_1 = require("./sources/remote_profiles");
9
+ const source_resolution_1 = require("./source_resolution");
7
10
  class NoopSourceAdapter {
8
11
  sourceType;
9
12
  constructor(sourceType) {
@@ -37,11 +40,15 @@ class AdapterRegistry {
37
40
  defaultDelivery = new NoopDeliveryAdapter();
38
41
  feishuDelivery = new feishu_1.FeishuDeliveryAdapter();
39
42
  githubDelivery = new github_1.GithubDeliveryAdapter();
43
+ homeDir;
44
+ remoteProfileRegistry;
40
45
  constructor(store, appendSourceEvent, options) {
46
+ this.homeDir = options?.homeDir ?? (0, paths_1.resolveAgentInboxHome)(process.env);
47
+ this.remoteProfileRegistry = options?.remoteProfileRegistry ?? new remote_profiles_1.RemoteSourceProfileRegistry();
41
48
  this.remoteSource = new remote_1.RemoteSourceRuntime(store, appendSourceEvent, {
42
- homeDir: options?.homeDir,
49
+ homeDir: this.homeDir,
43
50
  client: options?.remoteSourceClient,
44
- profileRegistry: options?.remoteProfileRegistry,
51
+ profileRegistry: this.remoteProfileRegistry,
45
52
  });
46
53
  }
47
54
  sourceAdapterFor(type) {
@@ -109,6 +116,30 @@ class AdapterRegistry {
109
116
  const adapter = this.sourceAdapterFor(source.sourceType);
110
117
  await adapter.removeSource?.(source.sourceId);
111
118
  }
119
+ async resolveSourceIdentity(source) {
120
+ return (0, source_resolution_1.resolveSourceIdentity)(source, {
121
+ homeDir: this.homeDir,
122
+ profileRegistry: this.remoteProfileRegistry,
123
+ });
124
+ }
125
+ async resolveSourceSchema(source) {
126
+ return (0, source_resolution_1.resolveSourceSchema)(source, {
127
+ homeDir: this.homeDir,
128
+ profileRegistry: this.remoteProfileRegistry,
129
+ });
130
+ }
131
+ async projectLifecycleSignal(source, rawPayload) {
132
+ if (source.sourceType === "local_event") {
133
+ return null;
134
+ }
135
+ return this.remoteSource.projectLifecycleSignal(source, rawPayload);
136
+ }
137
+ async expandSubscriptionShortcut(source, input) {
138
+ if (source.sourceType === "local_event") {
139
+ return null;
140
+ }
141
+ return this.remoteSource.expandSubscriptionShortcut(source, input);
142
+ }
112
143
  status() {
113
144
  return {
114
145
  remote: this.remoteSource.status?.() ?? {},
package/dist/src/cli.js CHANGED
@@ -76,11 +76,16 @@ async function main() {
76
76
  return;
77
77
  }
78
78
  if (command === "source" && normalized[1] === "remove") {
79
- const sourceId = normalized[2];
80
- if (!sourceId) {
81
- throw new Error("usage: agentinbox source remove <sourceId>");
79
+ const removeArgs = normalized.slice(2);
80
+ const positionals = positionalArgs(removeArgs, ["--with-subscriptions"]);
81
+ const sourceId = positionals[0];
82
+ if (!sourceId || positionals[1]) {
83
+ throw new Error("usage: agentinbox source remove <sourceId> [--with-subscriptions]");
82
84
  }
83
- await printRemote(client, `/sources/${encodeURIComponent(sourceId)}`, undefined, "DELETE");
85
+ const query = buildQuery({
86
+ with_subscriptions: hasFlag(normalized, "--with-subscriptions") ? "true" : undefined,
87
+ });
88
+ await printRemote(client, `/sources/${encodeURIComponent(sourceId)}${query}`, undefined, "DELETE");
84
89
  return;
85
90
  }
86
91
  if (command === "source" && normalized[1] === "update") {
@@ -120,11 +125,27 @@ async function main() {
120
125
  return;
121
126
  }
122
127
  if (command === "source" && normalized[1] === "schema") {
123
- const sourceType = normalized[2];
124
- if (!sourceType) {
125
- throw new Error("usage: agentinbox source schema <sourceType>");
128
+ if (normalized[2] === "preview") {
129
+ const sourceRef = normalized[3];
130
+ if (!sourceRef) {
131
+ throw new Error("usage: agentinbox source schema preview <sourceKind|sourceType> [--config-json JSON] [--config-ref REF]");
132
+ }
133
+ await printRemote(client, "/sources/schema-preview", {
134
+ sourceRef,
135
+ configRef: takeFlagValue(normalized, "--config-ref") ?? undefined,
136
+ config: (0, util_1.parseJsonArg)(takeFlagValue(normalized, "--config-json")),
137
+ });
138
+ return;
139
+ }
140
+ const sourceRef = normalized[2];
141
+ if (!sourceRef) {
142
+ throw new Error("usage: agentinbox source schema <sourceId|sourceType>");
126
143
  }
127
- await printRemote(client, `/source-types/${encodeURIComponent(sourceType)}/schema`, undefined, "GET");
144
+ if (sourceRef.startsWith("src_")) {
145
+ await printRemote(client, `/sources/${encodeURIComponent(sourceRef)}/schema`, undefined, "GET");
146
+ return;
147
+ }
148
+ await printRemote(client, `/source-types/${encodeURIComponent(sourceRef)}/schema`, undefined, "GET");
128
149
  return;
129
150
  }
130
151
  if (command === "source" && normalized[1] === "poll") {
@@ -159,6 +180,7 @@ async function main() {
159
180
  backend: detected.backend,
160
181
  runtimeKind: detected.runtimeKind,
161
182
  runtimeSessionId: detected.runtimeSessionId ?? undefined,
183
+ runtimePid: detected.runtimePid ?? undefined,
162
184
  tmuxPaneId: detected.tmuxPaneId ?? undefined,
163
185
  tty: detected.tty ?? undefined,
164
186
  termProgram: detected.termProgram ?? undefined,
@@ -223,19 +245,46 @@ async function main() {
223
245
  }
224
246
  if (command === "subscription" && normalized[1] === "add") {
225
247
  const args = normalized.slice(2);
226
- const positionals = positionalArgs(args, ["--agent-id", "--filter-json", "--filter-file", "--start-policy", "--start-offset", "--start-time"]);
248
+ const positionals = positionalArgs(args, [
249
+ "--agent-id",
250
+ "--shortcut",
251
+ "--shortcut-args-json",
252
+ "--filter-json",
253
+ "--filter-file",
254
+ "--tracked-resource-ref",
255
+ "--cleanup-policy-json",
256
+ "--start-policy",
257
+ "--start-offset",
258
+ "--start-time",
259
+ ]);
227
260
  const sourceId = positionals[0];
228
261
  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]");
262
+ throw new Error("usage: 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]");
230
263
  }
231
264
  const selection = await selectAgentForCommand(client, {
232
265
  explicitAgentId: takeFlagValue(normalized, "--agent-id"),
233
266
  autoRegister: true,
234
267
  });
268
+ const shortcutName = takeFlagValue(normalized, "--shortcut");
269
+ const shortcutArgsJson = takeFlagValue(normalized, "--shortcut-args-json");
270
+ if (shortcutName && (hasFlag(normalized, "--filter-stdin") || takeFlagValue(normalized, "--filter-json") != null || takeFlagValue(normalized, "--filter-file") != null || takeFlagValue(normalized, "--tracked-resource-ref") != null || takeFlagValue(normalized, "--cleanup-policy-json") != null)) {
271
+ throw new Error("subscription add shortcut does not allow filter, trackedResourceRef, or cleanupPolicy flags");
272
+ }
273
+ const cleanupPolicyJson = takeFlagValue(normalized, "--cleanup-policy-json");
235
274
  const response = await requestRemote(client, "/subscriptions", {
236
275
  agentId: selection.agentId,
237
276
  sourceId,
238
- filter: readSubscriptionFilter(normalized),
277
+ shortcut: shortcutName
278
+ ? {
279
+ name: shortcutName,
280
+ args: shortcutArgsJson != null ? (0, util_1.parseJsonArg)(shortcutArgsJson, "--shortcut-args-json") : {},
281
+ }
282
+ : undefined,
283
+ filter: shortcutName ? undefined : readSubscriptionFilter(normalized),
284
+ trackedResourceRef: takeFlagValue(normalized, "--tracked-resource-ref") ?? undefined,
285
+ cleanupPolicy: cleanupPolicyJson != null
286
+ ? (0, util_1.parseJsonArg)(cleanupPolicyJson, "--cleanup-policy-json")
287
+ : undefined,
239
288
  startPolicy: takeFlagValue(normalized, "--start-policy") ?? undefined,
240
289
  startOffset: parseOptionalNumber(takeFlagValue(normalized, "--start-offset")),
241
290
  startTime: takeFlagValue(normalized, "--start-time") ?? undefined,
@@ -296,6 +345,62 @@ async function main() {
296
345
  });
297
346
  return;
298
347
  }
348
+ if (command === "timer" && normalized[1] === "add") {
349
+ const args = normalized.slice(2);
350
+ const allowedFlags = ["--agent-id", "--at", "--every", "--cron", "--timezone", "--message", "--sender"];
351
+ if (positionalArgs(args, ["--agent-id", "--at", "--every", "--cron", "--timezone", "--message", "--sender"]).length > 0 || unexpectedFlags(args, allowedFlags).length > 0) {
352
+ throw new Error("usage: agentinbox timer add --agent-id ID (--at ISO8601 | --every DURATION | --cron EXPR) --message TEXT [--timezone TZ] [--sender SENDER]");
353
+ }
354
+ const agentId = takeFlagValue(normalized, "--agent-id");
355
+ const message = takeFlagValue(normalized, "--message");
356
+ const at = takeFlagValue(normalized, "--at");
357
+ const every = takeFlagValue(normalized, "--every");
358
+ const cron = takeFlagValue(normalized, "--cron");
359
+ if (!agentId || !message || [at, every, cron].filter(Boolean).length !== 1) {
360
+ throw new Error("usage: agentinbox timer add --agent-id ID (--at ISO8601 | --every DURATION | --cron EXPR) --message TEXT [--timezone TZ] [--sender SENDER]");
361
+ }
362
+ await printRemote(client, "/timers", {
363
+ agentId,
364
+ at: at ?? undefined,
365
+ every: every ? parseDurationMs(every) : undefined,
366
+ cron: cron ?? undefined,
367
+ timezone: takeFlagValue(normalized, "--timezone") ?? undefined,
368
+ message,
369
+ sender: takeFlagValue(normalized, "--sender") ?? undefined,
370
+ });
371
+ return;
372
+ }
373
+ if (command === "timer" && normalized[1] === "list") {
374
+ const query = buildQuery({
375
+ agent_id: takeFlagValue(normalized, "--agent-id"),
376
+ });
377
+ await printRemote(client, `/timers${query}`, undefined, "GET");
378
+ return;
379
+ }
380
+ if (command === "timer" && normalized[1] === "pause") {
381
+ const scheduleId = normalized[2];
382
+ if (!scheduleId) {
383
+ throw new Error("usage: agentinbox timer pause <scheduleId>");
384
+ }
385
+ await printRemote(client, `/timers/${encodeURIComponent(scheduleId)}/pause`, {});
386
+ return;
387
+ }
388
+ if (command === "timer" && normalized[1] === "resume") {
389
+ const scheduleId = normalized[2];
390
+ if (!scheduleId) {
391
+ throw new Error("usage: agentinbox timer resume <scheduleId>");
392
+ }
393
+ await printRemote(client, `/timers/${encodeURIComponent(scheduleId)}/resume`, {});
394
+ return;
395
+ }
396
+ if (command === "timer" && normalized[1] === "remove") {
397
+ const scheduleId = normalized[2];
398
+ if (!scheduleId) {
399
+ throw new Error("usage: agentinbox timer remove <scheduleId>");
400
+ }
401
+ await printRemote(client, `/timers/${encodeURIComponent(scheduleId)}`, undefined, "DELETE");
402
+ return;
403
+ }
299
404
  if (command === "inbox" && normalized[1] === "list") {
300
405
  await printRemote(client, "/agents", undefined, "GET");
301
406
  return;
@@ -326,6 +431,23 @@ async function main() {
326
431
  console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
327
432
  return;
328
433
  }
434
+ if (command === "inbox" && normalized[1] === "send") {
435
+ const args = normalized.slice(2);
436
+ const allowedFlags = ["--agent-id", "--message", "--sender"];
437
+ if (positionalArgs(args, ["--agent-id", "--message", "--sender"]).length > 0 || unexpectedFlags(args, allowedFlags).length > 0) {
438
+ throw new Error("usage: agentinbox inbox send --agent-id ID --message TEXT [--sender SENDER]");
439
+ }
440
+ const agentId = takeFlagValue(normalized, "--agent-id");
441
+ const message = takeFlagValue(normalized, "--message");
442
+ if (!agentId || !message) {
443
+ throw new Error("usage: agentinbox inbox send --agent-id ID --message TEXT [--sender SENDER]");
444
+ }
445
+ await printRemote(client, `/agents/${encodeURIComponent(agentId)}/inbox/items`, {
446
+ message,
447
+ sender: takeFlagValue(normalized, "--sender") ?? undefined,
448
+ });
449
+ return;
450
+ }
329
451
  if (command === "inbox" && normalized[1] === "watch") {
330
452
  const args = normalized.slice(2);
331
453
  if (positionalArgs(args, ["--agent-id", "--after-item", "--heartbeat-ms"]).length > 0) {
@@ -544,6 +666,7 @@ async function selectAgentForCommand(client, options) {
544
666
  backend: contextForCurrent.backend,
545
667
  runtimeKind: contextForCurrent.runtimeKind,
546
668
  runtimeSessionId: contextForCurrent.runtimeSessionId ?? undefined,
669
+ runtimePid: contextForCurrent.runtimePid ?? undefined,
547
670
  tmuxPaneId: contextForCurrent.tmuxPaneId ?? undefined,
548
671
  tty: contextForCurrent.tty ?? undefined,
549
672
  termProgram: contextForCurrent.termProgram ?? undefined,
@@ -600,6 +723,30 @@ function parseOptionalNumber(value) {
600
723
  }
601
724
  return parsed;
602
725
  }
726
+ function parseDurationMs(value) {
727
+ if (/^\d+$/.test(value)) {
728
+ return Number(value);
729
+ }
730
+ const match = /^(\d+)(ms|s|m|h|d)$/.exec(value);
731
+ if (!match) {
732
+ throw new Error(`invalid duration: ${value}`);
733
+ }
734
+ const amount = Number(match[1]);
735
+ switch (match[2]) {
736
+ case "ms":
737
+ return amount;
738
+ case "s":
739
+ return amount * 1_000;
740
+ case "m":
741
+ return amount * 60_000;
742
+ case "h":
743
+ return amount * 60 * 60_000;
744
+ case "d":
745
+ return amount * 24 * 60 * 60_000;
746
+ default:
747
+ throw new Error(`invalid duration: ${value}`);
748
+ }
749
+ }
603
750
  function normalizeHelpArgs(args) {
604
751
  if (args[0] !== "help") {
605
752
  return args;
@@ -714,6 +861,7 @@ Commands:
714
861
  daemon
715
862
  source
716
863
  agent
864
+ timer
717
865
  subscription
718
866
  inbox
719
867
  gc
@@ -741,10 +889,11 @@ Usage:
741
889
  agentinbox source list
742
890
  agentinbox source show <sourceId>
743
891
  agentinbox source update <sourceId> [--config-json JSON] [--config-ref REF | --clear-config-ref]
744
- agentinbox source remove <sourceId>
892
+ agentinbox source remove <sourceId> [--with-subscriptions]
745
893
  agentinbox source pause <remoteSourceId>
746
894
  agentinbox source resume <remoteSourceId>
747
- agentinbox source schema <sourceType>
895
+ agentinbox source schema <sourceId|sourceType>
896
+ agentinbox source schema preview <sourceKind|sourceType> [--config-json JSON] [--config-ref REF]
748
897
  agentinbox source poll <sourceId>
749
898
  agentinbox source event <sourceId> --native-id ID --event EVENT [--occurred-at ISO8601] [--metadata-json JSON] [--payload-json JSON]
750
899
  `,
@@ -759,11 +908,20 @@ Usage:
759
908
  agentinbox agent target add webhook <agentId> --url URL [--activation-mode MODE] [--notify-lease-ms N]
760
909
  agentinbox agent target list <agentId>
761
910
  agentinbox agent target remove <agentId> <targetId>
911
+ `,
912
+ timer: `agentinbox timer
913
+
914
+ Usage:
915
+ agentinbox timer add --agent-id ID (--at ISO8601 | --every DURATION | --cron EXPR) --message TEXT [--timezone TZ] [--sender SENDER]
916
+ agentinbox timer list [--agent-id ID]
917
+ agentinbox timer pause <scheduleId>
918
+ agentinbox timer resume <scheduleId>
919
+ agentinbox timer remove <scheduleId>
762
920
  `,
763
921
  subscription: `agentinbox subscription
764
922
 
765
923
  Usage:
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]
924
+ 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]
767
925
  agentinbox subscription list [--source-id ID] [--agent-id ID]
768
926
  agentinbox subscription show <subscriptionId>
769
927
  agentinbox subscription remove <subscriptionId>
@@ -777,6 +935,7 @@ Usage:
777
935
  agentinbox inbox list
778
936
  agentinbox inbox show <agentId>
779
937
  agentinbox inbox read [--agent-id ID] [--after-item ID] [--include-acked]
938
+ agentinbox inbox send --agent-id ID --message TEXT [--sender SENDER]
780
939
  agentinbox inbox watch [--agent-id ID] [--after-item ID] [--include-acked] [--heartbeat-ms N]
781
940
  agentinbox inbox ack [--agent-id ID] (--through <itemId> | --item <itemId> | --all)
782
941
  agentinbox inbox compact <agentId>
@@ -16,6 +16,7 @@ function summarizeActivationTarget(target) {
16
16
  itermSessionId: target.itermSessionId ?? null,
17
17
  runtimeKind: target.runtimeKind ?? null,
18
18
  runtimeSessionId: target.runtimeSessionId ?? null,
19
+ runtimePid: target.runtimePid ?? null,
19
20
  };
20
21
  }
21
22
  return {