@agentmeshhq/agent 0.2.1 → 0.3.0
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__/context-template.test.d.ts +4 -0
- package/dist/__tests__/context-template.test.js +233 -0
- package/dist/__tests__/context-template.test.js.map +1 -0
- package/dist/__tests__/loader.test.js +140 -28
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/no-respawn.test.d.ts +1 -0
- package/dist/__tests__/no-respawn.test.js +254 -0
- package/dist/__tests__/no-respawn.test.js.map +1 -0
- package/dist/__tests__/onboard.test.d.ts +5 -0
- package/dist/__tests__/onboard.test.js +341 -0
- package/dist/__tests__/onboard.test.js.map +1 -0
- package/dist/__tests__/shared-resource-guards.test.d.ts +7 -0
- package/dist/__tests__/shared-resource-guards.test.js +260 -0
- package/dist/__tests__/shared-resource-guards.test.js.map +1 -0
- package/dist/cli/inbox.d.ts +5 -0
- package/dist/cli/inbox.js +123 -0
- package/dist/cli/inbox.js.map +1 -0
- package/dist/cli/index.js +0 -0
- package/dist/cli/issue.d.ts +42 -0
- package/dist/cli/issue.js +297 -0
- package/dist/cli/issue.js.map +1 -0
- package/dist/cli/ready.d.ts +5 -0
- package/dist/cli/ready.js +131 -0
- package/dist/cli/ready.js.map +1 -0
- package/dist/cli/sync.d.ts +8 -0
- package/dist/cli/sync.js +154 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/config/loader.d.ts +0 -4
- package/dist/config/loader.js +102 -42
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +2 -2
- package/dist/core/daemon/context-template.d.ts +11 -0
- package/dist/core/daemon/context-template.js +144 -0
- package/dist/core/daemon/context-template.js.map +1 -0
- package/dist/core/daemon/crash-log.d.ts +0 -2
- package/dist/core/daemon/crash-log.js +0 -1
- package/dist/core/daemon/crash-log.js.map +1 -1
- package/dist/core/daemon/git-auth.d.ts +18 -0
- package/dist/core/daemon/git-auth.js +88 -0
- package/dist/core/daemon/git-auth.js.map +1 -0
- package/dist/core/daemon/health-policy.d.ts +0 -4
- package/dist/core/daemon/health-policy.js +0 -8
- package/dist/core/daemon/health-policy.js.map +1 -1
- package/dist/core/daemon/state.js +1 -0
- package/dist/core/daemon/state.js.map +1 -1
- package/dist/core/daemon/workspace.d.ts +13 -0
- package/dist/core/daemon/workspace.js +39 -0
- package/dist/core/daemon/workspace.js.map +1 -1
- package/dist/core/daemon.d.ts +9 -6
- package/dist/core/daemon.js +206 -185
- package/dist/core/daemon.js.map +1 -1
- package/dist/core/injector.d.ts +5 -1
- package/dist/core/injector.js +77 -0
- package/dist/core/injector.js.map +1 -1
- package/dist/core/issue-cache.d.ts +44 -0
- package/dist/core/issue-cache.js +75 -0
- package/dist/core/issue-cache.js.map +1 -0
- package/dist/core/registry.d.ts +62 -0
- package/dist/core/registry.js +18 -0
- package/dist/core/registry.js.map +1 -1
- package/package.json +12 -11
- package/LICENSE +0 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/core/daemon/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAS7B;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IAErE,OAAO,CAAC,GAAG,CAAC,oFAAoF,CAAC,CAAC;IAClG,OAAO,CAAC,GAAG,CAAC,2CAA2C,WAAW,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,oFAAoF,CAAC,CAAC;IAElG,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,+BAA+B,aAAa,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QAEzC,IAAI,CAAC;YACH,QAAQ,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACvE,QAAQ,CAAC,gBAAgB,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACpF,QAAQ,CAAC,mBAAmB,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACvF,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,iCAAkC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1E,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,WAAW,aAAa,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,aAAa,aAAa,IAAI,CAAC,CAAC;IAE5C,IAAI,CAAC;QACH,QAAQ,CAAC,sBAAsB,aAAa,KAAK,OAAO,MAAM,aAAa,GAAG,EAAE;YAC9E,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAoC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7E,OAAO,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;QAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,aAAa,IAAI,CAAC,CAAC;IACrD,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/core/daemon/workspace.ts"],"names":[],"mappings":"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"}
|
package/dist/core/daemon.d.ts
CHANGED
|
@@ -44,12 +44,11 @@ export declare class AgentDaemon {
|
|
|
44
44
|
private sandboxImage;
|
|
45
45
|
private sandboxCpu;
|
|
46
46
|
private sandboxMemory;
|
|
47
|
+
private onboardData;
|
|
47
48
|
private sandbox;
|
|
48
49
|
private healthCheckInterval;
|
|
49
50
|
private _preStartSessionId;
|
|
50
51
|
private _attemptedResumeSessionId;
|
|
51
|
-
private restartCount;
|
|
52
|
-
private lastStableTime;
|
|
53
52
|
private stuckSince;
|
|
54
53
|
private nudgeSentAt;
|
|
55
54
|
constructor(options: DaemonOptions);
|
|
@@ -67,10 +66,6 @@ export declare class AgentDaemon {
|
|
|
67
66
|
* Handles stuck agent - sends nudge first, then restarts if still stuck
|
|
68
67
|
*/
|
|
69
68
|
private handleStuckAgent;
|
|
70
|
-
/**
|
|
71
|
-
* Restarts the agent session (sandbox or non-sandbox)
|
|
72
|
-
*/
|
|
73
|
-
private restartSession;
|
|
74
69
|
stop(): Promise<void>;
|
|
75
70
|
/**
|
|
76
71
|
* Starts opencode serve mode (for Integration Service)
|
|
@@ -100,4 +95,12 @@ export declare class AgentDaemon {
|
|
|
100
95
|
* Creates ~/.agentmesh/opencode-sandbox.json with permissive permissions and model
|
|
101
96
|
*/
|
|
102
97
|
private ensureSandboxOpencodeConfig;
|
|
98
|
+
/**
|
|
99
|
+
* Caches onboard data to disk for offline fallback
|
|
100
|
+
*/
|
|
101
|
+
private cacheOnboardData;
|
|
102
|
+
/**
|
|
103
|
+
* Loads cached onboard data from disk (without credentials)
|
|
104
|
+
*/
|
|
105
|
+
private loadCachedOnboardData;
|
|
103
106
|
}
|
package/dist/core/daemon.js
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
1
|
+
import { execSync, spawn } from "node:child_process";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { getAgentState,
|
|
5
|
+
import { getAgentState, loadState, updateAgentInState } from "../config/loader.js";
|
|
6
6
|
import { loadContext, loadOrCreateContext, saveContext } from "../context/index.js";
|
|
7
7
|
import { renderMissingWorkdirMessage } from "./daemon/assignment-message.js";
|
|
8
8
|
import { bootstrapDaemon } from "./daemon/bootstrap.js";
|
|
9
|
+
import { removeClaudeMd, writeClaudeMd } from "./daemon/context-template.js";
|
|
9
10
|
import { formatCrashLog } from "./daemon/crash-log.js";
|
|
10
|
-
import {
|
|
11
|
+
import { cleanupGitAuth, setupGitAuth } from "./daemon/git-auth.js";
|
|
12
|
+
import { getNudgeMessage, getStuckDetail, isWithinNudgeWaitWindow, } from "./daemon/health-policy.js";
|
|
11
13
|
import { writeSandboxOpencodeConfig } from "./daemon/sandbox-config.js";
|
|
12
14
|
import { captureAgentChildPids, persistRunningState } from "./daemon/state.js";
|
|
13
15
|
import { startTmuxRuntimeSession } from "./daemon/tmux-session.js";
|
|
14
|
-
import { setupWorkspace } from "./daemon/workspace.js";
|
|
16
|
+
import { configureGitIdentity, setupWorkspace, validatePushAccess } from "./daemon/workspace.js";
|
|
15
17
|
import { Heartbeat } from "./heartbeat.js";
|
|
16
|
-
import { handleWebSocketEvent, injectRestoredContext, injectStartupMessage } from "./injector.js";
|
|
17
|
-
import { checkInbox, fetchAssignments, registerAgent } from "./registry.js";
|
|
18
|
+
import { handleWebSocketEvent, injectOnboardMessage, injectRestoredContext, injectStartupMessage, } from "./injector.js";
|
|
19
|
+
import { checkInbox, fetchAssignments, fetchOnboard, registerAgent, } from "./registry.js";
|
|
18
20
|
import { getRunnerDisplayName } from "./runner.js";
|
|
19
21
|
import { DockerSandbox } from "./sandbox.js";
|
|
20
|
-
import { getLatestSessionId,
|
|
21
|
-
import { captureSessionContext, captureSessionOutput,
|
|
22
|
+
import { getLatestSessionId, waitForNewSessionId } from "./session-id.js";
|
|
23
|
+
import { captureSessionContext, captureSessionOutput, destroySession, isSessionHealthy, killProcessTree, updateSessionEnvironment, } from "./tmux.js";
|
|
22
24
|
import { prepareOpenCodeRuntime } from "./tmux-runtime.js";
|
|
23
25
|
import { checkAgentProgress, cleanupOrphanContainers, isProcessRunning, sendNudge, } from "./watchdog.js";
|
|
24
26
|
import { AgentWebSocket } from "./websocket.js";
|
|
25
|
-
//
|
|
26
|
-
const MAX_RESTART_ATTEMPTS = 3;
|
|
27
|
-
// Time after which restart count resets (30 minutes of stable operation)
|
|
28
|
-
const RESTART_COUNT_RESET_MS = 30 * 60 * 1000;
|
|
29
|
-
// Time to wait after nudging before restarting (2 minutes)
|
|
27
|
+
// Time to wait after nudging before marking as stuck (2 minutes)
|
|
30
28
|
const NUDGE_WAIT_MS = 2 * 60 * 1000;
|
|
31
29
|
// Path to the sandbox OpenCode config (permissive permissions)
|
|
32
30
|
const SANDBOX_OPENCODE_CONFIG_PATH = path.join(os.homedir(), ".agentmesh", "opencode-sandbox.json");
|
|
@@ -56,14 +54,13 @@ export class AgentDaemon {
|
|
|
56
54
|
sandboxImage;
|
|
57
55
|
sandboxCpu;
|
|
58
56
|
sandboxMemory;
|
|
57
|
+
onboardData = null;
|
|
59
58
|
sandbox = null;
|
|
60
59
|
healthCheckInterval = null;
|
|
61
60
|
// Session resume tracking
|
|
62
61
|
_preStartSessionId;
|
|
63
62
|
_attemptedResumeSessionId;
|
|
64
|
-
//
|
|
65
|
-
restartCount = 0;
|
|
66
|
-
lastStableTime = null;
|
|
63
|
+
// Stuck detection tracking
|
|
67
64
|
stuckSince = null;
|
|
68
65
|
nudgeSentAt = null;
|
|
69
66
|
constructor(options) {
|
|
@@ -113,9 +110,6 @@ export class AgentDaemon {
|
|
|
113
110
|
console.log(`Cleaned up ${cleaned} orphan container(s)`);
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
|
-
// Reset restart count on manual start
|
|
117
|
-
this.restartCount = 0;
|
|
118
|
-
this.lastStableTime = new Date();
|
|
119
113
|
// Register with hub first (needed for assignment check)
|
|
120
114
|
console.log("Registering with AgentMesh hub...");
|
|
121
115
|
console.log(`Existing state: ${existingState ? `agentId=${existingState.agentId}` : "none"}`);
|
|
@@ -139,8 +133,65 @@ export class AgentDaemon {
|
|
|
139
133
|
else {
|
|
140
134
|
console.log(`Registered as: ${this.agentId}`);
|
|
141
135
|
}
|
|
136
|
+
// Fetch onboard payload (project context, credentials, team)
|
|
137
|
+
try {
|
|
138
|
+
this.onboardData = await fetchOnboard(this.config.hubUrl, this.token);
|
|
139
|
+
if (this.onboardData) {
|
|
140
|
+
console.log(`Onboard data received${this.onboardData.project ? `: project=${this.onboardData.project.name}` : ""}`);
|
|
141
|
+
// Set up git credentials before workspace setup
|
|
142
|
+
for (const repo of this.onboardData.repos) {
|
|
143
|
+
if (repo.credential) {
|
|
144
|
+
const extraEnv = setupGitAuth({
|
|
145
|
+
type: repo.credential.type,
|
|
146
|
+
value: repo.credential.value,
|
|
147
|
+
repoUrl: repo.url,
|
|
148
|
+
agentName: this.agentName,
|
|
149
|
+
});
|
|
150
|
+
Object.assign(this.runnerConfig.env, extraEnv);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Cache onboard data locally for offline fallback
|
|
154
|
+
this.cacheOnboardData();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.log("Onboard fetch failed (non-fatal):", error.message);
|
|
159
|
+
// Try loading cached onboard data
|
|
160
|
+
this.onboardData = this.loadCachedOnboardData();
|
|
161
|
+
if (this.onboardData) {
|
|
162
|
+
console.log("Loaded cached onboard data");
|
|
163
|
+
}
|
|
164
|
+
}
|
|
142
165
|
// Check assignments and auto-setup workdir if needed (before creating tmux session)
|
|
143
166
|
await this.checkAssignments();
|
|
167
|
+
// Enforce unique working directories — no two running agents may share the same workdir
|
|
168
|
+
if (this.agentConfig.workdir) {
|
|
169
|
+
const resolvedWorkdir = path.resolve(this.agentConfig.workdir);
|
|
170
|
+
const state = loadState();
|
|
171
|
+
const conflict = state.agents.find((a) => a.name !== this.agentName &&
|
|
172
|
+
a.workdir &&
|
|
173
|
+
path.resolve(a.workdir) === resolvedWorkdir &&
|
|
174
|
+
a.pid > 0 &&
|
|
175
|
+
isProcessRunning(a.pid));
|
|
176
|
+
if (conflict) {
|
|
177
|
+
throw new Error(`Workdir conflict: "${resolvedWorkdir}" is already in use by agent "${conflict.name}" (PID: ${conflict.pid}).\n` +
|
|
178
|
+
`Each agent must have its own working directory to avoid git conflicts.\n` +
|
|
179
|
+
`Use --workdir to specify a unique path, e.g.:\n` +
|
|
180
|
+
` agentmesh start --name ${this.agentName} --workdir ~/Dev/${this.assignedProject || "project"}-${this.agentName}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Check for serve port collision
|
|
184
|
+
if (this.serveMode) {
|
|
185
|
+
const state = loadState();
|
|
186
|
+
const portConflict = state.agents.find((a) => a.name !== this.agentName &&
|
|
187
|
+
a.servePort === this.servePort &&
|
|
188
|
+
a.pid > 0 &&
|
|
189
|
+
isProcessRunning(a.pid));
|
|
190
|
+
if (portConflict) {
|
|
191
|
+
throw new Error(`Port ${this.servePort} already in use by agent "${portConflict.name}" (PID: ${portConflict.pid}).\n` +
|
|
192
|
+
`Use --serve-port to specify a different port.`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
144
195
|
// Choose runtime mode: sandbox > serve > tmux
|
|
145
196
|
if (this.sandboxMode) {
|
|
146
197
|
await this.startSandboxMode();
|
|
@@ -277,6 +328,20 @@ export class AgentDaemon {
|
|
|
277
328
|
console.error("Failed to check inbox:", error);
|
|
278
329
|
injectStartupMessage(this.agentName, 0);
|
|
279
330
|
}
|
|
331
|
+
// Inject onboard project context
|
|
332
|
+
if (this.onboardData?.project) {
|
|
333
|
+
injectOnboardMessage(this.agentName, this.onboardData);
|
|
334
|
+
}
|
|
335
|
+
// Write persistent CLAUDE.md context file
|
|
336
|
+
if (this.onboardData && this.agentConfig.workdir) {
|
|
337
|
+
const mdPath = writeClaudeMd({
|
|
338
|
+
workdir: this.agentConfig.workdir,
|
|
339
|
+
onboard: this.onboardData,
|
|
340
|
+
});
|
|
341
|
+
if (mdPath) {
|
|
342
|
+
console.log(`✓ CLAUDE.md written: ${mdPath}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
280
345
|
// Restore context from previous session
|
|
281
346
|
if (this.shouldRestoreContext && this.agentId) {
|
|
282
347
|
console.log("Checking for previous context...");
|
|
@@ -368,17 +433,11 @@ Nudge agent:
|
|
|
368
433
|
this.healthCheckInterval = setInterval(async () => {
|
|
369
434
|
if (!this.isRunning)
|
|
370
435
|
return;
|
|
371
|
-
// Reset restart count after stable operation
|
|
372
|
-
if (shouldResetRestartCount(this.restartCount, this.lastStableTime, RESTART_COUNT_RESET_MS)) {
|
|
373
|
-
console.log(`[HEALTH] Agent stable for 30+ minutes, resetting restart count`);
|
|
374
|
-
this.restartCount = 0;
|
|
375
|
-
resetAgentRestartCount(this.agentName);
|
|
376
|
-
}
|
|
377
436
|
// For sandbox mode, pass container name so health check looks inside container
|
|
378
437
|
const containerName = this.sandboxMode ? this.sandbox?.getContainerName() : undefined;
|
|
379
438
|
const health = isSessionHealthy(this.agentName, containerName);
|
|
380
439
|
if (!health.healthy) {
|
|
381
|
-
// Session died -
|
|
440
|
+
// Session died - log and mark as failed (no auto-restart)
|
|
382
441
|
await this.handleSessionDeath(health.reason || "unknown", logDir);
|
|
383
442
|
return;
|
|
384
443
|
}
|
|
@@ -395,7 +454,7 @@ Nudge agent:
|
|
|
395
454
|
console.log(`[HEALTH] Agent is waiting for human input: ${progress.details}`);
|
|
396
455
|
}
|
|
397
456
|
else if (progress.status === "permission_blocked" || progress.status === "stuck") {
|
|
398
|
-
|
|
457
|
+
this.handleStuckAgent(progress);
|
|
399
458
|
}
|
|
400
459
|
else if (progress.status === "active") {
|
|
401
460
|
// Agent is working - reset stuck tracking
|
|
@@ -405,7 +464,6 @@ Nudge agent:
|
|
|
405
464
|
this.nudgeSentAt = null;
|
|
406
465
|
updateAgentInState(this.agentName, { stuckSince: undefined, status: "running" });
|
|
407
466
|
}
|
|
408
|
-
this.lastStableTime = new Date();
|
|
409
467
|
}
|
|
410
468
|
}, 60000); // Check every 60 seconds
|
|
411
469
|
}
|
|
@@ -428,57 +486,34 @@ Nudge agent:
|
|
|
428
486
|
agentName: this.agentName,
|
|
429
487
|
agentId: this.agentId,
|
|
430
488
|
reason,
|
|
431
|
-
restartCount: this.restartCount,
|
|
432
|
-
maxRestartAttempts: MAX_RESTART_ATTEMPTS,
|
|
433
489
|
sandboxLabel: this.sandboxMode ? this.sandbox?.getContainerName() || "sandbox" : "none",
|
|
434
490
|
workdir: this.agentConfig.workdir,
|
|
435
491
|
model: this.runnerConfig.model,
|
|
436
492
|
lastOutput,
|
|
437
493
|
});
|
|
438
494
|
fs.appendFileSync(logFile, crashLog);
|
|
439
|
-
// Save context
|
|
495
|
+
// Save context before marking as failed
|
|
440
496
|
if (this.agentId) {
|
|
441
497
|
this.saveAgentContext();
|
|
442
498
|
}
|
|
443
|
-
//
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
this.lastStableTime = new Date();
|
|
456
|
-
}
|
|
457
|
-
catch (error) {
|
|
458
|
-
console.error(`[RESTART] Failed to restart: ${error.message}`);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
// Exceeded restart limit - mark as failed
|
|
463
|
-
console.error(`[FAILED] Agent exceeded restart limit (${MAX_RESTART_ATTEMPTS}). Manual intervention required.`);
|
|
464
|
-
// Terminal bell to alert user
|
|
465
|
-
process.stdout.write("\x07");
|
|
466
|
-
updateAgentInState(this.agentName, {
|
|
467
|
-
status: "failed",
|
|
468
|
-
restartCount: this.restartCount,
|
|
469
|
-
});
|
|
470
|
-
// Stop monitoring
|
|
471
|
-
this.isRunning = false;
|
|
472
|
-
if (this.healthCheckInterval) {
|
|
473
|
-
clearInterval(this.healthCheckInterval);
|
|
474
|
-
this.healthCheckInterval = null;
|
|
475
|
-
}
|
|
499
|
+
// Mark as failed — no auto-restart, user must intervene
|
|
500
|
+
console.error(`[FAILED] Session died: ${reason}. Manual intervention required (use 'agentmesh restart ${this.agentName}').`);
|
|
501
|
+
// Terminal bell to alert user
|
|
502
|
+
process.stdout.write("\x07");
|
|
503
|
+
updateAgentInState(this.agentName, {
|
|
504
|
+
status: "failed",
|
|
505
|
+
});
|
|
506
|
+
// Stop monitoring
|
|
507
|
+
this.isRunning = false;
|
|
508
|
+
if (this.healthCheckInterval) {
|
|
509
|
+
clearInterval(this.healthCheckInterval);
|
|
510
|
+
this.healthCheckInterval = null;
|
|
476
511
|
}
|
|
477
512
|
}
|
|
478
513
|
/**
|
|
479
514
|
* Handles stuck agent - sends nudge first, then restarts if still stuck
|
|
480
515
|
*/
|
|
481
|
-
|
|
516
|
+
handleStuckAgent(progress) {
|
|
482
517
|
const now = new Date();
|
|
483
518
|
if (!this.stuckSince) {
|
|
484
519
|
// First detection of stuck state
|
|
@@ -489,7 +524,7 @@ Nudge agent:
|
|
|
489
524
|
status: "stuck",
|
|
490
525
|
});
|
|
491
526
|
}
|
|
492
|
-
//
|
|
527
|
+
// Nudge worker agents — don't escalate to restart
|
|
493
528
|
if (this.isWorkerAgent) {
|
|
494
529
|
// If we haven't sent a nudge yet, send one
|
|
495
530
|
if (!this.nudgeSentAt) {
|
|
@@ -510,124 +545,9 @@ Nudge agent:
|
|
|
510
545
|
// Still waiting for agent to respond to nudge
|
|
511
546
|
return;
|
|
512
547
|
}
|
|
548
|
+
// Nudge grace period expired — log warning but do NOT restart
|
|
549
|
+
console.log(`[HEALTH] Agent still stuck after nudge. Manual intervention required.`);
|
|
513
550
|
}
|
|
514
|
-
// Agent still stuck - trigger restart (or restart immediately if not a worker)
|
|
515
|
-
console.log(`[HEALTH] Agent still stuck${this.isWorkerAgent ? " after nudge" : ""}, triggering restart...`);
|
|
516
|
-
this.stuckSince = null;
|
|
517
|
-
this.nudgeSentAt = null;
|
|
518
|
-
await this.handleSessionDeath("stuck_after_nudge", path.join(os.homedir(), ".agentmesh", "logs"));
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* Restarts the agent session (sandbox or non-sandbox)
|
|
522
|
-
*/
|
|
523
|
-
async restartSession() {
|
|
524
|
-
// Retrieve tracked child PIDs before destroying the session
|
|
525
|
-
const currentState = getAgentState(this.agentName);
|
|
526
|
-
const childPids = currentState?.childPids ?? [];
|
|
527
|
-
// Destroy existing session AND kill all tracked child processes
|
|
528
|
-
destroySession(this.agentName, childPids);
|
|
529
|
-
// Allow cleanup to settle before spawning a new session
|
|
530
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
531
|
-
if (this.sandboxMode && this.sandbox) {
|
|
532
|
-
// Restart sandbox container
|
|
533
|
-
const newContainerId = await this.sandbox.restart();
|
|
534
|
-
console.log(`[RESTART] New container: ${newContainerId.substring(0, 12)}`);
|
|
535
|
-
// Recreate tmux session for sandbox
|
|
536
|
-
const containerName = this.sandbox.getContainerName();
|
|
537
|
-
// Build environment args for docker exec
|
|
538
|
-
const envArgs = [];
|
|
539
|
-
const allEnv = {
|
|
540
|
-
...this.runnerConfig.env,
|
|
541
|
-
AGENT_TOKEN: this.token,
|
|
542
|
-
AGENTMESH_AGENT_ID: this.agentId,
|
|
543
|
-
};
|
|
544
|
-
for (const [key, value] of Object.entries(allEnv)) {
|
|
545
|
-
if (value !== undefined && value !== "") {
|
|
546
|
-
envArgs.push(`-e "${key}=${value}"`);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
const envString = envArgs.join(" ");
|
|
550
|
-
const modelArg = this.runnerConfig.env?.OPENCODE_MODEL
|
|
551
|
-
? ` --model ${this.runnerConfig.env.OPENCODE_MODEL}`
|
|
552
|
-
: "";
|
|
553
|
-
const dockerExecCommand = `docker exec -it ${envString} ${containerName} opencode${modelArg}`;
|
|
554
|
-
const created = createSession(this.agentName, dockerExecCommand, undefined, undefined);
|
|
555
|
-
if (!created) {
|
|
556
|
-
throw new Error("Failed to create tmux session for restarted sandbox");
|
|
557
|
-
}
|
|
558
|
-
// Track new child PIDs and update state
|
|
559
|
-
const newChildPids = captureAgentChildPids(this.agentName);
|
|
560
|
-
updateAgentInState(this.agentName, {
|
|
561
|
-
sandboxContainer: containerName,
|
|
562
|
-
childPids: newChildPids,
|
|
563
|
-
});
|
|
564
|
-
if (newChildPids.length > 0) {
|
|
565
|
-
console.log(`[RESTART] Tracking ${newChildPids.length} child PIDs: ${newChildPids.join(", ")}`);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
else {
|
|
569
|
-
// Non-sandbox restart — load saved session ID for native resume
|
|
570
|
-
let savedSessionId;
|
|
571
|
-
let savedContext = null;
|
|
572
|
-
if (this.agentId) {
|
|
573
|
-
savedContext = loadContext(this.agentId);
|
|
574
|
-
savedSessionId = savedContext?.custom?.opencodeSessionId;
|
|
575
|
-
if (savedSessionId) {
|
|
576
|
-
console.log(`[RESTART] Attempting to resume OpenCode session: ${savedSessionId}`);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
const preRestartSessionId = snapshotSessionId(this.agentName);
|
|
580
|
-
const created = createSession(this.agentName, this.agentConfig.command, this.agentConfig.workdir, this.runnerConfig.env, savedSessionId);
|
|
581
|
-
if (!created) {
|
|
582
|
-
throw new Error("Failed to create tmux session");
|
|
583
|
-
}
|
|
584
|
-
// Re-inject environment
|
|
585
|
-
updateSessionEnvironment(this.agentName, {
|
|
586
|
-
AGENT_TOKEN: this.token,
|
|
587
|
-
AGENTMESH_AGENT_ID: this.agentId,
|
|
588
|
-
...this.runnerConfig.env,
|
|
589
|
-
});
|
|
590
|
-
// Track new child PIDs
|
|
591
|
-
const newChildPids = captureAgentChildPids(this.agentName);
|
|
592
|
-
updateAgentInState(this.agentName, { childPids: newChildPids });
|
|
593
|
-
if (newChildPids.length > 0) {
|
|
594
|
-
console.log(`[RESTART] Tracking ${newChildPids.length} child PIDs: ${newChildPids.join(", ")}`);
|
|
595
|
-
}
|
|
596
|
-
// Verify native resume and fallback if needed
|
|
597
|
-
if (savedSessionId && savedContext) {
|
|
598
|
-
const newSessionId = await waitForNewSessionId(this.agentName, preRestartSessionId, 15000);
|
|
599
|
-
if (!newSessionId) {
|
|
600
|
-
const health = isSessionHealthy(this.agentName);
|
|
601
|
-
const currentSessionId = getLatestSessionId(this.agentName);
|
|
602
|
-
if (!health.healthy) {
|
|
603
|
-
console.log(`[RESTART] Fallback: OpenCode not healthy, injecting text summary.`);
|
|
604
|
-
savedContext.custom = { ...savedContext.custom, opencodeSessionId: undefined };
|
|
605
|
-
saveContext(savedContext);
|
|
606
|
-
injectRestoredContext(this.agentName, savedContext);
|
|
607
|
-
}
|
|
608
|
-
else if (currentSessionId === savedSessionId) {
|
|
609
|
-
console.log(`[RESTART] Resumed OpenCode session ${savedSessionId}`);
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
console.log(`[RESTART] Fallback: session not found. Injecting text summary.`);
|
|
613
|
-
savedContext.custom = { ...savedContext.custom, opencodeSessionId: undefined };
|
|
614
|
-
saveContext(savedContext);
|
|
615
|
-
injectRestoredContext(this.agentName, savedContext);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
else if (newSessionId === savedSessionId) {
|
|
619
|
-
console.log(`[RESTART] Resumed OpenCode session ${savedSessionId}`);
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
console.log(`[RESTART] Fallback: resume failed (got ${newSessionId}). Injecting text summary.`);
|
|
623
|
-
savedContext.custom = { ...savedContext.custom, opencodeSessionId: newSessionId };
|
|
624
|
-
saveContext(savedContext);
|
|
625
|
-
injectRestoredContext(this.agentName, savedContext);
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
// Wait for session to be ready
|
|
630
|
-
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
631
551
|
}
|
|
632
552
|
async stop() {
|
|
633
553
|
console.log(`\nStopping agent: ${this.agentName}`);
|
|
@@ -642,6 +562,12 @@ Nudge agent:
|
|
|
642
562
|
console.log("Saving agent context...");
|
|
643
563
|
this.saveAgentContext();
|
|
644
564
|
}
|
|
565
|
+
// Clean up git credential files
|
|
566
|
+
cleanupGitAuth(this.agentName);
|
|
567
|
+
// Remove CLAUDE.md context file
|
|
568
|
+
if (this.agentConfig.workdir) {
|
|
569
|
+
removeClaudeMd(this.agentConfig.workdir);
|
|
570
|
+
}
|
|
645
571
|
// Stop heartbeat
|
|
646
572
|
if (this.heartbeat) {
|
|
647
573
|
this.heartbeat.stop();
|
|
@@ -912,8 +838,51 @@ Logs: docker logs ${containerName}
|
|
|
912
838
|
if (!this.agentConfig.workdir) {
|
|
913
839
|
const assignmentWithWorkdir = assignments.find((a) => a.project.workdir);
|
|
914
840
|
if (assignmentWithWorkdir?.project.workdir) {
|
|
915
|
-
|
|
916
|
-
|
|
841
|
+
// Append agent name as sibling directory to avoid shared workdir conflicts
|
|
842
|
+
// e.g. /Users/raju/Dev/agentmesh -> /Users/raju/Dev/agentmesh-agent-1
|
|
843
|
+
const baseWorkdir = assignmentWithWorkdir.project.workdir;
|
|
844
|
+
const uniqueWorkdir = path.join(path.dirname(baseWorkdir), `${path.basename(baseWorkdir)}-${this.agentName}`);
|
|
845
|
+
console.log(`Using workdir from project settings (per-agent): ${uniqueWorkdir}`);
|
|
846
|
+
// If the unique dir doesn't exist, set up workspace (clone or pull)
|
|
847
|
+
const gitDir = path.join(uniqueWorkdir, ".git");
|
|
848
|
+
if (!fs.existsSync(gitDir)) {
|
|
849
|
+
// Find repo info from assignments or onboard data for cloning
|
|
850
|
+
const repoAssignment = assignments.find((a) => a.repo !== null);
|
|
851
|
+
if (repoAssignment?.repo) {
|
|
852
|
+
this.agentConfig.workdir = setupWorkspace({
|
|
853
|
+
workspacePath: uniqueWorkdir,
|
|
854
|
+
repoUrl: repoAssignment.repo.url,
|
|
855
|
+
defaultBranch: repoAssignment.repo.default_branch,
|
|
856
|
+
projectName: repoAssignment.project.name,
|
|
857
|
+
});
|
|
858
|
+
configureGitIdentity({
|
|
859
|
+
workspacePath: uniqueWorkdir,
|
|
860
|
+
agentName: this.agentName,
|
|
861
|
+
agentDisplayName: this.onboardData?.agent.display_name ?? this.agentName,
|
|
862
|
+
});
|
|
863
|
+
validatePushAccess(uniqueWorkdir);
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
// No repo info — just create the directory
|
|
867
|
+
fs.mkdirSync(uniqueWorkdir, { recursive: true });
|
|
868
|
+
this.agentConfig.workdir = uniqueWorkdir;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
else {
|
|
872
|
+
// Directory exists with .git — pull latest
|
|
873
|
+
console.log(`Workspace exists, pulling latest...`);
|
|
874
|
+
try {
|
|
875
|
+
execSync("git fetch origin && git pull", {
|
|
876
|
+
cwd: uniqueWorkdir,
|
|
877
|
+
stdio: "pipe",
|
|
878
|
+
timeout: 30_000,
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
catch (error) {
|
|
882
|
+
console.warn(`Could not pull latest: ${error.message}`);
|
|
883
|
+
}
|
|
884
|
+
this.agentConfig.workdir = uniqueWorkdir;
|
|
885
|
+
}
|
|
917
886
|
return;
|
|
918
887
|
}
|
|
919
888
|
// No project.workdir set, check if we have a repo assignment
|
|
@@ -930,6 +899,13 @@ Logs: docker logs ${containerName}
|
|
|
930
899
|
defaultBranch: repo.default_branch,
|
|
931
900
|
projectName: repoAssignment.project.name,
|
|
932
901
|
});
|
|
902
|
+
// Configure git identity and validate push access
|
|
903
|
+
configureGitIdentity({
|
|
904
|
+
workspacePath: expandedPath,
|
|
905
|
+
agentName: this.agentName,
|
|
906
|
+
agentDisplayName: this.onboardData?.agent.display_name ?? this.agentName,
|
|
907
|
+
});
|
|
908
|
+
validatePushAccess(expandedPath);
|
|
933
909
|
return;
|
|
934
910
|
}
|
|
935
911
|
console.error(renderMissingWorkdirMessage({
|
|
@@ -962,5 +938,50 @@ Logs: docker logs ${containerName}
|
|
|
962
938
|
});
|
|
963
939
|
console.log(`Updated sandbox OpenCode config: ${SANDBOX_OPENCODE_CONFIG_PATH}`);
|
|
964
940
|
}
|
|
941
|
+
/**
|
|
942
|
+
* Caches onboard data to disk for offline fallback
|
|
943
|
+
*/
|
|
944
|
+
cacheOnboardData() {
|
|
945
|
+
if (!this.onboardData || !this.agentId)
|
|
946
|
+
return;
|
|
947
|
+
try {
|
|
948
|
+
const cacheDir = path.join(os.homedir(), ".agentmesh", "context");
|
|
949
|
+
if (!fs.existsSync(cacheDir)) {
|
|
950
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
951
|
+
}
|
|
952
|
+
// Strip credential values before caching
|
|
953
|
+
const cacheData = {
|
|
954
|
+
...this.onboardData,
|
|
955
|
+
repos: this.onboardData.repos.map((r) => ({
|
|
956
|
+
...r,
|
|
957
|
+
credential: r.credential ? { type: r.credential.type, value: "***" } : null,
|
|
958
|
+
})),
|
|
959
|
+
cached_at: new Date().toISOString(),
|
|
960
|
+
};
|
|
961
|
+
const cachePath = path.join(cacheDir, `${this.agentId}-onboard.json`);
|
|
962
|
+
fs.writeFileSync(cachePath, JSON.stringify(cacheData, null, 2));
|
|
963
|
+
}
|
|
964
|
+
catch (error) {
|
|
965
|
+
console.log("Failed to cache onboard data:", error.message);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Loads cached onboard data from disk (without credentials)
|
|
970
|
+
*/
|
|
971
|
+
loadCachedOnboardData() {
|
|
972
|
+
if (!this.agentId)
|
|
973
|
+
return null;
|
|
974
|
+
try {
|
|
975
|
+
const cachePath = path.join(os.homedir(), ".agentmesh", "context", `${this.agentId}-onboard.json`);
|
|
976
|
+
if (!fs.existsSync(cachePath))
|
|
977
|
+
return null;
|
|
978
|
+
const raw = fs.readFileSync(cachePath, "utf-8");
|
|
979
|
+
const data = JSON.parse(raw);
|
|
980
|
+
return data;
|
|
981
|
+
}
|
|
982
|
+
catch {
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
965
986
|
}
|
|
966
987
|
//# sourceMappingURL=daemon.js.map
|