@holon-run/agentinbox 1.0.3 → 1.0.5
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 +13 -6
- package/dist/src/adapters.js +12 -0
- package/dist/src/cli.js +242 -62
- package/dist/src/current_agent.js +31 -0
- package/dist/src/http.js +127 -16
- package/dist/src/service.js +39 -30
- package/dist/src/source_hosts.js +2 -4
- package/dist/src/source_schema.js +1 -3
- package/dist/src/sources/feishu.js +1030 -31
- package/dist/src/sources/github.js +15 -6
- package/dist/src/sources/remote.js +25 -0
- package/dist/src/sources/remote_modules.js +30 -6
- package/dist/src/store.js +92 -30
- package/drizzle/migrations/0004_provider_raw_payload.sql +3 -0
- package/drizzle/schema.ts +2 -0
- package/package.json +3 -2
- package/skills/README.md +2 -2
- package/skills/agentinbox/SKILL.md +59 -14
package/README.md
CHANGED
|
@@ -13,8 +13,9 @@ In practice, that means `AgentInbox` can:
|
|
|
13
13
|
|
|
14
14
|
- share one GitHub or Feishu source across multiple local agents
|
|
15
15
|
- materialize those events into durable inboxes
|
|
16
|
-
-
|
|
17
|
-
|
|
16
|
+
- activate terminal-backed sessions in `tmux` or `iTerm2`, or Holon agents
|
|
17
|
+
through runtime-provided webhook triggers, without embedding connector logic
|
|
18
|
+
in the agent runtime
|
|
18
19
|
|
|
19
20
|
## Event Flow
|
|
20
21
|
|
|
@@ -111,7 +112,7 @@ node dist/src/cli.js --help
|
|
|
111
112
|
|
|
112
113
|
## Recommended Onboarding
|
|
113
114
|
|
|
114
|
-
If you are using Codex
|
|
115
|
+
If you are using Codex, Claude Code, or Holon, start with the bundled AgentInbox skill:
|
|
115
116
|
|
|
116
117
|
- repo copy: [`skills/agentinbox/SKILL.md`](./skills/agentinbox/SKILL.md)
|
|
117
118
|
- docs site copy: `https://agentinbox.holon.run/skills/agentinbox/SKILL`
|
|
@@ -120,7 +121,7 @@ If you use the community `skills` installer, you can install the bundled skill
|
|
|
120
121
|
directly:
|
|
121
122
|
|
|
122
123
|
```bash
|
|
123
|
-
npx skills add holon-run/agentinbox --skill agentinbox -a codex -a claude-code
|
|
124
|
+
npx skills add holon-run/agentinbox --skill agentinbox -a codex -a claude-code -a holon
|
|
124
125
|
```
|
|
125
126
|
|
|
126
127
|
That skill is the recommended onboarding path. It can guide the agent through:
|
|
@@ -128,7 +129,8 @@ That skill is the recommended onboarding path. It can guide the agent through:
|
|
|
128
129
|
- checking or installing `agentinbox`
|
|
129
130
|
- checking or installing `uxc`
|
|
130
131
|
- importing GitHub auth from the local `gh` CLI via `uxc auth credential import github --from gh`
|
|
131
|
-
- registering the current
|
|
132
|
+
- registering the current runtime/session as an agent, including Holon webhook
|
|
133
|
+
activation when running in Holon
|
|
132
134
|
- adding GitHub sources and standing subscriptions using the docs-site examples
|
|
133
135
|
|
|
134
136
|
## Quick Start
|
|
@@ -139,15 +141,20 @@ Start the local daemon:
|
|
|
139
141
|
agentinbox daemon start
|
|
140
142
|
```
|
|
141
143
|
|
|
142
|
-
Register the current
|
|
144
|
+
Register the current runtime/session:
|
|
143
145
|
|
|
144
146
|
```bash
|
|
145
147
|
agentinbox agent register
|
|
146
148
|
agentinbox agent register --agent-id agent-alpha
|
|
149
|
+
agentinbox agent register --agent-id agent-alpha --webhook-url <external-trigger-url>
|
|
147
150
|
agentinbox agent register --notify-lease-ms 600000 --min-unacked-items 5
|
|
148
151
|
agentinbox agent current
|
|
149
152
|
```
|
|
150
153
|
|
|
154
|
+
Terminal-backed runtimes attach a terminal activation target. In Holon, the
|
|
155
|
+
no-arg form uses `HOLON_AGENT_ID` and `HOLON_EXTERNAL_TRIGGER_URL` when present;
|
|
156
|
+
otherwise pass `--webhook-url` explicitly.
|
|
157
|
+
|
|
151
158
|
`notifyLeaseMs` and `minUnackedItems` are target-facing notification policy:
|
|
152
159
|
they control how often a target may be reminded and how many unacked items must
|
|
153
160
|
accumulate before AgentInbox notifies it. Service-wide activation batching
|
package/dist/src/adapters.js
CHANGED
|
@@ -208,6 +208,18 @@ class AdapterRegistry {
|
|
|
208
208
|
}
|
|
209
209
|
return module.invokeDeliveryOperation({ handle, operation, input, attempt, source });
|
|
210
210
|
}
|
|
211
|
+
async listSourceOperations(source) {
|
|
212
|
+
if (source.sourceType === "local_event") {
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
return this.remoteSource.listSourceOperations(source);
|
|
216
|
+
}
|
|
217
|
+
async invokeSourceOperation(source, operation, input) {
|
|
218
|
+
if (source.sourceType === "local_event") {
|
|
219
|
+
throw new Error(`source operations are not supported for source type ${source.sourceType}`);
|
|
220
|
+
}
|
|
221
|
+
return this.remoteSource.invokeSourceOperation(source, operation, input);
|
|
222
|
+
}
|
|
211
223
|
status() {
|
|
212
224
|
return {
|
|
213
225
|
remote: this.remoteSource.status?.() ?? {},
|
package/dist/src/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const commander_1 = require("commander");
|
|
9
10
|
const adapters_1 = require("./adapters");
|
|
10
11
|
const client_1 = require("./client");
|
|
11
12
|
const control_server_1 = require("./control_server");
|
|
@@ -24,11 +25,16 @@ async function main() {
|
|
|
24
25
|
const normalized = shouldTreatJsonFlagAsNoop(detectedArgs)
|
|
25
26
|
? stripNoopJsonFlag(detectedArgs)
|
|
26
27
|
: detectedArgs;
|
|
28
|
+
const shell = parseCommanderShell(normalized);
|
|
27
29
|
const command = normalized[0];
|
|
28
30
|
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
29
31
|
printHelp(normalized.slice(1));
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
34
|
+
if (shell.isBareGroup) {
|
|
35
|
+
printHelp([command]);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
32
38
|
if (command === "version" || command === "--version" || command === "-v") {
|
|
33
39
|
if (hasHelpFlag(normalized.slice(1))) {
|
|
34
40
|
printHelp(["version"]);
|
|
@@ -57,7 +63,7 @@ async function main() {
|
|
|
57
63
|
printHelp([command]);
|
|
58
64
|
return;
|
|
59
65
|
}
|
|
60
|
-
const client = await createClient(normalized);
|
|
66
|
+
const client = await createClient(clientArgsForCommand(normalized));
|
|
61
67
|
if (command === "host" && normalized[1] === "add") {
|
|
62
68
|
const [hostType, hostKey] = normalized.slice(2, 4);
|
|
63
69
|
if (!hostType || !hostKey) {
|
|
@@ -72,7 +78,10 @@ async function main() {
|
|
|
72
78
|
return;
|
|
73
79
|
}
|
|
74
80
|
if (command === "host" && normalized[1] === "list") {
|
|
75
|
-
|
|
81
|
+
const query = buildQuery({
|
|
82
|
+
limit: parseOptionalLimitArg(normalized),
|
|
83
|
+
});
|
|
84
|
+
await printRemote(client, `/hosts${query}`, undefined, "GET");
|
|
76
85
|
return;
|
|
77
86
|
}
|
|
78
87
|
if (command === "host" && normalized[1] === "show") {
|
|
@@ -106,7 +115,10 @@ async function main() {
|
|
|
106
115
|
return;
|
|
107
116
|
}
|
|
108
117
|
if (command === "stream" && normalized[1] === "list") {
|
|
109
|
-
|
|
118
|
+
const query = buildQuery({
|
|
119
|
+
limit: parseOptionalLimitArg(normalized),
|
|
120
|
+
});
|
|
121
|
+
await printRemote(client, `/streams${query}`, undefined, "GET");
|
|
110
122
|
return;
|
|
111
123
|
}
|
|
112
124
|
if (command === "stream" && normalized[1] === "show") {
|
|
@@ -266,7 +278,10 @@ async function main() {
|
|
|
266
278
|
return;
|
|
267
279
|
}
|
|
268
280
|
if (command === "source" && normalized[1] === "list") {
|
|
269
|
-
|
|
281
|
+
const query = buildQuery({
|
|
282
|
+
limit: parseOptionalLimitArg(normalized),
|
|
283
|
+
});
|
|
284
|
+
await printRemote(client, `/sources${query}`, undefined, "GET");
|
|
270
285
|
return;
|
|
271
286
|
}
|
|
272
287
|
if (command === "source" && normalized[1] === "show") {
|
|
@@ -334,6 +349,27 @@ async function main() {
|
|
|
334
349
|
await printRemote(client, `/sources/${encodeURIComponent(sourceRef)}/schema`, undefined, "GET");
|
|
335
350
|
return;
|
|
336
351
|
}
|
|
352
|
+
if (command === "source" && normalized[1] === "actions") {
|
|
353
|
+
const sourceId = normalized[2];
|
|
354
|
+
if (!sourceId) {
|
|
355
|
+
throw new Error("usage: agentinbox source actions <sourceId>");
|
|
356
|
+
}
|
|
357
|
+
await printRemote(client, `/sources/${encodeURIComponent(sourceId)}/actions`, undefined, "GET");
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
if (command === "source" && normalized[1] === "invoke") {
|
|
361
|
+
const sourceId = normalized[2];
|
|
362
|
+
const operation = takeFlagValue(normalized, "--operation");
|
|
363
|
+
const inputJson = takeFlagValue(normalized, "--input-json");
|
|
364
|
+
if (!sourceId || !operation || !inputJson) {
|
|
365
|
+
throw new Error("usage: agentinbox source invoke <sourceId> --operation NAME --input-json JSON");
|
|
366
|
+
}
|
|
367
|
+
await printRemote(client, `/sources/${encodeURIComponent(sourceId)}/invoke`, {
|
|
368
|
+
operation,
|
|
369
|
+
input: (0, util_1.parseJsonArg)(inputJson, "--input-json"),
|
|
370
|
+
});
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
337
373
|
if (command === "source" && normalized[1] === "poll") {
|
|
338
374
|
const sourceId = normalized[2];
|
|
339
375
|
if (!sourceId) {
|
|
@@ -363,15 +399,18 @@ async function main() {
|
|
|
363
399
|
const notifyLeaseMs = parseOptionalNumber(takeFlagValue(normalized, "--notify-lease-ms")) ?? undefined;
|
|
364
400
|
const minUnackedItems = parseOptionalNumber(takeFlagValue(normalized, "--min-unacked-items")) ?? undefined;
|
|
365
401
|
const webhookUrl = takeFlagValue(normalized, "--webhook-url");
|
|
402
|
+
const holonContext = (0, current_agent_1.detectHolonRuntimeContext)(process.env);
|
|
366
403
|
if (webhookUrl) {
|
|
367
|
-
|
|
368
|
-
|
|
404
|
+
const resolvedAgentId = agentId ?? holonContext?.agentId;
|
|
405
|
+
if (!resolvedAgentId) {
|
|
406
|
+
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
407
|
}
|
|
370
408
|
const webhookNotifyLeaseMs = parseOptionalNumber(takeFlagValue(normalized, "--webhook-notify-lease-ms")) ?? notifyLeaseMs;
|
|
371
409
|
const webhookMinUnackedItems = parseOptionalNumber(takeFlagValue(normalized, "--webhook-min-unacked-items")) ?? minUnackedItems;
|
|
372
410
|
await printRemote(client, "/agents", {
|
|
373
|
-
agentId,
|
|
411
|
+
agentId: resolvedAgentId,
|
|
374
412
|
forceRebind: normalized.includes("--force-rebind"),
|
|
413
|
+
...(holonContext ? { runtimeKind: holonContext.runtimeKind } : {}),
|
|
375
414
|
webhook: {
|
|
376
415
|
url: webhookUrl,
|
|
377
416
|
activationMode: takeFlagValue(normalized, "--webhook-activation-mode") ?? undefined,
|
|
@@ -381,6 +420,28 @@ async function main() {
|
|
|
381
420
|
});
|
|
382
421
|
return;
|
|
383
422
|
}
|
|
423
|
+
if ((0, current_agent_1.isHolonRuntimeEnv)(process.env)) {
|
|
424
|
+
if (!holonContext) {
|
|
425
|
+
throw new Error("agent register in Holon requires HOLON_AGENT_ID");
|
|
426
|
+
}
|
|
427
|
+
if (!holonContext.externalTriggerUrl) {
|
|
428
|
+
throw new Error("agent register in Holon requires --webhook-url or HOLON_EXTERNAL_TRIGGER_URL");
|
|
429
|
+
}
|
|
430
|
+
const webhookNotifyLeaseMs = parseOptionalNumber(takeFlagValue(normalized, "--webhook-notify-lease-ms")) ?? notifyLeaseMs;
|
|
431
|
+
const webhookMinUnackedItems = parseOptionalNumber(takeFlagValue(normalized, "--webhook-min-unacked-items")) ?? minUnackedItems;
|
|
432
|
+
await printRemote(client, "/agents", {
|
|
433
|
+
agentId: agentId ?? holonContext.agentId,
|
|
434
|
+
forceRebind: normalized.includes("--force-rebind"),
|
|
435
|
+
runtimeKind: holonContext.runtimeKind,
|
|
436
|
+
webhook: {
|
|
437
|
+
url: holonContext.externalTriggerUrl,
|
|
438
|
+
activationMode: takeFlagValue(normalized, "--webhook-activation-mode") ?? undefined,
|
|
439
|
+
notifyLeaseMs: webhookNotifyLeaseMs,
|
|
440
|
+
minUnackedItems: webhookMinUnackedItems,
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
384
445
|
const detected = (0, terminal_1.detectTerminalContext)(process.env);
|
|
385
446
|
await printRemote(client, "/agents", {
|
|
386
447
|
agentId,
|
|
@@ -399,7 +460,7 @@ async function main() {
|
|
|
399
460
|
return;
|
|
400
461
|
}
|
|
401
462
|
if (command === "agent" && normalized[1] === "list") {
|
|
402
|
-
await printAgentList(client);
|
|
463
|
+
await printAgentList(client, parseOptionalLimitArg(normalized));
|
|
403
464
|
return;
|
|
404
465
|
}
|
|
405
466
|
if (command === "agent" && normalized[1] === "current") {
|
|
@@ -448,9 +509,12 @@ async function main() {
|
|
|
448
509
|
if (command === "agent" && normalized[1] === "target" && normalized[2] === "list") {
|
|
449
510
|
const agentId = normalized[3];
|
|
450
511
|
if (!agentId) {
|
|
451
|
-
throw new Error("usage: agentinbox agent target list <agentId>");
|
|
512
|
+
throw new Error("usage: agentinbox agent target list <agentId> [--limit N]");
|
|
452
513
|
}
|
|
453
|
-
|
|
514
|
+
const query = buildQuery({
|
|
515
|
+
limit: parseOptionalLimitArg(normalized),
|
|
516
|
+
});
|
|
517
|
+
await printRemote(client, `/agents/${encodeURIComponent(agentId)}/targets${query}`, undefined, "GET");
|
|
454
518
|
return;
|
|
455
519
|
}
|
|
456
520
|
if (command === "agent" && normalized[1] === "target" && normalized[2] === "remove") {
|
|
@@ -522,6 +586,7 @@ async function main() {
|
|
|
522
586
|
const query = buildQuery({
|
|
523
587
|
source_id: takeFlagValue(normalized, "--source-id"),
|
|
524
588
|
agent_id: takeFlagValue(normalized, "--agent-id"),
|
|
589
|
+
limit: parseOptionalLimitArg(normalized),
|
|
525
590
|
});
|
|
526
591
|
await printRemote(client, `/subscriptions${query}`, undefined, "GET");
|
|
527
592
|
return;
|
|
@@ -599,6 +664,7 @@ async function main() {
|
|
|
599
664
|
if (command === "timer" && normalized[1] === "list") {
|
|
600
665
|
const query = buildQuery({
|
|
601
666
|
agent_id: takeFlagValue(normalized, "--agent-id"),
|
|
667
|
+
limit: parseOptionalLimitArg(normalized),
|
|
602
668
|
});
|
|
603
669
|
await printRemote(client, `/timers${query}`, undefined, "GET");
|
|
604
670
|
return;
|
|
@@ -628,7 +694,10 @@ async function main() {
|
|
|
628
694
|
return;
|
|
629
695
|
}
|
|
630
696
|
if (command === "inbox" && normalized[1] === "list") {
|
|
631
|
-
|
|
697
|
+
const query = buildQuery({
|
|
698
|
+
limit: parseOptionalLimitArg(normalized),
|
|
699
|
+
});
|
|
700
|
+
await printRemote(client, `/agents${query}`, undefined, "GET");
|
|
632
701
|
return;
|
|
633
702
|
}
|
|
634
703
|
if (command === "inbox" && normalized[1] === "show") {
|
|
@@ -641,9 +710,9 @@ async function main() {
|
|
|
641
710
|
}
|
|
642
711
|
if (command === "inbox" && normalized[1] === "read") {
|
|
643
712
|
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]");
|
|
713
|
+
const allowedFlags = ["--agent-id", "--after-entry", "--include-acked", "--limit"];
|
|
714
|
+
if (positionalArgs(args, ["--agent-id", "--after-entry", "--limit"]).length > 0 || unexpectedFlags(args, allowedFlags).length > 0) {
|
|
715
|
+
throw new Error("usage: agentinbox inbox read [--agent-id ID] [--after-entry ID] [--include-acked] [--limit N]");
|
|
647
716
|
}
|
|
648
717
|
const selection = await selectAgentForCommand(client, {
|
|
649
718
|
explicitAgentId: takeFlagValue(normalized, "--agent-id"),
|
|
@@ -652,6 +721,7 @@ async function main() {
|
|
|
652
721
|
const query = buildQuery({
|
|
653
722
|
after_entry_id: takeFlagValue(normalized, "--after-entry"),
|
|
654
723
|
include_acked: hasFlag(normalized, "--include-acked") ? "true" : undefined,
|
|
724
|
+
limit: parseOptionalLimitArg(normalized),
|
|
655
725
|
});
|
|
656
726
|
const response = await requestRemote(client, `/agents/${encodeURIComponent(selection.agentId)}/inbox/entries${query}`, undefined, "GET");
|
|
657
727
|
console.log((0, util_1.jsonResponse)(withCommandMetadata(response.data, selection)));
|
|
@@ -835,6 +905,53 @@ async function main() {
|
|
|
835
905
|
}
|
|
836
906
|
throw new Error(`unknown command: ${normalized.join(" ")}`);
|
|
837
907
|
}
|
|
908
|
+
const COMMAND_SHELL_SPECS = [
|
|
909
|
+
{ name: "serve", group: false, summary: "Run the AgentInbox control server." },
|
|
910
|
+
{ name: "daemon", group: true, summary: "Manage the local AgentInbox daemon." },
|
|
911
|
+
{ name: "host", group: true, summary: "Manage source hosts." },
|
|
912
|
+
{ name: "stream", group: true, summary: "Manage source streams." },
|
|
913
|
+
{ name: "follow", group: true, summary: "Create high-level source subscriptions." },
|
|
914
|
+
{ name: "source", group: true, summary: "Manage source streams through the source alias." },
|
|
915
|
+
{ name: "agent", group: true, summary: "Manage local agent registrations and activation targets." },
|
|
916
|
+
{ name: "timer", group: true, summary: "Manage agent reminder timers." },
|
|
917
|
+
{ name: "subscription", group: true, summary: "Manage source subscriptions." },
|
|
918
|
+
{ name: "inbox", group: true, summary: "Read and manage agent inboxes." },
|
|
919
|
+
{ name: "gc", group: false, summary: "Run garbage collection." },
|
|
920
|
+
{ name: "deliver", group: true, summary: "Send outbound delivery actions." },
|
|
921
|
+
{ name: "status", group: false, summary: "Show daemon status." },
|
|
922
|
+
{ name: "version", group: false, summary: "Show CLI version." },
|
|
923
|
+
];
|
|
924
|
+
const COMMANDER_SHELL = createCommanderShell();
|
|
925
|
+
function createCommanderShell() {
|
|
926
|
+
const program = new commander_1.Command();
|
|
927
|
+
program
|
|
928
|
+
.name("agentinbox")
|
|
929
|
+
.allowUnknownOption(true)
|
|
930
|
+
.allowExcessArguments(true)
|
|
931
|
+
.exitOverride()
|
|
932
|
+
.configureOutput({
|
|
933
|
+
writeOut: () => { },
|
|
934
|
+
writeErr: () => { },
|
|
935
|
+
});
|
|
936
|
+
for (const spec of COMMAND_SHELL_SPECS) {
|
|
937
|
+
program
|
|
938
|
+
.command(`${spec.name} [args...]`)
|
|
939
|
+
.description(spec.summary)
|
|
940
|
+
.allowUnknownOption(true)
|
|
941
|
+
.allowExcessArguments(true);
|
|
942
|
+
}
|
|
943
|
+
return program;
|
|
944
|
+
}
|
|
945
|
+
function parseCommanderShell(args) {
|
|
946
|
+
const command = args[0] ?? null;
|
|
947
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
948
|
+
return { isBareGroup: false };
|
|
949
|
+
}
|
|
950
|
+
const spec = COMMANDER_SHELL.commands.find((item) => item.name() === command);
|
|
951
|
+
return {
|
|
952
|
+
isBareGroup: Boolean(COMMAND_SHELL_SPECS.find((item) => item.name === spec?.name())?.group && args.length === 1),
|
|
953
|
+
};
|
|
954
|
+
}
|
|
838
955
|
async function runServe(args) {
|
|
839
956
|
const port = parseOptionalNumber(takeFlagValue(args, "--port"));
|
|
840
957
|
const homeOverride = takeFlagValue(args, "--home");
|
|
@@ -925,12 +1042,12 @@ async function createClient(args) {
|
|
|
925
1042
|
});
|
|
926
1043
|
return new client_1.AgentInboxClient(transport);
|
|
927
1044
|
}
|
|
928
|
-
async function printAgentList(client) {
|
|
929
|
-
const records = await listAgentsWithTargets(client);
|
|
930
|
-
console.log((0, util_1.jsonResponse)((0, current_agent_1.annotateAgents)(records,
|
|
1045
|
+
async function printAgentList(client, limit) {
|
|
1046
|
+
const records = await listAgentsWithTargets(client, limit);
|
|
1047
|
+
console.log((0, util_1.jsonResponse)((0, current_agent_1.annotateAgents)(records, tryDetectCurrentAgentContext())));
|
|
931
1048
|
}
|
|
932
1049
|
async function printCurrentAgent(client) {
|
|
933
|
-
const context =
|
|
1050
|
+
const context = getRequiredCurrentAgentContext();
|
|
934
1051
|
const records = await listAgentsWithTargets(client);
|
|
935
1052
|
const current = (0, current_agent_1.resolveCurrentAgent)(records, context);
|
|
936
1053
|
if (!current) {
|
|
@@ -940,7 +1057,7 @@ async function printCurrentAgent(client) {
|
|
|
940
1057
|
}
|
|
941
1058
|
async function selectAgentForCommand(client, options) {
|
|
942
1059
|
const records = await listAgentsWithTargets(client);
|
|
943
|
-
const context =
|
|
1060
|
+
const context = tryDetectCurrentAgentContext();
|
|
944
1061
|
if (options.explicitAgentId) {
|
|
945
1062
|
const current = context ? (0, current_agent_1.resolveCurrentAgent)(records, context) : null;
|
|
946
1063
|
const requested = records.find((entry) => entry.agent.agentId === options.explicitAgentId);
|
|
@@ -960,7 +1077,7 @@ async function selectAgentForCommand(client, options) {
|
|
|
960
1077
|
warnings,
|
|
961
1078
|
};
|
|
962
1079
|
}
|
|
963
|
-
const contextForCurrent =
|
|
1080
|
+
const contextForCurrent = getRequiredCurrentAgentContext();
|
|
964
1081
|
const current = (0, current_agent_1.resolveCurrentAgent)(records, contextForCurrent);
|
|
965
1082
|
if (current) {
|
|
966
1083
|
return {
|
|
@@ -972,17 +1089,7 @@ async function selectAgentForCommand(client, options) {
|
|
|
972
1089
|
if (!options.autoRegister) {
|
|
973
1090
|
throw new Error(noCurrentAgentMessage());
|
|
974
1091
|
}
|
|
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
|
-
});
|
|
1092
|
+
await requestRemote(client, "/agents", registrationInputForCurrentContext(contextForCurrent));
|
|
986
1093
|
const refreshed = await listAgentsWithTargets(client);
|
|
987
1094
|
const registered = (0, current_agent_1.resolveCurrentAgent)(refreshed, contextForCurrent);
|
|
988
1095
|
if (!registered) {
|
|
@@ -994,8 +1101,38 @@ async function selectAgentForCommand(client, options) {
|
|
|
994
1101
|
warnings: [],
|
|
995
1102
|
};
|
|
996
1103
|
}
|
|
997
|
-
|
|
998
|
-
|
|
1104
|
+
function registrationInputForCurrentContext(context) {
|
|
1105
|
+
if ((0, current_agent_1.isHolonRuntimeContext)(context)) {
|
|
1106
|
+
if (!context.externalTriggerUrl) {
|
|
1107
|
+
throw new Error("unable to auto-register current Holon agent: HOLON_EXTERNAL_TRIGGER_URL is not set");
|
|
1108
|
+
}
|
|
1109
|
+
return {
|
|
1110
|
+
agentId: context.agentId,
|
|
1111
|
+
runtimeKind: context.runtimeKind,
|
|
1112
|
+
webhook: {
|
|
1113
|
+
url: context.externalTriggerUrl,
|
|
1114
|
+
notifyLeaseMs: undefined,
|
|
1115
|
+
},
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
return {
|
|
1119
|
+
backend: context.backend,
|
|
1120
|
+
runtimeKind: context.runtimeKind,
|
|
1121
|
+
runtimeSessionId: context.runtimeSessionId ?? undefined,
|
|
1122
|
+
runtimePid: context.runtimePid ?? undefined,
|
|
1123
|
+
tmuxPaneId: context.tmuxPaneId ?? undefined,
|
|
1124
|
+
tty: context.tty ?? undefined,
|
|
1125
|
+
termProgram: context.termProgram ?? undefined,
|
|
1126
|
+
itermSessionId: context.itermSessionId ?? undefined,
|
|
1127
|
+
notifyLeaseMs: undefined,
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
async function listAgentsWithTargets(client, limit) {
|
|
1131
|
+
const query = buildQuery({
|
|
1132
|
+
include_targets: "true",
|
|
1133
|
+
limit,
|
|
1134
|
+
});
|
|
1135
|
+
const response = await requestRemote(client, `/agents${query}`, undefined, "GET");
|
|
999
1136
|
return response.data.agents;
|
|
1000
1137
|
}
|
|
1001
1138
|
async function printRemote(client, endpoint, body, method = "POST") {
|
|
@@ -1005,13 +1142,38 @@ async function printRemote(client, endpoint, body, method = "POST") {
|
|
|
1005
1142
|
async function requestRemote(client, endpoint, body, method = "POST") {
|
|
1006
1143
|
const response = await client.request(endpoint, body, method);
|
|
1007
1144
|
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
1008
|
-
|
|
1145
|
+
const bodyText = (0, util_1.jsonResponse)(response.data);
|
|
1146
|
+
throw new Error(`request ${method} ${endpoint} failed with HTTP ${response.statusCode}: ${bodyText}`);
|
|
1009
1147
|
}
|
|
1010
1148
|
return { data: response.data };
|
|
1011
1149
|
}
|
|
1012
1150
|
function noCurrentAgentMessage() {
|
|
1013
1151
|
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
1152
|
}
|
|
1153
|
+
function clientArgsForCommand(args) {
|
|
1154
|
+
if (isAgentTargetAddWebhookCommand(args)) {
|
|
1155
|
+
return withoutFlagValues(args, "--url");
|
|
1156
|
+
}
|
|
1157
|
+
return args;
|
|
1158
|
+
}
|
|
1159
|
+
function isAgentTargetAddWebhookCommand(args) {
|
|
1160
|
+
return args[0] === "agent" && args[1] === "target" && args[2] === "add" && args[3] === "webhook";
|
|
1161
|
+
}
|
|
1162
|
+
function withoutFlagValues(args, flag) {
|
|
1163
|
+
const filtered = [];
|
|
1164
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
1165
|
+
const value = args[index];
|
|
1166
|
+
if (value !== flag) {
|
|
1167
|
+
filtered.push(value);
|
|
1168
|
+
continue;
|
|
1169
|
+
}
|
|
1170
|
+
const nextIndex = index + 1;
|
|
1171
|
+
if (nextIndex < args.length && !args[nextIndex].startsWith("--")) {
|
|
1172
|
+
index = nextIndex;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return filtered;
|
|
1176
|
+
}
|
|
1015
1177
|
function takeFlagValue(args, flag) {
|
|
1016
1178
|
const index = args.indexOf(flag);
|
|
1017
1179
|
if (index === -1) {
|
|
@@ -1102,6 +1264,17 @@ function buildQuery(params) {
|
|
|
1102
1264
|
const query = search.toString();
|
|
1103
1265
|
return query ? `?${query}` : "";
|
|
1104
1266
|
}
|
|
1267
|
+
function parseOptionalLimitArg(args) {
|
|
1268
|
+
const raw = takeFlagValue(args, "--limit");
|
|
1269
|
+
if (raw === undefined) {
|
|
1270
|
+
return undefined;
|
|
1271
|
+
}
|
|
1272
|
+
const parsed = Number.parseInt(raw, 10);
|
|
1273
|
+
if (!Number.isFinite(parsed) || parsed < 1 || String(parsed) !== raw) {
|
|
1274
|
+
throw new Error("`--limit` must be a positive integer");
|
|
1275
|
+
}
|
|
1276
|
+
return String(parsed);
|
|
1277
|
+
}
|
|
1105
1278
|
function readSubscriptionFilter(args) {
|
|
1106
1279
|
const filterJson = takeFlagValue(args, "--filter-json");
|
|
1107
1280
|
const filterFile = takeFlagValue(args, "--filter-file");
|
|
@@ -1193,7 +1366,14 @@ function normalizeSubscriptionAddOutput(data, shortcutUsed) {
|
|
|
1193
1366
|
}
|
|
1194
1367
|
return data;
|
|
1195
1368
|
}
|
|
1196
|
-
function
|
|
1369
|
+
function getRequiredCurrentAgentContext() {
|
|
1370
|
+
const holonContext = (0, current_agent_1.detectHolonRuntimeContext)(process.env);
|
|
1371
|
+
if (holonContext) {
|
|
1372
|
+
return holonContext;
|
|
1373
|
+
}
|
|
1374
|
+
if ((0, current_agent_1.isHolonRuntimeEnv)(process.env)) {
|
|
1375
|
+
throw new Error("unable to detect current Holon agent: HOLON_AGENT_ID is not set");
|
|
1376
|
+
}
|
|
1197
1377
|
try {
|
|
1198
1378
|
return (0, terminal_1.detectTerminalContext)(process.env);
|
|
1199
1379
|
}
|
|
@@ -1202,7 +1382,11 @@ function getRequiredTerminalContext() {
|
|
|
1202
1382
|
throw new Error(`unable to resolve current agent: ${message}`);
|
|
1203
1383
|
}
|
|
1204
1384
|
}
|
|
1205
|
-
function
|
|
1385
|
+
function tryDetectCurrentAgentContext() {
|
|
1386
|
+
const holonContext = (0, current_agent_1.detectHolonRuntimeContext)(process.env);
|
|
1387
|
+
if (holonContext || (0, current_agent_1.isHolonRuntimeEnv)(process.env)) {
|
|
1388
|
+
return holonContext;
|
|
1389
|
+
}
|
|
1206
1390
|
try {
|
|
1207
1391
|
return (0, terminal_1.detectTerminalContext)(process.env);
|
|
1208
1392
|
}
|
|
@@ -1235,10 +1419,9 @@ function unexpectedFlags(args, allowedFlags) {
|
|
|
1235
1419
|
const allowed = new Set(allowedFlags);
|
|
1236
1420
|
return args.filter((token) => token.startsWith("--") && !allowed.has(token));
|
|
1237
1421
|
}
|
|
1238
|
-
function
|
|
1239
|
-
const
|
|
1240
|
-
|
|
1241
|
-
root: `agentinbox
|
|
1422
|
+
function renderRootHelp() {
|
|
1423
|
+
const commands = COMMAND_SHELL_SPECS.map((spec) => ` ${spec.name}`).join("\n");
|
|
1424
|
+
return `agentinbox
|
|
1242
1425
|
|
|
1243
1426
|
Usage:
|
|
1244
1427
|
agentinbox <command> [options]
|
|
@@ -1247,19 +1430,13 @@ Usage:
|
|
|
1247
1430
|
agentinbox --version, -v
|
|
1248
1431
|
|
|
1249
1432
|
Commands:
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
inbox
|
|
1258
|
-
gc
|
|
1259
|
-
deliver
|
|
1260
|
-
status
|
|
1261
|
-
version
|
|
1262
|
-
`,
|
|
1433
|
+
${commands}
|
|
1434
|
+
`;
|
|
1435
|
+
}
|
|
1436
|
+
function printHelp(path = []) {
|
|
1437
|
+
const key = path[0] ?? "root";
|
|
1438
|
+
const helpByKey = {
|
|
1439
|
+
root: renderRootHelp(),
|
|
1263
1440
|
serve: `agentinbox serve
|
|
1264
1441
|
|
|
1265
1442
|
Usage:
|
|
@@ -1277,7 +1454,7 @@ Usage:
|
|
|
1277
1454
|
|
|
1278
1455
|
Usage:
|
|
1279
1456
|
agentinbox host add <hostType> <hostKey> [--config-json JSON] [--config-ref REF]
|
|
1280
|
-
agentinbox host list
|
|
1457
|
+
agentinbox host list [--limit N]
|
|
1281
1458
|
agentinbox host show <hostId>
|
|
1282
1459
|
agentinbox host schema <hostId>
|
|
1283
1460
|
`,
|
|
@@ -1285,7 +1462,7 @@ Usage:
|
|
|
1285
1462
|
|
|
1286
1463
|
Usage:
|
|
1287
1464
|
agentinbox stream add <hostId> <streamKind> <streamKey> [--config-json JSON] [--config-ref REF]
|
|
1288
|
-
agentinbox stream list
|
|
1465
|
+
agentinbox stream list [--limit N]
|
|
1289
1466
|
agentinbox stream show <streamId>
|
|
1290
1467
|
agentinbox stream update <streamId> [--config-json JSON] [--config-ref REF | --clear-config-ref]
|
|
1291
1468
|
agentinbox stream remove <streamId> [--with-subscriptions]
|
|
@@ -1305,18 +1482,21 @@ Examples:
|
|
|
1305
1482
|
agentinbox follow github repo --agent-id <agentId> --arg owner=holon-run --arg repo=agentinbox
|
|
1306
1483
|
agentinbox follow github pr --agent-id <agentId> --arg owner=holon-run --arg repo=agentinbox --arg number=87 --arg withCi=true
|
|
1307
1484
|
agentinbox follow github issue --agent-id <agentId> --arg owner=holon-run --arg repo=agentinbox --arg number=180
|
|
1485
|
+
agentinbox follow feishu mentions --agent-id <agentId> --config-json '{"uxcAuth":"feishu-default"}'
|
|
1308
1486
|
`,
|
|
1309
1487
|
source: `agentinbox source
|
|
1310
1488
|
|
|
1311
1489
|
Usage:
|
|
1312
1490
|
agentinbox source add <hostId> <streamKind> <streamKey> [--config-json JSON] [--config-ref REF]
|
|
1313
|
-
agentinbox source list
|
|
1491
|
+
agentinbox source list [--limit N]
|
|
1314
1492
|
agentinbox source show <sourceId>
|
|
1315
1493
|
agentinbox source update <sourceId> [--config-json JSON] [--config-ref REF | --clear-config-ref]
|
|
1316
1494
|
agentinbox source remove <sourceId> [--with-subscriptions]
|
|
1317
1495
|
agentinbox source pause <remoteSourceId>
|
|
1318
1496
|
agentinbox source resume <remoteSourceId>
|
|
1319
1497
|
agentinbox source schema <sourceId>
|
|
1498
|
+
agentinbox source actions <sourceId>
|
|
1499
|
+
agentinbox source invoke <sourceId> --operation NAME --input-json JSON
|
|
1320
1500
|
agentinbox source poll <sourceId>
|
|
1321
1501
|
agentinbox source event <sourceId> --native-id ID --event EVENT [--occurred-at ISO8601] [--metadata-json JSON] [--payload-json JSON]
|
|
1322
1502
|
`,
|
|
@@ -1325,13 +1505,13 @@ Usage:
|
|
|
1325
1505
|
Usage:
|
|
1326
1506
|
agentinbox agent register [--agent-id ID] [--force-rebind] [--notify-lease-ms N] [--min-unacked-items N]
|
|
1327
1507
|
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
|
|
1508
|
+
agentinbox agent list [--limit N]
|
|
1329
1509
|
agentinbox agent current
|
|
1330
1510
|
agentinbox agent show <agentId>
|
|
1331
1511
|
agentinbox agent remove <agentId>
|
|
1332
1512
|
agentinbox agent resume <agentId>
|
|
1333
1513
|
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>
|
|
1514
|
+
agentinbox agent target list <agentId> [--limit N]
|
|
1335
1515
|
agentinbox agent target remove <agentId> <targetId>
|
|
1336
1516
|
agentinbox agent target resume <agentId> <targetId>
|
|
1337
1517
|
`,
|
|
@@ -1339,7 +1519,7 @@ Usage:
|
|
|
1339
1519
|
|
|
1340
1520
|
Usage:
|
|
1341
1521
|
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]
|
|
1522
|
+
agentinbox timer list [--agent-id ID] [--limit N]
|
|
1343
1523
|
agentinbox timer pause <scheduleId>
|
|
1344
1524
|
agentinbox timer resume <scheduleId>
|
|
1345
1525
|
agentinbox timer remove <scheduleId>
|
|
@@ -1348,7 +1528,7 @@ Usage:
|
|
|
1348
1528
|
|
|
1349
1529
|
Usage:
|
|
1350
1530
|
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]
|
|
1531
|
+
agentinbox subscription list [--source-id ID] [--agent-id ID] [--limit N]
|
|
1352
1532
|
agentinbox subscription show <subscriptionId>
|
|
1353
1533
|
agentinbox subscription remove <subscriptionId>
|
|
1354
1534
|
agentinbox subscription poll <subscriptionId>
|
|
@@ -1358,9 +1538,9 @@ Usage:
|
|
|
1358
1538
|
inbox: `agentinbox inbox
|
|
1359
1539
|
|
|
1360
1540
|
Usage:
|
|
1361
|
-
agentinbox inbox list
|
|
1541
|
+
agentinbox inbox list [--limit N]
|
|
1362
1542
|
agentinbox inbox show <agentId>
|
|
1363
|
-
agentinbox inbox read [--agent-id ID] [--after-entry ID] [--include-acked]
|
|
1543
|
+
agentinbox inbox read [--agent-id ID] [--after-entry ID] [--include-acked] [--limit N]
|
|
1364
1544
|
agentinbox inbox send --agent-id ID --message TEXT [--sender SENDER]
|
|
1365
1545
|
agentinbox inbox watch [--agent-id ID] [--after-entry ID] [--include-acked] [--heartbeat-ms N]
|
|
1366
1546
|
agentinbox inbox ack [--agent-id ID] (--through <entryId> | --entry <entryId> | --all)
|