@agentmeshhq/agent 0.4.16 → 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/LICENSE +21 -0
- 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 +78 -1
- package/dist/__tests__/injector.test.js.map +1 -1
- 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__/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__/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 +88 -0
- 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/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/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/roles.d.ts +2 -2
- package/dist/core/daemon/roles.js +3 -0
- package/dist/core/daemon/roles.js.map +1 -1
- 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 +12 -0
- package/dist/core/daemon.js +134 -2
- package/dist/core/daemon.js.map +1 -1
- package/dist/core/injector.js +164 -27
- package/dist/core/injector.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 +11 -12
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches project state from hub APIs and formats it for LLM injection.
|
|
3
|
+
*
|
|
4
|
+
* Each tick sends a full snapshot — the LLM reasons from a single tick
|
|
5
|
+
* without needing conversation history.
|
|
6
|
+
*
|
|
7
|
+
* Epic #883
|
|
8
|
+
*/
|
|
9
|
+
export interface WatcherContext {
|
|
10
|
+
hubUrl: string;
|
|
11
|
+
token: string;
|
|
12
|
+
workspace: string;
|
|
13
|
+
teamId: string;
|
|
14
|
+
agentName: string;
|
|
15
|
+
log: (msg: string) => void;
|
|
16
|
+
}
|
|
17
|
+
interface HandoffSnapshot {
|
|
18
|
+
handoff_id: string;
|
|
19
|
+
from_agent_id: string | null;
|
|
20
|
+
to_agent_id: string | null;
|
|
21
|
+
scope: string;
|
|
22
|
+
status: string;
|
|
23
|
+
created_at: string;
|
|
24
|
+
accepted_at: string | null;
|
|
25
|
+
}
|
|
26
|
+
interface ClaimSnapshot {
|
|
27
|
+
claim_id: string;
|
|
28
|
+
agent_id: string;
|
|
29
|
+
scope: string;
|
|
30
|
+
paths: string[];
|
|
31
|
+
status: string;
|
|
32
|
+
expires_at: string;
|
|
33
|
+
}
|
|
34
|
+
interface BlockerSnapshot {
|
|
35
|
+
blocker_id: string;
|
|
36
|
+
agent_id: string;
|
|
37
|
+
scope: string;
|
|
38
|
+
category: string;
|
|
39
|
+
description: string;
|
|
40
|
+
status: string;
|
|
41
|
+
created_at: string;
|
|
42
|
+
}
|
|
43
|
+
interface AgentSnapshot {
|
|
44
|
+
agent_id: string;
|
|
45
|
+
display_name: string;
|
|
46
|
+
status: string;
|
|
47
|
+
model: string;
|
|
48
|
+
last_heartbeat_at: string | null;
|
|
49
|
+
metadata?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
interface TeamMemberSnapshot {
|
|
52
|
+
agent_id: string;
|
|
53
|
+
display_name: string;
|
|
54
|
+
role: string;
|
|
55
|
+
}
|
|
56
|
+
export interface WatcherStatePayload {
|
|
57
|
+
fetchedAt: string;
|
|
58
|
+
handoffs: HandoffSnapshot[];
|
|
59
|
+
claims: ClaimSnapshot[];
|
|
60
|
+
blockers: BlockerSnapshot[];
|
|
61
|
+
agents: AgentSnapshot[];
|
|
62
|
+
teamMembers: TeamMemberSnapshot[];
|
|
63
|
+
}
|
|
64
|
+
export declare function fetchWatcherState(ctx: WatcherContext): Promise<WatcherStatePayload>;
|
|
65
|
+
export declare function formatStateForLlm(state: WatcherStatePayload, tickNumber: number, triggerReasons: string[]): string;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches project state from hub APIs and formats it for LLM injection.
|
|
3
|
+
*
|
|
4
|
+
* Each tick sends a full snapshot — the LLM reasons from a single tick
|
|
5
|
+
* without needing conversation history.
|
|
6
|
+
*
|
|
7
|
+
* Epic #883
|
|
8
|
+
*/
|
|
9
|
+
async function fetchJson(url, token) {
|
|
10
|
+
const res = await fetch(url, {
|
|
11
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
12
|
+
});
|
|
13
|
+
if (!res.ok) {
|
|
14
|
+
throw new Error(`${url} returned ${res.status}`);
|
|
15
|
+
}
|
|
16
|
+
return res.json();
|
|
17
|
+
}
|
|
18
|
+
export async function fetchWatcherState(ctx) {
|
|
19
|
+
const base = `${ctx.hubUrl}/api/v1/workspaces/${ctx.workspace}`;
|
|
20
|
+
const [handoffsRes, claimsRes, blockersRes, agentsRes, membersRes] = await Promise.all([
|
|
21
|
+
fetchJson(`${base}/handoffs?limit=50`, ctx.token).catch(() => ({
|
|
22
|
+
data: [],
|
|
23
|
+
})),
|
|
24
|
+
fetchJson(`${base}/claims`, ctx.token).catch(() => ({
|
|
25
|
+
data: [],
|
|
26
|
+
})),
|
|
27
|
+
fetchJson(`${base}/blockers`, ctx.token).catch(() => ({
|
|
28
|
+
data: [],
|
|
29
|
+
})),
|
|
30
|
+
fetchJson(`${base}/agents`, ctx.token).catch(() => ({
|
|
31
|
+
data: [],
|
|
32
|
+
})),
|
|
33
|
+
fetchJson(`${ctx.hubUrl}/api/v1/workspaces/${ctx.workspace}/teams/${ctx.teamId}/members`, ctx.token).catch(() => ({ data: [] })),
|
|
34
|
+
]);
|
|
35
|
+
return {
|
|
36
|
+
fetchedAt: new Date().toISOString(),
|
|
37
|
+
handoffs: handoffsRes.data,
|
|
38
|
+
claims: claimsRes.data.filter((c) => c.status === "active"),
|
|
39
|
+
blockers: blockersRes.data.filter((b) => b.status === "open"),
|
|
40
|
+
agents: agentsRes.data,
|
|
41
|
+
teamMembers: membersRes.data,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function timeSince(iso) {
|
|
45
|
+
const ms = Date.now() - new Date(iso).getTime();
|
|
46
|
+
const seconds = Math.floor(ms / 1000);
|
|
47
|
+
if (seconds < 60)
|
|
48
|
+
return `${seconds}s`;
|
|
49
|
+
if (seconds < 3600)
|
|
50
|
+
return `${Math.floor(seconds / 60)}m`;
|
|
51
|
+
if (seconds < 86400)
|
|
52
|
+
return `${Math.floor(seconds / 3600)}h`;
|
|
53
|
+
return `${Math.floor(seconds / 86400)}d`;
|
|
54
|
+
}
|
|
55
|
+
function agentHealth(agent) {
|
|
56
|
+
if (!agent.last_heartbeat_at)
|
|
57
|
+
return "unknown";
|
|
58
|
+
const ago = (Date.now() - new Date(agent.last_heartbeat_at).getTime()) / 1000;
|
|
59
|
+
if (ago < 15)
|
|
60
|
+
return "online";
|
|
61
|
+
if (ago < 45)
|
|
62
|
+
return "idle";
|
|
63
|
+
if (ago < 120)
|
|
64
|
+
return "stale";
|
|
65
|
+
return "offline";
|
|
66
|
+
}
|
|
67
|
+
export function formatStateForLlm(state, tickNumber, triggerReasons) {
|
|
68
|
+
const lines = [];
|
|
69
|
+
lines.push(`[AgentMesh Watcher] === TICK #${tickNumber} === ${state.fetchedAt}`);
|
|
70
|
+
lines.push(`Triggered by: ${triggerReasons.join(" + ")}`);
|
|
71
|
+
lines.push("");
|
|
72
|
+
// Build agent ID → display name lookup
|
|
73
|
+
const agentNames = new Map();
|
|
74
|
+
for (const a of state.agents) {
|
|
75
|
+
agentNames.set(a.agent_id, a.display_name);
|
|
76
|
+
}
|
|
77
|
+
const resolveName = (id) => {
|
|
78
|
+
if (!id)
|
|
79
|
+
return "-";
|
|
80
|
+
return agentNames.get(id) ?? id.slice(0, 12);
|
|
81
|
+
};
|
|
82
|
+
// Handoffs — only non-completed
|
|
83
|
+
const activeHandoffs = state.handoffs.filter((h) => h.status !== "completed");
|
|
84
|
+
lines.push(`## Handoffs (${activeHandoffs.length} active)`);
|
|
85
|
+
if (activeHandoffs.length === 0) {
|
|
86
|
+
lines.push("No active handoffs.");
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
lines.push("| ID | From | To | Status | Age |");
|
|
90
|
+
lines.push("|---|---|---|---|---|");
|
|
91
|
+
for (const h of activeHandoffs.slice(0, 20)) {
|
|
92
|
+
const age = h.created_at ? timeSince(h.created_at) : "?";
|
|
93
|
+
lines.push(`| ${h.handoff_id.slice(0, 12)} | ${resolveName(h.from_agent_id)} | ${resolveName(h.to_agent_id)} | ${h.status} | ${age} |`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
lines.push("");
|
|
97
|
+
// Agents
|
|
98
|
+
lines.push(`## Agents (${state.agents.length})`);
|
|
99
|
+
if (state.agents.length > 0) {
|
|
100
|
+
lines.push("| Name | Status | Health | Last Seen |");
|
|
101
|
+
lines.push("|---|---|---|---|");
|
|
102
|
+
for (const a of state.agents.slice(0, 20)) {
|
|
103
|
+
const health = agentHealth(a);
|
|
104
|
+
const lastSeen = a.last_heartbeat_at ? timeSince(a.last_heartbeat_at) : "never";
|
|
105
|
+
lines.push(`| ${a.display_name} | ${a.status} | ${health} | ${lastSeen} ago |`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
lines.push("");
|
|
109
|
+
// Team members
|
|
110
|
+
if (state.teamMembers.length > 0) {
|
|
111
|
+
lines.push(`## Team Members (${state.teamMembers.length})`);
|
|
112
|
+
for (const m of state.teamMembers) {
|
|
113
|
+
lines.push(`- ${m.display_name} (${m.role})`);
|
|
114
|
+
}
|
|
115
|
+
lines.push("");
|
|
116
|
+
}
|
|
117
|
+
// Blockers
|
|
118
|
+
lines.push(`## Blockers (${state.blockers.length} open)`);
|
|
119
|
+
if (state.blockers.length === 0) {
|
|
120
|
+
lines.push("No open blockers.");
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
for (const b of state.blockers.slice(0, 10)) {
|
|
124
|
+
const age = b.created_at ? timeSince(b.created_at) : "?";
|
|
125
|
+
lines.push(`- ${b.blocker_id.slice(0, 12)}: "${b.description.slice(0, 80)}" (${b.category}, ${age}, agent: ${resolveName(b.agent_id)})`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
lines.push("");
|
|
129
|
+
// Claims
|
|
130
|
+
lines.push(`## Claims (${state.claims.length} active)`);
|
|
131
|
+
if (state.claims.length === 0) {
|
|
132
|
+
lines.push("No active claims.");
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
for (const c of state.claims.slice(0, 10)) {
|
|
136
|
+
lines.push(`- ${resolveName(c.agent_id)}: ${c.paths.join(", ")} (${c.scope})`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
lines.push("");
|
|
140
|
+
// Available actions
|
|
141
|
+
lines.push("## Available Actions");
|
|
142
|
+
lines.push('- `agentmesh nudge <agent-name> "<message>"` — nudge an agent');
|
|
143
|
+
lines.push("- `agentmesh handoff reassign <handoff-id> --to <agent-id>` — reassign a handoff");
|
|
144
|
+
lines.push("- `agentmesh handoff complete <handoff-id>` — mark handoff done");
|
|
145
|
+
lines.push('- `agentmesh blocker create "<description>"` — create a blocker');
|
|
146
|
+
lines.push("- `agentmesh claims release <claim-id>` — release a stale claim");
|
|
147
|
+
lines.push("");
|
|
148
|
+
lines.push("Analyze the above state and take any necessary actions. When done, wait for the next tick.");
|
|
149
|
+
return lines.join("\n");
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=watcher-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher-state.js","sourceRoot":"","sources":["../../../src/core/daemon/watcher-state.ts"],"names":[],"mappings":"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"}
|
package/dist/core/daemon.d.ts
CHANGED
|
@@ -62,8 +62,11 @@ export declare class AgentDaemon {
|
|
|
62
62
|
private autonomous;
|
|
63
63
|
private healthCheckInterval;
|
|
64
64
|
private inboxPollInterval;
|
|
65
|
+
private commandPollInterval;
|
|
65
66
|
private leadInterval;
|
|
66
67
|
private leadContext;
|
|
68
|
+
private watcherLoopHandle;
|
|
69
|
+
private watcherQueue;
|
|
67
70
|
private stopCleanupScheduler;
|
|
68
71
|
private authHealthWatcher;
|
|
69
72
|
private _preStartSessionId;
|
|
@@ -71,12 +74,14 @@ export declare class AgentDaemon {
|
|
|
71
74
|
private stuckSince;
|
|
72
75
|
private lastPendingHandoffAlertAt;
|
|
73
76
|
private remoteAutomationPaused;
|
|
77
|
+
private rateLimitDetected;
|
|
74
78
|
private lastAutonomyPolicyFetchAt;
|
|
75
79
|
private teamId;
|
|
76
80
|
private pendingClaimCreations;
|
|
77
81
|
private sessionRecoveryAttempts;
|
|
78
82
|
private lastSessionRecoveryAt;
|
|
79
83
|
private initialInboxCheckComplete;
|
|
84
|
+
private commandPollInFlight;
|
|
80
85
|
constructor(options: DaemonOptions);
|
|
81
86
|
start(): Promise<void>;
|
|
82
87
|
/**
|
|
@@ -84,6 +89,11 @@ export declare class AgentDaemon {
|
|
|
84
89
|
* Includes auto-restart logic and progress watchdog
|
|
85
90
|
*/
|
|
86
91
|
private autoAcceptPendingHandoffs;
|
|
92
|
+
/**
|
|
93
|
+
* GH-887: After accepting a handoff, verify the LLM acknowledged it.
|
|
94
|
+
* If rate-limited, pause auto-acceptance. If stuck after retries, log warning.
|
|
95
|
+
*/
|
|
96
|
+
private verifyHandoffInjection;
|
|
87
97
|
private autoAcceptHandoffFromEvent;
|
|
88
98
|
private isAutomationPaused;
|
|
89
99
|
private sweepInboxOnWebSocketConnect;
|
|
@@ -97,6 +107,8 @@ export declare class AgentDaemon {
|
|
|
97
107
|
private releaseAllAutoClaims;
|
|
98
108
|
private reconcileAutoClaims;
|
|
99
109
|
private startHealthMonitor;
|
|
110
|
+
private startCommandPoller;
|
|
111
|
+
private pollNextCommand;
|
|
100
112
|
/**
|
|
101
113
|
* Handles session death - logs crash and attempts auto-restart
|
|
102
114
|
*/
|
package/dist/core/daemon.js
CHANGED
|
@@ -13,12 +13,15 @@ import { formatCrashLog } from "./daemon/crash-log.js";
|
|
|
13
13
|
import { evaluateRestartState, filterActiveClaimsForAgent, filterCompletedHandoffsForAgent, formatRestartLifecycleLog, } from "./daemon/done-state-guard.js";
|
|
14
14
|
import { cleanupGitAuth, setupGitAuth } from "./daemon/git-auth.js";
|
|
15
15
|
import { getStuckDetail } from "./daemon/health-policy.js";
|
|
16
|
+
import { verifyInjection } from "./daemon/injection-verify.js";
|
|
16
17
|
import { runLeadTick } from "./daemon/lead-loop.js";
|
|
17
18
|
import { isKnownRole, ROLE_DAEMON_BEHAVIOUR, VALID_ROLES } from "./daemon/roles.js";
|
|
18
19
|
import { writeSandboxOpencodeConfig } from "./daemon/sandbox-config.js";
|
|
19
20
|
import { isRecoverableSessionFailure } from "./daemon/session-recovery.js";
|
|
20
21
|
import { captureAgentChildPids, persistRunningState } from "./daemon/state.js";
|
|
21
22
|
import { startTmuxRuntimeSession } from "./daemon/tmux-session.js";
|
|
23
|
+
import { handleWatcherWebSocketEvent, startWatcherLoop, } from "./daemon/watcher-loop.js";
|
|
24
|
+
import { WatcherTickQueue } from "./daemon/watcher-queue.js";
|
|
22
25
|
import { configureGitIdentity, setupWorkspace, updateWorkspaceFromRemote, validatePushAccess, } from "./daemon/workspace.js";
|
|
23
26
|
import { findPendingHandoffBreaches } from "./handoff-sla.js";
|
|
24
27
|
import { Heartbeat } from "./heartbeat.js";
|
|
@@ -74,8 +77,11 @@ export class AgentDaemon {
|
|
|
74
77
|
autonomous;
|
|
75
78
|
healthCheckInterval = null;
|
|
76
79
|
inboxPollInterval = null;
|
|
80
|
+
commandPollInterval = null;
|
|
77
81
|
leadInterval = null;
|
|
78
82
|
leadContext = null;
|
|
83
|
+
watcherLoopHandle = null;
|
|
84
|
+
watcherQueue = null;
|
|
79
85
|
stopCleanupScheduler = null;
|
|
80
86
|
authHealthWatcher = null;
|
|
81
87
|
// Session resume tracking
|
|
@@ -85,12 +91,14 @@ export class AgentDaemon {
|
|
|
85
91
|
stuckSince = null;
|
|
86
92
|
lastPendingHandoffAlertAt = null;
|
|
87
93
|
remoteAutomationPaused = false;
|
|
94
|
+
rateLimitDetected = false;
|
|
88
95
|
lastAutonomyPolicyFetchAt = null;
|
|
89
96
|
teamId;
|
|
90
97
|
pendingClaimCreations = new Set();
|
|
91
98
|
sessionRecoveryAttempts = 0;
|
|
92
99
|
lastSessionRecoveryAt = null;
|
|
93
100
|
initialInboxCheckComplete = false;
|
|
101
|
+
commandPollInFlight = false;
|
|
94
102
|
constructor(options) {
|
|
95
103
|
const boot = bootstrapDaemon(options);
|
|
96
104
|
this.config = boot.config;
|
|
@@ -357,8 +365,14 @@ export class AgentDaemon {
|
|
|
357
365
|
token: newToken,
|
|
358
366
|
onMessage: (event) => {
|
|
359
367
|
console.log(`[WS] Received event: ${event.type}`);
|
|
368
|
+
if (this.watcherQueue) {
|
|
369
|
+
handleWatcherWebSocketEvent(event, this.watcherQueue);
|
|
370
|
+
}
|
|
360
371
|
this.autoAcceptHandoffFromEvent(event);
|
|
361
|
-
handleWebSocketEvent(this.agentName, event
|
|
372
|
+
handleWebSocketEvent(this.agentName, event, {
|
|
373
|
+
hubUrl: this.config.hubUrl,
|
|
374
|
+
token: this.token ?? undefined,
|
|
375
|
+
});
|
|
362
376
|
},
|
|
363
377
|
onConnect: () => {
|
|
364
378
|
console.log("WebSocket reconnected with new token");
|
|
@@ -384,6 +398,10 @@ export class AgentDaemon {
|
|
|
384
398
|
token: this.token,
|
|
385
399
|
onMessage: (event) => {
|
|
386
400
|
console.log(`[WS] Received event: ${event.type}`);
|
|
401
|
+
// Feed watcher queue before standard handlers (GH-883)
|
|
402
|
+
if (this.watcherQueue) {
|
|
403
|
+
handleWatcherWebSocketEvent(event, this.watcherQueue);
|
|
404
|
+
}
|
|
387
405
|
this.autoAcceptHandoffFromEvent(event);
|
|
388
406
|
handleWebSocketEvent(this.agentName, event, {
|
|
389
407
|
hubUrl: this.config.hubUrl,
|
|
@@ -520,6 +538,7 @@ export class AgentDaemon {
|
|
|
520
538
|
this.isRunning = true;
|
|
521
539
|
// Start session health monitoring (every 60 seconds)
|
|
522
540
|
this.startHealthMonitor();
|
|
541
|
+
this.startCommandPoller();
|
|
523
542
|
// Start lead coordination loop for lead/coordinator roles (GH-824, GH-829)
|
|
524
543
|
const roleBehaviour = isKnownRole(this.projectRole)
|
|
525
544
|
? ROLE_DAEMON_BEHAVIOUR[this.projectRole]
|
|
@@ -540,6 +559,19 @@ export class AgentDaemon {
|
|
|
540
559
|
}, 120_000);
|
|
541
560
|
console.log("[lead-loop] Lead coordination loop started (2-minute tick)");
|
|
542
561
|
}
|
|
562
|
+
// Start LLM watcher loop for watcher role (GH-883)
|
|
563
|
+
if (roleBehaviour === "watcher-loop" && this.token) {
|
|
564
|
+
this.watcherQueue = new WatcherTickQueue();
|
|
565
|
+
this.watcherLoopHandle = startWatcherLoop({
|
|
566
|
+
hubUrl: this.config.hubUrl,
|
|
567
|
+
token: this.token,
|
|
568
|
+
workspace: this.config.workspace,
|
|
569
|
+
teamId: this.teamId ?? "",
|
|
570
|
+
agentName: this.agentName,
|
|
571
|
+
log: (msg) => console.log(msg),
|
|
572
|
+
}, this.watcherQueue);
|
|
573
|
+
console.log("[watcher-loop] LLM watcher loop started (2-minute tick)");
|
|
574
|
+
}
|
|
543
575
|
// Start evicted-agent cleanup scheduler (GH-421)
|
|
544
576
|
if (this.token) {
|
|
545
577
|
this.stopCleanupScheduler = startCleanupScheduler({
|
|
@@ -579,6 +611,11 @@ Nudge agent:
|
|
|
579
611
|
inboxItems.length === 0) {
|
|
580
612
|
return inboxItems;
|
|
581
613
|
}
|
|
614
|
+
// GH-887: Skip auto-accept if rate-limited
|
|
615
|
+
if (this.rateLimitDetected) {
|
|
616
|
+
console.log("[AUTO-ACCEPT] Skipping — agent is rate-limited");
|
|
617
|
+
return inboxItems;
|
|
618
|
+
}
|
|
582
619
|
const accepted = new Set();
|
|
583
620
|
for (const item of inboxItems) {
|
|
584
621
|
if (item.type && item.type !== "handoff") {
|
|
@@ -590,6 +627,8 @@ Nudge agent:
|
|
|
590
627
|
accepted.add(item.id);
|
|
591
628
|
console.log(`[AUTO-ACCEPT] Accepted handoff ${item.id}`);
|
|
592
629
|
await this.ensureClaimForHandoff(item.id, item.scope);
|
|
630
|
+
// GH-887: Verify the LLM actually started processing
|
|
631
|
+
void this.verifyHandoffInjection(item.id, item.scope);
|
|
593
632
|
}
|
|
594
633
|
}
|
|
595
634
|
catch (error) {
|
|
@@ -598,6 +637,34 @@ Nudge agent:
|
|
|
598
637
|
}
|
|
599
638
|
return inboxItems.filter((item) => !accepted.has(item.id));
|
|
600
639
|
}
|
|
640
|
+
/**
|
|
641
|
+
* GH-887: After accepting a handoff, verify the LLM acknowledged it.
|
|
642
|
+
* If rate-limited, pause auto-acceptance. If stuck after retries, log warning.
|
|
643
|
+
*/
|
|
644
|
+
async verifyHandoffInjection(handoffId, scope) {
|
|
645
|
+
try {
|
|
646
|
+
const result = await verifyInjection(this.agentName, handoffId, scope);
|
|
647
|
+
if (result.rateLimited) {
|
|
648
|
+
this.rateLimitDetected = true;
|
|
649
|
+
console.warn(`[INJECT-VERIFY] Rate limit detected — pausing auto-accept for ${this.agentName}`);
|
|
650
|
+
// Clear rate limit after 5 minutes (check again then)
|
|
651
|
+
setTimeout(() => {
|
|
652
|
+
this.rateLimitDetected = false;
|
|
653
|
+
console.log("[INJECT-VERIFY] Rate limit cooldown expired — resuming auto-accept");
|
|
654
|
+
}, 300_000);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
if (result.verified) {
|
|
658
|
+
console.log(`[INJECT-VERIFY] Handoff ${handoffId} verified (${result.attempts} attempt${result.attempts > 1 ? "s" : ""})`);
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
console.warn(`[INJECT-VERIFY] Handoff ${handoffId} NOT verified after ${result.attempts} attempts — LLM may be stuck`);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
catch (error) {
|
|
665
|
+
console.warn(`[INJECT-VERIFY] Error verifying ${handoffId}: ${error.message}`);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
601
668
|
autoAcceptHandoffFromEvent(event) {
|
|
602
669
|
if (!this.autoAcceptHandoffs || !this.token) {
|
|
603
670
|
return;
|
|
@@ -911,6 +978,58 @@ Nudge agent:
|
|
|
911
978
|
}, 5 * 60 * 1000); // Poll every 5 minutes
|
|
912
979
|
}
|
|
913
980
|
}
|
|
981
|
+
startCommandPoller() {
|
|
982
|
+
if (!this.token || !this.agentId || !this.isWorkerAgent) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
// Poll every 5s so commands created during WS disconnects are still picked up.
|
|
986
|
+
this.commandPollInterval = setInterval(() => {
|
|
987
|
+
void this.pollNextCommand();
|
|
988
|
+
}, 5000);
|
|
989
|
+
void this.pollNextCommand();
|
|
990
|
+
}
|
|
991
|
+
async pollNextCommand() {
|
|
992
|
+
if (!this.isRunning || this.commandPollInFlight || !this.token || !this.agentId) {
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
this.commandPollInFlight = true;
|
|
996
|
+
try {
|
|
997
|
+
const params = new URLSearchParams({ target_agent_id: this.agentId });
|
|
998
|
+
const res = await fetch(`${this.config.hubUrl}/api/v1/workspaces/${this.config.workspace}/commands/next?${params.toString()}`, {
|
|
999
|
+
headers: {
|
|
1000
|
+
Authorization: `Bearer ${this.token}`,
|
|
1001
|
+
},
|
|
1002
|
+
});
|
|
1003
|
+
if (!res.ok) {
|
|
1004
|
+
if (res.status !== 404) {
|
|
1005
|
+
const body = await res.text();
|
|
1006
|
+
console.warn(`[command-poller] hub returned ${res.status}: ${body}`);
|
|
1007
|
+
}
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
const payload = (await res.json());
|
|
1011
|
+
if (!payload.command) {
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
handleWebSocketEvent(this.agentName, {
|
|
1015
|
+
type: "control.command",
|
|
1016
|
+
command_id: payload.command.command_id,
|
|
1017
|
+
workspace_id: payload.command.workspace_id,
|
|
1018
|
+
target_agent_id: payload.command.target_agent_id,
|
|
1019
|
+
command_type: payload.command.command_type,
|
|
1020
|
+
payload: payload.command.payload ?? {},
|
|
1021
|
+
}, {
|
|
1022
|
+
hubUrl: this.config.hubUrl,
|
|
1023
|
+
token: this.token ?? undefined,
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
catch (err) {
|
|
1027
|
+
console.warn(`[command-poller] error: ${err.message}`);
|
|
1028
|
+
}
|
|
1029
|
+
finally {
|
|
1030
|
+
this.commandPollInFlight = false;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
914
1033
|
/**
|
|
915
1034
|
* Handles session death - logs crash and attempts auto-restart
|
|
916
1035
|
*/
|
|
@@ -966,12 +1085,21 @@ Nudge agent:
|
|
|
966
1085
|
clearInterval(this.inboxPollInterval);
|
|
967
1086
|
this.inboxPollInterval = null;
|
|
968
1087
|
}
|
|
1088
|
+
if (this.commandPollInterval) {
|
|
1089
|
+
clearInterval(this.commandPollInterval);
|
|
1090
|
+
this.commandPollInterval = null;
|
|
1091
|
+
}
|
|
1092
|
+
if (this.watcherLoopHandle) {
|
|
1093
|
+
this.watcherLoopHandle.stop();
|
|
1094
|
+
this.watcherLoopHandle = null;
|
|
1095
|
+
this.watcherQueue = null;
|
|
1096
|
+
}
|
|
969
1097
|
}
|
|
970
1098
|
async tryRecoverSession(reason) {
|
|
971
1099
|
if (!this.isWorkerAgent || this.serveMode || this.sandboxMode) {
|
|
972
1100
|
return false;
|
|
973
1101
|
}
|
|
974
|
-
if (!isRecoverableSessionFailure(reason)) {
|
|
1102
|
+
if (!isRecoverableSessionFailure(reason, this.agentName)) {
|
|
975
1103
|
return false;
|
|
976
1104
|
}
|
|
977
1105
|
const now = Date.now();
|
|
@@ -1069,6 +1197,10 @@ Nudge agent:
|
|
|
1069
1197
|
clearInterval(this.inboxPollInterval);
|
|
1070
1198
|
this.inboxPollInterval = null;
|
|
1071
1199
|
}
|
|
1200
|
+
if (this.commandPollInterval) {
|
|
1201
|
+
clearInterval(this.commandPollInterval);
|
|
1202
|
+
this.commandPollInterval = null;
|
|
1203
|
+
}
|
|
1072
1204
|
if (this.leadInterval) {
|
|
1073
1205
|
clearInterval(this.leadInterval);
|
|
1074
1206
|
this.leadInterval = null;
|