@holon-run/agentinbox 0.2.0 → 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/dist/src/cli.js CHANGED
@@ -180,6 +180,7 @@ async function main() {
180
180
  backend: detected.backend,
181
181
  runtimeKind: detected.runtimeKind,
182
182
  runtimeSessionId: detected.runtimeSessionId ?? undefined,
183
+ runtimePid: detected.runtimePid ?? undefined,
183
184
  tmuxPaneId: detected.tmuxPaneId ?? undefined,
184
185
  tty: detected.tty ?? undefined,
185
186
  termProgram: detected.termProgram ?? undefined,
@@ -344,6 +345,62 @@ async function main() {
344
345
  });
345
346
  return;
346
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
+ }
347
404
  if (command === "inbox" && normalized[1] === "list") {
348
405
  await printRemote(client, "/agents", undefined, "GET");
349
406
  return;
@@ -374,6 +431,23 @@ async function main() {
374
431
  console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
375
432
  return;
376
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
+ }
377
451
  if (command === "inbox" && normalized[1] === "watch") {
378
452
  const args = normalized.slice(2);
379
453
  if (positionalArgs(args, ["--agent-id", "--after-item", "--heartbeat-ms"]).length > 0) {
@@ -592,6 +666,7 @@ async function selectAgentForCommand(client, options) {
592
666
  backend: contextForCurrent.backend,
593
667
  runtimeKind: contextForCurrent.runtimeKind,
594
668
  runtimeSessionId: contextForCurrent.runtimeSessionId ?? undefined,
669
+ runtimePid: contextForCurrent.runtimePid ?? undefined,
595
670
  tmuxPaneId: contextForCurrent.tmuxPaneId ?? undefined,
596
671
  tty: contextForCurrent.tty ?? undefined,
597
672
  termProgram: contextForCurrent.termProgram ?? undefined,
@@ -648,6 +723,30 @@ function parseOptionalNumber(value) {
648
723
  }
649
724
  return parsed;
650
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
+ }
651
750
  function normalizeHelpArgs(args) {
652
751
  if (args[0] !== "help") {
653
752
  return args;
@@ -762,6 +861,7 @@ Commands:
762
861
  daemon
763
862
  source
764
863
  agent
864
+ timer
765
865
  subscription
766
866
  inbox
767
867
  gc
@@ -808,6 +908,15 @@ Usage:
808
908
  agentinbox agent target add webhook <agentId> --url URL [--activation-mode MODE] [--notify-lease-ms N]
809
909
  agentinbox agent target list <agentId>
810
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>
811
920
  `,
812
921
  subscription: `agentinbox subscription
813
922
 
@@ -826,6 +935,7 @@ Usage:
826
935
  agentinbox inbox list
827
936
  agentinbox inbox show <agentId>
828
937
  agentinbox inbox read [--agent-id ID] [--after-item ID] [--include-acked]
938
+ agentinbox inbox send --agent-id ID --message TEXT [--sender SENDER]
829
939
  agentinbox inbox watch [--agent-id ID] [--after-item ID] [--include-acked] [--heartbeat-ms N]
830
940
  agentinbox inbox ack [--agent-id ID] (--through <itemId> | --item <itemId> | --all)
831
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 {
package/dist/src/http.js CHANGED
@@ -419,6 +419,7 @@ function buildFastifyServer(service) {
419
419
  backend: { type: "string", minLength: 1 },
420
420
  runtimeKind: { type: "string" },
421
421
  runtimeSessionId: { type: "string" },
422
+ runtimePid: { type: "integer", minimum: 1 },
422
423
  tmuxPaneId: { type: "string" },
423
424
  tty: { type: "string" },
424
425
  termProgram: { type: "string" },
@@ -439,6 +440,7 @@ function buildFastifyServer(service) {
439
440
  backend: String(body.backend),
440
441
  runtimeKind: optionalString(body.runtimeKind),
441
442
  runtimeSessionId: optionalString(body.runtimeSessionId),
443
+ runtimePid: typeof body.runtimePid === "number" ? body.runtimePid : null,
442
444
  mode: "agent_prompt",
443
445
  tmuxPaneId: optionalString(body.tmuxPaneId),
444
446
  tty: optionalString(body.tty),
@@ -563,6 +565,123 @@ function buildFastifyServer(service) {
563
565
  const params = request.params;
564
566
  return service.removeActivationTarget(decodeURIComponent(params.agentId), decodeURIComponent(params.targetId));
565
567
  });
568
+ app.get("/timers", {
569
+ schema: {
570
+ tags: ["timers"],
571
+ querystring: {
572
+ type: "object",
573
+ additionalProperties: false,
574
+ properties: {
575
+ agent_id: { type: "string" },
576
+ },
577
+ },
578
+ response: {
579
+ 200: {
580
+ type: "object",
581
+ required: ["timers"],
582
+ properties: {
583
+ timers: { type: "array", items: jsonObjectSchema },
584
+ },
585
+ },
586
+ },
587
+ },
588
+ }, async (request) => {
589
+ const query = request.query;
590
+ return { timers: service.listTimers(query.agent_id) };
591
+ });
592
+ app.post("/timers", {
593
+ schema: {
594
+ tags: ["timers"],
595
+ body: {
596
+ type: "object",
597
+ additionalProperties: false,
598
+ required: ["agentId", "message"],
599
+ properties: {
600
+ agentId: { type: "string", minLength: 1 },
601
+ at: { type: "string", minLength: 1 },
602
+ every: { type: "integer", minimum: 60000 },
603
+ cron: { type: "string", minLength: 1 },
604
+ timezone: { type: "string", minLength: 1 },
605
+ message: { type: "string", minLength: 1 },
606
+ sender: { type: "string", minLength: 1 },
607
+ },
608
+ },
609
+ response: {
610
+ 200: jsonObjectSchema,
611
+ 400: errorResponseSchema,
612
+ },
613
+ },
614
+ }, async (request) => {
615
+ const body = request.body;
616
+ return service.registerTimer({
617
+ agentId: String(body.agentId),
618
+ at: optionalString(body.at) ?? null,
619
+ every: typeof body.every === "number" ? body.every : null,
620
+ cron: optionalString(body.cron) ?? null,
621
+ timezone: optionalString(body.timezone) ?? null,
622
+ message: String(body.message),
623
+ sender: optionalString(body.sender) ?? null,
624
+ });
625
+ });
626
+ app.post("/timers/:scheduleId/pause", {
627
+ schema: {
628
+ tags: ["timers"],
629
+ params: {
630
+ type: "object",
631
+ required: ["scheduleId"],
632
+ properties: {
633
+ scheduleId: { type: "string", minLength: 1 },
634
+ },
635
+ },
636
+ response: {
637
+ 200: jsonObjectSchema,
638
+ 400: errorResponseSchema,
639
+ 404: errorResponseSchema,
640
+ },
641
+ },
642
+ }, async (request) => {
643
+ const params = request.params;
644
+ return service.pauseTimer(decodeURIComponent(params.scheduleId));
645
+ });
646
+ app.post("/timers/:scheduleId/resume", {
647
+ schema: {
648
+ tags: ["timers"],
649
+ params: {
650
+ type: "object",
651
+ required: ["scheduleId"],
652
+ properties: {
653
+ scheduleId: { type: "string", minLength: 1 },
654
+ },
655
+ },
656
+ response: {
657
+ 200: jsonObjectSchema,
658
+ 400: errorResponseSchema,
659
+ 404: errorResponseSchema,
660
+ },
661
+ },
662
+ }, async (request) => {
663
+ const params = request.params;
664
+ return service.resumeTimer(decodeURIComponent(params.scheduleId));
665
+ });
666
+ app.delete("/timers/:scheduleId", {
667
+ schema: {
668
+ tags: ["timers"],
669
+ params: {
670
+ type: "object",
671
+ required: ["scheduleId"],
672
+ properties: {
673
+ scheduleId: { type: "string", minLength: 1 },
674
+ },
675
+ },
676
+ response: {
677
+ 200: jsonObjectSchema,
678
+ 404: errorResponseSchema,
679
+ },
680
+ },
681
+ }, async (request) => {
682
+ const params = request.params;
683
+ return service.removeTimer(decodeURIComponent(params.scheduleId));
684
+ });
566
685
  app.get("/subscriptions", {
567
686
  schema: {
568
687
  tags: ["subscriptions"],
@@ -812,6 +931,39 @@ function buildFastifyServer(service) {
812
931
  }),
813
932
  };
814
933
  });
934
+ app.post("/agents/:agentId/inbox/items", {
935
+ schema: {
936
+ tags: ["inbox"],
937
+ params: {
938
+ type: "object",
939
+ required: ["agentId"],
940
+ properties: {
941
+ agentId: { type: "string", minLength: 1 },
942
+ },
943
+ },
944
+ body: {
945
+ type: "object",
946
+ additionalProperties: false,
947
+ required: ["message"],
948
+ properties: {
949
+ message: { type: "string", minLength: 1 },
950
+ sender: { type: "string", minLength: 1 },
951
+ },
952
+ },
953
+ response: {
954
+ 200: jsonObjectSchema,
955
+ 400: errorResponseSchema,
956
+ 404: errorResponseSchema,
957
+ },
958
+ },
959
+ }, async (request) => {
960
+ const params = request.params;
961
+ const body = request.body;
962
+ return service.addDirectInboxTextMessage(decodeURIComponent(params.agentId), {
963
+ message: body.message,
964
+ sender: body.sender ?? null,
965
+ });
966
+ });
815
967
  app.get("/agents/:agentId/inbox/watch", {
816
968
  schema: {
817
969
  tags: ["inbox"],
@@ -1060,7 +1212,11 @@ function normalizeValidationMessage(message) {
1060
1212
  return message;
1061
1213
  }
1062
1214
  function isBadRequestError(message) {
1063
- return (message.startsWith("manual append is not supported") ||
1215
+ return (message.startsWith("direct inbox ") ||
1216
+ message.startsWith("timers require ") ||
1217
+ message.startsWith("timer ") ||
1218
+ message.startsWith("invalid timezone: ") ||
1219
+ message.startsWith("manual append is not supported") ||
1064
1220
  message.startsWith("sources/events requires") ||
1065
1221
  message.startsWith("source remove requires") ||
1066
1222
  message.startsWith("deliveryHandle requires") ||