@schoolai/shipyard 3.23.0 → 3.24.0-rc.20260813.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/capability-detector-worker.js +4 -4
- package/dist/{chunk-QI5ERXFK.js → chunk-BGJ6QJNS.js} +27 -2
- package/dist/chunk-BGJ6QJNS.js.map +1 -0
- package/dist/{chunk-Y4RRW6MA.js → chunk-BLGHJ3OJ.js} +2 -2
- package/dist/{chunk-OCYT65KO.js → chunk-BN54GQR3.js} +139 -20
- package/dist/chunk-BN54GQR3.js.map +1 -0
- package/dist/{chunk-W3EMVBWP.js → chunk-DDC5OQOC.js} +3 -3
- package/dist/{chunk-7E6VXTEO.js → chunk-JZTUQVHQ.js} +2 -2
- package/dist/{chunk-CKQL7TWQ.js → chunk-NG355H2L.js} +39 -14
- package/dist/chunk-NG355H2L.js.map +1 -0
- package/dist/{chunk-UESTOND6.js → chunk-RL25HGER.js} +3 -3
- package/dist/chunk-RL25HGER.js.map +1 -0
- package/dist/{chunk-HQTCVJRK.js → chunk-TU3MSY2I.js} +2 -2
- package/dist/{chunk-LRBG3X5U.js → chunk-UK3IMOSP.js} +2 -2
- package/dist/cursor-runner.js +24 -17
- package/dist/cursor-runner.js.map +1 -1
- package/dist/electron-utility.js +2 -2
- package/dist/index.js +4 -4
- package/dist/{login-WL5WEEGJ.js → login-AX7SM2SJ.js} +3 -3
- package/dist/{plan-backfill-EF6KR6BE.js → plan-backfill-XYOUK2DY.js} +4 -4
- package/dist/{serve-J3MG3WHK.js → serve-RWFBSQIE.js} +670 -257
- package/dist/{serve-J3MG3WHK.js.map → serve-RWFBSQIE.js.map} +1 -1
- package/dist/{start-TCI35UML.js → start-ZV22UPMC.js} +6 -6
- package/package.json +1 -1
- package/dist/chunk-CKQL7TWQ.js.map +0 -1
- package/dist/chunk-OCYT65KO.js.map +0 -1
- package/dist/chunk-QI5ERXFK.js.map +0 -1
- package/dist/chunk-UESTOND6.js.map +0 -1
- /package/dist/{chunk-Y4RRW6MA.js.map → chunk-BLGHJ3OJ.js.map} +0 -0
- /package/dist/{chunk-W3EMVBWP.js.map → chunk-DDC5OQOC.js.map} +0 -0
- /package/dist/{chunk-7E6VXTEO.js.map → chunk-JZTUQVHQ.js.map} +0 -0
- /package/dist/{chunk-HQTCVJRK.js.map → chunk-TU3MSY2I.js.map} +0 -0
- /package/dist/{chunk-LRBG3X5U.js.map → chunk-UK3IMOSP.js.map} +0 -0
- /package/dist/{login-WL5WEEGJ.js.map → login-AX7SM2SJ.js.map} +0 -0
- /package/dist/{plan-backfill-EF6KR6BE.js.map → plan-backfill-XYOUK2DY.js.map} +0 -0
- /package/dist/{start-TCI35UML.js.map → start-ZV22UPMC.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
guardedSubscribe,
|
|
13
13
|
makeInitialAttemptState,
|
|
14
14
|
shutdownFileWatcherGuard
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JZTUQVHQ.js";
|
|
16
16
|
import {
|
|
17
17
|
TRAILER_SCHEMA_VERSION,
|
|
18
18
|
appendTrailerToMessage,
|
|
@@ -39,13 +39,13 @@ import {
|
|
|
39
39
|
startPlanBackfillForDaemon,
|
|
40
40
|
sync,
|
|
41
41
|
validatePeerId
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-UK3IMOSP.js";
|
|
43
43
|
import {
|
|
44
44
|
loadAuthToken
|
|
45
45
|
} from "./chunk-2UE3TNY7.js";
|
|
46
46
|
import {
|
|
47
47
|
getDaemonVersion
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-DDC5OQOC.js";
|
|
49
49
|
import {
|
|
50
50
|
collectPriorCrashDetail,
|
|
51
51
|
getRecentWasmPanicMessages
|
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
CHARS_PER_TOKEN,
|
|
57
57
|
CODEX_BUNDLED_VERSION,
|
|
58
58
|
CURSOR_MODEL_CATALOG,
|
|
59
|
+
DAEMON_PR_COLD_DISCOVERY_INTERVAL_MS,
|
|
59
60
|
DAEMON_PR_POLL_INTERVAL_MS,
|
|
60
61
|
PROFILE_AUTH_ADAPTERS,
|
|
61
62
|
REDACTED_THINKING_PLACEHOLDER,
|
|
@@ -87,6 +88,7 @@ import {
|
|
|
87
88
|
cursorImportConversation,
|
|
88
89
|
cursorPermissionModeMap,
|
|
89
90
|
decideCursorAuthRefresh,
|
|
91
|
+
decidePrColdDiscoveryPlan,
|
|
90
92
|
decidePrPollPlan,
|
|
91
93
|
deduplicatePRs,
|
|
92
94
|
detectAgentProviders,
|
|
@@ -135,6 +137,7 @@ import {
|
|
|
135
137
|
notificationsSince,
|
|
136
138
|
pickLastKnownCapabilities,
|
|
137
139
|
profileRegistry,
|
|
140
|
+
reconcileCursorSupportsFastMode,
|
|
138
141
|
recordGithubReadFailure,
|
|
139
142
|
refreshCodexAuthSlice,
|
|
140
143
|
refreshCommands,
|
|
@@ -154,6 +157,7 @@ import {
|
|
|
154
157
|
searchPrs,
|
|
155
158
|
setBootstrapPhaseBreadcrumbSink,
|
|
156
159
|
setBootstrapPhaseMetricsSink,
|
|
160
|
+
setCursorFastModeSupportLookup,
|
|
157
161
|
skipForMainChannel,
|
|
158
162
|
snapshotProfileAuth,
|
|
159
163
|
supportsAdaptiveThinking,
|
|
@@ -174,7 +178,7 @@ import {
|
|
|
174
178
|
unresolveReviewThread,
|
|
175
179
|
withLabelAsync,
|
|
176
180
|
writeCursorApiKeyToVault
|
|
177
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-BN54GQR3.js";
|
|
178
182
|
import {
|
|
179
183
|
buildNodeSpawnEnv,
|
|
180
184
|
nodeSpawnEnvOverlay,
|
|
@@ -229,14 +233,15 @@ import {
|
|
|
229
233
|
createOneShotPool
|
|
230
234
|
} from "./chunk-ZFKJAYAN.js";
|
|
231
235
|
import {
|
|
232
|
-
parseRunnerToDaemon
|
|
233
|
-
|
|
236
|
+
parseRunnerToDaemon,
|
|
237
|
+
shouldUseCursorFastModePricing
|
|
238
|
+
} from "./chunk-NG355H2L.js";
|
|
234
239
|
import {
|
|
235
240
|
XML_TAGS,
|
|
236
241
|
createAssetResolver,
|
|
237
242
|
toSdkContent,
|
|
238
243
|
toSdkPermissionMode
|
|
239
|
-
} from "./chunk-
|
|
244
|
+
} from "./chunk-TU3MSY2I.js";
|
|
240
245
|
import {
|
|
241
246
|
AGENT_IDS,
|
|
242
247
|
AGENT_SYSTEM_CLAUDE_CODE,
|
|
@@ -441,7 +446,7 @@ import {
|
|
|
441
446
|
unsafeAssertSourceId,
|
|
442
447
|
vizFileExtension,
|
|
443
448
|
withPreferredRuntimeAuthMethod
|
|
444
|
-
} from "./chunk-
|
|
449
|
+
} from "./chunk-BGJ6QJNS.js";
|
|
445
450
|
import {
|
|
446
451
|
AuthGitHubCallbackRequestSchema,
|
|
447
452
|
AuthGitHubCallbackResponseSchema,
|
|
@@ -489,7 +494,7 @@ import {
|
|
|
489
494
|
VaultKeyPutResponseSchema,
|
|
490
495
|
classifyClaudeCodeCompatibility,
|
|
491
496
|
classifyCodexCompatibility
|
|
492
|
-
} from "./chunk-
|
|
497
|
+
} from "./chunk-RL25HGER.js";
|
|
493
498
|
import {
|
|
494
499
|
external_exports as external_exports2
|
|
495
500
|
} from "./chunk-EHQITHQX.js";
|
|
@@ -6016,7 +6021,7 @@ function nanoid(size = 21) {
|
|
|
6016
6021
|
}
|
|
6017
6022
|
|
|
6018
6023
|
// src/services/bootstrap/signaling.ts
|
|
6019
|
-
var DAEMON_NPM_VERSION = true ? "3.
|
|
6024
|
+
var DAEMON_NPM_VERSION = true ? "3.24.0" : "unknown";
|
|
6020
6025
|
function createDaemonSignaling(config) {
|
|
6021
6026
|
const agentId = config.agentId ?? nanoid();
|
|
6022
6027
|
function send(msg) {
|
|
@@ -7350,6 +7355,9 @@ function computeTransportEnabled(server, live) {
|
|
|
7350
7355
|
return server.enabled;
|
|
7351
7356
|
}
|
|
7352
7357
|
function resolveSnapshotAwareLive(s2, sessionEntry, workspaceLive, inSnapshot) {
|
|
7358
|
+
if (workspaceLive?.status === "needs-auth") {
|
|
7359
|
+
return { live: workspaceLive, transportEnabled: true };
|
|
7360
|
+
}
|
|
7353
7361
|
if (sessionEntry) {
|
|
7354
7362
|
return { live: sessionEntry, transportEnabled: sessionEntry.status !== "disabled" };
|
|
7355
7363
|
}
|
|
@@ -7362,6 +7370,22 @@ function resolveSnapshotAwareLive(s2, sessionEntry, workspaceLive, inSnapshot) {
|
|
|
7362
7370
|
transportEnabled: computeTransportEnabled(s2, workspaceLive)
|
|
7363
7371
|
};
|
|
7364
7372
|
}
|
|
7373
|
+
function collectMcpSessionCoordinatorDivergences(sessionServers, liveStatuses) {
|
|
7374
|
+
const out = [];
|
|
7375
|
+
for (const [name, session] of Object.entries(sessionServers)) {
|
|
7376
|
+
if (!session) continue;
|
|
7377
|
+
const coordinator = liveStatuses[name];
|
|
7378
|
+
if (!coordinator) continue;
|
|
7379
|
+
if (session.status === "connected" && coordinator.status === "needs-auth") {
|
|
7380
|
+
out.push({
|
|
7381
|
+
name,
|
|
7382
|
+
sessionStatus: session.status,
|
|
7383
|
+
coordinatorStatus: coordinator.status
|
|
7384
|
+
});
|
|
7385
|
+
}
|
|
7386
|
+
}
|
|
7387
|
+
return out;
|
|
7388
|
+
}
|
|
7365
7389
|
function buildWorkspaceRow(s2, live, transportEnabled, userEnabled) {
|
|
7366
7390
|
const accountIssue = s2.source === "claudeai" && s2.authStatus === "unauthenticated" && s2.url === void 0 ? {
|
|
7367
7391
|
errorType: "agent_signin_required",
|
|
@@ -12063,32 +12087,69 @@ function createPublishTools(ctx) {
|
|
|
12063
12087
|
true
|
|
12064
12088
|
);
|
|
12065
12089
|
}
|
|
12066
|
-
|
|
12067
|
-
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
const allBindings = store.listByTask(taskId);
|
|
12076
|
-
const match = allBindings.find((b2) => b2.publishId === publishId);
|
|
12077
|
-
if (match) {
|
|
12078
|
-
await store.deleteBinding(taskId, match.bindKind, match.bindKey);
|
|
12079
|
-
}
|
|
12080
|
-
}
|
|
12090
|
+
const taskId = resolveHarnessTaskId(ctx.taskId, ctx.getTaskIdForThread);
|
|
12091
|
+
const outcome = await runUnpublish({
|
|
12092
|
+
publishId,
|
|
12093
|
+
taskId,
|
|
12094
|
+
sessionServerUrl: ctx.sessionServerUrl,
|
|
12095
|
+
authToken: token,
|
|
12096
|
+
publishedArtifactStore: ctx.publishedArtifactStore
|
|
12097
|
+
});
|
|
12098
|
+
if (outcome.ok) {
|
|
12081
12099
|
return textResult(JSON.stringify({ ok: true }));
|
|
12082
|
-
} catch (err3) {
|
|
12083
|
-
return textResult(
|
|
12084
|
-
`Failed to unpublish: ${err3 instanceof Error ? err3.message : String(err3)}`,
|
|
12085
|
-
true
|
|
12086
|
-
);
|
|
12087
12100
|
}
|
|
12101
|
+
return textResult(outcome.error, true);
|
|
12088
12102
|
}
|
|
12089
12103
|
}
|
|
12090
12104
|
];
|
|
12091
12105
|
}
|
|
12106
|
+
async function runUnpublish(params) {
|
|
12107
|
+
try {
|
|
12108
|
+
await deletePublish({
|
|
12109
|
+
sessionServerUrl: params.sessionServerUrl,
|
|
12110
|
+
authToken: params.authToken,
|
|
12111
|
+
publishId: params.publishId
|
|
12112
|
+
});
|
|
12113
|
+
} catch (err3) {
|
|
12114
|
+
return {
|
|
12115
|
+
ok: false,
|
|
12116
|
+
error: `Failed to unpublish: ${err3 instanceof Error ? err3.message : String(err3)}`
|
|
12117
|
+
};
|
|
12118
|
+
}
|
|
12119
|
+
const store = params.publishedArtifactStore;
|
|
12120
|
+
if (store) {
|
|
12121
|
+
const match = store.listByTask(params.taskId).find((b2) => b2.publishId === params.publishId);
|
|
12122
|
+
if (match) {
|
|
12123
|
+
await store.deleteBinding(params.taskId, match.bindKind, match.bindKey);
|
|
12124
|
+
}
|
|
12125
|
+
}
|
|
12126
|
+
return { ok: true };
|
|
12127
|
+
}
|
|
12128
|
+
async function handleUnpublishRequest(params) {
|
|
12129
|
+
const { correlationId, sendControl } = params;
|
|
12130
|
+
const token = params.getAuthToken();
|
|
12131
|
+
if (!token) {
|
|
12132
|
+
sendControl({
|
|
12133
|
+
type: "unpublish_result",
|
|
12134
|
+
correlationId,
|
|
12135
|
+
ok: false,
|
|
12136
|
+
error: "Not authenticated. Please log in before unpublishing."
|
|
12137
|
+
});
|
|
12138
|
+
return;
|
|
12139
|
+
}
|
|
12140
|
+
const outcome = await runUnpublish({
|
|
12141
|
+
publishId: params.publishId,
|
|
12142
|
+
taskId: params.taskId,
|
|
12143
|
+
sessionServerUrl: params.sessionServerUrl,
|
|
12144
|
+
authToken: token,
|
|
12145
|
+
publishedArtifactStore: params.publishedArtifactStore
|
|
12146
|
+
});
|
|
12147
|
+
if (outcome.ok) {
|
|
12148
|
+
sendControl({ type: "unpublish_result", correlationId, ok: true });
|
|
12149
|
+
} else {
|
|
12150
|
+
sendControl({ type: "unpublish_result", correlationId, ok: false, error: outcome.error });
|
|
12151
|
+
}
|
|
12152
|
+
}
|
|
12092
12153
|
async function handlePublishRequest(params) {
|
|
12093
12154
|
const { correlationId, target, ttl, title, sendControl } = params;
|
|
12094
12155
|
function emitProgress(phase, detail) {
|
|
@@ -14692,6 +14753,7 @@ function filterOutboundForCollab(msg, collabTaskId, getTaskSync) {
|
|
|
14692
14753
|
*/
|
|
14693
14754
|
case "publish_progress":
|
|
14694
14755
|
case "publish_result":
|
|
14756
|
+
case "unpublish_result":
|
|
14695
14757
|
return null;
|
|
14696
14758
|
/**
|
|
14697
14759
|
* task_index_version is a heartbeat staleness probe response carrying the
|
|
@@ -15461,6 +15523,61 @@ async function routeRequestSkills(args) {
|
|
|
15461
15523
|
args.sendControl(args.buildSnapshot());
|
|
15462
15524
|
}
|
|
15463
15525
|
|
|
15526
|
+
// src/services/channels/control-channel/unpublish-request-wiring.ts
|
|
15527
|
+
function wireOnRequestUnpublish(deps, logAdapter) {
|
|
15528
|
+
return ({ correlationId, taskId, publishId, sendControl }) => {
|
|
15529
|
+
logAdapter({
|
|
15530
|
+
event: "unpublish_request_received",
|
|
15531
|
+
correlationId,
|
|
15532
|
+
taskId,
|
|
15533
|
+
publishId
|
|
15534
|
+
});
|
|
15535
|
+
const wrappedSendControl = (msg) => {
|
|
15536
|
+
if (msg.type === "unpublish_result") {
|
|
15537
|
+
logAdapter({
|
|
15538
|
+
event: "unpublish_result",
|
|
15539
|
+
correlationId,
|
|
15540
|
+
ok: msg.ok,
|
|
15541
|
+
error: msg.ok ? void 0 : msg.error
|
|
15542
|
+
});
|
|
15543
|
+
}
|
|
15544
|
+
sendControl(msg);
|
|
15545
|
+
};
|
|
15546
|
+
const sessionServerUrl = deps.sessionServerUrl;
|
|
15547
|
+
const getAuthToken = deps.getAuthToken;
|
|
15548
|
+
if (!sessionServerUrl || !getAuthToken) {
|
|
15549
|
+
wrappedSendControl({
|
|
15550
|
+
type: "unpublish_result",
|
|
15551
|
+
correlationId,
|
|
15552
|
+
ok: false,
|
|
15553
|
+
error: "Unpublish not available: session server not configured."
|
|
15554
|
+
});
|
|
15555
|
+
return;
|
|
15556
|
+
}
|
|
15557
|
+
handleUnpublishRequest({
|
|
15558
|
+
correlationId,
|
|
15559
|
+
taskId,
|
|
15560
|
+
publishId,
|
|
15561
|
+
sessionServerUrl,
|
|
15562
|
+
getAuthToken,
|
|
15563
|
+
publishedArtifactStore: deps.publishedArtifactStore ?? null,
|
|
15564
|
+
sendControl: wrappedSendControl
|
|
15565
|
+
}).catch((err3) => {
|
|
15566
|
+
logAdapter({
|
|
15567
|
+
event: "unpublish_request_unhandled_error",
|
|
15568
|
+
correlationId,
|
|
15569
|
+
error: err3 instanceof Error ? err3.message : String(err3)
|
|
15570
|
+
});
|
|
15571
|
+
wrappedSendControl({
|
|
15572
|
+
type: "unpublish_result",
|
|
15573
|
+
correlationId,
|
|
15574
|
+
ok: false,
|
|
15575
|
+
error: `Unexpected error: ${err3 instanceof Error ? err3.message : String(err3)}`
|
|
15576
|
+
});
|
|
15577
|
+
});
|
|
15578
|
+
};
|
|
15579
|
+
}
|
|
15580
|
+
|
|
15464
15581
|
// src/services/channels/control-channel-handler.ts
|
|
15465
15582
|
function handleControlChannel(send, callbacks, log) {
|
|
15466
15583
|
function sendControl(msg) {
|
|
@@ -15957,6 +16074,14 @@ function routeMessage(msg, callbacks, sendControl, log) {
|
|
|
15957
16074
|
sendControl
|
|
15958
16075
|
});
|
|
15959
16076
|
break;
|
|
16077
|
+
case "request_unpublish":
|
|
16078
|
+
callbacks.onRequestUnpublish({
|
|
16079
|
+
correlationId: msg.correlationId,
|
|
16080
|
+
taskId: msg.taskId,
|
|
16081
|
+
publishId: msg.publishId,
|
|
16082
|
+
sendControl
|
|
16083
|
+
});
|
|
16084
|
+
break;
|
|
15960
16085
|
case "start_from_linear":
|
|
15961
16086
|
callbacks.onStartFromLinear(msg);
|
|
15962
16087
|
break;
|
|
@@ -21436,7 +21561,11 @@ function matchCollabQueueCorrelationIds(messages, queueEntries) {
|
|
|
21436
21561
|
}
|
|
21437
21562
|
|
|
21438
21563
|
// src/services/session/claude-tool-guard.ts
|
|
21439
|
-
var SHIPYARD_DENIED_CLAUDE_TOOLS = [
|
|
21564
|
+
var SHIPYARD_DENIED_CLAUDE_TOOLS = [
|
|
21565
|
+
"Artifact",
|
|
21566
|
+
"EnterWorktree",
|
|
21567
|
+
"ExitWorktree"
|
|
21568
|
+
];
|
|
21440
21569
|
function detectDeniedToolsPresent(initTools, denied = SHIPYARD_DENIED_CLAUDE_TOOLS) {
|
|
21441
21570
|
const present = new Set(initTools);
|
|
21442
21571
|
return denied.filter((name) => present.has(name));
|
|
@@ -27032,6 +27161,14 @@ function wireControlChannel(rawChannel, daemon, logAdapter, deps) {
|
|
|
27032
27161
|
});
|
|
27033
27162
|
});
|
|
27034
27163
|
},
|
|
27164
|
+
onRequestUnpublish: wireOnRequestUnpublish(
|
|
27165
|
+
{
|
|
27166
|
+
sessionServerUrl: deps?.sessionServerUrl,
|
|
27167
|
+
getAuthToken: deps?.getAuthToken,
|
|
27168
|
+
publishedArtifactStore: deps?.publishedArtifactStore
|
|
27169
|
+
},
|
|
27170
|
+
logAdapter
|
|
27171
|
+
),
|
|
27035
27172
|
onStartFromLinear: (payload) => linearStartHandler.handleStartFromLinear(payload),
|
|
27036
27173
|
/**
|
|
27037
27174
|
* Browser-initiated flush for a specific resource URI (PROTOCOL_VERSION 48).
|
|
@@ -33580,6 +33717,7 @@ function buildCollabRoomManager(deps) {
|
|
|
33580
33717
|
import { randomUUID as randomUUID25 } from "crypto";
|
|
33581
33718
|
import { mkdir as mkdir36 } from "fs/promises";
|
|
33582
33719
|
import { join as join79 } from "path";
|
|
33720
|
+
import { getHeapStatistics } from "v8";
|
|
33583
33721
|
|
|
33584
33722
|
// src/shared/capabilities/cursor-boot-auth.ts
|
|
33585
33723
|
async function mergeCursorAuthFromVault(caps, detect, log) {
|
|
@@ -34291,6 +34429,24 @@ function mergeWithDefaultComposerSettings(caller, defaults) {
|
|
|
34291
34429
|
return normalizeComposerSettings(merged);
|
|
34292
34430
|
}
|
|
34293
34431
|
|
|
34432
|
+
// src/services/task/session-activity.ts
|
|
34433
|
+
function isActiveUserWork(state) {
|
|
34434
|
+
switch (state) {
|
|
34435
|
+
case "spawning":
|
|
34436
|
+
case "running":
|
|
34437
|
+
case "stopping":
|
|
34438
|
+
return true;
|
|
34439
|
+
case "warm_idle":
|
|
34440
|
+
case "resumable_idle":
|
|
34441
|
+
case "cold_idle":
|
|
34442
|
+
return false;
|
|
34443
|
+
default: {
|
|
34444
|
+
const _exhaustive = state;
|
|
34445
|
+
throw new Error(`Unhandled session state: ${JSON.stringify(_exhaustive)}`);
|
|
34446
|
+
}
|
|
34447
|
+
}
|
|
34448
|
+
}
|
|
34449
|
+
|
|
34294
34450
|
// src/services/bootstrap/rehydrate.ts
|
|
34295
34451
|
var ACTIVE_STATUSES = {
|
|
34296
34452
|
open: true,
|
|
@@ -34313,9 +34469,11 @@ var ACTIVE_STATUSES = {
|
|
|
34313
34469
|
*/
|
|
34314
34470
|
canceled: false
|
|
34315
34471
|
};
|
|
34316
|
-
function planStaleSweep(tasks,
|
|
34472
|
+
function planStaleSweep(tasks, getSessionState) {
|
|
34317
34473
|
return Object.values(tasks).map((task) => {
|
|
34318
|
-
|
|
34474
|
+
const state = getSessionState(task.taskId);
|
|
34475
|
+
const isLive = state !== null && isActiveUserWork(state);
|
|
34476
|
+
if (ACTIVE_STATUSES[task.status] && !isLive) {
|
|
34319
34477
|
return { kind: "mark_input_required", taskId: task.taskId, previousStatus: task.status };
|
|
34320
34478
|
}
|
|
34321
34479
|
return { kind: "keep", taskId: task.taskId };
|
|
@@ -34342,6 +34500,15 @@ function classifyPersistedSessions(sessions, knownTaskIds) {
|
|
|
34342
34500
|
}
|
|
34343
34501
|
var EAGER_RESTORE_STATUSES = {
|
|
34344
34502
|
open: true,
|
|
34503
|
+
/**
|
|
34504
|
+
* Since the `planStaleSweep` fix for issue #5224, an eagerly-restored
|
|
34505
|
+
* `in_progress` task lands in `resumable_idle` and is immediately demoted
|
|
34506
|
+
* to `input_required` by the sweep three lines later in the boot sequence
|
|
34507
|
+
* — the eventual status is identical to `input_required` either way.
|
|
34508
|
+
* Eager restore is still worth it here purely as a warm-cache optimization:
|
|
34509
|
+
* the resumable SDK session is materialized immediately rather than on the
|
|
34510
|
+
* user's next message, so replying doesn't pay the lazy-restore cost.
|
|
34511
|
+
*/
|
|
34345
34512
|
in_progress: true,
|
|
34346
34513
|
/**
|
|
34347
34514
|
* Excluded for boot-cost reasons, not correctness: `planStaleSweep`
|
|
@@ -34696,7 +34863,7 @@ async function migrateLegacyPreviewData(canvasRepo, previewStateStore, taskState
|
|
|
34696
34863
|
}
|
|
34697
34864
|
async function sweepStaleTasks(taskStateStore, taskManager, log) {
|
|
34698
34865
|
const tasks = await taskStateStore.listTasks();
|
|
34699
|
-
const actions = planStaleSweep(tasks, (id) => taskManager.
|
|
34866
|
+
const actions = planStaleSweep(tasks, (id) => taskManager.getTaskState(id)?.sessionState ?? null);
|
|
34700
34867
|
const noBroadcast = { broadcast: false };
|
|
34701
34868
|
for (const action of actions) {
|
|
34702
34869
|
if (action.kind === "mark_input_required") {
|
|
@@ -37464,7 +37631,7 @@ function createDaemonPrPollingService(deps) {
|
|
|
37464
37631
|
syncing = true;
|
|
37465
37632
|
return true;
|
|
37466
37633
|
}
|
|
37467
|
-
async function
|
|
37634
|
+
async function loadPlanTasks2() {
|
|
37468
37635
|
const records = await deps.taskStateStore.listTasks();
|
|
37469
37636
|
return Object.values(records).map(
|
|
37470
37637
|
(record) => toPrPollPlanTask(record, deps.getPrState(record.taskId))
|
|
@@ -37488,7 +37655,7 @@ function createDaemonPrPollingService(deps) {
|
|
|
37488
37655
|
}
|
|
37489
37656
|
}
|
|
37490
37657
|
async function runSyncCore() {
|
|
37491
|
-
const tasks = await
|
|
37658
|
+
const tasks = await loadPlanTasks2();
|
|
37492
37659
|
if (disposed) return;
|
|
37493
37660
|
const tasksById = new Map(tasks.map((task) => [task.taskId, task]));
|
|
37494
37661
|
stopIneligibleSubscriptions(tasksById);
|
|
@@ -37549,70 +37716,8 @@ function createDaemonPrPollingService(deps) {
|
|
|
37549
37716
|
return { start, requestSync, dispose };
|
|
37550
37717
|
}
|
|
37551
37718
|
|
|
37552
|
-
// src/services/pr-
|
|
37553
|
-
|
|
37554
|
-
const { taskId } = payload;
|
|
37555
|
-
const pr = payload.currentBranchPR;
|
|
37556
|
-
if (!pr || attributedTaskIds.has(taskId)) return;
|
|
37557
|
-
attributedTaskIds.add(taskId);
|
|
37558
|
-
effects.forceRefresh(taskId);
|
|
37559
|
-
effects.attribute(taskId, pr);
|
|
37560
|
-
}
|
|
37561
|
-
|
|
37562
|
-
// src/services/pr-poll-subscriptions.ts
|
|
37563
|
-
function createPRPollSubscriptionCoordinator(poller) {
|
|
37564
|
-
const subscriptions = /* @__PURE__ */ new Map();
|
|
37565
|
-
function startPolling(taskId, cwd, source = "browser") {
|
|
37566
|
-
const existing = subscriptions.get(taskId);
|
|
37567
|
-
if (existing) {
|
|
37568
|
-
const wasEmpty = existing.sources.size === 0;
|
|
37569
|
-
const cwdChanged = existing.cwd !== cwd;
|
|
37570
|
-
existing.cwd = cwd;
|
|
37571
|
-
existing.sources.add(source);
|
|
37572
|
-
if (wasEmpty) {
|
|
37573
|
-
poller.startPolling(taskId, cwd);
|
|
37574
|
-
} else if (cwdChanged) {
|
|
37575
|
-
void poller.updateCwd(taskId, cwd);
|
|
37576
|
-
} else if (source === "browser") {
|
|
37577
|
-
poller.refreshNow(taskId);
|
|
37578
|
-
}
|
|
37579
|
-
return;
|
|
37580
|
-
}
|
|
37581
|
-
subscriptions.set(taskId, { cwd, sources: /* @__PURE__ */ new Set([source]) });
|
|
37582
|
-
poller.startPolling(taskId, cwd);
|
|
37583
|
-
}
|
|
37584
|
-
function stopPolling(taskId, source = "browser") {
|
|
37585
|
-
const entry = subscriptions.get(taskId);
|
|
37586
|
-
if (!entry) return;
|
|
37587
|
-
entry.sources.delete(source);
|
|
37588
|
-
if (entry.sources.size > 0) return;
|
|
37589
|
-
subscriptions.delete(taskId);
|
|
37590
|
-
poller.stopPolling(taskId);
|
|
37591
|
-
}
|
|
37592
|
-
function getCwd(taskId) {
|
|
37593
|
-
return subscriptions.get(taskId)?.cwd ?? poller.getCwd(taskId);
|
|
37594
|
-
}
|
|
37595
|
-
async function updateCwd(taskId, newCwd) {
|
|
37596
|
-
const entry = subscriptions.get(taskId);
|
|
37597
|
-
if (!entry) return;
|
|
37598
|
-
if (entry.cwd === newCwd) return;
|
|
37599
|
-
entry.cwd = newCwd;
|
|
37600
|
-
await poller.updateCwd(taskId, newCwd);
|
|
37601
|
-
}
|
|
37602
|
-
function dispose() {
|
|
37603
|
-
subscriptions.clear();
|
|
37604
|
-
poller.dispose();
|
|
37605
|
-
}
|
|
37606
|
-
return {
|
|
37607
|
-
startPolling,
|
|
37608
|
-
stopPolling,
|
|
37609
|
-
forceRefresh: poller.forceRefresh,
|
|
37610
|
-
refreshNow: poller.refreshNow,
|
|
37611
|
-
getCwd,
|
|
37612
|
-
updateCwd,
|
|
37613
|
-
dispose
|
|
37614
|
-
};
|
|
37615
|
-
}
|
|
37719
|
+
// src/services/pr-cold-discovery.ts
|
|
37720
|
+
import { existsSync as existsSync7 } from "fs";
|
|
37616
37721
|
|
|
37617
37722
|
// src/services/pr-stack/build-stack-graph.ts
|
|
37618
37723
|
var DEFAULT_MAX_DEPTH = 20;
|
|
@@ -37938,47 +38043,47 @@ async function fetchCIDataWithRemote(pr, cwd, remote) {
|
|
|
37938
38043
|
);
|
|
37939
38044
|
return { requiredChecks };
|
|
37940
38045
|
}
|
|
38046
|
+
async function fetchFastPRState(cwd, log) {
|
|
38047
|
+
const backoff = getGithubReadBackoffState();
|
|
38048
|
+
if (backoff.backoffUntil !== null) {
|
|
38049
|
+
log.warn(
|
|
38050
|
+
{ backoffUntil: backoff.backoffUntil, reason: backoff.reason },
|
|
38051
|
+
"PR polling skipped during GitHub read backoff"
|
|
38052
|
+
);
|
|
38053
|
+
return null;
|
|
38054
|
+
}
|
|
38055
|
+
const available = await isGhAvailable();
|
|
38056
|
+
if (!available) {
|
|
38057
|
+
return {
|
|
38058
|
+
prAvailable: false,
|
|
38059
|
+
currentBranchPR: null,
|
|
38060
|
+
assignedReviews: [],
|
|
38061
|
+
userPRs: [],
|
|
38062
|
+
allPRs: [],
|
|
38063
|
+
remote: ""
|
|
38064
|
+
};
|
|
38065
|
+
}
|
|
38066
|
+
const [prResults, remote] = await Promise.all([
|
|
38067
|
+
Promise.allSettled([getPRForCurrentBranch(cwd), getAssignedReviews(cwd), getUserPRs(cwd)]),
|
|
38068
|
+
gitExecSafe(cwd, ["remote", "get-url", "origin"]).then((v2) => v2 ?? "")
|
|
38069
|
+
]);
|
|
38070
|
+
const [currentPR, assigned, user] = prResults;
|
|
38071
|
+
const { allPRs, currentBranchPR: rawPR } = deduplicatePRs(currentPR, assigned, user);
|
|
38072
|
+
const currentBranchPR = rawPR ? await enrichClosedPR(rawPR, cwd) : null;
|
|
38073
|
+
return {
|
|
38074
|
+
prAvailable: true,
|
|
38075
|
+
currentBranchPR,
|
|
38076
|
+
assignedReviews: assigned.status === "fulfilled" ? assigned.value : [],
|
|
38077
|
+
userPRs: user.status === "fulfilled" ? user.value : [],
|
|
38078
|
+
allPRs,
|
|
38079
|
+
remote
|
|
38080
|
+
};
|
|
38081
|
+
}
|
|
37941
38082
|
function createPRPoller(callbacks, log, resolveTopLevel = getGitTopLevel) {
|
|
37942
38083
|
const repos = /* @__PURE__ */ new Map();
|
|
37943
38084
|
const taskToRepo = /* @__PURE__ */ new Map();
|
|
37944
38085
|
let disposed = false;
|
|
37945
38086
|
let activePollCount = 0;
|
|
37946
|
-
async function fetchFastPRState(cwd) {
|
|
37947
|
-
const backoff = getGithubReadBackoffState();
|
|
37948
|
-
if (backoff.backoffUntil !== null) {
|
|
37949
|
-
log.warn(
|
|
37950
|
-
{ backoffUntil: backoff.backoffUntil, reason: backoff.reason },
|
|
37951
|
-
"PR polling skipped during GitHub read backoff"
|
|
37952
|
-
);
|
|
37953
|
-
return null;
|
|
37954
|
-
}
|
|
37955
|
-
const available = await isGhAvailable();
|
|
37956
|
-
if (!available) {
|
|
37957
|
-
return {
|
|
37958
|
-
prAvailable: false,
|
|
37959
|
-
currentBranchPR: null,
|
|
37960
|
-
assignedReviews: [],
|
|
37961
|
-
userPRs: [],
|
|
37962
|
-
allPRs: [],
|
|
37963
|
-
remote: ""
|
|
37964
|
-
};
|
|
37965
|
-
}
|
|
37966
|
-
const [prResults, remote] = await Promise.all([
|
|
37967
|
-
Promise.allSettled([getPRForCurrentBranch(cwd), getAssignedReviews(cwd), getUserPRs(cwd)]),
|
|
37968
|
-
gitExecSafe(cwd, ["remote", "get-url", "origin"]).then((v2) => v2 ?? "")
|
|
37969
|
-
]);
|
|
37970
|
-
const [currentPR, assigned, user] = prResults;
|
|
37971
|
-
const { allPRs, currentBranchPR: rawPR } = deduplicatePRs(currentPR, assigned, user);
|
|
37972
|
-
const currentBranchPR = rawPR ? await enrichClosedPR(rawPR, cwd) : null;
|
|
37973
|
-
return {
|
|
37974
|
-
prAvailable: true,
|
|
37975
|
-
currentBranchPR,
|
|
37976
|
-
assignedReviews: assigned.status === "fulfilled" ? assigned.value : [],
|
|
37977
|
-
userPRs: user.status === "fulfilled" ? user.value : [],
|
|
37978
|
-
allPRs,
|
|
37979
|
-
remote
|
|
37980
|
-
};
|
|
37981
|
-
}
|
|
37982
38087
|
async function fetchEnrichment(fast, cwd) {
|
|
37983
38088
|
const ciData = await fetchCIDataWithRemote(fast.currentBranchPR, cwd, fast.remote).catch(
|
|
37984
38089
|
() => ({
|
|
@@ -38115,7 +38220,7 @@ function createPRPoller(callbacks, log, resolveTopLevel = getGitTopLevel) {
|
|
|
38115
38220
|
const currentBranch = await gitExecSafe(entry.cwd, ["rev-parse", "--abbrev-ref", "HEAD"]) ?? "";
|
|
38116
38221
|
if (disposed) return;
|
|
38117
38222
|
handleBranchChange(topLevel, entry, currentBranch);
|
|
38118
|
-
const fast = await fetchFastPRState(entry.cwd);
|
|
38223
|
+
const fast = await fetchFastPRState(entry.cwd, log);
|
|
38119
38224
|
if (!fast || disposed) return;
|
|
38120
38225
|
entry.lastPolledAt = Date.now();
|
|
38121
38226
|
pushPhase1IfChanged(topLevel, entry, fast);
|
|
@@ -38311,6 +38416,190 @@ function createPRPoller(callbacks, log, resolveTopLevel = getGitTopLevel) {
|
|
|
38311
38416
|
return { startPolling, stopPolling, forceRefresh, refreshNow, getCwd, updateCwd, dispose };
|
|
38312
38417
|
}
|
|
38313
38418
|
|
|
38419
|
+
// src/services/pr-cold-discovery.ts
|
|
38420
|
+
async function loadPlanTasks(taskStateStore, getPrState) {
|
|
38421
|
+
const records = await taskStateStore.listTasks();
|
|
38422
|
+
return Object.values(records).map(
|
|
38423
|
+
(record) => toPrPollPlanTask(record, getPrState(record.taskId))
|
|
38424
|
+
);
|
|
38425
|
+
}
|
|
38426
|
+
function createPrColdDiscoveryService(deps) {
|
|
38427
|
+
const intervalMs = deps.intervalMs ?? DAEMON_PR_COLD_DISCOVERY_INTERVAL_MS;
|
|
38428
|
+
const now = deps.now ?? Date.now;
|
|
38429
|
+
const checkPR = deps.checkPR ?? fetchFastPRState;
|
|
38430
|
+
const lastCheckedAt = /* @__PURE__ */ new Map();
|
|
38431
|
+
let timer = null;
|
|
38432
|
+
let disposed = false;
|
|
38433
|
+
let syncing = false;
|
|
38434
|
+
let syncQueued = false;
|
|
38435
|
+
let unsubscribeTaskStore = null;
|
|
38436
|
+
async function checkTask(task) {
|
|
38437
|
+
if (!task.cwd) return;
|
|
38438
|
+
if (!existsSync7(task.cwd)) {
|
|
38439
|
+
deps.log.debug({ taskId: task.taskId, cwd: task.cwd }, "Cold discovery skipped, cwd missing");
|
|
38440
|
+
return;
|
|
38441
|
+
}
|
|
38442
|
+
try {
|
|
38443
|
+
const fast = await checkPR(task.cwd, deps.log);
|
|
38444
|
+
if (fast?.currentBranchPR) {
|
|
38445
|
+
deps.log.debug(
|
|
38446
|
+
{ taskId: task.taskId, prUrl: fast.currentBranchPR.url },
|
|
38447
|
+
"Cold discovery found a PR, handing off to daemon polling"
|
|
38448
|
+
);
|
|
38449
|
+
deps.subscriptions.startPolling(task.taskId, task.cwd, "daemon");
|
|
38450
|
+
}
|
|
38451
|
+
} catch (err3) {
|
|
38452
|
+
recordGithubReadFailure(err3);
|
|
38453
|
+
deps.log.warn({ err: err3, taskId: task.taskId }, "Cold discovery check failed");
|
|
38454
|
+
}
|
|
38455
|
+
}
|
|
38456
|
+
function tryEnterSync() {
|
|
38457
|
+
if (disposed) return false;
|
|
38458
|
+
if (syncing) {
|
|
38459
|
+
syncQueued = true;
|
|
38460
|
+
return false;
|
|
38461
|
+
}
|
|
38462
|
+
syncing = true;
|
|
38463
|
+
return true;
|
|
38464
|
+
}
|
|
38465
|
+
async function runSyncCore() {
|
|
38466
|
+
const tasks = await loadPlanTasks(deps.taskStateStore, deps.getPrState);
|
|
38467
|
+
if (disposed) return;
|
|
38468
|
+
const tasksById = new Map(tasks.map((task) => [task.taskId, task]));
|
|
38469
|
+
const currentTime = now();
|
|
38470
|
+
const toCheck = decidePrColdDiscoveryPlan(
|
|
38471
|
+
tasks,
|
|
38472
|
+
currentTime,
|
|
38473
|
+
lastCheckedAt,
|
|
38474
|
+
deps.getRateLimitState(),
|
|
38475
|
+
{
|
|
38476
|
+
intervalMs
|
|
38477
|
+
}
|
|
38478
|
+
);
|
|
38479
|
+
for (const taskId of toCheck) {
|
|
38480
|
+
lastCheckedAt.set(taskId, currentTime);
|
|
38481
|
+
}
|
|
38482
|
+
if (toCheck.length > 0) {
|
|
38483
|
+
deps.log.debug({ taskIds: toCheck }, "Cold PR discovery candidates selected");
|
|
38484
|
+
}
|
|
38485
|
+
await Promise.all(
|
|
38486
|
+
toCheck.map((taskId) => {
|
|
38487
|
+
const task = tasksById.get(taskId);
|
|
38488
|
+
return task ? checkTask(task) : Promise.resolve();
|
|
38489
|
+
})
|
|
38490
|
+
);
|
|
38491
|
+
}
|
|
38492
|
+
function finishSync() {
|
|
38493
|
+
syncing = false;
|
|
38494
|
+
if (!syncQueued || disposed) return;
|
|
38495
|
+
syncQueued = false;
|
|
38496
|
+
void sync2();
|
|
38497
|
+
}
|
|
38498
|
+
async function sync2() {
|
|
38499
|
+
if (!tryEnterSync()) return;
|
|
38500
|
+
try {
|
|
38501
|
+
await runSyncCore();
|
|
38502
|
+
} catch (err3) {
|
|
38503
|
+
deps.log.warn(
|
|
38504
|
+
{ error: err3 instanceof Error ? err3.message : String(err3) },
|
|
38505
|
+
"Cold PR discovery sync failed"
|
|
38506
|
+
);
|
|
38507
|
+
} finally {
|
|
38508
|
+
finishSync();
|
|
38509
|
+
}
|
|
38510
|
+
}
|
|
38511
|
+
function requestSync() {
|
|
38512
|
+
void sync2();
|
|
38513
|
+
}
|
|
38514
|
+
function start() {
|
|
38515
|
+
if (timer !== null || disposed) return;
|
|
38516
|
+
unsubscribeTaskStore = deps.taskStateStore.subscribe((event) => {
|
|
38517
|
+
if (event.kind === "delete") {
|
|
38518
|
+
lastCheckedAt.delete(event.id);
|
|
38519
|
+
return;
|
|
38520
|
+
}
|
|
38521
|
+
requestSync();
|
|
38522
|
+
});
|
|
38523
|
+
requestSync();
|
|
38524
|
+
timer = setInterval(requestSync, intervalMs);
|
|
38525
|
+
timer.unref();
|
|
38526
|
+
}
|
|
38527
|
+
function dispose() {
|
|
38528
|
+
disposed = true;
|
|
38529
|
+
if (timer) clearInterval(timer);
|
|
38530
|
+
timer = null;
|
|
38531
|
+
unsubscribeTaskStore?.();
|
|
38532
|
+
unsubscribeTaskStore = null;
|
|
38533
|
+
lastCheckedAt.clear();
|
|
38534
|
+
}
|
|
38535
|
+
return { start, dispose };
|
|
38536
|
+
}
|
|
38537
|
+
|
|
38538
|
+
// src/services/pr-first-discovery.ts
|
|
38539
|
+
function applyPrFirstDiscovery(payload, attributedTaskIds, effects) {
|
|
38540
|
+
const { taskId } = payload;
|
|
38541
|
+
const pr = payload.currentBranchPR;
|
|
38542
|
+
if (!pr || attributedTaskIds.has(taskId)) return;
|
|
38543
|
+
attributedTaskIds.add(taskId);
|
|
38544
|
+
effects.forceRefresh(taskId);
|
|
38545
|
+
effects.attribute(taskId, pr);
|
|
38546
|
+
}
|
|
38547
|
+
|
|
38548
|
+
// src/services/pr-poll-subscriptions.ts
|
|
38549
|
+
function createPRPollSubscriptionCoordinator(poller) {
|
|
38550
|
+
const subscriptions = /* @__PURE__ */ new Map();
|
|
38551
|
+
function startPolling(taskId, cwd, source = "browser") {
|
|
38552
|
+
const existing = subscriptions.get(taskId);
|
|
38553
|
+
if (existing) {
|
|
38554
|
+
const wasEmpty = existing.sources.size === 0;
|
|
38555
|
+
const cwdChanged = existing.cwd !== cwd;
|
|
38556
|
+
existing.cwd = cwd;
|
|
38557
|
+
existing.sources.add(source);
|
|
38558
|
+
if (wasEmpty) {
|
|
38559
|
+
poller.startPolling(taskId, cwd);
|
|
38560
|
+
} else if (cwdChanged) {
|
|
38561
|
+
void poller.updateCwd(taskId, cwd);
|
|
38562
|
+
} else if (source === "browser") {
|
|
38563
|
+
poller.refreshNow(taskId);
|
|
38564
|
+
}
|
|
38565
|
+
return;
|
|
38566
|
+
}
|
|
38567
|
+
subscriptions.set(taskId, { cwd, sources: /* @__PURE__ */ new Set([source]) });
|
|
38568
|
+
poller.startPolling(taskId, cwd);
|
|
38569
|
+
}
|
|
38570
|
+
function stopPolling(taskId, source = "browser") {
|
|
38571
|
+
const entry = subscriptions.get(taskId);
|
|
38572
|
+
if (!entry) return;
|
|
38573
|
+
entry.sources.delete(source);
|
|
38574
|
+
if (entry.sources.size > 0) return;
|
|
38575
|
+
subscriptions.delete(taskId);
|
|
38576
|
+
poller.stopPolling(taskId);
|
|
38577
|
+
}
|
|
38578
|
+
function getCwd(taskId) {
|
|
38579
|
+
return subscriptions.get(taskId)?.cwd ?? poller.getCwd(taskId);
|
|
38580
|
+
}
|
|
38581
|
+
async function updateCwd(taskId, newCwd) {
|
|
38582
|
+
const entry = subscriptions.get(taskId);
|
|
38583
|
+
if (!entry) return;
|
|
38584
|
+
if (entry.cwd === newCwd) return;
|
|
38585
|
+
entry.cwd = newCwd;
|
|
38586
|
+
await poller.updateCwd(taskId, newCwd);
|
|
38587
|
+
}
|
|
38588
|
+
function dispose() {
|
|
38589
|
+
subscriptions.clear();
|
|
38590
|
+
poller.dispose();
|
|
38591
|
+
}
|
|
38592
|
+
return {
|
|
38593
|
+
startPolling,
|
|
38594
|
+
stopPolling,
|
|
38595
|
+
forceRefresh: poller.forceRefresh,
|
|
38596
|
+
refreshNow: poller.refreshNow,
|
|
38597
|
+
getCwd,
|
|
38598
|
+
updateCwd,
|
|
38599
|
+
dispose
|
|
38600
|
+
};
|
|
38601
|
+
}
|
|
38602
|
+
|
|
38314
38603
|
// src/services/channels/control-channel/pr-ingest-dedup.ts
|
|
38315
38604
|
var INGEST_DEDUPE_WINDOW_MS = 15e3;
|
|
38316
38605
|
function createPrIngestDedup() {
|
|
@@ -38499,6 +38788,14 @@ function buildPRAttributionSubsystem(daemon, options) {
|
|
|
38499
38788
|
log: prPollerLog
|
|
38500
38789
|
});
|
|
38501
38790
|
daemonPrPolling.start();
|
|
38791
|
+
const prColdDiscovery = createPrColdDiscoveryService({
|
|
38792
|
+
taskStateStore: daemon.taskStateStore,
|
|
38793
|
+
subscriptions: prPoller,
|
|
38794
|
+
getPrState,
|
|
38795
|
+
getRateLimitState: getGithubReadBackoffState,
|
|
38796
|
+
log: prPollerLog
|
|
38797
|
+
});
|
|
38798
|
+
prColdDiscovery.start();
|
|
38502
38799
|
const unsubscribeCwdChanged = daemon.taskManager.addOnCwdChanged((taskId, newCwd) => {
|
|
38503
38800
|
void prPoller.updateCwd(taskId, newCwd);
|
|
38504
38801
|
});
|
|
@@ -38575,6 +38872,7 @@ function buildPRAttributionSubsystem(daemon, options) {
|
|
|
38575
38872
|
seedReadyPromise,
|
|
38576
38873
|
dispose: () => {
|
|
38577
38874
|
daemonPrPolling?.dispose();
|
|
38875
|
+
prColdDiscovery.dispose();
|
|
38578
38876
|
unsubscribeCwdChanged();
|
|
38579
38877
|
prPoller.dispose();
|
|
38580
38878
|
}
|
|
@@ -39897,6 +40195,11 @@ var EXTENSION_KIND = {
|
|
|
39897
40195
|
".jpeg": "screenshot",
|
|
39898
40196
|
".gif": "screenshot",
|
|
39899
40197
|
".webp": "screenshot",
|
|
40198
|
+
/**
|
|
40199
|
+
* #5231 — asset download already maps .svg → image/svg+xml; registration must
|
|
40200
|
+
* match so the viewer takes the visual path instead of monospace `other`.
|
|
40201
|
+
*/
|
|
40202
|
+
".svg": "screenshot",
|
|
39900
40203
|
".mp4": "video",
|
|
39901
40204
|
".webm": "video",
|
|
39902
40205
|
".mov": "video",
|
|
@@ -51381,7 +51684,7 @@ import { extname as extname3 } from "path";
|
|
|
51381
51684
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
51382
51685
|
|
|
51383
51686
|
// src/services/lsp/language-server-registry.ts
|
|
51384
|
-
import { existsSync as
|
|
51687
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
|
|
51385
51688
|
import { createRequire as createRequire3 } from "module";
|
|
51386
51689
|
import { dirname as dirname22, isAbsolute as isAbsolute4, join as join53 } from "path";
|
|
51387
51690
|
function decideTypescriptServer(d) {
|
|
@@ -51507,7 +51810,7 @@ function createRegistryDeps(requireFrom) {
|
|
|
51507
51810
|
resolveBin: (pkg, binName) => resolveBinViaPackageJson(pkg, binName, req),
|
|
51508
51811
|
resolveTsgoBinary: () => resolveTsgoBinaryPath(req),
|
|
51509
51812
|
nodeExecPath: resolveNodeExecPath(),
|
|
51510
|
-
fileExists: (path5) =>
|
|
51813
|
+
fileExists: (path5) => existsSync8(path5),
|
|
51511
51814
|
readJsonFile: (path5) => {
|
|
51512
51815
|
try {
|
|
51513
51816
|
return parse2(readFileSync8(path5, "utf-8"));
|
|
@@ -51531,7 +51834,7 @@ function resolveTsgoBinaryPath(req) {
|
|
|
51531
51834
|
}
|
|
51532
51835
|
const exeDir = join53(dirname22(pkgJsonPath), "lib");
|
|
51533
51836
|
const exe = process.platform === "win32" ? join53(exeDir, "tsgo.exe") : join53(exeDir, "tsgo");
|
|
51534
|
-
if (!
|
|
51837
|
+
if (!existsSync8(exe)) {
|
|
51535
51838
|
throw new Error(`tsgo native binary not found: ${exe}`);
|
|
51536
51839
|
}
|
|
51537
51840
|
return exe;
|
|
@@ -70010,7 +70313,7 @@ function applyCursorUsage(result, usage, ctx) {
|
|
|
70010
70313
|
};
|
|
70011
70314
|
const catalog = CURSOR_MODEL_CATALOG.find((m2) => m2.id === ctx.modelId);
|
|
70012
70315
|
if (catalog !== void 0) {
|
|
70013
|
-
const fastPricing = ctx.fastMode
|
|
70316
|
+
const fastPricing = shouldUseCursorFastModePricing(ctx.fastMode, ctx.fastModeParam) ? catalog.fastModePricing : void 0;
|
|
70014
70317
|
const costIn = fastPricing?.costInputUsd ?? catalog.costInputUsd;
|
|
70015
70318
|
const costOut = fastPricing?.costOutputUsd ?? catalog.costOutputUsd;
|
|
70016
70319
|
if (costIn !== void 0 && costOut !== void 0) {
|
|
@@ -70314,18 +70617,16 @@ var CursorAgentSubprocess = class {
|
|
|
70314
70617
|
#injectedAgentId = null;
|
|
70315
70618
|
/**
|
|
70316
70619
|
* Live Fast Mode flag. Mirrored in the runner via `init` (initial value)
|
|
70317
|
-
* and `set_fast_mode` IPC (subsequent toggles).
|
|
70318
|
-
*
|
|
70319
|
-
* `
|
|
70320
|
-
* `#fastModeParam !== null`.
|
|
70620
|
+
* and `set_fast_mode` IPC (subsequent toggles). The runner attaches
|
|
70621
|
+
* `SendOptions.model.params` with value `"true"`/`"false"` whenever
|
|
70622
|
+
* `#fastModeParam` is non-null; `#fastMode` selects which value.
|
|
70321
70623
|
*/
|
|
70322
70624
|
#fastMode = false;
|
|
70323
70625
|
/**
|
|
70324
|
-
* Resolved Fast Mode binding for this task's `modelId`. Frozen at
|
|
70325
|
-
* time — the daemon never re-discovers per-task because Cursor
|
|
70326
|
-
* Fast
|
|
70327
|
-
*
|
|
70328
|
-
* just keeps using the binding it was given.
|
|
70626
|
+
* Resolved Fast Mode ON-binding for this task's `modelId`. Frozen at
|
|
70627
|
+
* spawn time — the daemon never re-discovers per-task because Cursor
|
|
70628
|
+
* Fast Mode bindings are stable for the lifetime of a session. Null
|
|
70629
|
+
* means the model exposes no Fast Mode knob (omit `model.params`).
|
|
70329
70630
|
*/
|
|
70330
70631
|
#fastModeParam = null;
|
|
70331
70632
|
/**
|
|
@@ -71440,12 +71741,7 @@ var CursorAgentSubprocess = class {
|
|
|
71440
71741
|
status: normalizeCursorMcpStatus(s2.status)
|
|
71441
71742
|
}));
|
|
71442
71743
|
if (this.#mcpStatus.length === 0) {
|
|
71443
|
-
const fallback = [HARNESS_SERVER_NAME,
|
|
71444
|
-
(name) => ({
|
|
71445
|
-
name,
|
|
71446
|
-
status: "connected"
|
|
71447
|
-
})
|
|
71448
|
-
);
|
|
71744
|
+
const fallback = [{ name: HARNESS_SERVER_NAME, status: "connected" }];
|
|
71449
71745
|
this.#mcpStatus = fallback;
|
|
71450
71746
|
logger.info({
|
|
71451
71747
|
event: "cursor_subprocess_mcp_status_seeded_from_spawn",
|
|
@@ -71759,49 +72055,41 @@ function createCursorMeCache(deps) {
|
|
|
71759
72055
|
import { createHash as createHash8 } from "crypto";
|
|
71760
72056
|
|
|
71761
72057
|
// src/services/session/profiles/cursor-fast-mode-resolver.ts
|
|
71762
|
-
|
|
71763
|
-
|
|
71764
|
-
|
|
71765
|
-
const lower = rawId.toLowerCase();
|
|
71766
|
-
for (const prefix of FAST_MODE_ID_PREFIXES) {
|
|
71767
|
-
if (lower.startsWith(prefix)) return true;
|
|
71768
|
-
}
|
|
71769
|
-
return false;
|
|
71770
|
-
}
|
|
71771
|
-
function pickFastModeValue(values) {
|
|
71772
|
-
const lowerToOriginal = /* @__PURE__ */ new Map();
|
|
72058
|
+
function findTrueFalseValues(values) {
|
|
72059
|
+
let trueValue;
|
|
72060
|
+
let falseValue;
|
|
71773
72061
|
for (const entry of values) {
|
|
71774
|
-
|
|
71775
|
-
|
|
71776
|
-
|
|
71777
|
-
const match = lowerToOriginal.get(preferred);
|
|
71778
|
-
if (match !== void 0) return match;
|
|
72062
|
+
const lower = entry.value.toLowerCase();
|
|
72063
|
+
if (lower === "true") trueValue = entry.value;
|
|
72064
|
+
if (lower === "false") falseValue = entry.value;
|
|
71779
72065
|
}
|
|
71780
|
-
return null;
|
|
72066
|
+
if (trueValue === void 0 || falseValue === void 0) return null;
|
|
72067
|
+
return { trueValue, falseValue };
|
|
71781
72068
|
}
|
|
71782
72069
|
function resolveCursorFastModeParam(model) {
|
|
71783
72070
|
const warnings = [];
|
|
71784
72071
|
const parameters = model.parameters ?? [];
|
|
71785
|
-
const
|
|
71786
|
-
|
|
71787
|
-
);
|
|
71788
|
-
if (matching.length === 0) {
|
|
72072
|
+
const fastParams = parameters.filter((param) => param.id.toLowerCase() === "fast");
|
|
72073
|
+
if (fastParams.length === 0) {
|
|
71789
72074
|
return { param: null, warnings };
|
|
71790
72075
|
}
|
|
71791
|
-
if (
|
|
72076
|
+
if (fastParams.length > 1) {
|
|
71792
72077
|
warnings.push(
|
|
71793
|
-
`cursor model ${model.id} exposes ${
|
|
72078
|
+
`cursor model ${model.id} exposes ${fastParams.length} parameters named "fast"; picking first`
|
|
71794
72079
|
);
|
|
71795
72080
|
}
|
|
71796
|
-
const chosen =
|
|
72081
|
+
const chosen = fastParams[0];
|
|
71797
72082
|
if (chosen === void 0) {
|
|
71798
72083
|
return { param: null, warnings };
|
|
71799
72084
|
}
|
|
71800
|
-
const
|
|
71801
|
-
if (
|
|
72085
|
+
const pair = findTrueFalseValues(chosen.values);
|
|
72086
|
+
if (pair === null) {
|
|
72087
|
+
warnings.push(
|
|
72088
|
+
`cursor model ${model.id} has parameter id="fast" but values are not {true,false}; refusing to bind (values=[${chosen.values.map((v2) => v2.value).join(",")}])`
|
|
72089
|
+
);
|
|
71802
72090
|
return { param: null, warnings };
|
|
71803
72091
|
}
|
|
71804
|
-
return { param: { id: chosen.id, value }, warnings };
|
|
72092
|
+
return { param: { id: chosen.id, value: pair.trueValue }, warnings };
|
|
71805
72093
|
}
|
|
71806
72094
|
|
|
71807
72095
|
// src/services/session/profiles/cursor-models-cache.ts
|
|
@@ -71860,6 +72148,7 @@ function createCursorModelsCache(deps) {
|
|
|
71860
72148
|
function recordModel(model) {
|
|
71861
72149
|
const { param, warnings } = resolveCursorFastModeParam(model);
|
|
71862
72150
|
cache2.set(model.id, { fastModeParam: param });
|
|
72151
|
+
const catalogClaimsFast = CURSOR_MODEL_CATALOG.find((entry) => entry.id === model.id)?.supportsFastMode === true;
|
|
71863
72152
|
if (param !== null) {
|
|
71864
72153
|
deps.log("info", {
|
|
71865
72154
|
event: "cursor_fast_mode_resolved",
|
|
@@ -71869,7 +72158,16 @@ function createCursorModelsCache(deps) {
|
|
|
71869
72158
|
});
|
|
71870
72159
|
} else {
|
|
71871
72160
|
const reason = (model.parameters?.length ?? 0) === 0 ? "no_parameters" : "no_matching_param";
|
|
71872
|
-
|
|
72161
|
+
if (catalogClaimsFast) {
|
|
72162
|
+
deps.log("warn", {
|
|
72163
|
+
event: "cursor_fast_mode_catalog_drift",
|
|
72164
|
+
modelId: model.id,
|
|
72165
|
+
reason,
|
|
72166
|
+
catalogSupportsFastMode: true
|
|
72167
|
+
});
|
|
72168
|
+
} else {
|
|
72169
|
+
deps.log("info", { event: "cursor_fast_mode_unresolved", modelId: model.id, reason });
|
|
72170
|
+
}
|
|
71873
72171
|
}
|
|
71874
72172
|
for (const warning of warnings) {
|
|
71875
72173
|
deps.log("warn", {
|
|
@@ -71925,10 +72223,40 @@ function createCursorModelsCache(deps) {
|
|
|
71925
72223
|
lastKeyHash = keyHash;
|
|
71926
72224
|
lastRefreshAt = now();
|
|
71927
72225
|
ready = true;
|
|
72226
|
+
deps.onRefreshComplete?.();
|
|
71928
72227
|
}
|
|
71929
72228
|
return { getFastModeParam, isReady, refresh };
|
|
71930
72229
|
}
|
|
71931
72230
|
|
|
72231
|
+
// src/services/session/profiles/cursor-models-cache-wiring.ts
|
|
72232
|
+
function createWiredCursorModelsCache(deps) {
|
|
72233
|
+
let modelsApplier = null;
|
|
72234
|
+
const cache2 = createCursorModelsCache({
|
|
72235
|
+
listModels: deps.listModels,
|
|
72236
|
+
log: deps.log,
|
|
72237
|
+
onRefreshComplete: () => {
|
|
72238
|
+
const current = deps.getCurrentModels();
|
|
72239
|
+
if (current === void 0 || modelsApplier === null) return;
|
|
72240
|
+
if (!cache2.isReady()) return;
|
|
72241
|
+
const next = reconcileCursorSupportsFastMode(current, {
|
|
72242
|
+
isReady: () => true,
|
|
72243
|
+
supportsFastMode: (modelId) => cache2.getFastModeParam(modelId) !== null
|
|
72244
|
+
});
|
|
72245
|
+
void modelsApplier(next);
|
|
72246
|
+
}
|
|
72247
|
+
});
|
|
72248
|
+
setCursorFastModeSupportLookup({
|
|
72249
|
+
isReady: () => cache2.isReady(),
|
|
72250
|
+
supportsFastMode: (modelId) => cache2.getFastModeParam(modelId) !== null
|
|
72251
|
+
});
|
|
72252
|
+
return {
|
|
72253
|
+
cache: cache2,
|
|
72254
|
+
setModelsApplier: (apply) => {
|
|
72255
|
+
modelsApplier = apply;
|
|
72256
|
+
}
|
|
72257
|
+
};
|
|
72258
|
+
}
|
|
72259
|
+
|
|
71932
72260
|
// src/services/session/profiles/cursor-vault-key-cache.ts
|
|
71933
72261
|
function createCursorVaultKeyCache() {
|
|
71934
72262
|
let current = null;
|
|
@@ -74335,6 +74663,12 @@ function logPerf(entry) {
|
|
|
74335
74663
|
}
|
|
74336
74664
|
}
|
|
74337
74665
|
var DEFAULT_READ_CACHE_BUDGET_BYTES = 384 * 1024 * 1024;
|
|
74666
|
+
var READ_CACHE_HEAP_FRACTION = 0.05;
|
|
74667
|
+
var READ_CACHE_BUDGET_CAP_BYTES = 2048 * 1024 * 1024;
|
|
74668
|
+
function computeReadCacheBudgetBytes(heapSizeLimitBytes) {
|
|
74669
|
+
const scaled = Math.round(heapSizeLimitBytes * READ_CACHE_HEAP_FRACTION);
|
|
74670
|
+
return Math.min(READ_CACHE_BUDGET_CAP_BYTES, Math.max(DEFAULT_READ_CACHE_BUDGET_BYTES, scaled));
|
|
74671
|
+
}
|
|
74338
74672
|
function buildJsonlConversationStore(dataDir, opts = {}) {
|
|
74339
74673
|
const channelsDir = join67(dataDir, "channels");
|
|
74340
74674
|
const seqCounters = /* @__PURE__ */ new Map();
|
|
@@ -75982,7 +76316,7 @@ var LoroDocSweeper = class {
|
|
|
75982
76316
|
};
|
|
75983
76317
|
|
|
75984
76318
|
// src/services/task/manager/task-manager.ts
|
|
75985
|
-
import { existsSync as
|
|
76319
|
+
import { existsSync as existsSync13 } from "fs";
|
|
75986
76320
|
import { homedir as homedir13 } from "os";
|
|
75987
76321
|
import { dirname as dirname37 } from "path";
|
|
75988
76322
|
|
|
@@ -78488,6 +78822,13 @@ function handleSpawning(snapshot, event) {
|
|
|
78488
78822
|
}
|
|
78489
78823
|
return noop(snapshot);
|
|
78490
78824
|
}
|
|
78825
|
+
function buildStallGiveUpMessage(recoveryAttempts) {
|
|
78826
|
+
if (recoveryAttempts <= 0) {
|
|
78827
|
+
return "The agent stopped responding mid-run. Send a message to try again.";
|
|
78828
|
+
}
|
|
78829
|
+
const plural = recoveryAttempts === 1 ? "time" : "times";
|
|
78830
|
+
return `The agent stopped responding mid-run. Automatic recovery already retried ${recoveryAttempts} ${plural} without success \u2014 send a message to resume.`;
|
|
78831
|
+
}
|
|
78491
78832
|
function runningStallTimeout(sessionId, event) {
|
|
78492
78833
|
const b2 = createEffectBuilder();
|
|
78493
78834
|
b2.log("running", "resumable_idle", event.type);
|
|
@@ -78495,11 +78836,7 @@ function runningStallTimeout(sessionId, event) {
|
|
|
78495
78836
|
b2.effects.push({ type: "clear_queue" });
|
|
78496
78837
|
if (!event.recoveryArmed) {
|
|
78497
78838
|
b2.taskStatus("input_required");
|
|
78498
|
-
b2.emitError(
|
|
78499
|
-
"The agent stopped responding mid-run. Send a message to try again.",
|
|
78500
|
-
"sdk_error",
|
|
78501
|
-
"run_stall_timeout"
|
|
78502
|
-
);
|
|
78839
|
+
b2.emitError(buildStallGiveUpMessage(event.recoveryAttempts), "sdk_error", "run_stall_timeout");
|
|
78503
78840
|
}
|
|
78504
78841
|
b2.effects.push({ type: "kill_runner" });
|
|
78505
78842
|
return {
|
|
@@ -79320,10 +79657,13 @@ var AgentSessionManager = class {
|
|
|
79320
79657
|
return;
|
|
79321
79658
|
}
|
|
79322
79659
|
let recoveryArmed = false;
|
|
79660
|
+
let recoveryAttempts = 0;
|
|
79323
79661
|
try {
|
|
79324
|
-
|
|
79662
|
+
const outcome = this.#config.onStallTimeout?.() ?? { armed: false, recoveryAttempts: 0 };
|
|
79663
|
+
recoveryArmed = outcome.armed;
|
|
79664
|
+
recoveryAttempts = outcome.recoveryAttempts;
|
|
79325
79665
|
} finally {
|
|
79326
|
-
this.#dispatch({ type: "run_stall_timeout", recoveryArmed });
|
|
79666
|
+
this.#dispatch({ type: "run_stall_timeout", recoveryArmed, recoveryAttempts });
|
|
79327
79667
|
}
|
|
79328
79668
|
}, timeoutMs);
|
|
79329
79669
|
}
|
|
@@ -79351,48 +79691,98 @@ var AgentSessionManager = class {
|
|
|
79351
79691
|
|
|
79352
79692
|
// src/services/conversation/cursor-recovery-controller.ts
|
|
79353
79693
|
var MAX_SIGNAL_DEATH_RETRIES = 1;
|
|
79354
|
-
var MAX_STALL_RESUME_RETRIES =
|
|
79694
|
+
var MAX_STALL_RESUME_RETRIES = 3;
|
|
79695
|
+
var STALL_RESUME_BASE_DELAY_MS = 3e3;
|
|
79696
|
+
var STALL_RESUME_BACKOFF_MULTIPLIER = 3;
|
|
79697
|
+
function stallResumeDelayMs(attempt) {
|
|
79698
|
+
return STALL_RESUME_BASE_DELAY_MS * STALL_RESUME_BACKOFF_MULTIPLIER ** (attempt - 1);
|
|
79699
|
+
}
|
|
79355
79700
|
var MAX_CRASH_DEATH_RETRIES = 1;
|
|
79356
79701
|
var CursorRecoveryController = class {
|
|
79357
79702
|
#signalDeathRetries = 0;
|
|
79358
79703
|
#stallResumeRetries = 0;
|
|
79359
79704
|
#stallResumeArmed = false;
|
|
79360
79705
|
#crashDeathRetries = 0;
|
|
79706
|
+
/**
|
|
79707
|
+
* Pending timer for the settle-delay before an armed stall resume fires.
|
|
79708
|
+
* Cleared at every call site that supersedes the in-flight resume (new
|
|
79709
|
+
* user turn, stop, rewind, dispose) plus its own callback on fire — the
|
|
79710
|
+
* same shape as `RateLimitFlapController#timer`. A single handle suffices;
|
|
79711
|
+
* `consumeStallResumeOnDeath` cannot run twice without an intervening
|
|
79712
|
+
* `onStallTimeout` re-arming it.
|
|
79713
|
+
*/
|
|
79714
|
+
#stallResumeTimer = null;
|
|
79361
79715
|
#deps;
|
|
79362
79716
|
constructor(deps) {
|
|
79363
79717
|
this.#deps = deps;
|
|
79364
79718
|
}
|
|
79719
|
+
/**
|
|
79720
|
+
* Cancel a pending delayed stall resume. Idempotent. Call from any path
|
|
79721
|
+
* that supersedes the armed resume (new user turn, stop, rewind, dispose)
|
|
79722
|
+
* — without this, a fresh intent would race the deferred
|
|
79723
|
+
* `respawnForResume()` fired by the settle-delay timer.
|
|
79724
|
+
*/
|
|
79725
|
+
cancelPendingResume() {
|
|
79726
|
+
if (this.#stallResumeTimer !== null) {
|
|
79727
|
+
clearTimeout(this.#stallResumeTimer);
|
|
79728
|
+
this.#stallResumeTimer = null;
|
|
79729
|
+
}
|
|
79730
|
+
}
|
|
79365
79731
|
/** Reset every budget. Call on each new user turn and on turn_complete. */
|
|
79366
79732
|
reset() {
|
|
79733
|
+
this.cancelPendingResume();
|
|
79367
79734
|
this.#signalDeathRetries = 0;
|
|
79368
79735
|
this.#stallResumeRetries = 0;
|
|
79369
79736
|
this.#stallResumeArmed = false;
|
|
79370
79737
|
this.#crashDeathRetries = 0;
|
|
79371
79738
|
}
|
|
79739
|
+
/**
|
|
79740
|
+
* Call on `turn_complete` instead of `reset()`. A successful auto-recovery
|
|
79741
|
+
* otherwise leaves no trace that the daemon self-healed rather than the
|
|
79742
|
+
* run simply never stalling — log the recovery before clearing the budget.
|
|
79743
|
+
*/
|
|
79744
|
+
noteTurnCompleteRecovery() {
|
|
79745
|
+
if (this.#stallResumeRetries > 0) {
|
|
79746
|
+
this.#deps.log({
|
|
79747
|
+
event: "thread_cursor_stall_auto_resume_recovered",
|
|
79748
|
+
threadId: this.#deps.threadId,
|
|
79749
|
+
attempts: this.#stallResumeRetries
|
|
79750
|
+
});
|
|
79751
|
+
}
|
|
79752
|
+
this.reset();
|
|
79753
|
+
}
|
|
79372
79754
|
/**
|
|
79373
79755
|
* Fired by the manager when the stall watchdog expires, BEFORE the
|
|
79374
79756
|
* `run_stall_timeout` event transitions the FSM. A mid-run Cursor stall
|
|
79375
79757
|
* otherwise lands in `resumable_idle` with a "send a message to try again"
|
|
79376
|
-
* banner and strands the orphaned turn until the user returns. Arm a
|
|
79377
|
-
* resume so the imminent `kill_runner` death is resumed instead of
|
|
79378
|
-
* On repeat
|
|
79758
|
+
* banner and strands the orphaned turn until the user returns. Arm a
|
|
79759
|
+
* resume so the imminent `kill_runner` death is resumed instead of
|
|
79760
|
+
* surfaced. On repeat, up to `MAX_STALL_RESUME_RETRIES` times, stay
|
|
79761
|
+
* armed-off and let the existing banner run.
|
|
79379
79762
|
*
|
|
79380
|
-
* Returns true when a recovery was armed — the manager passes
|
|
79381
|
-
* `recoveryArmed` on the `run_stall_timeout` FSM event so the FSM
|
|
79382
|
-
* the user-facing error banner during the
|
|
79763
|
+
* Returns `armed: true` when a recovery was armed — the manager passes
|
|
79764
|
+
* this as `recoveryArmed` on the `run_stall_timeout` FSM event so the FSM
|
|
79765
|
+
* suppresses the user-facing error banner during the self-heal.
|
|
79766
|
+
* `recoveryAttempts` is only ever positive on the cap-exceeded give-up
|
|
79767
|
+
* (see `StallTimeoutOutcome`), letting the FSM distinguish "never
|
|
79768
|
+
* attempted" from "tried N times".
|
|
79383
79769
|
*/
|
|
79384
79770
|
onStallTimeout() {
|
|
79385
|
-
if (this.#deps.getState() !== "running") return false;
|
|
79386
|
-
if (this.#deps.getAgentSystem() !== AGENT_SYSTEM_CURSOR)
|
|
79771
|
+
if (this.#deps.getState() !== "running") return { armed: false, recoveryAttempts: 0 };
|
|
79772
|
+
if (this.#deps.getAgentSystem() !== AGENT_SYSTEM_CURSOR) {
|
|
79773
|
+
return { armed: false, recoveryAttempts: 0 };
|
|
79774
|
+
}
|
|
79387
79775
|
this.#stallResumeRetries++;
|
|
79388
79776
|
if (this.#stallResumeRetries > MAX_STALL_RESUME_RETRIES) {
|
|
79777
|
+
const recoveryAttempts = this.#stallResumeRetries - 1;
|
|
79389
79778
|
this.#deps.log({
|
|
79390
79779
|
event: "thread_cursor_stall_resume_cap_exceeded",
|
|
79391
79780
|
threadId: this.#deps.threadId,
|
|
79392
|
-
retries: this.#stallResumeRetries
|
|
79781
|
+
retries: this.#stallResumeRetries,
|
|
79782
|
+
maxRetries: MAX_STALL_RESUME_RETRIES
|
|
79393
79783
|
});
|
|
79394
79784
|
this.#stallResumeRetries = 0;
|
|
79395
|
-
return false;
|
|
79785
|
+
return { armed: false, recoveryAttempts };
|
|
79396
79786
|
}
|
|
79397
79787
|
this.#deps.log({
|
|
79398
79788
|
event: "thread_cursor_stall_resume_armed",
|
|
@@ -79400,19 +79790,41 @@ var CursorRecoveryController = class {
|
|
|
79400
79790
|
retries: this.#stallResumeRetries
|
|
79401
79791
|
});
|
|
79402
79792
|
this.#stallResumeArmed = true;
|
|
79403
|
-
return true;
|
|
79793
|
+
return { armed: true, recoveryAttempts: 0 };
|
|
79404
79794
|
}
|
|
79405
79795
|
/**
|
|
79406
|
-
* Consume an armed stall resume on the `kill_runner` death. By now the FSM
|
|
79407
|
-
* in `resumable_idle` and the subprocess was already cleared by
|
|
79408
|
-
* force-kill
|
|
79409
|
-
*
|
|
79796
|
+
* Consume an armed stall resume on the `kill_runner` death. By now the FSM
|
|
79797
|
+
* is in `resumable_idle` and the subprocess was already cleared by
|
|
79798
|
+
* Thread's force-kill. Schedule the actual resume after
|
|
79799
|
+
* `stallResumeDelayMs(attempt)` rather than firing immediately — the
|
|
79800
|
+
* settle window that prevents the busy collision (see
|
|
79801
|
+
* `MAX_STALL_RESUME_RETRIES`'s doc comment). Returns true as soon as it
|
|
79802
|
+
* commits to handling the death (the timer is in-flight); the caller must
|
|
79803
|
+
* not also surface it.
|
|
79410
79804
|
*/
|
|
79411
79805
|
consumeStallResumeOnDeath() {
|
|
79412
79806
|
if (!this.#stallResumeArmed) return false;
|
|
79413
79807
|
this.#stallResumeArmed = false;
|
|
79414
|
-
this
|
|
79415
|
-
this.#
|
|
79808
|
+
this.cancelPendingResume();
|
|
79809
|
+
const attempt = this.#stallResumeRetries;
|
|
79810
|
+
const delayMs = stallResumeDelayMs(attempt);
|
|
79811
|
+
this.#deps.log({
|
|
79812
|
+
event: "thread_cursor_stall_auto_resume_scheduled",
|
|
79813
|
+
threadId: this.#deps.threadId,
|
|
79814
|
+
attempt,
|
|
79815
|
+
delayMs
|
|
79816
|
+
});
|
|
79817
|
+
this.#stallResumeTimer = setTimeout(() => {
|
|
79818
|
+
this.#stallResumeTimer = null;
|
|
79819
|
+
if (this.#deps.isDisposed()) return;
|
|
79820
|
+
this.#deps.log({
|
|
79821
|
+
event: "thread_cursor_stall_auto_resume",
|
|
79822
|
+
threadId: this.#deps.threadId,
|
|
79823
|
+
attempt,
|
|
79824
|
+
delayMs
|
|
79825
|
+
});
|
|
79826
|
+
this.#deps.respawnForResume();
|
|
79827
|
+
}, delayMs);
|
|
79416
79828
|
return true;
|
|
79417
79829
|
}
|
|
79418
79830
|
/**
|
|
@@ -80523,6 +80935,7 @@ var Thread = class {
|
|
|
80523
80935
|
threadId: config.threadId,
|
|
80524
80936
|
getState: () => this.#manager.state,
|
|
80525
80937
|
getAgentSystem: () => this.#agentSystem,
|
|
80938
|
+
isDisposed: () => this.#disposed,
|
|
80526
80939
|
log: config.log,
|
|
80527
80940
|
clearSubprocess: () => {
|
|
80528
80941
|
this.#subprocess?.setOnCwdChanged(null);
|
|
@@ -80683,8 +81096,16 @@ var Thread = class {
|
|
|
80683
81096
|
* Unlike `handleUserMessage`, this does NOT call `#recovery.noteNewUserTurn()`
|
|
80684
81097
|
* (which resets the request-aborted retry budget) because a synthetic wake is
|
|
80685
81098
|
* not a real user message.
|
|
81099
|
+
*
|
|
81100
|
+
* DOES cancel a pending flap/stall-resume timer, same reasoning as `stop()`
|
|
81101
|
+
* and `rewind()`: `sendMessage` from `resumable_idle` walks the FSM to
|
|
81102
|
+
* `spawning` on its own, so a still-armed timer firing later would call
|
|
81103
|
+
* `respawnForResume()` against whatever run this wake started — a resume
|
|
81104
|
+
* with nothing to do with the death it was originally scheduled for.
|
|
80686
81105
|
*/
|
|
80687
81106
|
pushSyntheticMessageAndWake(content) {
|
|
81107
|
+
this.#rateLimitFlap.cancelPendingRetry();
|
|
81108
|
+
this.#cursorRecovery.cancelPendingResume();
|
|
80688
81109
|
this.#manager.sendMessage(content);
|
|
80689
81110
|
}
|
|
80690
81111
|
/**
|
|
@@ -80725,6 +81146,7 @@ var Thread = class {
|
|
|
80725
81146
|
}
|
|
80726
81147
|
stop() {
|
|
80727
81148
|
this.#rateLimitFlap.cancelPendingRetry();
|
|
81149
|
+
this.#cursorRecovery.cancelPendingResume();
|
|
80728
81150
|
this.#manager.stop();
|
|
80729
81151
|
}
|
|
80730
81152
|
/**
|
|
@@ -80734,6 +81156,7 @@ var Thread = class {
|
|
|
80734
81156
|
*/
|
|
80735
81157
|
rewind(resumeAtMessageId) {
|
|
80736
81158
|
this.#rateLimitFlap.cancelPendingRetry();
|
|
81159
|
+
this.#cursorRecovery.cancelPendingResume();
|
|
80737
81160
|
this.#manager.rewind(resumeAtMessageId);
|
|
80738
81161
|
}
|
|
80739
81162
|
notifySetupReady() {
|
|
@@ -80887,6 +81310,7 @@ var Thread = class {
|
|
|
80887
81310
|
await this.#asyncQueue;
|
|
80888
81311
|
this.#disposed = true;
|
|
80889
81312
|
this.#rateLimitFlap.cancelPendingRetry();
|
|
81313
|
+
this.#cursorRecovery.cancelPendingResume();
|
|
80890
81314
|
this.#permissionHandler.denyAllPending("Thread disposed");
|
|
80891
81315
|
this.#permissionQueue.length = 0;
|
|
80892
81316
|
this.#streamDelta.dispose();
|
|
@@ -81527,7 +81951,7 @@ var Thread = class {
|
|
|
81527
81951
|
});
|
|
81528
81952
|
this.#streamDelta.resetForTurn();
|
|
81529
81953
|
this.#recovery.resetRetriesOnTurnComplete();
|
|
81530
|
-
this.#cursorRecovery.
|
|
81954
|
+
this.#cursorRecovery.noteTurnCompleteRecovery();
|
|
81531
81955
|
this.#rateLimitFlap.noteRecoveredOnTurnComplete((event.result.outputTokens ?? 0) > 0);
|
|
81532
81956
|
this.#emitThreadTurnStats(event.result);
|
|
81533
81957
|
this.#manager.notifyTurnComplete();
|
|
@@ -81691,7 +82115,7 @@ var Thread = class {
|
|
|
81691
82115
|
|
|
81692
82116
|
// src/services/plan/plan-handler.ts
|
|
81693
82117
|
import { randomUUID as randomUUID21 } from "crypto";
|
|
81694
|
-
import { existsSync as
|
|
82118
|
+
import { existsSync as existsSync11, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
|
|
81695
82119
|
import { mkdir as mkdir33, readFile as readFile45, writeFile as writeFile26 } from "fs/promises";
|
|
81696
82120
|
import { homedir as homedir10 } from "os";
|
|
81697
82121
|
import { dirname as dirname34, join as join73 } from "path";
|
|
@@ -81803,7 +82227,7 @@ function decideWatchResolved(trigger, snapshot) {
|
|
|
81803
82227
|
|
|
81804
82228
|
// src/services/plan/plan-file-bridge.ts
|
|
81805
82229
|
import { createHash as createHash12, randomUUID as randomUUID20 } from "crypto";
|
|
81806
|
-
import { existsSync as
|
|
82230
|
+
import { existsSync as existsSync9 } from "fs";
|
|
81807
82231
|
import { readFile as readFile44, rename as rename18, writeFile as writeFile25 } from "fs/promises";
|
|
81808
82232
|
import { basename as basename13, dirname as dirname33 } from "path";
|
|
81809
82233
|
var FILE_READ_MAX_RETRIES = 3;
|
|
@@ -81998,7 +82422,7 @@ var PlanFileBridge = class _PlanFileBridge {
|
|
|
81998
82422
|
*/
|
|
81999
82423
|
async #startDirectoryWatcher(filePath) {
|
|
82000
82424
|
const dir = dirname33(filePath);
|
|
82001
|
-
if (!
|
|
82425
|
+
if (!existsSync9(dir)) return;
|
|
82002
82426
|
const targetFilename = basename13(filePath);
|
|
82003
82427
|
let sub;
|
|
82004
82428
|
try {
|
|
@@ -82231,7 +82655,7 @@ var PlanFileBridge = class _PlanFileBridge {
|
|
|
82231
82655
|
}
|
|
82232
82656
|
async #doWriteBackToFile() {
|
|
82233
82657
|
if (this.#disposed || !this.#filePath) return;
|
|
82234
|
-
if (!
|
|
82658
|
+
if (!existsSync9(this.#filePath)) return;
|
|
82235
82659
|
const content = this.#config.planRepo.getContent(this.#config.taskId);
|
|
82236
82660
|
const hash = contentHash(content);
|
|
82237
82661
|
if (hash === this.#lastWrittenHash) return;
|
|
@@ -82462,7 +82886,7 @@ function greedyLCS(a, b2) {
|
|
|
82462
82886
|
}
|
|
82463
82887
|
|
|
82464
82888
|
// src/services/plan/plan-file-watcher.ts
|
|
82465
|
-
import { existsSync as
|
|
82889
|
+
import { existsSync as existsSync10 } from "fs";
|
|
82466
82890
|
import { homedir as homedir9 } from "os";
|
|
82467
82891
|
import { join as join72 } from "path";
|
|
82468
82892
|
var DEFAULT_PLANS_DIR = join72(homedir9(), ".claude", "plans");
|
|
@@ -82525,7 +82949,7 @@ function createPlanFileWatcher(deps) {
|
|
|
82525
82949
|
deps.onTimeout();
|
|
82526
82950
|
}, PLAN_WATCH_TIMEOUT_MS);
|
|
82527
82951
|
const plansDir = deps.plansDir ?? DEFAULT_PLANS_DIR;
|
|
82528
|
-
if (!
|
|
82952
|
+
if (!existsSync10(plansDir)) {
|
|
82529
82953
|
deps.log({
|
|
82530
82954
|
event: "plan_watch_skip_missing_dir",
|
|
82531
82955
|
taskId: deps.taskId,
|
|
@@ -82988,7 +83412,7 @@ var PlanHandler = class {
|
|
|
82988
83412
|
}
|
|
82989
83413
|
async #rehydratePlanFileBridge(filePath, toolUseId) {
|
|
82990
83414
|
if (this.#deps.isDisposed()) return;
|
|
82991
|
-
if (!
|
|
83415
|
+
if (!existsSync11(filePath)) {
|
|
82992
83416
|
this.#deps.log({
|
|
82993
83417
|
event: "plan_bridge_rehydrate_file_missing",
|
|
82994
83418
|
taskId: this.#deps.taskId,
|
|
@@ -83687,7 +84111,7 @@ var PlanHandler = class {
|
|
|
83687
84111
|
return newest?.path ?? null;
|
|
83688
84112
|
}
|
|
83689
84113
|
const plansDir = join73(homedir10(), ".claude", "plans");
|
|
83690
|
-
if (!
|
|
84114
|
+
if (!existsSync11(plansDir)) return null;
|
|
83691
84115
|
try {
|
|
83692
84116
|
const files = readdirSync5(plansDir).filter((f2) => f2.endsWith(".md")).map((f2) => ({
|
|
83693
84117
|
path: join73(plansDir, f2),
|
|
@@ -89478,7 +89902,7 @@ async function resolveTaskListPrepend(ctx) {
|
|
|
89478
89902
|
}
|
|
89479
89903
|
|
|
89480
89904
|
// src/services/task/cc-task-file-store.ts
|
|
89481
|
-
import { existsSync as
|
|
89905
|
+
import { existsSync as existsSync12 } from "fs";
|
|
89482
89906
|
import { readdir as readdir21, readFile as readFile47 } from "fs/promises";
|
|
89483
89907
|
import { homedir as homedir11 } from "os";
|
|
89484
89908
|
import { basename as basename14, dirname as dirname36, join as join75 } from "path";
|
|
@@ -89607,7 +90031,7 @@ function createCCTaskFileWatcher(listId, log) {
|
|
|
89607
90031
|
}
|
|
89608
90032
|
}
|
|
89609
90033
|
async function startDirWatcher(reason = "initial") {
|
|
89610
|
-
if (!
|
|
90034
|
+
if (!existsSync12(dir)) return false;
|
|
89611
90035
|
try {
|
|
89612
90036
|
const sub = await guardedSubscribe(dir, onDirEvent, { ignore: ["**/*/"] }, "lazy", reason);
|
|
89613
90037
|
if (watchState.stopped) {
|
|
@@ -94249,12 +94673,22 @@ function pushTaskMcpStateSnapshot(ctx, taskId) {
|
|
|
94249
94673
|
for (const s2 of ctx.sessionMcpsByTask.get(taskId) ?? []) {
|
|
94250
94674
|
sessionServers[s2.name] = { status: normalizeMcpStatus(s2.status) };
|
|
94251
94675
|
}
|
|
94676
|
+
const liveStatuses = liveStatusesFromStatusEntries(ctx.getMcpCoordinator()?.getStatuses() ?? []);
|
|
94677
|
+
for (const divergence of collectMcpSessionCoordinatorDivergences(sessionServers, liveStatuses)) {
|
|
94678
|
+
logger.info({
|
|
94679
|
+
event: "mcp_session_coordinator_status_divergence",
|
|
94680
|
+
taskId,
|
|
94681
|
+
serverName: divergence.name,
|
|
94682
|
+
sessionStatus: divergence.sessionStatus,
|
|
94683
|
+
coordinatorStatus: divergence.coordinatorStatus
|
|
94684
|
+
});
|
|
94685
|
+
}
|
|
94252
94686
|
const message = {
|
|
94253
94687
|
type: "mcp_state_snapshot",
|
|
94254
94688
|
taskId,
|
|
94255
94689
|
servers: resolveMcpStateSnapshot({
|
|
94256
94690
|
workspaceServers: workspaceServersFromCapabilities(ctx.getCapabilities()),
|
|
94257
|
-
liveStatuses
|
|
94691
|
+
liveStatuses,
|
|
94258
94692
|
sessionServers,
|
|
94259
94693
|
perTaskDisabled: settings.disabledMcpServers ?? null,
|
|
94260
94694
|
perTaskSnapshot: settings.mcpServerSnapshot ?? null
|
|
@@ -96547,16 +96981,6 @@ var TaskManager = class {
|
|
|
96547
96981
|
getOrchestrator(taskId) {
|
|
96548
96982
|
return this.#tasks.get(taskId)?.orchestrator ?? null;
|
|
96549
96983
|
}
|
|
96550
|
-
/**
|
|
96551
|
-
* True if the task has an orchestrator with a live or resumable session.
|
|
96552
|
-
* cold_idle orchestrators are NOT considered running — the SDK session is
|
|
96553
|
-
* expired and the task needs user input to restart.
|
|
96554
|
-
*/
|
|
96555
|
-
isRunning(taskId) {
|
|
96556
|
-
const task = this.#tasks.get(taskId);
|
|
96557
|
-
if (!task) return false;
|
|
96558
|
-
return task.orchestrator.state !== "cold_idle";
|
|
96559
|
-
}
|
|
96560
96984
|
get size() {
|
|
96561
96985
|
return this.#tasks.size;
|
|
96562
96986
|
}
|
|
@@ -96951,7 +97375,7 @@ var TaskManager = class {
|
|
|
96951
97375
|
function pathExistsForLog2(path5) {
|
|
96952
97376
|
if (!path5) return false;
|
|
96953
97377
|
try {
|
|
96954
|
-
return
|
|
97378
|
+
return existsSync13(path5);
|
|
96955
97379
|
} catch {
|
|
96956
97380
|
return false;
|
|
96957
97381
|
}
|
|
@@ -97594,7 +98018,9 @@ async function createDaemon(deps) {
|
|
|
97594
98018
|
const compactor = startLoroCompactor(storageAdapter);
|
|
97595
98019
|
const taskStateStore = buildTaskStateStore(deps.dataDir);
|
|
97596
98020
|
const planRepo = new PlanRepository(repo, PLAN_EPOCH, createPlanContentBridge(), storageAdapter);
|
|
97597
|
-
const jsonlStore = buildJsonlConversationStore(deps.dataDir
|
|
98021
|
+
const jsonlStore = buildJsonlConversationStore(deps.dataDir, {
|
|
98022
|
+
readCacheBudgetBytes: computeReadCacheBudgetBytes(getHeapStatistics().heap_size_limit)
|
|
98023
|
+
});
|
|
97598
98024
|
const store = buildObservableConversationStore(jsonlStore);
|
|
97599
98025
|
const sessionPersistence = buildSessionPersistence(deps.dataDir);
|
|
97600
98026
|
const collabQueuePersistence = buildCollabQueuePersistence(deps.dataDir);
|
|
@@ -97654,14 +98080,15 @@ async function createDaemon(deps) {
|
|
|
97654
98080
|
const CURSOR_VAULT_WRITE_TIMEOUT_MS = 5e3;
|
|
97655
98081
|
const cursorStoredByRef = { current: "" };
|
|
97656
98082
|
const cursorVaultKeyCache = createCursorVaultKeyCache();
|
|
97657
|
-
const cursorModelsCache =
|
|
98083
|
+
const { cache: cursorModelsCache, setModelsApplier: setCursorFastModeModelsApplierFn } = createWiredCursorModelsCache({
|
|
97658
98084
|
listModels: async (options) => {
|
|
97659
98085
|
const { Cursor } = await import("@cursor/sdk");
|
|
97660
98086
|
return Cursor.models.list(options);
|
|
97661
98087
|
},
|
|
97662
98088
|
log: (level, entry) => {
|
|
97663
98089
|
logger[level](entry);
|
|
97664
|
-
}
|
|
98090
|
+
},
|
|
98091
|
+
getCurrentModels: () => capabilitiesRef.current?.models
|
|
97665
98092
|
});
|
|
97666
98093
|
cursorVaultKeyCache.subscribe((key) => {
|
|
97667
98094
|
void cursorModelsCache.refresh(key);
|
|
@@ -99792,6 +100219,7 @@ async function createDaemon(deps) {
|
|
|
99792
100219
|
clearCursorVaultCache: () => {
|
|
99793
100220
|
cursorVaultKeyCache.set(null);
|
|
99794
100221
|
},
|
|
100222
|
+
setCursorFastModeModelsApplier: setCursorFastModeModelsApplierFn,
|
|
99795
100223
|
notifyCodexAccountId: (accountId) => {
|
|
99796
100224
|
codexEngineRef.current?.notifyAccountId(accountId);
|
|
99797
100225
|
},
|
|
@@ -99921,7 +100349,7 @@ async function createDaemon(deps) {
|
|
|
99921
100349
|
}
|
|
99922
100350
|
|
|
99923
100351
|
// src/services/serve-helpers.ts
|
|
99924
|
-
import { existsSync as
|
|
100352
|
+
import { existsSync as existsSync14 } from "fs";
|
|
99925
100353
|
|
|
99926
100354
|
// src/services/bootstrap/self-update.ts
|
|
99927
100355
|
import { execFile as execFile11, spawn as spawn13 } from "child_process";
|
|
@@ -100589,7 +101017,7 @@ function resolveClaudeCodePath(log) {
|
|
|
100589
101017
|
log({ event: "claude_code_path_resolved", source: "sdk_default" });
|
|
100590
101018
|
return void 0;
|
|
100591
101019
|
}
|
|
100592
|
-
if (!
|
|
101020
|
+
if (!existsSync14(envPath)) {
|
|
100593
101021
|
log({ event: "claude_code_path_skipped", source: "env", path: envPath, reason: "missing" });
|
|
100594
101022
|
log({ event: "claude_code_path_resolved", source: "sdk_default" });
|
|
100595
101023
|
return void 0;
|
|
@@ -101978,24 +102406,6 @@ function buildPluginConfigStore(pluginsDir) {
|
|
|
101978
102406
|
};
|
|
101979
102407
|
}
|
|
101980
102408
|
|
|
101981
|
-
// src/services/task/session-activity.ts
|
|
101982
|
-
function isActiveUserWork(state) {
|
|
101983
|
-
switch (state) {
|
|
101984
|
-
case "spawning":
|
|
101985
|
-
case "running":
|
|
101986
|
-
case "stopping":
|
|
101987
|
-
return true;
|
|
101988
|
-
case "warm_idle":
|
|
101989
|
-
case "resumable_idle":
|
|
101990
|
-
case "cold_idle":
|
|
101991
|
-
return false;
|
|
101992
|
-
default: {
|
|
101993
|
-
const _exhaustive = state;
|
|
101994
|
-
throw new Error(`Unhandled session state: ${JSON.stringify(_exhaustive)}`);
|
|
101995
|
-
}
|
|
101996
|
-
}
|
|
101997
|
-
}
|
|
101998
|
-
|
|
101999
102409
|
// src/services/task/electron-idle-rpc.ts
|
|
102000
102410
|
function registerElectronIdleRpc(taskManager, parentPort2) {
|
|
102001
102411
|
parentPort2.on("message", (event) => {
|
|
@@ -102613,6 +103023,9 @@ async function runServeBody(options, captureRefs) {
|
|
|
102613
103023
|
log: logAdapter
|
|
102614
103024
|
});
|
|
102615
103025
|
codexSkillsApplyScopedPatchRef = applyScopedPatch;
|
|
103026
|
+
daemon.setCursorFastModeModelsApplier(async (models) => {
|
|
103027
|
+
await applyScopedPatch({ models });
|
|
103028
|
+
});
|
|
102616
103029
|
void (async () => {
|
|
102617
103030
|
try {
|
|
102618
103031
|
const seed = await loadCodexSkillsCache(codexSkillsCachePath);
|
|
@@ -103067,4 +103480,4 @@ export {
|
|
|
103067
103480
|
decideWorkspaceScope,
|
|
103068
103481
|
serve
|
|
103069
103482
|
};
|
|
103070
|
-
//# sourceMappingURL=serve-
|
|
103483
|
+
//# sourceMappingURL=serve-RWFBSQIE.js.map
|