@agentmeshhq/agent 0.4.15 → 0.4.18
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/__tests__/bootstrap.test.js +24 -0
- package/dist/__tests__/bootstrap.test.js.map +1 -1
- package/dist/__tests__/injection-verify.test.d.ts +1 -0
- package/dist/__tests__/injection-verify.test.js +93 -0
- package/dist/__tests__/injection-verify.test.js.map +1 -0
- package/dist/__tests__/injector.test.js +115 -1
- package/dist/__tests__/injector.test.js.map +1 -1
- package/dist/__tests__/lead-loop.test.d.ts +1 -0
- package/dist/__tests__/lead-loop.test.js +170 -0
- package/dist/__tests__/lead-loop.test.js.map +1 -0
- package/dist/__tests__/relay.test.d.ts +1 -0
- package/dist/__tests__/relay.test.js +17 -0
- package/dist/__tests__/relay.test.js.map +1 -0
- package/dist/__tests__/roles.test.d.ts +1 -0
- package/dist/__tests__/roles.test.js +78 -0
- package/dist/__tests__/roles.test.js.map +1 -0
- package/dist/__tests__/runner.test.js +17 -0
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/session-recovery.test.js +214 -11
- package/dist/__tests__/session-recovery.test.js.map +1 -1
- package/dist/__tests__/start-team-id.test.js +8 -3
- package/dist/__tests__/start-team-id.test.js.map +1 -1
- package/dist/__tests__/startup-diagnostics.test.d.ts +1 -0
- package/dist/__tests__/startup-diagnostics.test.js +250 -0
- package/dist/__tests__/startup-diagnostics.test.js.map +1 -0
- package/dist/__tests__/tmux-runtime.test.js +13 -0
- package/dist/__tests__/tmux-runtime.test.js.map +1 -1
- package/dist/__tests__/watcher-queue.test.d.ts +1 -0
- package/dist/__tests__/watcher-queue.test.js +85 -0
- package/dist/__tests__/watcher-queue.test.js.map +1 -0
- package/dist/__tests__/watcher-state.test.d.ts +1 -0
- package/dist/__tests__/watcher-state.test.js +159 -0
- package/dist/__tests__/watcher-state.test.js.map +1 -0
- package/dist/cli/commands.d.ts +32 -0
- package/dist/cli/commands.js +165 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.js +95 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/relay.d.ts +1 -0
- package/dist/cli/relay.js +16 -2
- package/dist/cli/relay.js.map +1 -1
- package/dist/cli/start.d.ts +2 -0
- package/dist/cli/start.js +42 -7
- package/dist/cli/start.js.map +1 -1
- package/dist/config/schema.d.ts +1 -1
- package/dist/core/chat-output-parser.d.ts +24 -0
- package/dist/core/chat-output-parser.js +134 -0
- package/dist/core/chat-output-parser.js.map +1 -0
- package/dist/core/chat-output-parser.test.d.ts +7 -0
- package/dist/core/chat-output-parser.test.js +130 -0
- package/dist/core/chat-output-parser.test.js.map +1 -0
- package/dist/core/daemon/bootstrap.js +14 -4
- package/dist/core/daemon/bootstrap.js.map +1 -1
- package/dist/core/daemon/context-template.d.ts +5 -1
- package/dist/core/daemon/context-template.js +16 -2
- package/dist/core/daemon/context-template.js.map +1 -1
- package/dist/core/daemon/crash-log.js +5 -0
- package/dist/core/daemon/crash-log.js.map +1 -1
- package/dist/core/daemon/injection-verify.d.ts +25 -0
- package/dist/core/daemon/injection-verify.js +94 -0
- package/dist/core/daemon/injection-verify.js.map +1 -0
- package/dist/core/daemon/lead-loop.d.ts +22 -0
- package/dist/core/daemon/lead-loop.js +155 -0
- package/dist/core/daemon/lead-loop.js.map +1 -0
- package/dist/core/daemon/roles.d.ts +25 -0
- package/dist/core/daemon/roles.js +46 -0
- package/dist/core/daemon/roles.js.map +1 -0
- package/dist/core/daemon/session-recovery.d.ts +18 -1
- package/dist/core/daemon/session-recovery.js +89 -5
- package/dist/core/daemon/session-recovery.js.map +1 -1
- package/dist/core/daemon/startup-diagnostics.d.ts +76 -0
- package/dist/core/daemon/startup-diagnostics.js +277 -0
- package/dist/core/daemon/startup-diagnostics.js.map +1 -0
- package/dist/core/daemon/watcher-loop.d.ts +27 -0
- package/dist/core/daemon/watcher-loop.js +134 -0
- package/dist/core/daemon/watcher-loop.js.map +1 -0
- package/dist/core/daemon/watcher-queue.d.ts +33 -0
- package/dist/core/daemon/watcher-queue.js +71 -0
- package/dist/core/daemon/watcher-queue.js.map +1 -0
- package/dist/core/daemon/watcher-state.d.ts +66 -0
- package/dist/core/daemon/watcher-state.js +151 -0
- package/dist/core/daemon/watcher-state.js.map +1 -0
- package/dist/core/daemon.d.ts +14 -0
- package/dist/core/daemon.js +182 -3
- package/dist/core/daemon.js.map +1 -1
- package/dist/core/injector.js +198 -1
- package/dist/core/injector.js.map +1 -1
- package/dist/core/registry.d.ts +5 -0
- package/dist/core/registry.js +19 -0
- package/dist/core/registry.js.map +1 -1
- package/dist/core/runner/build.js +7 -31
- package/dist/core/runner/build.js.map +1 -1
- package/dist/core/runner/detect.js +2 -8
- package/dist/core/runner/detect.js.map +1 -1
- package/dist/core/runner/index.d.ts +3 -1
- package/dist/core/runner/index.js +2 -0
- package/dist/core/runner/index.js.map +1 -1
- package/dist/core/runner/kimi-models.d.ts +4 -0
- package/dist/core/runner/kimi-models.js +24 -0
- package/dist/core/runner/kimi-models.js.map +1 -0
- package/dist/core/runner/registry.d.ts +3 -0
- package/dist/core/runner/registry.js +75 -0
- package/dist/core/runner/registry.js.map +1 -0
- package/dist/core/runner/types.d.ts +17 -1
- package/dist/core/tmux-runtime.d.ts +1 -1
- package/dist/core/tmux-runtime.js +13 -0
- package/dist/core/tmux-runtime.js.map +1 -1
- package/dist/core/tmux.d.ts +4 -0
- package/dist/core/tmux.js +49 -11
- package/dist/core/tmux.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const execAsync = promisify(exec);
|
|
4
|
+
function ciGreen(pr) {
|
|
5
|
+
const checks = pr.statusCheckRollup;
|
|
6
|
+
if (!checks || checks.length === 0)
|
|
7
|
+
return true; // no checks = assume green
|
|
8
|
+
return checks.every((c) => {
|
|
9
|
+
if (c.conclusion)
|
|
10
|
+
return c.conclusion === "SUCCESS";
|
|
11
|
+
if (c.state)
|
|
12
|
+
return c.state === "SUCCESS";
|
|
13
|
+
return false;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** Fetch the reviewer agent ID from the hub at tick time. */
|
|
17
|
+
async function resolveReviewerAgentId(hubUrl, workspace, token) {
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch(`${hubUrl}/api/v1/workspaces/${workspace}/agents`, {
|
|
20
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
21
|
+
});
|
|
22
|
+
if (!res.ok)
|
|
23
|
+
return null;
|
|
24
|
+
const body = (await res.json());
|
|
25
|
+
const agents = body.data ?? [];
|
|
26
|
+
// Find agent with role "reviewer" or display_name containing "reviewer"
|
|
27
|
+
const reviewer = agents.find((a) => a.metadata?.role === "reviewer" || a.display_name?.toLowerCase().includes("reviewer"));
|
|
28
|
+
return reviewer?.agent_id ?? null;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check whether an active (non-completed, non-rejected) handoff already exists
|
|
36
|
+
* for this PR number sent from this agent.
|
|
37
|
+
*/
|
|
38
|
+
async function handoffExistsForPr(hubUrl, workspace, token, prNumber) {
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(`${hubUrl}/api/v1/workspaces/${workspace}/handoffs?limit=50`, {
|
|
41
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
42
|
+
});
|
|
43
|
+
if (!res.ok)
|
|
44
|
+
return false;
|
|
45
|
+
const body = (await res.json());
|
|
46
|
+
const handoffs = body.data ?? [];
|
|
47
|
+
return handoffs.some((h) => h.scope?.includes(`#${prNumber}`) && h.status !== "completed" && h.status !== "rejected");
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Create a handoff to the reviewer agent for this PR. */
|
|
54
|
+
async function createReviewHandoff(hubUrl, workspace, token, reviewerAgentId, pr) {
|
|
55
|
+
try {
|
|
56
|
+
const res = await fetch(`${hubUrl}/api/v1/workspaces/${workspace}/handoffs`, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: `Bearer ${token}`,
|
|
60
|
+
"Content-Type": "application/json",
|
|
61
|
+
},
|
|
62
|
+
body: JSON.stringify({
|
|
63
|
+
to_agent_id: reviewerAgentId,
|
|
64
|
+
scope: `Review PR #${pr.number}: ${pr.title}`,
|
|
65
|
+
reason: `PR #${pr.number} (${pr.headRefName}) is open and needs review before merge.`,
|
|
66
|
+
metadata: { pr_number: pr.number, watcher_generated: true },
|
|
67
|
+
}),
|
|
68
|
+
});
|
|
69
|
+
if (!res.ok)
|
|
70
|
+
return null;
|
|
71
|
+
const body = (await res.json());
|
|
72
|
+
return body.handoff_id ?? null;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* One coordination tick for a lead agent:
|
|
80
|
+
* 1. Poll open PRs via `gh pr list`
|
|
81
|
+
* 2. Update BEHIND branches via `gh pr update-branch`
|
|
82
|
+
* 3. Route unreviewed PRs to the reviewer via hub handoffs
|
|
83
|
+
* 4. Merge APPROVED + CI-green + MERGEABLE PRs
|
|
84
|
+
*/
|
|
85
|
+
export async function runLeadTick(ctx) {
|
|
86
|
+
const run = ctx.exec ?? execAsync;
|
|
87
|
+
let prs;
|
|
88
|
+
try {
|
|
89
|
+
const { stdout } = await run("gh pr list --state open --json number,title,headRefName,mergeable,reviewDecision,statusCheckRollup");
|
|
90
|
+
prs = JSON.parse(stdout.trim());
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
ctx.log(`[lead-tick] Failed to list PRs: ${err.message}`);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (prs.length === 0) {
|
|
97
|
+
ctx.log("[lead-tick] No open PRs.");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Resolve reviewer once per tick
|
|
101
|
+
const reviewerAgentId = ctx.reviewerAgentId ?? (await resolveReviewerAgentId(ctx.hubUrl, ctx.workspace, ctx.token));
|
|
102
|
+
let updated = 0;
|
|
103
|
+
let routed = 0;
|
|
104
|
+
let merged = 0;
|
|
105
|
+
let skipped = 0;
|
|
106
|
+
for (const pr of prs) {
|
|
107
|
+
try {
|
|
108
|
+
// 1. Update BEHIND branches
|
|
109
|
+
if (pr.mergeable === "BEHIND") {
|
|
110
|
+
try {
|
|
111
|
+
await run(`gh pr update-branch ${pr.number}`);
|
|
112
|
+
ctx.log(`[lead-tick] PR #${pr.number}: updated BEHIND branch`);
|
|
113
|
+
updated++;
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
ctx.log(`[lead-tick] PR #${pr.number}: update-branch failed: ${err.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// 2. Route unreviewed PRs to reviewer
|
|
120
|
+
if ((!pr.reviewDecision || pr.reviewDecision === "REVIEW_REQUIRED") && reviewerAgentId) {
|
|
121
|
+
const alreadySent = await handoffExistsForPr(ctx.hubUrl, ctx.workspace, ctx.token, pr.number);
|
|
122
|
+
if (!alreadySent) {
|
|
123
|
+
const handoffId = await createReviewHandoff(ctx.hubUrl, ctx.workspace, ctx.token, reviewerAgentId, pr);
|
|
124
|
+
if (handoffId) {
|
|
125
|
+
ctx.log(`[lead-tick] PR #${pr.number}: review handoff created → ${handoffId}`);
|
|
126
|
+
routed++;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
ctx.log(`[lead-tick] PR #${pr.number}: failed to create review handoff`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// 3. Merge APPROVED + CI-green + MERGEABLE PRs
|
|
134
|
+
if (pr.reviewDecision === "APPROVED" && pr.mergeable === "MERGEABLE" && ciGreen(pr)) {
|
|
135
|
+
try {
|
|
136
|
+
await run(`gh pr merge ${pr.number} --squash --delete-branch`);
|
|
137
|
+
ctx.log(`[lead-tick] PR #${pr.number}: merged`);
|
|
138
|
+
merged++;
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
ctx.log(`[lead-tick] PR #${pr.number}: merge failed: ${err.message}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else if (pr.reviewDecision === "APPROVED") {
|
|
145
|
+
skipped++;
|
|
146
|
+
ctx.log(`[lead-tick] PR #${pr.number}: approved but not mergeable (mergeable=${pr.mergeable}, ci=${ciGreen(pr)})`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
ctx.log(`[lead-tick] PR #${pr.number}: unexpected error: ${err.message}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
ctx.log(`[lead-tick] done — prs=${prs.length} updated=${updated} routed=${routed} merged=${merged} skipped=${skipped}`);
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=lead-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lead-loop.js","sourceRoot":"","sources":["../../../src/core/daemon/lead-loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predefined agent roles — each role activates specific daemon behaviour and
|
|
3
|
+
* injects a role-scoped system prompt into the agent's CLAUDE.md context.
|
|
4
|
+
*
|
|
5
|
+
* Adding a new role requires updating all three exports below.
|
|
6
|
+
*/
|
|
7
|
+
/** Canonical set of predefined roles. Free-form strings are still accepted for
|
|
8
|
+
* hub auto-assignment but will not activate role-specific daemon behaviour. */
|
|
9
|
+
export type AgentRole = "coordinator" | "developer" | "reviewer" | "lead" | "observer" | "watcher";
|
|
10
|
+
export declare const VALID_ROLES: readonly AgentRole[];
|
|
11
|
+
export declare function isKnownRole(role: string): role is AgentRole;
|
|
12
|
+
/**
|
|
13
|
+
* System prompt injected into CLAUDE.md for each predefined role.
|
|
14
|
+
* Injected at session start — works for all runners (opencode, claude, codex, custom).
|
|
15
|
+
*/
|
|
16
|
+
export declare const ROLE_SYSTEM_PROMPTS: Record<AgentRole, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Maps each predefined role to a daemon behaviour mode:
|
|
19
|
+
* - "lead-loop" → starts runLeadTick every 2 minutes
|
|
20
|
+
* - "worker" → standard inbox poll + auto-accept handoffs
|
|
21
|
+
* - "observer" → heartbeat only; no auto-accept, no lead loop
|
|
22
|
+
*
|
|
23
|
+
* Replaces inferAttendedFromRole() in bootstrap.ts for known roles.
|
|
24
|
+
*/
|
|
25
|
+
export declare const ROLE_DAEMON_BEHAVIOUR: Record<AgentRole, "lead-loop" | "worker" | "observer" | "watcher-loop">;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predefined agent roles — each role activates specific daemon behaviour and
|
|
3
|
+
* injects a role-scoped system prompt into the agent's CLAUDE.md context.
|
|
4
|
+
*
|
|
5
|
+
* Adding a new role requires updating all three exports below.
|
|
6
|
+
*/
|
|
7
|
+
export const VALID_ROLES = [
|
|
8
|
+
"coordinator",
|
|
9
|
+
"developer",
|
|
10
|
+
"reviewer",
|
|
11
|
+
"lead",
|
|
12
|
+
"observer",
|
|
13
|
+
"watcher",
|
|
14
|
+
];
|
|
15
|
+
export function isKnownRole(role) {
|
|
16
|
+
return VALID_ROLES.includes(role);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* System prompt injected into CLAUDE.md for each predefined role.
|
|
20
|
+
* Injected at session start — works for all runners (opencode, claude, codex, custom).
|
|
21
|
+
*/
|
|
22
|
+
export const ROLE_SYSTEM_PROMPTS = {
|
|
23
|
+
coordinator: "You are a coordinator agent. Your job is to route work, manage PR reviews via handoffs, and merge approved pull requests. Do not implement features yourself — delegate to developer agents.",
|
|
24
|
+
developer: "You are a developer agent. Your job is to implement features and bug fixes assigned via handoffs, write tests, and open pull requests for review.",
|
|
25
|
+
reviewer: "You are a reviewer agent. Your job is to review pull requests and handoff proposals for correctness, quality, and consistency. Approve, request changes, or reject with clear reasoning.",
|
|
26
|
+
lead: "You are a lead agent. You coordinate the team, route work to the right agents, monitor SLAs, and escalate blockers. You also review high-level architecture decisions.",
|
|
27
|
+
observer: "You are an observer agent. You monitor team activity and provide strategic input when asked. You do not accept handoffs automatically and do not modify code directly.",
|
|
28
|
+
watcher: "You are a watcher agent. Every ~2 minutes you receive a project state snapshot showing handoffs, agent health, blockers, and claims. Analyze the state and take corrective actions using agentmesh CLI commands: nudge stuck agents, escalate breached SLAs, reassign stalled handoffs, create blockers, release stale claims. Process one tick at a time — after analysis and action, wait for the next tick. Do not take actions unprompted between ticks.",
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Maps each predefined role to a daemon behaviour mode:
|
|
32
|
+
* - "lead-loop" → starts runLeadTick every 2 minutes
|
|
33
|
+
* - "worker" → standard inbox poll + auto-accept handoffs
|
|
34
|
+
* - "observer" → heartbeat only; no auto-accept, no lead loop
|
|
35
|
+
*
|
|
36
|
+
* Replaces inferAttendedFromRole() in bootstrap.ts for known roles.
|
|
37
|
+
*/
|
|
38
|
+
export const ROLE_DAEMON_BEHAVIOUR = {
|
|
39
|
+
coordinator: "lead-loop",
|
|
40
|
+
developer: "worker",
|
|
41
|
+
reviewer: "worker",
|
|
42
|
+
lead: "lead-loop",
|
|
43
|
+
observer: "observer",
|
|
44
|
+
watcher: "watcher-loop",
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=roles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../../../src/core/daemon/roles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,CAAC,MAAM,WAAW,GAAyB;IAC/C,aAAa;IACb,WAAW;IACX,UAAU;IACV,MAAM;IACN,UAAU;IACV,SAAS;CACV,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAQ,WAAiC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA8B;IAC5D,WAAW,EACT,8LAA8L;IAChM,SAAS,EACP,mJAAmJ;IACrJ,QAAQ,EACN,0LAA0L;IAC5L,IAAI,EAAE,wKAAwK;IAC9K,QAAQ,EACN,wKAAwK;IAC1K,OAAO,EACL,8bAA8b;CACjc,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAG9B;IACF,WAAW,EAAE,WAAW;IACxB,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,WAAW;IACjB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,cAAc;CACxB,CAAC"}
|
|
@@ -1 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ProcessExitEvent } from "./startup-diagnostics.js";
|
|
2
|
+
/**
|
|
3
|
+
* Gets the most recent process exit event from diagnostics
|
|
4
|
+
*/
|
|
5
|
+
export declare function getLastProcessExit(agentName: string): ProcessExitEvent | null;
|
|
6
|
+
/**
|
|
7
|
+
* Determines if a session failure is recoverable based on the reason
|
|
8
|
+
* and startup diagnostics.
|
|
9
|
+
*
|
|
10
|
+
* A failure is considered recoverable if:
|
|
11
|
+
* 1. The reason matches known recoverable patterns
|
|
12
|
+
* 2. The process exited during startup (within 15s) AND the exit event is fresh
|
|
13
|
+
* (within 60s) - this suggests a transient issue that may resolve on retry
|
|
14
|
+
*
|
|
15
|
+
* The freshness guard prevents old exit events from misclassifying unrelated
|
|
16
|
+
* future failures as recoverable.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isRecoverableSessionFailure(reason: string, agentName?: string): boolean;
|
|
@@ -1,7 +1,91 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { readStartupDiagnostics } from "./startup-diagnostics.js";
|
|
2
|
+
/**
|
|
3
|
+
* Extended reasons that can indicate a recoverable session failure
|
|
4
|
+
*/
|
|
5
|
+
const RECOVERABLE_REASONS = [
|
|
6
|
+
"session_not_found",
|
|
7
|
+
"pane_dead",
|
|
8
|
+
"no_pid",
|
|
9
|
+
"pane_died",
|
|
10
|
+
"process_replaced",
|
|
11
|
+
"session_terminated",
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Maximum age of an exit event to consider it relevant (60 seconds)
|
|
15
|
+
* Exit events older than this are considered stale and unrelated to current failures
|
|
16
|
+
*/
|
|
17
|
+
const MAX_EXIT_EVENT_AGE_MS = 60000;
|
|
18
|
+
/**
|
|
19
|
+
* Startup window - if process exits within this time of startup, it's recoverable
|
|
20
|
+
*/
|
|
21
|
+
const STARTUP_WINDOW_MS = 15000;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a reason string matches recoverable patterns
|
|
24
|
+
*/
|
|
25
|
+
function matchesRecoverablePattern(reason) {
|
|
26
|
+
return (RECOVERABLE_REASONS.includes(reason) ||
|
|
27
|
+
reason.startsWith("check_failed") ||
|
|
28
|
+
reason.startsWith("session_creation_failed") ||
|
|
29
|
+
reason.startsWith("pane_dead"));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Gets the most recent process exit event from diagnostics
|
|
33
|
+
*/
|
|
34
|
+
export function getLastProcessExit(agentName) {
|
|
35
|
+
const entries = readStartupDiagnostics(agentName);
|
|
36
|
+
// Find the most recent exit entry
|
|
37
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
38
|
+
if (entries[i].type === "exit") {
|
|
39
|
+
return entries[i].data;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Determines if a session failure is recoverable based on the reason
|
|
46
|
+
* and startup diagnostics.
|
|
47
|
+
*
|
|
48
|
+
* A failure is considered recoverable if:
|
|
49
|
+
* 1. The reason matches known recoverable patterns
|
|
50
|
+
* 2. The process exited during startup (within 15s) AND the exit event is fresh
|
|
51
|
+
* (within 60s) - this suggests a transient issue that may resolve on retry
|
|
52
|
+
*
|
|
53
|
+
* The freshness guard prevents old exit events from misclassifying unrelated
|
|
54
|
+
* future failures as recoverable.
|
|
55
|
+
*/
|
|
56
|
+
export function isRecoverableSessionFailure(reason, agentName) {
|
|
57
|
+
// First check pattern match
|
|
58
|
+
if (matchesRecoverablePattern(reason)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
// If we have agent name, check startup diagnostics
|
|
62
|
+
if (agentName) {
|
|
63
|
+
const entries = readStartupDiagnostics(agentName);
|
|
64
|
+
let lastExit = null;
|
|
65
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
66
|
+
if (entries[i].type === "exit") {
|
|
67
|
+
lastExit = {
|
|
68
|
+
exit: entries[i].data,
|
|
69
|
+
timestamp: entries[i].timestamp,
|
|
70
|
+
};
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (lastExit) {
|
|
75
|
+
// Check freshness: exit event must be recent enough to be relevant
|
|
76
|
+
const exitTimestamp = new Date(lastExit.timestamp).getTime();
|
|
77
|
+
const now = Date.now();
|
|
78
|
+
const exitAgeMs = now - exitTimestamp;
|
|
79
|
+
// Only consider fresh exit events (within last 60 seconds)
|
|
80
|
+
if (exitAgeMs <= MAX_EXIT_EVENT_AGE_MS) {
|
|
81
|
+
// If process exited within 15 seconds of startup, consider it recoverable
|
|
82
|
+
// This catches cases where the runner crashed immediately
|
|
83
|
+
if (lastExit.exit.elapsedMs < STARTUP_WINDOW_MS) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
6
90
|
}
|
|
7
91
|
//# sourceMappingURL=session-recovery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-recovery.js","sourceRoot":"","sources":["../../../src/core/daemon/session-recovery.ts"],"names":[],"mappings":"AAAA,MAAM,
|
|
1
|
+
{"version":3,"file":"session-recovery.js","sourceRoot":"","sources":["../../../src/core/daemon/session-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEzF;;GAEG;AACH,MAAM,mBAAmB,GAAG;IAC1B,mBAAmB;IACnB,WAAW;IACX,QAAQ;IACR,WAAW;IACX,kBAAkB;IAClB,oBAAoB;CACrB,CAAC;AAEF;;;GAGG;AACH,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAEpC;;GAEG;AACH,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC;;GAEG;AACH,SAAS,yBAAyB,CAAC,MAAc;IAC/C,OAAO,CACL,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC;QACjC,MAAM,CAAC,UAAU,CAAC,yBAAyB,CAAC;QAC5C,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAC/B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAClD,kCAAkC;IAClC,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,IAAwB,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAc,EAAE,SAAkB;IAC5E,4BAA4B;IAC5B,IAAI,yBAAyB,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mDAAmD;IACnD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAOlD,IAAI,QAAQ,GAAqB,IAAI,CAAC;QAEtC,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC/B,QAAQ,GAAG;oBACT,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAwB;oBACzC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;iBAChC,CAAC;gBACF,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,mEAAmE;YACnE,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;YAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,GAAG,GAAG,aAAa,CAAC;YAEtC,2DAA2D;YAC3D,IAAI,SAAS,IAAI,qBAAqB,EAAE,CAAC;gBACvC,0EAA0E;gBAC1E,0DAA0D;gBAC1D,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;oBAChD,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup Diagnostics for Agent Tmux Sessions
|
|
3
|
+
*
|
|
4
|
+
* Provides structured logging for runner startup to diagnose
|
|
5
|
+
* session creation failures and early exits.
|
|
6
|
+
*/
|
|
7
|
+
export interface StartupDiagnostics {
|
|
8
|
+
/** The final resolved command (with args) that was executed */
|
|
9
|
+
resolvedCommand: string;
|
|
10
|
+
/** Environment variables set (keys only, values redacted) */
|
|
11
|
+
envKeys: string[];
|
|
12
|
+
/** Session name used for tmux */
|
|
13
|
+
sessionName: string;
|
|
14
|
+
/** Working directory for the session */
|
|
15
|
+
workdir?: string;
|
|
16
|
+
/** Timestamp when session creation started */
|
|
17
|
+
startTime: string;
|
|
18
|
+
/** Runner type detected */
|
|
19
|
+
runnerKind: "opencode" | "claude" | "codex" | "other";
|
|
20
|
+
/** Whether autonomous mode was enabled */
|
|
21
|
+
autonomous?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface ProcessExitEvent {
|
|
24
|
+
/** Exit code (null if killed by signal) */
|
|
25
|
+
code: number | null;
|
|
26
|
+
/** Signal that killed the process (null if exited normally) */
|
|
27
|
+
signal: string | null;
|
|
28
|
+
/** Time elapsed since session creation (ms) */
|
|
29
|
+
elapsedMs: number;
|
|
30
|
+
/** Reason classification */
|
|
31
|
+
reason: string;
|
|
32
|
+
}
|
|
33
|
+
interface DiagnosticsEntry {
|
|
34
|
+
type: "startup" | "exit";
|
|
35
|
+
timestamp: string;
|
|
36
|
+
agentName: string;
|
|
37
|
+
data: StartupDiagnostics | ProcessExitEvent;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Redacts sensitive environment variable values, keeping only keys
|
|
41
|
+
*/
|
|
42
|
+
export declare function redactEnvKeys(env: Record<string, string | undefined>): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Detects the runner type from the command
|
|
45
|
+
*/
|
|
46
|
+
export declare function detectRunnerKind(command: string): "opencode" | "claude" | "codex" | "other";
|
|
47
|
+
/**
|
|
48
|
+
* Logs startup diagnostics for a new tmux session
|
|
49
|
+
*/
|
|
50
|
+
export declare function logSessionStartup(agentName: string, diagnostics: StartupDiagnostics): void;
|
|
51
|
+
/**
|
|
52
|
+
* Logs a process exit event
|
|
53
|
+
*/
|
|
54
|
+
export declare function logProcessExit(agentName: string, exitEvent: ProcessExitEvent): void;
|
|
55
|
+
/**
|
|
56
|
+
* Reads the recent diagnostics for an agent
|
|
57
|
+
*/
|
|
58
|
+
export declare function readStartupDiagnostics(agentName: string): DiagnosticsEntry[];
|
|
59
|
+
/**
|
|
60
|
+
* Clears old diagnostics for an agent (keeps last 100 entries)
|
|
61
|
+
*/
|
|
62
|
+
export declare function cleanupOldDiagnostics(agentName: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* Captures the current pane PID for an agent's session
|
|
65
|
+
*/
|
|
66
|
+
export declare function capturePanePid(sessionName: string): number | null;
|
|
67
|
+
/**
|
|
68
|
+
* Monitors a tmux session for early process exit
|
|
69
|
+
* Returns a cleanup function to stop monitoring
|
|
70
|
+
*/
|
|
71
|
+
export declare function monitorSessionExit(agentName: string, sessionName: string, startTime: Date, onEarlyExit?: (event: ProcessExitEvent) => void): () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Formats a diagnostic summary for display
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatDiagnosticSummary(agentName: string): string;
|
|
76
|
+
export {};
|