@holon-run/agentinbox 1.0.0-beta.2 → 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli.js +5 -2
- package/dist/src/current_agent.js +22 -4
- package/dist/src/service.js +15 -2
- package/dist/src/source_schema.js +2 -0
- package/dist/src/sources/github.js +5 -0
- package/dist/src/sources/github_ci.js +16 -0
- package/dist/src/sources/remote_modules.js +1 -0
- package/package.json +1 -1
package/dist/src/cli.js
CHANGED
|
@@ -871,7 +871,7 @@ async function printCurrentAgent(client) {
|
|
|
871
871
|
const records = await listAgentsWithTargets(client);
|
|
872
872
|
const current = (0, current_agent_1.resolveCurrentAgent)(records, context);
|
|
873
873
|
if (!current) {
|
|
874
|
-
throw new Error(
|
|
874
|
+
throw new Error(noCurrentAgentMessage());
|
|
875
875
|
}
|
|
876
876
|
console.log((0, util_1.jsonResponse)(current));
|
|
877
877
|
}
|
|
@@ -907,7 +907,7 @@ async function selectAgentForCommand(client, options) {
|
|
|
907
907
|
};
|
|
908
908
|
}
|
|
909
909
|
if (!options.autoRegister) {
|
|
910
|
-
throw new Error(
|
|
910
|
+
throw new Error(noCurrentAgentMessage());
|
|
911
911
|
}
|
|
912
912
|
await requestRemote(client, "/agents", {
|
|
913
913
|
backend: contextForCurrent.backend,
|
|
@@ -946,6 +946,9 @@ async function requestRemote(client, endpoint, body, method = "POST") {
|
|
|
946
946
|
}
|
|
947
947
|
return { data: response.data };
|
|
948
948
|
}
|
|
949
|
+
function noCurrentAgentMessage() {
|
|
950
|
+
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";
|
|
951
|
+
}
|
|
949
952
|
function takeFlagValue(args, flag) {
|
|
950
953
|
const index = args.indexOf(flag);
|
|
951
954
|
if (index === -1) {
|
|
@@ -39,6 +39,9 @@ function resolveCurrentAgent(agents, context) {
|
|
|
39
39
|
matchesCurrentTerminal: matchesCurrentTerminal(agent, context),
|
|
40
40
|
matchesCurrentRuntime: matchesCurrentRuntime(agent, context),
|
|
41
41
|
terminalIdentity: terminalIdentityForAgent(agent),
|
|
42
|
+
notifyCapable: notifyCapableForAgent(agent),
|
|
43
|
+
activeTargetCount: activeActivationTargetCount(agent),
|
|
44
|
+
offlineTargetCount: offlineActivationTargetCount(agent),
|
|
42
45
|
};
|
|
43
46
|
}
|
|
44
47
|
function annotateAgents(agents, context) {
|
|
@@ -52,24 +55,27 @@ function annotateAgents(agents, context) {
|
|
|
52
55
|
matchesCurrentRuntime: context ? matchesCurrentRuntime(entry, context) : false,
|
|
53
56
|
terminalIdentity: terminalIdentityForAgent(entry),
|
|
54
57
|
isCurrent: current?.agentId === entry.agent.agentId,
|
|
58
|
+
notifyCapable: notifyCapableForAgent(entry),
|
|
59
|
+
activeTargetCount: activeActivationTargetCount(entry),
|
|
60
|
+
offlineTargetCount: offlineActivationTargetCount(entry),
|
|
55
61
|
})),
|
|
56
62
|
};
|
|
57
63
|
}
|
|
58
64
|
function resolveAgentRecord(agents, context) {
|
|
59
65
|
if (context.tmuxPaneId) {
|
|
60
|
-
const match = agents.find((agent) =>
|
|
66
|
+
const match = agents.find((agent) => terminalTargetsForCurrentMatch(agent).some((target) => target.backend === "tmux" && target.tmuxPaneId === context.tmuxPaneId));
|
|
61
67
|
if (match) {
|
|
62
68
|
return match;
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
71
|
if (context.itermSessionId) {
|
|
66
|
-
const match = agents.find((agent) =>
|
|
72
|
+
const match = agents.find((agent) => terminalTargetsForCurrentMatch(agent).some((target) => target.backend === "iterm2" && target.itermSessionId === context.itermSessionId));
|
|
67
73
|
if (match) {
|
|
68
74
|
return match;
|
|
69
75
|
}
|
|
70
76
|
}
|
|
71
77
|
if (context.tty) {
|
|
72
|
-
const match = agents.find((agent) =>
|
|
78
|
+
const match = agents.find((agent) => terminalTargetsForCurrentMatch(agent).some((target) => target.tty === context.tty));
|
|
73
79
|
if (match) {
|
|
74
80
|
return match;
|
|
75
81
|
}
|
|
@@ -94,6 +100,18 @@ function activeTerminalTargets(agent) {
|
|
|
94
100
|
}
|
|
95
101
|
return terminalTargets(agent).filter((target) => target.status === "active");
|
|
96
102
|
}
|
|
103
|
+
function terminalTargetsForCurrentMatch(agent) {
|
|
104
|
+
return activeTerminalTargets(agent);
|
|
105
|
+
}
|
|
106
|
+
function activeActivationTargetCount(agent) {
|
|
107
|
+
return agent.activationTargets.filter((target) => target.status === "active").length;
|
|
108
|
+
}
|
|
109
|
+
function offlineActivationTargetCount(agent) {
|
|
110
|
+
return agent.activationTargets.filter((target) => target.status === "offline").length;
|
|
111
|
+
}
|
|
112
|
+
function notifyCapableForAgent(agent) {
|
|
113
|
+
return agent.agent.status === "active" && activeActivationTargetCount(agent) > 0;
|
|
114
|
+
}
|
|
97
115
|
function terminalIdentityForAgent(agent) {
|
|
98
116
|
const target = activeTerminalTargets(agent)[0];
|
|
99
117
|
if (!target) {
|
|
@@ -111,7 +129,7 @@ function terminalIdentityForAgent(agent) {
|
|
|
111
129
|
return null;
|
|
112
130
|
}
|
|
113
131
|
function matchesCurrentTerminal(agent, context) {
|
|
114
|
-
return
|
|
132
|
+
return terminalTargetsForCurrentMatch(agent).some((target) => (context.tmuxPaneId != null && target.tmuxPaneId === context.tmuxPaneId)
|
|
115
133
|
|| (context.itermSessionId != null && target.itermSessionId === context.itermSessionId)
|
|
116
134
|
|| (context.tty != null && target.tty === context.tty));
|
|
117
135
|
}
|
package/dist/src/service.js
CHANGED
|
@@ -505,7 +505,7 @@ class AgentInboxService {
|
|
|
505
505
|
return { removed: true };
|
|
506
506
|
}
|
|
507
507
|
registerTimer(input) {
|
|
508
|
-
this.
|
|
508
|
+
this.assertAgentNotifyCapable(input.agentId, "timer add");
|
|
509
509
|
const normalized = normalizeTimerInput(input);
|
|
510
510
|
const timezone = normalized.timezone ?? detectHostTimezone();
|
|
511
511
|
assertValidTimeZone(timezone);
|
|
@@ -794,7 +794,7 @@ class AgentInboxService {
|
|
|
794
794
|
return sibling;
|
|
795
795
|
}
|
|
796
796
|
async registerSingleSubscription(input) {
|
|
797
|
-
this.
|
|
797
|
+
this.assertAgentNotifyCapable(input.agentId, "subscription add");
|
|
798
798
|
const source = this.store.getSource(input.sourceId);
|
|
799
799
|
if (!source) {
|
|
800
800
|
throw new Error(`unknown source: ${input.sourceId}`);
|
|
@@ -1595,6 +1595,19 @@ class AgentInboxService {
|
|
|
1595
1595
|
watcher.onItems(items);
|
|
1596
1596
|
}
|
|
1597
1597
|
}
|
|
1598
|
+
assertAgentNotifyCapable(agentId, operation) {
|
|
1599
|
+
this.getAgent(agentId);
|
|
1600
|
+
const targets = this.store.listActivationTargetsForAgent(agentId);
|
|
1601
|
+
const activeTargetCount = targets.filter((target) => target.status === "active").length;
|
|
1602
|
+
if (activeTargetCount > 0) {
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
const offlineTargetCount = targets.filter((target) => target.status === "offline").length;
|
|
1606
|
+
const targetSummary = targets.length === 0
|
|
1607
|
+
? "it has no activation targets"
|
|
1608
|
+
: `all ${offlineTargetCount} activation target(s) are offline`;
|
|
1609
|
+
throw new Error(`agent ${agentId} is not notify-capable: ${targetSummary}; refusing ${operation} to avoid a silent notification black hole. Rebind with \`agentinbox agent register --force-rebind --agent-id ${agentId}\` or resume/add a target first.`);
|
|
1610
|
+
}
|
|
1598
1611
|
resolveAutoAgentId(input) {
|
|
1599
1612
|
for (let attempt = 0; attempt < 32; attempt += 1) {
|
|
1600
1613
|
const candidate = (0, terminal_1.assignedAgentIdFromContext)({
|
|
@@ -89,6 +89,7 @@ const SOURCE_SCHEMAS = {
|
|
|
89
89
|
{ name: "event", type: "string|null", description: "GitHub trigger event for the workflow run." },
|
|
90
90
|
{ name: "headBranch", type: "string|null", description: "Head branch for the workflow run." },
|
|
91
91
|
{ name: "headSha", type: "string|null", description: "Head commit SHA for the workflow run." },
|
|
92
|
+
{ name: "pullRequestNumbers", type: "number[]", description: "Pull request numbers associated with the workflow run." },
|
|
92
93
|
{ name: "actor", type: "string|null", description: "Actor login for the workflow run." },
|
|
93
94
|
{ name: "commitMessage", type: "string|null", description: "Head commit message when present." },
|
|
94
95
|
{ name: "htmlUrl", type: "string|null", description: "GitHub Actions run URL." },
|
|
@@ -101,6 +102,7 @@ const SOURCE_SCHEMAS = {
|
|
|
101
102
|
conclusion: "failure",
|
|
102
103
|
event: "pull_request",
|
|
103
104
|
head_branch: "main",
|
|
105
|
+
pull_requests: [{ number: 93 }],
|
|
104
106
|
actor: "jolestar",
|
|
105
107
|
head_commit: { message: "fix ci" },
|
|
106
108
|
},
|
|
@@ -382,6 +382,11 @@ function expandGithubSubscriptionShortcut(input) {
|
|
|
382
382
|
...(withCi
|
|
383
383
|
? [{
|
|
384
384
|
streamKind: "ci_runs",
|
|
385
|
+
filter: {
|
|
386
|
+
metadata: {
|
|
387
|
+
pullRequestNumbers: [number],
|
|
388
|
+
},
|
|
389
|
+
},
|
|
385
390
|
trackedResourceRef,
|
|
386
391
|
cleanupPolicy: { mode: "on_terminal" },
|
|
387
392
|
}]
|
|
@@ -240,6 +240,7 @@ function normalizeGithubWorkflowRunEvent(source, config, raw) {
|
|
|
240
240
|
const variant = buildWorkflowRunVariant(workflowName, status, conclusion);
|
|
241
241
|
const actor = asRecord(run.actor);
|
|
242
242
|
const headCommit = asRecord(run.head_commit);
|
|
243
|
+
const pullRequestNumbers = extractPullRequestNumbers(run.pull_requests);
|
|
243
244
|
return {
|
|
244
245
|
sourceId: source.sourceId,
|
|
245
246
|
sourceNativeId: `workflow_run:${runId}`,
|
|
@@ -259,6 +260,7 @@ function normalizeGithubWorkflowRunEvent(source, config, raw) {
|
|
|
259
260
|
event: asString(run.event),
|
|
260
261
|
headSha: asString(run.head_sha),
|
|
261
262
|
headBranch: asString(run.head_branch),
|
|
263
|
+
pullRequestNumbers,
|
|
262
264
|
runNumber: asNumber(run.run_number),
|
|
263
265
|
runAttempt: asNumber(run.run_attempt),
|
|
264
266
|
actor: asString(actor.login),
|
|
@@ -277,6 +279,7 @@ function normalizeGithubWorkflowRunEvent(source, config, raw) {
|
|
|
277
279
|
event: asString(run.event),
|
|
278
280
|
head_sha: asString(run.head_sha),
|
|
279
281
|
head_branch: asString(run.head_branch),
|
|
282
|
+
pull_requests: pullRequestNumbers.map((number) => ({ number })),
|
|
280
283
|
run_number: asNumber(run.run_number),
|
|
281
284
|
run_attempt: asNumber(run.run_attempt),
|
|
282
285
|
html_url: asString(run.html_url),
|
|
@@ -343,6 +346,19 @@ function asString(value) {
|
|
|
343
346
|
function asNumber(value) {
|
|
344
347
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
345
348
|
}
|
|
349
|
+
function extractPullRequestNumbers(value) {
|
|
350
|
+
if (!Array.isArray(value)) {
|
|
351
|
+
return [];
|
|
352
|
+
}
|
|
353
|
+
const numbers = new Set();
|
|
354
|
+
for (const entry of value) {
|
|
355
|
+
const number = asNumber(asRecord(entry).number);
|
|
356
|
+
if (number && Number.isInteger(number) && number > 0) {
|
|
357
|
+
numbers.add(number);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return Array.from(numbers).sort((left, right) => left - right);
|
|
361
|
+
}
|
|
346
362
|
function inferWorkflowRunStatus(run, conclusion) {
|
|
347
363
|
return asString(run.status)
|
|
348
364
|
?? (conclusion ? "completed" : null)
|
|
@@ -324,6 +324,7 @@ const GITHUB_REPO_CI_MODULE = {
|
|
|
324
324
|
{ name: "event", type: "string|null", description: "GitHub trigger event for the workflow run." },
|
|
325
325
|
{ name: "headBranch", type: "string|null", description: "Head branch for the workflow run." },
|
|
326
326
|
{ name: "headSha", type: "string|null", description: "Head commit SHA for the workflow run." },
|
|
327
|
+
{ name: "pullRequestNumbers", type: "number[]", description: "Pull request numbers associated with the workflow run." },
|
|
327
328
|
{ name: "actor", type: "string|null", description: "Actor login for the workflow run." },
|
|
328
329
|
{ name: "commitMessage", type: "string|null", description: "Head commit message when present." },
|
|
329
330
|
{ name: "htmlUrl", type: "string|null", description: "GitHub Actions run URL." },
|