@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/README.md +76 -16
- package/dist/src/adapters.js +38 -31
- package/dist/src/cli.js +279 -66
- package/dist/src/current_agent.js +126 -0
- package/dist/src/http.js +962 -354
- package/dist/src/service.js +94 -10
- package/dist/src/source_schema.js +2 -10
- package/dist/src/sources/feishu.js +14 -237
- package/dist/src/sources/github.js +10 -244
- package/dist/src/sources/github_ci.js +13 -12
- package/dist/src/sources/remote.js +362 -0
- package/dist/src/sources/remote_profiles.js +254 -0
- package/dist/src/store.js +119 -248
- package/dist/src/util.js +19 -3
- package/drizzle/migrations/0000_initial.sql +206 -0
- package/drizzle/migrations/0001_inbox_items_source_occurred_at_idx.sql +3 -0
- package/drizzle/migrations/meta/0001_snapshot.json +1181 -0
- package/drizzle/migrations/meta/_journal.json +20 -0
- package/drizzle/schema.ts +196 -0
- package/package.json +8 -2
- package/dist/src/matcher.js +0 -47
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
|
|
58
|
+
await printRemote(client, "/sources", {
|
|
58
59
|
sourceType: type,
|
|
59
60
|
sourceKey,
|
|
60
|
-
configRef: takeFlagValue(normalized, "--config-ref") ??
|
|
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
|
|
112
|
-
agentId: takeFlagValue(normalized, "--agent-id") ??
|
|
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 ??
|
|
117
|
-
tmuxPaneId: detected.tmuxPaneId ??
|
|
118
|
-
tty: detected.tty ??
|
|
119
|
-
termProgram: detected.termProgram ??
|
|
120
|
-
itermSessionId: detected.itermSessionId ??
|
|
121
|
-
notifyLeaseMs: parseOptionalNumber(takeFlagValue(normalized, "--notify-lease-ms")) ??
|
|
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
|
|
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")) ??
|
|
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
|
|
177
|
-
|
|
178
|
-
|
|
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
|
|
181
|
-
|
|
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: (
|
|
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
|
|
257
|
-
|
|
258
|
-
|
|
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
|
|
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
|
|
269
|
-
if (
|
|
270
|
-
throw new Error("usage: agentinbox inbox watch
|
|
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
|
|
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 (
|
|
291
|
-
throw new Error("usage: agentinbox inbox ack
|
|
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
|
|
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") ??
|
|
341
|
-
replyMode: takeFlagValue(normalized, "--reply-mode") ??
|
|
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
|
-
|
|
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
|
-
|
|
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 <
|
|
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
|
|
562
|
-
agentinbox inbox watch
|
|
563
|
-
agentinbox inbox ack
|
|
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
|
+
}
|