chatroom-cli 1.103.0 → 1.103.1
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/index.js +274 -139
- package/dist/index.js.map +14 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -81229,6 +81229,14 @@ var init_cursor_sdk_config = __esm(() => {
|
|
|
81229
81229
|
outputActivity: true,
|
|
81230
81230
|
processExited: true
|
|
81231
81231
|
},
|
|
81232
|
+
crashRecovery: {
|
|
81233
|
+
onSessionFailure: {
|
|
81234
|
+
maxAttempts: 6,
|
|
81235
|
+
intervalMs: 1e4,
|
|
81236
|
+
resumeFirstAttempts: 3,
|
|
81237
|
+
recoveryReason: "platform.cursor_sdk_session_reopen"
|
|
81238
|
+
}
|
|
81239
|
+
},
|
|
81232
81240
|
wireEvents: ["sdk.cursor.message", "sdk.cursor.run.completed", "wire.log.agent_end"]
|
|
81233
81241
|
};
|
|
81234
81242
|
});
|
|
@@ -103006,6 +103014,25 @@ function resolveResumableHarnessSessionId(snapshot) {
|
|
|
103006
103014
|
return snapshot.resumableHarnessSessionId ?? snapshot.harnessSessionId;
|
|
103007
103015
|
}
|
|
103008
103016
|
|
|
103017
|
+
// src/daemon/domain/entities/session-recovery-policy.ts
|
|
103018
|
+
function resolveSessionRecoveryPolicy(harness, classification2) {
|
|
103019
|
+
const caps = getHarnessCapabilities(harness);
|
|
103020
|
+
if (classification2.hadSessionFailure && caps.crashRecovery?.onSessionFailure) {
|
|
103021
|
+
return caps.crashRecovery.onSessionFailure;
|
|
103022
|
+
}
|
|
103023
|
+
return DEFAULT_CRASH_RECOVERY_POLICY;
|
|
103024
|
+
}
|
|
103025
|
+
var DEFAULT_CRASH_RECOVERY_POLICY;
|
|
103026
|
+
var init_session_recovery_policy = __esm(() => {
|
|
103027
|
+
init_types();
|
|
103028
|
+
DEFAULT_CRASH_RECOVERY_POLICY = {
|
|
103029
|
+
maxAttempts: 1,
|
|
103030
|
+
intervalMs: 0,
|
|
103031
|
+
resumeFirstAttempts: 0,
|
|
103032
|
+
recoveryReason: "platform.crash_recovery"
|
|
103033
|
+
};
|
|
103034
|
+
});
|
|
103035
|
+
|
|
103009
103036
|
// src/daemon/domain/usecase/classify-resume-storm-reason.ts
|
|
103010
103037
|
function classifyResumeStormReason(logLines) {
|
|
103011
103038
|
const blob = logLines.join(`
|
|
@@ -103114,18 +103141,6 @@ function appendRecentLogLine(slot, line) {
|
|
|
103114
103141
|
}
|
|
103115
103142
|
var RECENT_LOG_LINE_CAP2 = 100;
|
|
103116
103143
|
|
|
103117
|
-
// src/daemon/domain/usecase/cursor-sdk-session-reopen-retry.ts
|
|
103118
|
-
var CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS = 20, CURSOR_SDK_SESSION_REOPEN_INTERVAL_MS = 5000, CURSOR_SDK_SESSION_REOPEN_REASON = "platform.cursor_sdk_session_reopen", CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS = 3;
|
|
103119
|
-
|
|
103120
|
-
// src/daemon/domain/usecase/detect-cursor-sdk-run-error.ts
|
|
103121
|
-
function isCursorSdkRunErrorInLogs(logLines) {
|
|
103122
|
-
return logLines.some((line) => line.includes(" run-error]"));
|
|
103123
|
-
}
|
|
103124
|
-
function formatCursorSdkRunErrorMessage(logLines) {
|
|
103125
|
-
const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
|
|
103126
|
-
return line?.trim() ?? "Cursor SDK run failed";
|
|
103127
|
-
}
|
|
103128
|
-
|
|
103129
103144
|
// src/daemon/domain/usecase/handle-turn-completed.ts
|
|
103130
103145
|
async function handleTurnCompleted(deps, input, slot) {
|
|
103131
103146
|
if (await tryAbortResumeStorm(deps, input, slot)) {
|
|
@@ -103262,6 +103277,19 @@ var init_native_spawn_presence = __esm(() => {
|
|
|
103262
103277
|
init_execution_kind();
|
|
103263
103278
|
});
|
|
103264
103279
|
|
|
103280
|
+
// src/daemon/infrastructure/local/harness/session-monitors/no-op-session-monitor.ts
|
|
103281
|
+
var NO_FAILURE, noOpSessionMonitor;
|
|
103282
|
+
var init_no_op_session_monitor = __esm(() => {
|
|
103283
|
+
NO_FAILURE = {
|
|
103284
|
+
hadSessionFailure: false,
|
|
103285
|
+
failureKind: "none",
|
|
103286
|
+
recoverable: true
|
|
103287
|
+
};
|
|
103288
|
+
noOpSessionMonitor = {
|
|
103289
|
+
classifyExitFailure: () => NO_FAILURE
|
|
103290
|
+
};
|
|
103291
|
+
});
|
|
103292
|
+
|
|
103265
103293
|
// src/daemon/infrastructure/agent-process-manager/agent-process-manager.ts
|
|
103266
103294
|
function agentKey3(chatroomId, role) {
|
|
103267
103295
|
return `${chatroomId}:${role.toLowerCase()}`;
|
|
@@ -103271,7 +103299,7 @@ class AgentProcessManager {
|
|
|
103271
103299
|
deps;
|
|
103272
103300
|
slots = new Map;
|
|
103273
103301
|
lastHarnessSessions = new Map;
|
|
103274
|
-
|
|
103302
|
+
sessionRecoveryRetryInFlight = new Set;
|
|
103275
103303
|
exitRetryQueue = [];
|
|
103276
103304
|
exitRetryTimer = null;
|
|
103277
103305
|
turnEndQueue = new TurnEndQueue;
|
|
@@ -103689,12 +103717,12 @@ class AgentProcessManager {
|
|
|
103689
103717
|
});
|
|
103690
103718
|
}));
|
|
103691
103719
|
this.resetSlotAfterExit(slot);
|
|
103692
|
-
|
|
103720
|
+
const exitLifecyclePromise = this.emitExitEvent(slot, opts, ctx);
|
|
103693
103721
|
try {
|
|
103694
103722
|
await this.deps.persistence.clearAgentPid(this.deps.machineId, opts.chatroomId, opts.role);
|
|
103695
103723
|
} catch {}
|
|
103696
103724
|
this.untrackAllServices(opts.pid);
|
|
103697
|
-
lifecyclePromise.then(() => this.dispatchRestartAfterExit(opts, ctx, key)).catch(() => {});
|
|
103725
|
+
lifecyclePromise.then(() => this.dispatchRestartAfterExit(opts, ctx, key, exitLifecyclePromise)).catch(() => {});
|
|
103698
103726
|
}
|
|
103699
103727
|
captureExitContext(slot, opts, stopReason) {
|
|
103700
103728
|
return {
|
|
@@ -103742,7 +103770,7 @@ class AgentProcessManager {
|
|
|
103742
103770
|
slot.pendingOperation = undefined;
|
|
103743
103771
|
slot.nativeTurnPhase = undefined;
|
|
103744
103772
|
}
|
|
103745
|
-
|
|
103773
|
+
emitExitEvent(slot, opts, ctx) {
|
|
103746
103774
|
const stopReason = ctx.stopReason;
|
|
103747
103775
|
const exitArgs = {
|
|
103748
103776
|
sessionId: this.deps.sessionId,
|
|
@@ -103756,14 +103784,14 @@ class AgentProcessManager {
|
|
|
103756
103784
|
signal: opts.signal ?? undefined,
|
|
103757
103785
|
agentHarness: ctx.harness
|
|
103758
103786
|
};
|
|
103759
|
-
this.recordAgentExit(opts.role, exitArgs, "Failed to record agent exit event");
|
|
103787
|
+
return this.recordAgentExit(opts.role, exitArgs, "Failed to record agent exit event");
|
|
103760
103788
|
}
|
|
103761
103789
|
untrackAllServices(pid) {
|
|
103762
103790
|
for (const service3 of this.deps.agentServices.values()) {
|
|
103763
103791
|
service3.untrack(pid);
|
|
103764
103792
|
}
|
|
103765
103793
|
}
|
|
103766
|
-
dispatchRestartAfterExit(opts, ctx, _key) {
|
|
103794
|
+
dispatchRestartAfterExit(opts, ctx, _key, exitLifecyclePromise) {
|
|
103767
103795
|
if (this.isStopRequested(opts.chatroomId, opts.role)) {
|
|
103768
103796
|
return;
|
|
103769
103797
|
}
|
|
@@ -103774,14 +103802,123 @@ class AgentProcessManager {
|
|
|
103774
103802
|
}
|
|
103775
103803
|
return;
|
|
103776
103804
|
}
|
|
103777
|
-
this.maybeRestartAgent(opts, ctx);
|
|
103805
|
+
this.maybeRestartAgent(opts, ctx, exitLifecyclePromise);
|
|
103778
103806
|
}
|
|
103779
|
-
|
|
103780
|
-
|
|
103781
|
-
|
|
103807
|
+
maybeRestartAgent(opts, ctx, exitLifecyclePromise) {
|
|
103808
|
+
const { harness, recentLogLines } = ctx;
|
|
103809
|
+
const logs = recentLogLines ?? [];
|
|
103810
|
+
if (!harness || !ctx.workingDir) {
|
|
103811
|
+
console.log(`[AgentProcessManager] ⚠️ Cannot restart — missing harness or workingDir ` + `(role: ${opts.role}, harness: ${harness ?? "none"}, workingDir: ${ctx.workingDir ?? "none"})`);
|
|
103812
|
+
return;
|
|
103782
103813
|
}
|
|
103783
|
-
|
|
103784
|
-
|
|
103814
|
+
const monitor = this.deps.sessionMonitors.get(harness) ?? noOpSessionMonitor;
|
|
103815
|
+
const monitorCtx = {
|
|
103816
|
+
recentLogLines: logs,
|
|
103817
|
+
harness,
|
|
103818
|
+
wantResume: ctx.wantResume
|
|
103819
|
+
};
|
|
103820
|
+
const classification2 = monitor.classifyExitFailure(monitorCtx);
|
|
103821
|
+
this.retrySessionRecovery(opts, ctx, classification2, monitor, monitorCtx, exitLifecyclePromise);
|
|
103822
|
+
}
|
|
103823
|
+
async retrySessionRecovery(opts, ctx, classification2, monitor, monitorCtx, exitLifecyclePromise) {
|
|
103824
|
+
const harness = ctx.harness;
|
|
103825
|
+
const policy = resolveSessionRecoveryPolicy(harness, classification2);
|
|
103826
|
+
const key = agentKey3(opts.chatroomId, opts.role);
|
|
103827
|
+
const multiAttempt = policy.maxAttempts > 1;
|
|
103828
|
+
if (multiAttempt && this.sessionRecoveryRetryInFlight.has(key)) {
|
|
103829
|
+
return;
|
|
103830
|
+
}
|
|
103831
|
+
if (multiAttempt) {
|
|
103832
|
+
this.sessionRecoveryRetryInFlight.add(key);
|
|
103833
|
+
}
|
|
103834
|
+
try {
|
|
103835
|
+
await this.prepareSessionRecoveryBeforeRetry(opts, classification2, exitLifecyclePromise);
|
|
103836
|
+
const lastError = await this.runSessionRecoveryAttempts(opts, ctx, classification2, monitor, monitorCtx, policy, key, multiAttempt);
|
|
103837
|
+
if (lastError === null)
|
|
103838
|
+
return;
|
|
103839
|
+
if (multiAttempt) {
|
|
103840
|
+
const failureMessage = `${harness} session recovery failed after ${policy.maxAttempts} attempts: ${lastError}`;
|
|
103841
|
+
console.log(`[AgentProcessManager] ⛔ ${failureMessage}`);
|
|
103842
|
+
this.emitStartFailedEvent(opts.role, opts.chatroomId, failureMessage);
|
|
103843
|
+
} else {
|
|
103844
|
+
console.log(`[AgentProcessManager] ⚠️ Agent restart did not complete for ${opts.role}: ${lastError}`);
|
|
103845
|
+
}
|
|
103846
|
+
} catch (err) {
|
|
103847
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
103848
|
+
console.log(` ⚠️ Session recovery retry loop failed: ${message}`);
|
|
103849
|
+
this.emitStartFailedEvent(opts.role, opts.chatroomId, message);
|
|
103850
|
+
} finally {
|
|
103851
|
+
if (multiAttempt) {
|
|
103852
|
+
this.sessionRecoveryRetryInFlight.delete(key);
|
|
103853
|
+
}
|
|
103854
|
+
}
|
|
103855
|
+
}
|
|
103856
|
+
async prepareSessionRecoveryBeforeRetry(opts, classification2, exitLifecyclePromise) {
|
|
103857
|
+
if (!classification2.requiresTaskReleaseBeforeRecovery)
|
|
103858
|
+
return;
|
|
103859
|
+
this.clearLastInFlightTask(opts.chatroomId, opts.role);
|
|
103860
|
+
if (exitLifecyclePromise) {
|
|
103861
|
+
await exitLifecyclePromise;
|
|
103862
|
+
}
|
|
103863
|
+
}
|
|
103864
|
+
async runSessionRecoveryAttempts(opts, ctx, classification2, monitor, monitorCtx, policy, key, multiAttempt) {
|
|
103865
|
+
const generation = this.slots.get(key)?.stopGeneration;
|
|
103866
|
+
let lastError = "unknown";
|
|
103867
|
+
for (let attempt = 1;attempt <= policy.maxAttempts; attempt++) {
|
|
103868
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103869
|
+
return null;
|
|
103870
|
+
if (classification2.hadSessionFailure && policy.resumeFirstAttempts > 0 && attempt === policy.resumeFirstAttempts + 1) {
|
|
103871
|
+
this.clearHarnessSessionAfterResumePhaseFailure(key, opts);
|
|
103872
|
+
}
|
|
103873
|
+
const wantResume = monitor.resolveWantResume?.(attempt, classification2, monitorCtx) ?? (classification2.hadSessionFailure ? false : ctx.wantResume ?? true);
|
|
103874
|
+
if (multiAttempt) {
|
|
103875
|
+
const stored = this.lastHarnessSessions.get(key);
|
|
103876
|
+
const storedSessionId = stored ? resolveResumableHarnessSessionId(stored) : undefined;
|
|
103877
|
+
await this.emitSessionReopenRetry(opts.chatroomId, opts.role, attempt, policy.maxAttempts, attempt > 1 ? lastError : undefined, storedSessionId);
|
|
103878
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103879
|
+
return null;
|
|
103880
|
+
}
|
|
103881
|
+
const attemptResult = await this.executeSessionRecoveryAttempt(opts, ctx, policy, wantResume, multiAttempt, generation);
|
|
103882
|
+
if (attemptResult.kind === "success" || attemptResult.kind === "stopped")
|
|
103883
|
+
return null;
|
|
103884
|
+
if (attemptResult.kind === "crash_loop")
|
|
103885
|
+
return null;
|
|
103886
|
+
lastError = attemptResult.lastError;
|
|
103887
|
+
if (attempt < policy.maxAttempts && policy.intervalMs > 0) {
|
|
103888
|
+
await this.deps.clock.delay(policy.intervalMs);
|
|
103889
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103890
|
+
return null;
|
|
103891
|
+
}
|
|
103892
|
+
}
|
|
103893
|
+
return lastError;
|
|
103894
|
+
}
|
|
103895
|
+
async executeSessionRecoveryAttempt(opts, ctx, policy, wantResume, multiAttempt, generation) {
|
|
103896
|
+
const harness = ctx.harness;
|
|
103897
|
+
const ensureOpts = {
|
|
103898
|
+
chatroomId: opts.chatroomId,
|
|
103899
|
+
role: opts.role,
|
|
103900
|
+
agentHarness: harness,
|
|
103901
|
+
model: ctx.model,
|
|
103902
|
+
workingDir: ctx.workingDir,
|
|
103903
|
+
reason: policy.recoveryReason,
|
|
103904
|
+
wantResume
|
|
103905
|
+
};
|
|
103906
|
+
const result = await this.ensureRunning(ensureOpts);
|
|
103907
|
+
if (result.success)
|
|
103908
|
+
return { kind: "success" };
|
|
103909
|
+
if (this.isStopRequested(opts.chatroomId, opts.role, generation)) {
|
|
103910
|
+
return { kind: "stopped" };
|
|
103911
|
+
}
|
|
103912
|
+
const error51 = result.error ?? "unknown";
|
|
103913
|
+
if (!multiAttempt && result.error === "backoff") {
|
|
103914
|
+
await this.retryCrashRecoveryAfterBackoff(opts, ctx, ensureOpts, result.retryAfterMs);
|
|
103915
|
+
return { kind: "success" };
|
|
103916
|
+
}
|
|
103917
|
+
if (result.error === "crash_loop") {
|
|
103918
|
+
this.handleCrashLoopLimitReached(opts, ctx.recentLogLines);
|
|
103919
|
+
return { kind: "crash_loop" };
|
|
103920
|
+
}
|
|
103921
|
+
return { kind: "failed", lastError: error51 };
|
|
103785
103922
|
}
|
|
103786
103923
|
maybeEmitProviderUnavailable(chatroomId, role, slot) {
|
|
103787
103924
|
if (!slot || slot.harness !== "codex-sdk" || slot.providerUnavailableEmitted)
|
|
@@ -103813,48 +103950,6 @@ class AgentProcessManager {
|
|
|
103813
103950
|
recoverable: providerUnavailableRecoverable(classification2.reason)
|
|
103814
103951
|
}).catch(() => {});
|
|
103815
103952
|
}
|
|
103816
|
-
maybeRestartAgent(opts, ctx) {
|
|
103817
|
-
const { harness, model, workingDir, recentLogLines } = ctx;
|
|
103818
|
-
const logs = recentLogLines ?? [];
|
|
103819
|
-
if (!harness || !workingDir) {
|
|
103820
|
-
console.log(`[AgentProcessManager] ⚠️ Cannot restart — missing harness or workingDir ` + `(role: ${opts.role}, harness: ${harness ?? "none"}, workingDir: ${workingDir ?? "none"})`);
|
|
103821
|
-
return;
|
|
103822
|
-
}
|
|
103823
|
-
const hadRunError = this.hasCursorSdkRunErrorInContext(logs);
|
|
103824
|
-
if (harness === "cursor-sdk") {
|
|
103825
|
-
this.retryCursorSdkSessionReopen(opts, ctx, hadRunError);
|
|
103826
|
-
return;
|
|
103827
|
-
}
|
|
103828
|
-
this.attemptCrashRecoveryRestart(opts, ctx, {
|
|
103829
|
-
chatroomId: opts.chatroomId,
|
|
103830
|
-
role: opts.role,
|
|
103831
|
-
agentHarness: harness,
|
|
103832
|
-
model,
|
|
103833
|
-
workingDir,
|
|
103834
|
-
reason: "platform.crash_recovery",
|
|
103835
|
-
wantResume: hadRunError ? false : ctx.wantResume ?? true
|
|
103836
|
-
});
|
|
103837
|
-
}
|
|
103838
|
-
async attemptCrashRecoveryRestart(exitOpts, ctx, ensureOpts) {
|
|
103839
|
-
try {
|
|
103840
|
-
const result = await this.ensureRunning(ensureOpts);
|
|
103841
|
-
if (result.success)
|
|
103842
|
-
return;
|
|
103843
|
-
if (result.error === "backoff") {
|
|
103844
|
-
await this.retryCrashRecoveryAfterBackoff(exitOpts, ctx, ensureOpts, result.retryAfterMs);
|
|
103845
|
-
return;
|
|
103846
|
-
}
|
|
103847
|
-
if (result.error === "crash_loop") {
|
|
103848
|
-
this.handleCrashLoopLimitReached(exitOpts, ctx.recentLogLines);
|
|
103849
|
-
return;
|
|
103850
|
-
}
|
|
103851
|
-
console.log(`[AgentProcessManager] ⚠️ Agent restart did not complete for ${exitOpts.role}: ${result.error ?? "unknown"}`);
|
|
103852
|
-
} catch (err) {
|
|
103853
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
103854
|
-
console.log(` ⚠️ Failed to restart agent: ${message}`);
|
|
103855
|
-
this.emitStartFailedEvent(exitOpts.role, exitOpts.chatroomId, message);
|
|
103856
|
-
}
|
|
103857
|
-
}
|
|
103858
103953
|
async retryCrashRecoveryAfterBackoff(exitOpts, ctx, ensureOpts, retryAfterMs) {
|
|
103859
103954
|
if (retryAfterMs === undefined || retryAfterMs <= 0) {
|
|
103860
103955
|
return;
|
|
@@ -103892,71 +103987,6 @@ class AgentProcessManager {
|
|
|
103892
103987
|
});
|
|
103893
103988
|
}
|
|
103894
103989
|
}
|
|
103895
|
-
resolveCursorSdkReopenWantResume(hadRunError, attempt, ctx) {
|
|
103896
|
-
if (hadRunError && attempt <= CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS) {
|
|
103897
|
-
return true;
|
|
103898
|
-
}
|
|
103899
|
-
if (hadRunError) {
|
|
103900
|
-
return false;
|
|
103901
|
-
}
|
|
103902
|
-
return ctx.wantResume ?? true;
|
|
103903
|
-
}
|
|
103904
|
-
async retryCursorSdkSessionReopen(opts, ctx, hadRunError) {
|
|
103905
|
-
const key = agentKey3(opts.chatroomId, opts.role);
|
|
103906
|
-
if (this.sessionReopenRetryInFlight.has(key)) {
|
|
103907
|
-
return;
|
|
103908
|
-
}
|
|
103909
|
-
this.sessionReopenRetryInFlight.add(key);
|
|
103910
|
-
const generation = this.slots.get(key)?.stopGeneration;
|
|
103911
|
-
const harness = ctx.harness;
|
|
103912
|
-
const model = ctx.model;
|
|
103913
|
-
const workingDir = ctx.workingDir;
|
|
103914
|
-
let lastError = "unknown";
|
|
103915
|
-
try {
|
|
103916
|
-
for (let attempt = 1;attempt <= CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS; attempt++) {
|
|
103917
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103918
|
-
return;
|
|
103919
|
-
if (hadRunError && attempt === CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS + 1) {
|
|
103920
|
-
this.clearHarnessSessionAfterResumePhaseFailure(key, opts);
|
|
103921
|
-
}
|
|
103922
|
-
const wantResume = this.resolveCursorSdkReopenWantResume(hadRunError, attempt, ctx);
|
|
103923
|
-
const stored = this.lastHarnessSessions.get(key);
|
|
103924
|
-
const storedSessionId = stored ? resolveResumableHarnessSessionId(stored) : undefined;
|
|
103925
|
-
await this.emitSessionReopenRetry(opts.chatroomId, opts.role, attempt, attempt > 1 ? lastError : undefined, storedSessionId);
|
|
103926
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103927
|
-
return;
|
|
103928
|
-
const result = await this.ensureRunning({
|
|
103929
|
-
chatroomId: opts.chatroomId,
|
|
103930
|
-
role: opts.role,
|
|
103931
|
-
agentHarness: harness,
|
|
103932
|
-
model,
|
|
103933
|
-
workingDir,
|
|
103934
|
-
reason: CURSOR_SDK_SESSION_REOPEN_REASON,
|
|
103935
|
-
wantResume
|
|
103936
|
-
});
|
|
103937
|
-
if (result.success) {
|
|
103938
|
-
return;
|
|
103939
|
-
}
|
|
103940
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103941
|
-
return;
|
|
103942
|
-
lastError = result.error ?? "unknown";
|
|
103943
|
-
if (attempt < CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS) {
|
|
103944
|
-
await this.deps.clock.delay(CURSOR_SDK_SESSION_REOPEN_INTERVAL_MS);
|
|
103945
|
-
if (this.isStopRequested(opts.chatroomId, opts.role, generation))
|
|
103946
|
-
return;
|
|
103947
|
-
}
|
|
103948
|
-
}
|
|
103949
|
-
const failureMessage = `cursor-sdk session reopen failed after ${CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS} attempts: ${lastError}`;
|
|
103950
|
-
console.log(`[AgentProcessManager] ⛔ ${failureMessage}`);
|
|
103951
|
-
this.emitStartFailedEvent(opts.role, opts.chatroomId, failureMessage);
|
|
103952
|
-
} catch (err) {
|
|
103953
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
103954
|
-
console.log(` ⚠️ cursor-sdk session reopen retry loop failed: ${message}`);
|
|
103955
|
-
this.emitStartFailedEvent(opts.role, opts.chatroomId, message);
|
|
103956
|
-
} finally {
|
|
103957
|
-
this.sessionReopenRetryInFlight.delete(key);
|
|
103958
|
-
}
|
|
103959
|
-
}
|
|
103960
103990
|
emitStartFailedEvent(role, chatroomId, error51) {
|
|
103961
103991
|
logDaemonAuditEvent(this.deps.logEvent, {
|
|
103962
103992
|
type: "agent.startFailed",
|
|
@@ -104166,7 +104196,11 @@ class AgentProcessManager {
|
|
|
104166
104196
|
this.queueExitRetry({ role, args: exitArgs });
|
|
104167
104197
|
});
|
|
104168
104198
|
const emittedAt = this.deps.clock.now();
|
|
104169
|
-
this.deps.lifecycleOutbox.enqueue(buildExitedLifecycleFact(exitArgs, emittedAt)).
|
|
104199
|
+
return this.deps.lifecycleOutbox.enqueue(buildExitedLifecycleFact(exitArgs, emittedAt)).then(() => {
|
|
104200
|
+
return;
|
|
104201
|
+
}).catch((err) => {
|
|
104202
|
+
console.log(` ⚠️ Failed to enqueue agent exited lifecycle fact: ${err.message}`);
|
|
104203
|
+
});
|
|
104170
104204
|
}
|
|
104171
104205
|
async clearAgentPidQuietly(chatroomId, role) {
|
|
104172
104206
|
try {
|
|
@@ -104344,7 +104378,7 @@ class AgentProcessManager {
|
|
|
104344
104378
|
console.log(` ⚠️ Failed to emit sessionResumeFailed event: ${err.message}`);
|
|
104345
104379
|
}
|
|
104346
104380
|
}
|
|
104347
|
-
async emitSessionReopenRetry(chatroomId, role, attempt, error51, harnessSessionId) {
|
|
104381
|
+
async emitSessionReopenRetry(chatroomId, role, attempt, maxAttempts, error51, harnessSessionId) {
|
|
104348
104382
|
try {
|
|
104349
104383
|
await logDaemonAuditEvent(this.deps.logEvent, {
|
|
104350
104384
|
type: "agent.sessionReopenRetry",
|
|
@@ -104352,7 +104386,7 @@ class AgentProcessManager {
|
|
|
104352
104386
|
role,
|
|
104353
104387
|
machineId: this.deps.machineId,
|
|
104354
104388
|
attempt,
|
|
104355
|
-
maxAttempts
|
|
104389
|
+
maxAttempts,
|
|
104356
104390
|
...error51 ? { error: error51 } : {},
|
|
104357
104391
|
...harnessSessionId ? { harnessSessionId } : {}
|
|
104358
104392
|
});
|
|
@@ -104362,11 +104396,11 @@ class AgentProcessManager {
|
|
|
104362
104396
|
chatroomId,
|
|
104363
104397
|
role,
|
|
104364
104398
|
attempt,
|
|
104365
|
-
maxAttempts
|
|
104399
|
+
maxAttempts,
|
|
104366
104400
|
...error51 ? { error: error51 } : {},
|
|
104367
104401
|
...harnessSessionId ? { harnessSessionId } : {}
|
|
104368
104402
|
});
|
|
104369
|
-
console.log(`[AgentProcessManager] ✅ Emitted agent.sessionReopenRetry for ${role} (attempt ${attempt}/${
|
|
104403
|
+
console.log(`[AgentProcessManager] ✅ Emitted agent.sessionReopenRetry for ${role} (attempt ${attempt}/${maxAttempts})`);
|
|
104370
104404
|
} catch (err) {
|
|
104371
104405
|
console.log(` ⚠️ Failed to emit sessionReopenRetry event: ${err.message}`);
|
|
104372
104406
|
}
|
|
@@ -104945,6 +104979,7 @@ var init_agent_process_manager = __esm(() => {
|
|
|
104945
104979
|
init_agent_lifecycle_runtime();
|
|
104946
104980
|
init_agent_lifecycle_types();
|
|
104947
104981
|
init_agent_stop();
|
|
104982
|
+
init_session_recovery_policy();
|
|
104948
104983
|
init_spawn_policy();
|
|
104949
104984
|
init_abort_resume_storm();
|
|
104950
104985
|
init_classify_provider_error();
|
|
@@ -104956,6 +104991,99 @@ var init_agent_process_manager = __esm(() => {
|
|
|
104956
104991
|
init_native_task_delivery_coordinator();
|
|
104957
104992
|
init_native_turn_phase2();
|
|
104958
104993
|
init_native_spawn_presence();
|
|
104994
|
+
init_no_op_session_monitor();
|
|
104995
|
+
});
|
|
104996
|
+
|
|
104997
|
+
// src/daemon/domain/usecase/cursor-sdk-session-reopen-retry.ts
|
|
104998
|
+
var CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS = 3;
|
|
104999
|
+
|
|
105000
|
+
// src/daemon/domain/usecase/detect-cursor-sdk-run-error.ts
|
|
105001
|
+
function isCursorSdkRunErrorInLogs(logLines) {
|
|
105002
|
+
return logLines.some((line) => line.includes(" run-error]"));
|
|
105003
|
+
}
|
|
105004
|
+
function formatCursorSdkRunErrorMessage(logLines) {
|
|
105005
|
+
const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
|
|
105006
|
+
return line?.trim() ?? "Cursor SDK run failed";
|
|
105007
|
+
}
|
|
105008
|
+
function isCursorSdkAuthErrorInLogs(logLines) {
|
|
105009
|
+
if (classifyResumeStormReason(logLines) !== "auth_error")
|
|
105010
|
+
return false;
|
|
105011
|
+
return logLines.some((line) => line.includes("[cursor-sdk:"));
|
|
105012
|
+
}
|
|
105013
|
+
function hasCursorSdkSessionReopenTrigger(logLines) {
|
|
105014
|
+
return isCursorSdkRunErrorInLogs(logLines) || isCursorSdkAuthErrorInLogs(logLines);
|
|
105015
|
+
}
|
|
105016
|
+
var init_detect_cursor_sdk_run_error = __esm(() => {
|
|
105017
|
+
init_classify_resume_storm_reason();
|
|
105018
|
+
});
|
|
105019
|
+
|
|
105020
|
+
// src/daemon/infrastructure/local/harness/session-monitors/cursor-sdk-session-monitor.ts
|
|
105021
|
+
var cursorSdkSessionMonitor;
|
|
105022
|
+
var init_cursor_sdk_session_monitor = __esm(() => {
|
|
105023
|
+
init_detect_cursor_sdk_run_error();
|
|
105024
|
+
cursorSdkSessionMonitor = {
|
|
105025
|
+
classifyExitFailure(ctx) {
|
|
105026
|
+
const logs = ctx.recentLogLines;
|
|
105027
|
+
if (!hasCursorSdkSessionReopenTrigger(logs)) {
|
|
105028
|
+
return { hadSessionFailure: false, failureKind: "none", recoverable: true };
|
|
105029
|
+
}
|
|
105030
|
+
const auth = isCursorSdkAuthErrorInLogs(logs);
|
|
105031
|
+
console.log(`[CursorSdkSessionMonitor] session failure detected: ${formatCursorSdkRunErrorMessage(logs)}`);
|
|
105032
|
+
return {
|
|
105033
|
+
hadSessionFailure: true,
|
|
105034
|
+
failureKind: auth ? "auth_error" : "run_error",
|
|
105035
|
+
recoverable: true,
|
|
105036
|
+
requiresTaskReleaseBeforeRecovery: auth
|
|
105037
|
+
};
|
|
105038
|
+
},
|
|
105039
|
+
resolveWantResume(attempt, classification2, ctx) {
|
|
105040
|
+
if (classification2.hadSessionFailure && attempt <= CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS) {
|
|
105041
|
+
return true;
|
|
105042
|
+
}
|
|
105043
|
+
if (classification2.hadSessionFailure) {
|
|
105044
|
+
return false;
|
|
105045
|
+
}
|
|
105046
|
+
return ctx.wantResume ?? true;
|
|
105047
|
+
}
|
|
105048
|
+
};
|
|
105049
|
+
});
|
|
105050
|
+
|
|
105051
|
+
// src/daemon/infrastructure/local/harness/session-monitors/session-monitor-registry.ts
|
|
105052
|
+
function registerSessionMonitor(harnessId, monitor) {
|
|
105053
|
+
registry3.set(harnessId, monitor);
|
|
105054
|
+
}
|
|
105055
|
+
function getSessionMonitor(harnessId) {
|
|
105056
|
+
return registry3.get(harnessId);
|
|
105057
|
+
}
|
|
105058
|
+
function getAllSessionMonitors() {
|
|
105059
|
+
return new Map(registry3);
|
|
105060
|
+
}
|
|
105061
|
+
var registry3;
|
|
105062
|
+
var init_session_monitor_registry = __esm(() => {
|
|
105063
|
+
registry3 = new Map;
|
|
105064
|
+
});
|
|
105065
|
+
|
|
105066
|
+
// src/daemon/infrastructure/local/harness/session-monitors/init-session-monitors.ts
|
|
105067
|
+
function initSessionMonitorRegistry() {
|
|
105068
|
+
if (initialized2)
|
|
105069
|
+
return;
|
|
105070
|
+
for (const harness of AGENT_HARNESSES) {
|
|
105071
|
+
registerSessionMonitor(harness, harness === "cursor-sdk" ? cursorSdkSessionMonitor : noOpSessionMonitor);
|
|
105072
|
+
}
|
|
105073
|
+
for (const service3 of getAllHarnesses()) {
|
|
105074
|
+
if (!getSessionMonitor(service3.id)) {
|
|
105075
|
+
registerSessionMonitor(service3.id, noOpSessionMonitor);
|
|
105076
|
+
}
|
|
105077
|
+
}
|
|
105078
|
+
initialized2 = true;
|
|
105079
|
+
}
|
|
105080
|
+
var initialized2 = false;
|
|
105081
|
+
var init_init_session_monitors = __esm(() => {
|
|
105082
|
+
init_agent2();
|
|
105083
|
+
init_cursor_sdk_session_monitor();
|
|
105084
|
+
init_no_op_session_monitor();
|
|
105085
|
+
init_session_monitor_registry();
|
|
105086
|
+
init_registry2();
|
|
104959
105087
|
});
|
|
104960
105088
|
|
|
104961
105089
|
// src/daemon/entry/init-daemon.ts
|
|
@@ -105019,6 +105147,7 @@ function assembleDaemonSessionInit(args2) {
|
|
|
105019
105147
|
config: config4,
|
|
105020
105148
|
convexUrl,
|
|
105021
105149
|
agentServices,
|
|
105150
|
+
sessionMonitors,
|
|
105022
105151
|
cachedModels,
|
|
105023
105152
|
deps
|
|
105024
105153
|
} = args2;
|
|
@@ -105035,6 +105164,7 @@ function assembleDaemonSessionInit(args2) {
|
|
|
105035
105164
|
}),
|
|
105036
105165
|
logSink: activeLogSink,
|
|
105037
105166
|
agentServices,
|
|
105167
|
+
sessionMonitors,
|
|
105038
105168
|
backend: deps.backend,
|
|
105039
105169
|
sessionId: typedSessionId,
|
|
105040
105170
|
machineId,
|
|
@@ -105216,11 +105346,13 @@ Run: ${formatAuthLoginCommand(convexUrl)}`);
|
|
|
105216
105346
|
const config4 = yield* setupMachineEffect();
|
|
105217
105347
|
const { machineId } = config4;
|
|
105218
105348
|
initHarnessRegistry();
|
|
105349
|
+
initSessionMonitorRegistry();
|
|
105219
105350
|
const agentServices = new Map(getAllHarnesses().map((s) => [s.id, s]));
|
|
105351
|
+
const sessionMonitors = getAllSessionMonitors();
|
|
105220
105352
|
yield* registerMachineEffect(client4, typedSessionId, config4);
|
|
105221
105353
|
const cachedModels = yield* fetchCachedMachineModelsEffect(client4, typedSessionId, machineId);
|
|
105222
105354
|
yield* connectDaemonEffect(client4, typedSessionId, machineId);
|
|
105223
|
-
return { typedSessionId, config: config4, machineId, agentServices, cachedModels };
|
|
105355
|
+
return { typedSessionId, config: config4, machineId, agentServices, sessionMonitors, cachedModels };
|
|
105224
105356
|
}), activeLogSink, activeLogEvent, connectDaemonEffect = (client4, sessionId, machineId) => exports_Effect.tryPromise({
|
|
105225
105357
|
try: () => client4.mutation(api.machines.updateDaemonStatus, {
|
|
105226
105358
|
sessionId: asConvexSessionId(sessionId),
|
|
@@ -105308,6 +105440,8 @@ var init_init_daemon = __esm(() => {
|
|
|
105308
105440
|
init_agent_process_manager();
|
|
105309
105441
|
init_registry3();
|
|
105310
105442
|
init_services2();
|
|
105443
|
+
init_init_session_monitors();
|
|
105444
|
+
init_session_monitor_registry();
|
|
105311
105445
|
AUTH_WAIT_TIMEOUT_MS = 5 * 60 * 1000;
|
|
105312
105446
|
initDaemonEffect = exports_Effect.gen(function* () {
|
|
105313
105447
|
const lockAcquired = yield* exports_Effect.tryPromise({
|
|
@@ -105337,7 +105471,7 @@ var init_init_daemon = __esm(() => {
|
|
|
105337
105471
|
try: () => getConvexClient(),
|
|
105338
105472
|
catch: (e) => e
|
|
105339
105473
|
});
|
|
105340
|
-
const { typedSessionId, config: config4, machineId, agentServices, cachedModels } = yield* connectWithRetryEffect(client4, sessionId, convexUrl);
|
|
105474
|
+
const { typedSessionId, config: config4, machineId, agentServices, sessionMonitors, cachedModels } = yield* connectWithRetryEffect(client4, sessionId, convexUrl);
|
|
105341
105475
|
const init2 = assembleDaemonSessionInit({
|
|
105342
105476
|
client: client4,
|
|
105343
105477
|
typedSessionId,
|
|
@@ -105345,6 +105479,7 @@ var init_init_daemon = __esm(() => {
|
|
|
105345
105479
|
config: config4,
|
|
105346
105480
|
convexUrl,
|
|
105347
105481
|
agentServices,
|
|
105482
|
+
sessionMonitors,
|
|
105348
105483
|
cachedModels,
|
|
105349
105484
|
deps: createDefaultDeps22()
|
|
105350
105485
|
});
|
|
@@ -134957,4 +135092,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
134957
135092
|
});
|
|
134958
135093
|
program2.parse();
|
|
134959
135094
|
|
|
134960
|
-
//# debugId=
|
|
135095
|
+
//# debugId=48E3BD8E7ACDCBFA64756E2164756E21
|