@cortexkit/opencode-magic-context 0.36.0 → 0.36.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/config/index.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-dw9fs934.js → conflict-warning-hook-mt0ttc4x.js} +2 -2
- package/dist/features/magic-context/context-authority.d.ts +12 -0
- package/dist/features/magic-context/context-authority.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts +2 -0
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +2 -0
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/lease.d.ts +10 -3
- package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -0
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/module-apply.d.ts +5 -0
- package/dist/features/magic-context/dreamer/module-apply.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/promote-primers.d.ts +2 -0
- package/dist/features/magic-context/dreamer/promote-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -0
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts +5 -2
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts +2 -0
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts +2 -0
- package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/schema-fence-probe.d.ts +1 -0
- package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/condition-compiler.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/condition-compiler.d.ts.map +1 -1
- package/dist/features/magic-context/storage-clone.d.ts +6 -0
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +2 -0
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts +2 -0
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/hooks/magic-context/child-session-spawn.d.ts +1 -0
- package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-render-epoch.d.ts +5 -3
- package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
- package/dist/hooks/magic-context/embed-session-state.d.ts +1 -1
- package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +8 -0
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts +5 -2
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync.d.ts +1 -0
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-transport.d.ts +20 -3
- package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +1 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +6 -1
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +1 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-3nfgbsp4.js → index-1skzp4dc.js} +347 -44
- package/dist/{index-z8v31d85.js → index-3zqcdwqr.js} +137 -10
- package/dist/{index-0c9dmw9m.js → index-8mtsfhyg.js} +33 -3
- package/dist/{index-37rt2bka.js → index-zp6x6s6a.js} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +820 -548
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rust-tool-backends.d.ts +4 -0
- package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-7wbbvf87.js → recomp-orchestrator-a0g9b52q.js} +3 -3
- package/dist/shared/conflict-fixer.d.ts.map +1 -1
- package/dist/shared/jsonc-edit.d.ts +18 -0
- package/dist/shared/jsonc-edit.d.ts.map +1 -0
- package/dist/shared/jsonc-parser.d.ts +11 -1
- package/dist/shared/jsonc-parser.d.ts.map +1 -1
- package/dist/shared/prompt-surface.d.ts +5 -3
- package/dist/shared/prompt-surface.d.ts.map +1 -1
- package/dist/shared/rpc-utils.d.ts +16 -0
- package/dist/shared/rpc-utils.d.ts.map +1 -1
- package/dist/shared/tui-preferences.d.ts +9 -0
- package/dist/shared/tui-preferences.d.ts.map +1 -1
- package/dist/{storage-meta-session-kh5egr11.js → storage-meta-session-df9tstzr.js} +1 -1
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/config/index.test.ts +23 -0
- package/src/config/index.ts +41 -9
- package/src/config/schema/magic-context.test.ts +2 -1
- package/src/config/schema/magic-context.ts +3 -3
- package/src/shared/conflict-fixer.test.ts +174 -0
- package/src/shared/conflict-fixer.ts +66 -70
- package/src/shared/jsonc-edit.ts +295 -0
- package/src/shared/jsonc-parser.test.ts +33 -0
- package/src/shared/jsonc-parser.ts +54 -2
- package/src/shared/prompt-surface.test.ts +53 -2
- package/src/shared/prompt-surface.ts +20 -9
- package/src/shared/rpc-utils.test.ts +36 -0
- package/src/shared/rpc-utils.ts +71 -0
- package/src/shared/tui-preferences.test.ts +52 -2
- package/src/shared/tui-preferences.ts +42 -17
package/dist/index.js
CHANGED
|
@@ -60,6 +60,7 @@ import {
|
|
|
60
60
|
appendAutoSearchHintDecision,
|
|
61
61
|
applyDeferredCompactionMarker,
|
|
62
62
|
applyMirrorPage,
|
|
63
|
+
applyMirroredNoteCompileFields,
|
|
63
64
|
applyStrippedPlaceholderDelta,
|
|
64
65
|
archiveMemory,
|
|
65
66
|
backfillTagTokenCounts,
|
|
@@ -80,6 +81,7 @@ import {
|
|
|
80
81
|
clearEmergencyDropSample,
|
|
81
82
|
clearEmergencyRecovery,
|
|
82
83
|
clearHistorianFailureState,
|
|
84
|
+
clearHookInitFailure,
|
|
83
85
|
clearInjectionCache,
|
|
84
86
|
clearMemoryVerifications,
|
|
85
87
|
clearNoteNudgeTriggerAndCooldown,
|
|
@@ -99,6 +101,7 @@ import {
|
|
|
99
101
|
countEmbeddedCommits,
|
|
100
102
|
countPrimerCandidatesForProject,
|
|
101
103
|
createChildSessionWithFence,
|
|
104
|
+
createFailClosedController,
|
|
102
105
|
createPrimer,
|
|
103
106
|
createPromptSurfaceGuidanceEpochCache,
|
|
104
107
|
createPromptSurfaceRuntime,
|
|
@@ -153,6 +156,7 @@ import {
|
|
|
153
156
|
getHistorianFailureState,
|
|
154
157
|
getLastCompartmentEndMessage,
|
|
155
158
|
getLastCompartmentEndMessageId,
|
|
159
|
+
getLastHookInitFailure,
|
|
156
160
|
getLastNudgeLevel,
|
|
157
161
|
getLastNudgeUndropped,
|
|
158
162
|
getLatestIndexedCommitTimeMs,
|
|
@@ -235,6 +239,7 @@ import {
|
|
|
235
239
|
isDatabasePersisted,
|
|
236
240
|
isEmbeddingEnabled,
|
|
237
241
|
isEmergencyRecoveryArmed,
|
|
242
|
+
isFailClosedBlockingError,
|
|
238
243
|
isPidAlive,
|
|
239
244
|
isProviderOverflowReconfirmed,
|
|
240
245
|
lkgContentDigest,
|
|
@@ -274,6 +279,7 @@ import {
|
|
|
274
279
|
prepareCompartmentInjection,
|
|
275
280
|
primerOccurrenceKey,
|
|
276
281
|
primerOccurrenceUtcDay,
|
|
282
|
+
promptSurfaceConfigIdentity,
|
|
277
283
|
promptSurfaceHashMaterial,
|
|
278
284
|
promptSyncWithValidatedOutputRetry,
|
|
279
285
|
pruneAutoSearchHintDecisions,
|
|
@@ -291,6 +297,7 @@ import {
|
|
|
291
297
|
recordDetectedContextLimit,
|
|
292
298
|
recordEmbeddingMeasurement,
|
|
293
299
|
recordHighPressureNoEligibleHead,
|
|
300
|
+
recordHookInitFailure,
|
|
294
301
|
recordMemoryMapping,
|
|
295
302
|
recordMemoryVerifications,
|
|
296
303
|
recordMuralCueRejection,
|
|
@@ -320,6 +327,7 @@ import {
|
|
|
320
327
|
resetLastNudgeCycleIfTailShrank,
|
|
321
328
|
resetNoteNudgeCooldownOnly,
|
|
322
329
|
resetProtectedTailNoEligibleHead,
|
|
330
|
+
resolveAgentNameFromMessages,
|
|
323
331
|
resolveCompactionModeRecord,
|
|
324
332
|
resolveGitTopLevel,
|
|
325
333
|
resolveLegacyConfigSources,
|
|
@@ -365,6 +373,7 @@ import {
|
|
|
365
373
|
setRecompTerminal,
|
|
366
374
|
setSessionWorkMetrics,
|
|
367
375
|
setSqlitePragmaConfig,
|
|
376
|
+
shouldBypassFailClosedBlock,
|
|
368
377
|
shouldKeepSubagents,
|
|
369
378
|
snapRangeToCompartments,
|
|
370
379
|
sourceNameForMemory,
|
|
@@ -391,7 +400,7 @@ import {
|
|
|
391
400
|
upsertCommits,
|
|
392
401
|
verificationFileExists,
|
|
393
402
|
withContentLanguageDirective
|
|
394
|
-
} from "./index-
|
|
403
|
+
} from "./index-1skzp4dc.js";
|
|
395
404
|
import {
|
|
396
405
|
deriveHistorianChunkTokens,
|
|
397
406
|
deriveTriggerBudget,
|
|
@@ -455,6 +464,7 @@ import {
|
|
|
455
464
|
markSessionCleanupPending,
|
|
456
465
|
normalizeText,
|
|
457
466
|
partHasCompletedResult,
|
|
467
|
+
preloadTokenizer,
|
|
458
468
|
prependTag,
|
|
459
469
|
primeInMemoryTailRawMessageCache,
|
|
460
470
|
primeTailRawMessageCache,
|
|
@@ -472,7 +482,7 @@ import {
|
|
|
472
482
|
textMentionsRecentCommit,
|
|
473
483
|
updateSessionMeta,
|
|
474
484
|
withRawSessionMessageCache
|
|
475
|
-
} from "./index-
|
|
485
|
+
} from "./index-3zqcdwqr.js";
|
|
476
486
|
import {
|
|
477
487
|
Database,
|
|
478
488
|
closeQuietly,
|
|
@@ -486,12 +496,13 @@ import {
|
|
|
486
496
|
cleanupConflictWarnings,
|
|
487
497
|
detectConflicts,
|
|
488
498
|
sendConflictWarning
|
|
489
|
-
} from "./index-
|
|
499
|
+
} from "./index-zp6x6s6a.js";
|
|
490
500
|
import {
|
|
491
501
|
detectConfigFile,
|
|
502
|
+
isPrototypePollutionKey,
|
|
492
503
|
parseJsonc,
|
|
493
504
|
stripJsonComments
|
|
494
|
-
} from "./index-
|
|
505
|
+
} from "./index-8mtsfhyg.js";
|
|
495
506
|
import {
|
|
496
507
|
ANNOUNCEMENT_FEATURES,
|
|
497
508
|
ANNOUNCEMENT_FOOTER,
|
|
@@ -9515,10 +9526,15 @@ function loadConfigFileDetailed(configPath, source) {
|
|
|
9515
9526
|
configPath,
|
|
9516
9527
|
isProjectConfig: source === "project"
|
|
9517
9528
|
});
|
|
9529
|
+
const rejectedKeyPaths = [];
|
|
9530
|
+
const config = parseJsonc(substituted.text, {
|
|
9531
|
+
onRejectedKey: (path) => rejectedKeyPaths.push(path.join("."))
|
|
9532
|
+
});
|
|
9533
|
+
const unsafeKeyWarnings = rejectedKeyPaths.map((path) => `Ignored unsafe config key "${path}" (security: prototype-pollution keys are not allowed).`);
|
|
9518
9534
|
return {
|
|
9519
|
-
config
|
|
9520
|
-
warnings: substituted.warnings.map((
|
|
9521
|
-
outcome: substituted.warnings.length > 0 ? "substitution-failure" : "ok",
|
|
9535
|
+
config,
|
|
9536
|
+
warnings: [...substituted.warnings, ...unsafeKeyWarnings].map((warning) => `${configPath}: ${warning}`),
|
|
9537
|
+
outcome: rejectedKeyPaths.length > 0 ? "schema-recovery" : substituted.warnings.length > 0 ? "substitution-failure" : "ok",
|
|
9522
9538
|
source
|
|
9523
9539
|
};
|
|
9524
9540
|
} catch (error) {
|
|
@@ -9532,18 +9548,35 @@ function loadConfigFileDetailed(configPath, source) {
|
|
|
9532
9548
|
};
|
|
9533
9549
|
}
|
|
9534
9550
|
}
|
|
9551
|
+
function defineOwnConfigValue(target, key, value) {
|
|
9552
|
+
Object.defineProperty(target, key, {
|
|
9553
|
+
value,
|
|
9554
|
+
enumerable: true,
|
|
9555
|
+
configurable: true,
|
|
9556
|
+
writable: true
|
|
9557
|
+
});
|
|
9558
|
+
}
|
|
9535
9559
|
function deepMergeRawConfig(base, override) {
|
|
9536
|
-
const result = {
|
|
9560
|
+
const result = {};
|
|
9561
|
+
for (const key of Object.keys(base)) {
|
|
9562
|
+
if (isPrototypePollutionKey(key))
|
|
9563
|
+
continue;
|
|
9564
|
+
defineOwnConfigValue(result, key, base[key]);
|
|
9565
|
+
}
|
|
9537
9566
|
for (const key of Object.keys(override)) {
|
|
9538
|
-
|
|
9567
|
+
if (isPrototypePollutionKey(key))
|
|
9568
|
+
continue;
|
|
9569
|
+
const baseVal = Object.hasOwn(base, key) ? base[key] : undefined;
|
|
9539
9570
|
const overrideVal = override[key];
|
|
9571
|
+
let mergedValue;
|
|
9540
9572
|
if (baseVal !== null && typeof baseVal === "object" && !Array.isArray(baseVal) && overrideVal !== null && typeof overrideVal === "object" && !Array.isArray(overrideVal)) {
|
|
9541
|
-
|
|
9573
|
+
mergedValue = deepMergeRawConfig(baseVal, overrideVal);
|
|
9542
9574
|
} else if (key === "disabled_hooks" && Array.isArray(baseVal) && Array.isArray(overrideVal)) {
|
|
9543
|
-
|
|
9575
|
+
mergedValue = [...new Set([...baseVal, ...overrideVal])];
|
|
9544
9576
|
} else {
|
|
9545
|
-
|
|
9577
|
+
mergedValue = overrideVal;
|
|
9546
9578
|
}
|
|
9579
|
+
defineOwnConfigValue(result, key, mergedValue);
|
|
9547
9580
|
}
|
|
9548
9581
|
return result;
|
|
9549
9582
|
}
|
|
@@ -10157,171 +10190,6 @@ function buildDreamTaskPrompt(task, args) {
|
|
|
10157
10190
|
}
|
|
10158
10191
|
}
|
|
10159
10192
|
|
|
10160
|
-
// src/features/magic-context/fail-closed-block.ts
|
|
10161
|
-
var FAIL_CLOSED_DOCTOR_COMMAND = "npx @cortexkit/magic-context@latest doctor";
|
|
10162
|
-
var FAIL_CLOSED_REPROBE_EVERY_N = 5;
|
|
10163
|
-
|
|
10164
|
-
class FailClosedBlockingError extends Error {
|
|
10165
|
-
code = "FAIL_CLOSED_BLOCKING";
|
|
10166
|
-
reason;
|
|
10167
|
-
constructor(message, reason, options) {
|
|
10168
|
-
super(message, options);
|
|
10169
|
-
this.name = "FailClosedBlockingError";
|
|
10170
|
-
this.reason = reason;
|
|
10171
|
-
}
|
|
10172
|
-
}
|
|
10173
|
-
var OPENCODE_INTERNAL_AGENT_NAMES = new Set(["title", "summary", "compaction"]);
|
|
10174
|
-
function isMagicContextHiddenAgentName(agent) {
|
|
10175
|
-
if (agent === "sidekick" || agent === "smart-note-compiler" || agent.startsWith("smart-note-")) {
|
|
10176
|
-
return true;
|
|
10177
|
-
}
|
|
10178
|
-
if (agent === "historian" || agent.startsWith("historian-"))
|
|
10179
|
-
return true;
|
|
10180
|
-
if (agent === "dreamer" || agent.startsWith("dreamer-"))
|
|
10181
|
-
return true;
|
|
10182
|
-
return false;
|
|
10183
|
-
}
|
|
10184
|
-
var MAX_FORMATTED_BLOCKING_PROCESSES = 8;
|
|
10185
|
-
function formatFailClosedBlockingProcesses(processes) {
|
|
10186
|
-
const uniqueProcesses = new Map;
|
|
10187
|
-
for (const process2 of processes) {
|
|
10188
|
-
if (!process2.harness.trim() || !Number.isInteger(process2.pid) || process2.pid <= 0)
|
|
10189
|
-
continue;
|
|
10190
|
-
uniqueProcesses.set(`${process2.harness}\x00${process2.pid}`, {
|
|
10191
|
-
harness: process2.harness.trim(),
|
|
10192
|
-
pid: process2.pid
|
|
10193
|
-
});
|
|
10194
|
-
}
|
|
10195
|
-
const entries = [...uniqueProcesses.values()];
|
|
10196
|
-
const visible = entries.slice(0, MAX_FORMATTED_BLOCKING_PROCESSES);
|
|
10197
|
-
const rendered = visible.map(({ harness, pid }) => `${harness} (PID ${pid})`);
|
|
10198
|
-
const omitted = entries.length - visible.length;
|
|
10199
|
-
if (omitted > 0)
|
|
10200
|
-
rendered.push(`${omitted} more blocking process(es)`);
|
|
10201
|
-
if (rendered.length === 0)
|
|
10202
|
-
return "a live harness process";
|
|
10203
|
-
if (rendered.length === 1)
|
|
10204
|
-
return rendered[0];
|
|
10205
|
-
const last = rendered.pop();
|
|
10206
|
-
return `${rendered.join(", ")}, and ${last}`;
|
|
10207
|
-
}
|
|
10208
|
-
function formatFailClosedBlockingMessage(reason) {
|
|
10209
|
-
if (reason.kind === "migration_guard") {
|
|
10210
|
-
if (reason.unreadableFile) {
|
|
10211
|
-
const arm = reason.unreadableArm ?? "io";
|
|
10212
|
-
const recovery = arm === "io" ? `If no OpenCode server is running, it is safe to delete ${reason.unreadableFile} and retry.` : `The file may be a recent incomplete write; retry after the file is older than the ten-minute grace window, or stop OpenCode before deleting it.`;
|
|
10213
|
-
return [
|
|
10214
|
-
`Magic Context cannot migrate the shared database because RPC discovery file ${reason.unreadableFile} is uncertain (${arm} arm), so the absence of a live OpenCode server cannot be proven.`,
|
|
10215
|
-
recovery,
|
|
10216
|
-
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
10217
|
-
].join(" ");
|
|
10218
|
-
}
|
|
10219
|
-
return [
|
|
10220
|
-
`Magic Context cannot migrate the shared database because ${formatFailClosedBlockingProcesses(reason.blockingProcesses)} may be running an older Magic Context build that would fail against the migrated database.`,
|
|
10221
|
-
"Restart the blocking process (it will pick up the new build and migrate on start), or shut it down and retry.",
|
|
10222
|
-
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
10223
|
-
].join(" ");
|
|
10224
|
-
}
|
|
10225
|
-
if (reason.kind === "schema_fence") {
|
|
10226
|
-
return [
|
|
10227
|
-
`Magic Context cannot operate: this Magic Context build is older than the database; upgrade/restart this harness (upstream migration lane v${reason.persistedVersion}, build supports through v${reason.supportedVersion}).`,
|
|
10228
|
-
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
10229
|
-
].join(" ");
|
|
10230
|
-
}
|
|
10231
|
-
const cause = reason.cause.trim().length > 0 ? reason.cause.trim() : "unknown storage error";
|
|
10232
|
-
return [
|
|
10233
|
-
`Magic Context cannot operate: persistent storage failed (${cause}).`,
|
|
10234
|
-
"The plugin will not silently degrade to native compaction while enabled.",
|
|
10235
|
-
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
10236
|
-
].join(" ");
|
|
10237
|
-
}
|
|
10238
|
-
function createFailClosedBlockingError(reason, options) {
|
|
10239
|
-
return new FailClosedBlockingError(formatFailClosedBlockingMessage(reason), reason, options);
|
|
10240
|
-
}
|
|
10241
|
-
function isFailClosedBlockingError(error) {
|
|
10242
|
-
return error instanceof FailClosedBlockingError || typeof error === "object" && error !== null && error.name === "FailClosedBlockingError" && error.code === "FAIL_CLOSED_BLOCKING";
|
|
10243
|
-
}
|
|
10244
|
-
function shouldBypassFailClosedBlock(input) {
|
|
10245
|
-
if (input.isPiSubagentEnv === true)
|
|
10246
|
-
return true;
|
|
10247
|
-
if (input.isInternalChildSession === true)
|
|
10248
|
-
return true;
|
|
10249
|
-
const agent = typeof input.agent === "string" ? input.agent.trim() : "";
|
|
10250
|
-
if (agent.length === 0)
|
|
10251
|
-
return false;
|
|
10252
|
-
if (OPENCODE_INTERNAL_AGENT_NAMES.has(agent))
|
|
10253
|
-
return true;
|
|
10254
|
-
if (isMagicContextHiddenAgentName(agent))
|
|
10255
|
-
return true;
|
|
10256
|
-
return false;
|
|
10257
|
-
}
|
|
10258
|
-
function resolveAgentNameFromMessages(messages) {
|
|
10259
|
-
for (let i = messages.length - 1;i >= 0; i -= 1) {
|
|
10260
|
-
const info = messages[i]?.info;
|
|
10261
|
-
if (!info || typeof info !== "object")
|
|
10262
|
-
continue;
|
|
10263
|
-
const agent = info.agent;
|
|
10264
|
-
if (typeof agent === "string" && agent.length > 0)
|
|
10265
|
-
return agent;
|
|
10266
|
-
}
|
|
10267
|
-
return;
|
|
10268
|
-
}
|
|
10269
|
-
function createFailClosedController(options) {
|
|
10270
|
-
const reprobeEveryN = Math.max(1, options?.reprobeEveryN ?? FAIL_CLOSED_REPROBE_EVERY_N);
|
|
10271
|
-
let reason = null;
|
|
10272
|
-
let blockedPassCount = 0;
|
|
10273
|
-
return {
|
|
10274
|
-
arm(next) {
|
|
10275
|
-
reason = next;
|
|
10276
|
-
blockedPassCount = 0;
|
|
10277
|
-
},
|
|
10278
|
-
clear() {
|
|
10279
|
-
reason = null;
|
|
10280
|
-
blockedPassCount = 0;
|
|
10281
|
-
},
|
|
10282
|
-
isArmed() {
|
|
10283
|
-
return reason !== null;
|
|
10284
|
-
},
|
|
10285
|
-
getReason() {
|
|
10286
|
-
return reason;
|
|
10287
|
-
},
|
|
10288
|
-
async enforce(input) {
|
|
10289
|
-
if (!reason)
|
|
10290
|
-
return;
|
|
10291
|
-
if (!input.blockingEnabled)
|
|
10292
|
-
return;
|
|
10293
|
-
if (input.exempt)
|
|
10294
|
-
return;
|
|
10295
|
-
blockedPassCount += 1;
|
|
10296
|
-
const shouldReprobe = typeof input.tryReopen === "function" && (blockedPassCount === 1 || blockedPassCount % reprobeEveryN === 0);
|
|
10297
|
-
if (shouldReprobe) {
|
|
10298
|
-
try {
|
|
10299
|
-
const healed = await input.tryReopen?.();
|
|
10300
|
-
if (healed) {
|
|
10301
|
-
reason = null;
|
|
10302
|
-
blockedPassCount = 0;
|
|
10303
|
-
return;
|
|
10304
|
-
}
|
|
10305
|
-
} catch {}
|
|
10306
|
-
}
|
|
10307
|
-
const blockedReason = reason;
|
|
10308
|
-
if (!blockedReason)
|
|
10309
|
-
return;
|
|
10310
|
-
throw createFailClosedBlockingError(blockedReason);
|
|
10311
|
-
}
|
|
10312
|
-
};
|
|
10313
|
-
}
|
|
10314
|
-
var lastHookInitFailure = null;
|
|
10315
|
-
function recordHookInitFailure(failure) {
|
|
10316
|
-
lastHookInitFailure = failure;
|
|
10317
|
-
}
|
|
10318
|
-
function clearHookInitFailure() {
|
|
10319
|
-
lastHookInitFailure = null;
|
|
10320
|
-
}
|
|
10321
|
-
function getLastHookInitFailure() {
|
|
10322
|
-
return lastHookInitFailure;
|
|
10323
|
-
}
|
|
10324
|
-
|
|
10325
10193
|
// src/features/magic-context/session-project-backfill.ts
|
|
10326
10194
|
import { randomUUID } from "node:crypto";
|
|
10327
10195
|
import { existsSync as existsSync4 } from "node:fs";
|
|
@@ -11576,7 +11444,9 @@ var CONNECT_BACKOFF_MAX_MS = 30000;
|
|
|
11576
11444
|
var HANDSHAKE_TIMEOUT_MS = 2000;
|
|
11577
11445
|
var MODULE_SEND_TIMEOUT_MS = 15000;
|
|
11578
11446
|
var TRANSFORM_SEND_TIMEOUT_MS = 5000;
|
|
11447
|
+
var MAX_WRAPUP_REQUEST_BUDGET_MS = 3800000;
|
|
11579
11448
|
var SERIAL_LANE_MAX_WAITERS = 16;
|
|
11449
|
+
var SERIAL_LANE_MAX_WAITERS_PER_SESSION = 8;
|
|
11580
11450
|
var SERIAL_LANE_MIN_REMAINING_MS = 25;
|
|
11581
11451
|
var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
|
|
11582
11452
|
function getDefaultConnectionFile() {
|
|
@@ -11627,6 +11497,9 @@ function isConnectionFailure(error) {
|
|
|
11627
11497
|
].includes(code) || /\bclient closed\b|\bconnection closed\b|\bclosed the connection\b/i.test(message);
|
|
11628
11498
|
});
|
|
11629
11499
|
}
|
|
11500
|
+
function isModuleTransportGenerationChangedResult(value) {
|
|
11501
|
+
return isRecord(value) && value.transport_status === "connection_generation_changed" && typeof value.previous_generation === "number" && typeof value.current_generation === "number";
|
|
11502
|
+
}
|
|
11630
11503
|
|
|
11631
11504
|
class SubcModuleTransport {
|
|
11632
11505
|
connectionFile;
|
|
@@ -11635,10 +11508,13 @@ class SubcModuleTransport {
|
|
|
11635
11508
|
routeSessionPrefix;
|
|
11636
11509
|
client = null;
|
|
11637
11510
|
routes = new Map;
|
|
11511
|
+
routeOpenings = new Map;
|
|
11638
11512
|
canonicalRootCache = new Map;
|
|
11639
|
-
|
|
11513
|
+
sessionLanes = new Map;
|
|
11514
|
+
queuedLaneWaiters = 0;
|
|
11515
|
+
wrapupSessions = new Map;
|
|
11640
11516
|
nextProbeMs = 0;
|
|
11641
|
-
|
|
11517
|
+
connectionPromise = null;
|
|
11642
11518
|
authorityProjectRoot = "";
|
|
11643
11519
|
authorityBindRoot = "";
|
|
11644
11520
|
backoffMs = CONNECT_BACKOFF_INITIAL_MS;
|
|
@@ -11684,6 +11560,11 @@ class SubcModuleTransport {
|
|
|
11684
11560
|
laneTimeoutError() {
|
|
11685
11561
|
return this.deadlineError("while queued");
|
|
11686
11562
|
}
|
|
11563
|
+
connectionChangedError(detail) {
|
|
11564
|
+
const error = new Error(detail);
|
|
11565
|
+
error.code = "ECONNRESET";
|
|
11566
|
+
return error;
|
|
11567
|
+
}
|
|
11687
11568
|
async beforeDeadline(operation, deadlineMs, detail) {
|
|
11688
11569
|
const remainingMs = deadlineMs - Date.now();
|
|
11689
11570
|
if (remainingMs <= 0)
|
|
@@ -11701,22 +11582,30 @@ class SubcModuleTransport {
|
|
|
11701
11582
|
clearTimeout(timer);
|
|
11702
11583
|
}
|
|
11703
11584
|
}
|
|
11704
|
-
|
|
11585
|
+
cleanupLane(sessionId, lane) {
|
|
11586
|
+
if (!lane.active && lane.waiters.length === 0 && this.sessionLanes.get(sessionId) === lane) {
|
|
11587
|
+
this.sessionLanes.delete(sessionId);
|
|
11588
|
+
}
|
|
11589
|
+
}
|
|
11590
|
+
laneRelease(sessionId, lane) {
|
|
11705
11591
|
let released = false;
|
|
11706
11592
|
return () => {
|
|
11707
11593
|
if (released)
|
|
11708
11594
|
return;
|
|
11709
11595
|
released = true;
|
|
11710
|
-
|
|
11711
|
-
this.dispatchNextLaneWaiter();
|
|
11596
|
+
lane.active = false;
|
|
11597
|
+
this.dispatchNextLaneWaiter(sessionId, lane);
|
|
11712
11598
|
};
|
|
11713
11599
|
}
|
|
11714
|
-
dispatchNextLaneWaiter() {
|
|
11715
|
-
if (
|
|
11600
|
+
dispatchNextLaneWaiter(sessionId, lane) {
|
|
11601
|
+
if (lane.active)
|
|
11716
11602
|
return;
|
|
11717
|
-
while (
|
|
11718
|
-
const waiter =
|
|
11719
|
-
if (!waiter
|
|
11603
|
+
while (lane.waiters.length > 0) {
|
|
11604
|
+
const waiter = lane.waiters.shift();
|
|
11605
|
+
if (!waiter)
|
|
11606
|
+
continue;
|
|
11607
|
+
this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
|
|
11608
|
+
if (waiter.settled)
|
|
11720
11609
|
continue;
|
|
11721
11610
|
waiter.settled = true;
|
|
11722
11611
|
clearTimeout(waiter.timer);
|
|
@@ -11729,10 +11618,16 @@ class SubcModuleTransport {
|
|
|
11729
11618
|
waiter.reject(this.laneTimeoutError());
|
|
11730
11619
|
continue;
|
|
11731
11620
|
}
|
|
11732
|
-
|
|
11733
|
-
waiter.resolve(this.laneRelease());
|
|
11621
|
+
lane.active = true;
|
|
11622
|
+
waiter.resolve(this.laneRelease(sessionId, lane));
|
|
11734
11623
|
return;
|
|
11735
11624
|
}
|
|
11625
|
+
this.cleanupLane(sessionId, lane);
|
|
11626
|
+
}
|
|
11627
|
+
queueFullError() {
|
|
11628
|
+
const error = new Error("module transport queue is full");
|
|
11629
|
+
error.code = "EBUSY";
|
|
11630
|
+
return error;
|
|
11736
11631
|
}
|
|
11737
11632
|
acquireCorrectnessLane(sessionId, signal, deadlineMs) {
|
|
11738
11633
|
if (signal?.aborted) {
|
|
@@ -11741,14 +11636,14 @@ class SubcModuleTransport {
|
|
|
11741
11636
|
if (deadlineMs - Date.now() < SERIAL_LANE_MIN_REMAINING_MS) {
|
|
11742
11637
|
return Promise.reject(this.laneTimeoutError());
|
|
11743
11638
|
}
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11639
|
+
const lane = this.sessionLanes.get(sessionId) ?? { active: false, waiters: [] };
|
|
11640
|
+
this.sessionLanes.set(sessionId, lane);
|
|
11641
|
+
if (!lane.active && lane.waiters.length === 0) {
|
|
11642
|
+
lane.active = true;
|
|
11643
|
+
return Promise.resolve(this.laneRelease(sessionId, lane));
|
|
11747
11644
|
}
|
|
11748
|
-
if (this.
|
|
11749
|
-
|
|
11750
|
-
error.code = "EBUSY";
|
|
11751
|
-
return Promise.reject(error);
|
|
11645
|
+
if (this.queuedLaneWaiters >= SERIAL_LANE_MAX_WAITERS || lane.waiters.length >= SERIAL_LANE_MAX_WAITERS_PER_SESSION) {
|
|
11646
|
+
return Promise.reject(this.queueFullError());
|
|
11752
11647
|
}
|
|
11753
11648
|
return new Promise((resolve3, reject) => {
|
|
11754
11649
|
const waiter = {};
|
|
@@ -11758,14 +11653,14 @@ class SubcModuleTransport {
|
|
|
11758
11653
|
waiter.settled = true;
|
|
11759
11654
|
clearTimeout(waiter.timer);
|
|
11760
11655
|
signal?.removeEventListener("abort", waiter.onAbort);
|
|
11761
|
-
const index =
|
|
11762
|
-
if (index >= 0)
|
|
11763
|
-
|
|
11656
|
+
const index = lane.waiters.indexOf(waiter);
|
|
11657
|
+
if (index >= 0) {
|
|
11658
|
+
lane.waiters.splice(index, 1);
|
|
11659
|
+
this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
|
|
11660
|
+
}
|
|
11764
11661
|
reject(error);
|
|
11765
|
-
|
|
11766
|
-
this.dispatchNextLaneWaiter();
|
|
11662
|
+
this.cleanupLane(sessionId, lane);
|
|
11767
11663
|
};
|
|
11768
|
-
waiter.sessionId = sessionId;
|
|
11769
11664
|
waiter.signal = signal;
|
|
11770
11665
|
waiter.deadlineMs = deadlineMs;
|
|
11771
11666
|
waiter.resolve = resolve3;
|
|
@@ -11774,17 +11669,40 @@ class SubcModuleTransport {
|
|
|
11774
11669
|
waiter.onAbort = () => removeAndReject(signal?.reason ?? new Error("module transport call aborted"));
|
|
11775
11670
|
waiter.timer = setTimeout(() => removeAndReject(this.laneTimeoutError()), Math.max(0, deadlineMs - Date.now()));
|
|
11776
11671
|
signal?.addEventListener("abort", waiter.onAbort, { once: true });
|
|
11777
|
-
|
|
11672
|
+
lane.waiters.push(waiter);
|
|
11673
|
+
this.queuedLaneWaiters += 1;
|
|
11778
11674
|
});
|
|
11779
11675
|
}
|
|
11780
11676
|
async call(args) {
|
|
11781
|
-
const
|
|
11677
|
+
const wrapupInFlight = (this.wrapupSessions.get(args.sessionId) ?? 0) > 0;
|
|
11678
|
+
const attemptTimeoutMs = args.timeoutMs ?? (args.method === "session.wrapup" || args.method === "session.status" && wrapupInFlight ? MAX_WRAPUP_REQUEST_BUDGET_MS : args.method === "transform" ? Math.min(this.requestTimeoutMs, TRANSFORM_SEND_TIMEOUT_MS) : this.requestTimeoutMs);
|
|
11679
|
+
const tracksWrapup = args.method === "session.wrapup";
|
|
11680
|
+
if (tracksWrapup) {
|
|
11681
|
+
this.wrapupSessions.set(args.sessionId, (this.wrapupSessions.get(args.sessionId) ?? 0) + 1);
|
|
11682
|
+
}
|
|
11683
|
+
const finishWrapupTracking = () => {
|
|
11684
|
+
if (!tracksWrapup)
|
|
11685
|
+
return;
|
|
11686
|
+
const remaining = (this.wrapupSessions.get(args.sessionId) ?? 1) - 1;
|
|
11687
|
+
if (remaining > 0)
|
|
11688
|
+
this.wrapupSessions.set(args.sessionId, remaining);
|
|
11689
|
+
else
|
|
11690
|
+
this.wrapupSessions.delete(args.sessionId);
|
|
11691
|
+
};
|
|
11782
11692
|
const laneDeadlineMs = Date.now() + attemptTimeoutMs;
|
|
11783
|
-
|
|
11784
|
-
|
|
11693
|
+
let releaseLane;
|
|
11694
|
+
try {
|
|
11695
|
+
releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, laneDeadlineMs);
|
|
11696
|
+
} catch (error) {
|
|
11697
|
+
finishWrapupTracking();
|
|
11698
|
+
throw error;
|
|
11699
|
+
}
|
|
11700
|
+
let activeAttemptClient = null;
|
|
11701
|
+
const onAbort = () => this.invalidateConnection(activeAttemptClient ?? this.client);
|
|
11785
11702
|
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
11786
11703
|
try {
|
|
11787
11704
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
11705
|
+
activeAttemptClient = null;
|
|
11788
11706
|
let ensuredRoute = null;
|
|
11789
11707
|
try {
|
|
11790
11708
|
if (args.signal?.aborted) {
|
|
@@ -11792,22 +11710,35 @@ class SubcModuleTransport {
|
|
|
11792
11710
|
}
|
|
11793
11711
|
const attemptDeadlineMs = Date.now() + attemptTimeoutMs;
|
|
11794
11712
|
ensuredRoute = await this.ensureRoute(args.sessionId, args.projectRoot, attemptDeadlineMs);
|
|
11713
|
+
activeAttemptClient = ensuredRoute.client;
|
|
11795
11714
|
if (args.signal?.aborted) {
|
|
11796
11715
|
throw args.signal.reason ?? new Error("module transport call aborted");
|
|
11797
11716
|
}
|
|
11798
|
-
|
|
11717
|
+
const response = await this.beforeDeadline(ensuredRoute.client.request(ensuredRoute.route, args.body, {
|
|
11799
11718
|
priority: Priority.Background,
|
|
11800
11719
|
admissionClass: AdmissionClass.Normal,
|
|
11801
11720
|
timeoutMs: Math.max(1, attemptDeadlineMs - Date.now())
|
|
11802
11721
|
}), attemptDeadlineMs, "waiting for the module response");
|
|
11722
|
+
if (this.client !== ensuredRoute.client || this.connectionGeneration !== ensuredRoute.generation) {
|
|
11723
|
+
throw this.connectionChangedError("subc connection changed while awaiting the module response");
|
|
11724
|
+
}
|
|
11725
|
+
return response;
|
|
11803
11726
|
} catch (error) {
|
|
11804
11727
|
if (isConnectionFailure(error)) {
|
|
11728
|
+
const previousGeneration = ensuredRoute?.generation ?? this.connectionGeneration;
|
|
11805
11729
|
if (ensuredRoute) {
|
|
11806
11730
|
this.dropRoute(ensuredRoute.routeKey, ensuredRoute.route);
|
|
11807
11731
|
this.invalidateConnection(ensuredRoute.client);
|
|
11808
11732
|
} else {
|
|
11809
11733
|
this.invalidateConnection();
|
|
11810
11734
|
}
|
|
11735
|
+
if (args.generationSensitive && !args.signal?.aborted) {
|
|
11736
|
+
return {
|
|
11737
|
+
transport_status: "connection_generation_changed",
|
|
11738
|
+
previous_generation: previousGeneration,
|
|
11739
|
+
current_generation: this.connectionGeneration
|
|
11740
|
+
};
|
|
11741
|
+
}
|
|
11811
11742
|
if (attempt === 0 && !args.signal?.aborted)
|
|
11812
11743
|
continue;
|
|
11813
11744
|
}
|
|
@@ -11817,6 +11748,7 @@ class SubcModuleTransport {
|
|
|
11817
11748
|
throw new Error("module transport route retry exhausted");
|
|
11818
11749
|
} finally {
|
|
11819
11750
|
args.signal?.removeEventListener("abort", onAbort);
|
|
11751
|
+
finishWrapupTracking();
|
|
11820
11752
|
releaseLane();
|
|
11821
11753
|
}
|
|
11822
11754
|
}
|
|
@@ -11907,7 +11839,7 @@ class SubcModuleTransport {
|
|
|
11907
11839
|
});
|
|
11908
11840
|
}
|
|
11909
11841
|
}
|
|
11910
|
-
if (routes.length === 0 && this.
|
|
11842
|
+
if (routes.length === 0 && this.sessionLanes.get(sessionId)?.active) {
|
|
11911
11843
|
this.invalidateConnection(client);
|
|
11912
11844
|
}
|
|
11913
11845
|
}
|
|
@@ -11922,23 +11854,36 @@ class SubcModuleTransport {
|
|
|
11922
11854
|
}
|
|
11923
11855
|
if (existing)
|
|
11924
11856
|
this.routes.delete(routeKey);
|
|
11925
|
-
const
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
}
|
|
11936
|
-
const
|
|
11937
|
-
|
|
11938
|
-
|
|
11857
|
+
const opening = this.routeOpenings.get(routeKey);
|
|
11858
|
+
if (opening?.client === client && opening.generation === generation) {
|
|
11859
|
+
return await opening.promise;
|
|
11860
|
+
}
|
|
11861
|
+
const promise = (async () => {
|
|
11862
|
+
const target = { kind: "tool_provider", module_id: this.moduleId };
|
|
11863
|
+
const identity = {
|
|
11864
|
+
project_root: projectRoot,
|
|
11865
|
+
harness: getHarness(),
|
|
11866
|
+
session: `${this.routeSessionPrefix}${sessionId}`
|
|
11867
|
+
};
|
|
11868
|
+
const route = await this.beforeDeadline(client.routeOpen(target, identity), deadlineMs, "opening the module route");
|
|
11869
|
+
if (this.client !== client || generation !== this.connectionGeneration) {
|
|
11870
|
+
await client.closeRoute(route).catch(() => {
|
|
11871
|
+
return;
|
|
11872
|
+
});
|
|
11873
|
+
throw this.connectionChangedError("subc connection changed while opening module route");
|
|
11874
|
+
}
|
|
11875
|
+
this.routes.set(routeKey, { route, generation });
|
|
11876
|
+
return { client, route, routeKey, generation };
|
|
11877
|
+
})();
|
|
11878
|
+
const routeOpening = { client, generation, promise };
|
|
11879
|
+
this.routeOpenings.set(routeKey, routeOpening);
|
|
11880
|
+
try {
|
|
11881
|
+
return await promise;
|
|
11882
|
+
} finally {
|
|
11883
|
+
if (this.routeOpenings.get(routeKey) === routeOpening) {
|
|
11884
|
+
this.routeOpenings.delete(routeKey);
|
|
11885
|
+
}
|
|
11939
11886
|
}
|
|
11940
|
-
this.routes.set(routeKey, { route, generation });
|
|
11941
|
-
return { client, route, routeKey, generation };
|
|
11942
11887
|
}
|
|
11943
11888
|
dropRoute(routeKey, route) {
|
|
11944
11889
|
const existing = this.routes.get(routeKey);
|
|
@@ -11966,9 +11911,17 @@ class SubcModuleTransport {
|
|
|
11966
11911
|
}
|
|
11967
11912
|
return resolved;
|
|
11968
11913
|
}
|
|
11914
|
+
connectClient() {
|
|
11915
|
+
return SubcClient.connect({
|
|
11916
|
+
connectionFile: this.connectionFile,
|
|
11917
|
+
handshakeTimeoutMs: HANDSHAKE_TIMEOUT_MS
|
|
11918
|
+
});
|
|
11919
|
+
}
|
|
11969
11920
|
async ensureConnected() {
|
|
11970
11921
|
if (this.client)
|
|
11971
11922
|
return this.client;
|
|
11923
|
+
if (this.connectionPromise)
|
|
11924
|
+
return await this.connectionPromise;
|
|
11972
11925
|
const now = Date.now();
|
|
11973
11926
|
if (now < this.nextProbeMs) {
|
|
11974
11927
|
const error = new Error(`subc connection backoff active until ${this.nextProbeMs}`);
|
|
@@ -11976,38 +11929,44 @@ class SubcModuleTransport {
|
|
|
11976
11929
|
throw error;
|
|
11977
11930
|
}
|
|
11978
11931
|
const generation = this.connectionGeneration;
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
11988
|
-
|
|
11932
|
+
const connecting = (async () => {
|
|
11933
|
+
let candidate = null;
|
|
11934
|
+
try {
|
|
11935
|
+
candidate = await this.connectClient();
|
|
11936
|
+
if (generation !== this.connectionGeneration) {
|
|
11937
|
+
candidate.close();
|
|
11938
|
+
throw this.connectionChangedError("subc connection attempt was superseded");
|
|
11939
|
+
}
|
|
11940
|
+
this.client = candidate;
|
|
11941
|
+
this.routes.clear();
|
|
11942
|
+
this.backoffMs = CONNECT_BACKOFF_INITIAL_MS;
|
|
11943
|
+
this.nextProbeMs = 0;
|
|
11944
|
+
return candidate;
|
|
11945
|
+
} catch (error) {
|
|
11946
|
+
candidate?.close();
|
|
11947
|
+
if (generation === this.connectionGeneration)
|
|
11948
|
+
this.invalidateConnection();
|
|
11949
|
+
this.nextProbeMs = Date.now() + this.backoffMs;
|
|
11950
|
+
this.backoffMs = Math.min(this.backoffMs * 2, CONNECT_BACKOFF_MAX_MS);
|
|
11989
11951
|
throw error;
|
|
11990
11952
|
}
|
|
11991
|
-
|
|
11992
|
-
|
|
11993
|
-
|
|
11994
|
-
|
|
11995
|
-
|
|
11996
|
-
|
|
11997
|
-
|
|
11998
|
-
this.invalidateConnection();
|
|
11999
|
-
this.nextProbeMs = Date.now() + this.backoffMs;
|
|
12000
|
-
this.backoffMs = Math.min(this.backoffMs * 2, CONNECT_BACKOFF_MAX_MS);
|
|
12001
|
-
throw error;
|
|
11953
|
+
})();
|
|
11954
|
+
this.connectionPromise = connecting;
|
|
11955
|
+
try {
|
|
11956
|
+
return await connecting;
|
|
11957
|
+
} finally {
|
|
11958
|
+
if (this.connectionPromise === connecting)
|
|
11959
|
+
this.connectionPromise = null;
|
|
12002
11960
|
}
|
|
12003
11961
|
}
|
|
12004
11962
|
invalidateConnection(client = this.client) {
|
|
12005
|
-
if (client && this.client
|
|
11963
|
+
if (client && this.client !== client)
|
|
12006
11964
|
return;
|
|
12007
11965
|
this.connectionGeneration += 1;
|
|
12008
11966
|
this.invalidateStateSyncCapabilities();
|
|
12009
11967
|
this.client = null;
|
|
12010
11968
|
this.routes.clear();
|
|
11969
|
+
this.routeOpenings.clear();
|
|
12011
11970
|
client?.close();
|
|
12012
11971
|
}
|
|
12013
11972
|
}
|
|
@@ -12062,13 +12021,15 @@ function rowKeys(leaseKey) {
|
|
|
12062
12021
|
return {
|
|
12063
12022
|
holder: "dreaming_lease_holder",
|
|
12064
12023
|
heartbeat: "dreaming_lease_heartbeat",
|
|
12065
|
-
expiry: "dreaming_lease_expiry"
|
|
12024
|
+
expiry: "dreaming_lease_expiry",
|
|
12025
|
+
generation: "dreaming_lease_generation"
|
|
12066
12026
|
};
|
|
12067
12027
|
}
|
|
12068
12028
|
return {
|
|
12069
12029
|
holder: `lease:${leaseKey}:holder`,
|
|
12070
12030
|
heartbeat: `lease:${leaseKey}:heartbeat`,
|
|
12071
|
-
expiry: `lease:${leaseKey}:expiry
|
|
12031
|
+
expiry: `lease:${leaseKey}:expiry`,
|
|
12032
|
+
generation: `lease:${leaseKey}:generation`
|
|
12072
12033
|
};
|
|
12073
12034
|
}
|
|
12074
12035
|
function getLeaseExpiry(db, keys) {
|
|
@@ -12086,6 +12047,13 @@ function isLeaseActive(db, leaseKey = DREAMING_LEASE_KEY) {
|
|
|
12086
12047
|
function getLeaseHolder(db, leaseKey = DREAMING_LEASE_KEY) {
|
|
12087
12048
|
return getDreamState(db, rowKeys(leaseKey).holder);
|
|
12088
12049
|
}
|
|
12050
|
+
function getLeaseGeneration(db, leaseKey = DREAMING_LEASE_KEY) {
|
|
12051
|
+
const value = getDreamState(db, rowKeys(leaseKey).generation);
|
|
12052
|
+
if (!value)
|
|
12053
|
+
return null;
|
|
12054
|
+
const generation = Number(value);
|
|
12055
|
+
return Number.isSafeInteger(generation) && generation > 0 ? generation : null;
|
|
12056
|
+
}
|
|
12089
12057
|
function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_KEY) {
|
|
12090
12058
|
const keys = rowKeys(leaseKey);
|
|
12091
12059
|
const holder = getDreamState(db, keys.holder);
|
|
@@ -12097,6 +12065,9 @@ function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_
|
|
|
12097
12065
|
const expiry = Number(expiryStr);
|
|
12098
12066
|
return Number.isFinite(expiry) && expiry >= Date.now();
|
|
12099
12067
|
}
|
|
12068
|
+
function leaseOwnershipMatches(db, expectedHolder, expectedGeneration, leaseKey = DREAMING_LEASE_KEY) {
|
|
12069
|
+
return getLeaseGeneration(db, leaseKey) === expectedGeneration && peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey);
|
|
12070
|
+
}
|
|
12100
12071
|
function runImmediate(db, body) {
|
|
12101
12072
|
db.exec("BEGIN IMMEDIATE");
|
|
12102
12073
|
let committed = false;
|
|
@@ -12113,26 +12084,30 @@ function runImmediate(db, body) {
|
|
|
12113
12084
|
}
|
|
12114
12085
|
}
|
|
12115
12086
|
}
|
|
12116
|
-
function
|
|
12087
|
+
function acquireLeaseWithAcquisition(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
12117
12088
|
const keys = rowKeys(leaseKey);
|
|
12118
12089
|
return runImmediate(db, () => {
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
return false;
|
|
12123
|
-
}
|
|
12090
|
+
const existingHolder = getLeaseHolder(db, leaseKey);
|
|
12091
|
+
if (isLeaseActive(db, leaseKey) && existingHolder && existingHolder !== holderId) {
|
|
12092
|
+
return null;
|
|
12124
12093
|
}
|
|
12125
12094
|
const now = Date.now();
|
|
12095
|
+
const priorGeneration = getLeaseGeneration(db, leaseKey) ?? 0;
|
|
12096
|
+
const generation = existingHolder === holderId ? Math.max(1, priorGeneration) : priorGeneration + 1;
|
|
12126
12097
|
setDreamState(db, keys.holder, holderId);
|
|
12127
12098
|
setDreamState(db, keys.heartbeat, String(now));
|
|
12128
12099
|
setDreamState(db, keys.expiry, String(now + LEASE_DURATION_MS));
|
|
12129
|
-
|
|
12100
|
+
setDreamState(db, keys.generation, String(generation));
|
|
12101
|
+
return { acquiredAt: now, generation };
|
|
12130
12102
|
});
|
|
12131
12103
|
}
|
|
12132
|
-
function
|
|
12104
|
+
function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
12105
|
+
return acquireLeaseWithAcquisition(db, holderId, leaseKey) !== null;
|
|
12106
|
+
}
|
|
12107
|
+
function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY, expectedGeneration) {
|
|
12133
12108
|
const keys = rowKeys(leaseKey);
|
|
12134
12109
|
return runImmediate(db, () => {
|
|
12135
|
-
if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey)) {
|
|
12110
|
+
if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey) || expectedGeneration !== undefined && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
|
|
12136
12111
|
return false;
|
|
12137
12112
|
}
|
|
12138
12113
|
const now = Date.now();
|
|
@@ -12150,9 +12125,12 @@ function runLeaseGuardedWrite(db, holderId, leaseKey, fn) {
|
|
|
12150
12125
|
});
|
|
12151
12126
|
}
|
|
12152
12127
|
var LEASE_HEARTBEAT_INTERVAL_MS = 60 * 1000;
|
|
12153
|
-
function startLeaseHeartbeat(db, holderId, leaseKey, onLost,
|
|
12128
|
+
function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisition = LEASE_HEARTBEAT_INTERVAL_MS) {
|
|
12129
|
+
const intervalMs = typeof intervalOrAcquisition === "number" ? intervalOrAcquisition : LEASE_HEARTBEAT_INTERVAL_MS;
|
|
12130
|
+
const acquisition = typeof intervalOrAcquisition === "number" ? undefined : intervalOrAcquisition;
|
|
12154
12131
|
let lost = false;
|
|
12155
|
-
let
|
|
12132
|
+
let expectedGeneration = acquisition?.generation ?? getLeaseGeneration(db, leaseKey);
|
|
12133
|
+
let lastConfirmedAt = acquisition?.acquiredAt ?? Date.now();
|
|
12156
12134
|
const declareLost = (reason) => {
|
|
12157
12135
|
if (lost)
|
|
12158
12136
|
return;
|
|
@@ -12163,15 +12141,25 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_
|
|
|
12163
12141
|
if (lost)
|
|
12164
12142
|
return;
|
|
12165
12143
|
try {
|
|
12166
|
-
if (renewLease(db, holderId, leaseKey)) {
|
|
12144
|
+
if (renewLease(db, holderId, leaseKey, expectedGeneration === null ? undefined : expectedGeneration)) {
|
|
12167
12145
|
lastConfirmedAt = Date.now();
|
|
12168
12146
|
return;
|
|
12169
12147
|
}
|
|
12148
|
+
if (expectedGeneration !== null && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
|
|
12149
|
+
declareLost("lease generation changed — another holder acquired it");
|
|
12150
|
+
return;
|
|
12151
|
+
}
|
|
12170
12152
|
if (Date.now() - lastConfirmedAt > LEASE_DURATION_MS) {
|
|
12171
12153
|
declareLost("lease lapsed past TTL — another holder may have run");
|
|
12172
12154
|
return;
|
|
12173
12155
|
}
|
|
12174
|
-
|
|
12156
|
+
const reacquired = acquireLeaseWithAcquisition(db, holderId, leaseKey);
|
|
12157
|
+
if (reacquired) {
|
|
12158
|
+
if (expectedGeneration !== null && reacquired.generation !== expectedGeneration) {
|
|
12159
|
+
declareLost("lease generation changed during reacquisition");
|
|
12160
|
+
return;
|
|
12161
|
+
}
|
|
12162
|
+
expectedGeneration = reacquired.generation;
|
|
12175
12163
|
lastConfirmedAt = Date.now();
|
|
12176
12164
|
return;
|
|
12177
12165
|
}
|
|
@@ -12678,7 +12666,7 @@ var DREAMER_DOCS_AGENT = "dreamer-docs";
|
|
|
12678
12666
|
var DREAMER_REVIEWER_AGENT = "dreamer-reviewer";
|
|
12679
12667
|
|
|
12680
12668
|
// src/features/magic-context/mural/compress-cues.ts
|
|
12681
|
-
import { createHash as
|
|
12669
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
12682
12670
|
|
|
12683
12671
|
// src/features/magic-context/dreamer/manifest-parser.ts
|
|
12684
12672
|
function extractCompleteManifestBody(text, rootName) {
|
|
@@ -12714,6 +12702,16 @@ function assertManifestCoversExactly(ids, expectedIds, rootName) {
|
|
|
12714
12702
|
}
|
|
12715
12703
|
|
|
12716
12704
|
// src/features/magic-context/dreamer/module-apply.ts
|
|
12705
|
+
class DreamerModuleBusyError extends Error {
|
|
12706
|
+
state;
|
|
12707
|
+
transient = true;
|
|
12708
|
+
constructor(state) {
|
|
12709
|
+
super(`Rust memory authority is ${state}; dreamer mutation deferred until authority settles.`);
|
|
12710
|
+
this.state = state;
|
|
12711
|
+
this.name = "DreamerModuleBusyError";
|
|
12712
|
+
}
|
|
12713
|
+
}
|
|
12714
|
+
|
|
12717
12715
|
class DreamerModuleFailureError extends Error {
|
|
12718
12716
|
transient = true;
|
|
12719
12717
|
constructor(operation, cause) {
|
|
@@ -12735,9 +12733,12 @@ async function resolveDreamerModuleRoute(args) {
|
|
|
12735
12733
|
projectRoot: args.projectRoot,
|
|
12736
12734
|
domain: "memories"
|
|
12737
12735
|
});
|
|
12738
|
-
|
|
12736
|
+
const authority = result.authority;
|
|
12737
|
+
if (authority?.state === "DRAINING")
|
|
12738
|
+
throw new DreamerModuleBusyError(authority.state);
|
|
12739
|
+
if (authority?.state !== "MODULE")
|
|
12739
12740
|
return;
|
|
12740
|
-
const generation =
|
|
12741
|
+
const generation = authority.generation;
|
|
12741
12742
|
if (typeof generation !== "number")
|
|
12742
12743
|
throw new Error("Rust authority status omitted generation");
|
|
12743
12744
|
return {
|
|
@@ -12771,6 +12772,68 @@ function getModuleMemoryIdentities(db, projectIdentity, contextIds) {
|
|
|
12771
12772
|
] : []));
|
|
12772
12773
|
}
|
|
12773
12774
|
|
|
12775
|
+
// src/features/magic-context/dreamer/provider-output-failure.ts
|
|
12776
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
12777
|
+
var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
|
|
12778
|
+
|
|
12779
|
+
class DreamerProviderOutputFailureError extends Error {
|
|
12780
|
+
fingerprint;
|
|
12781
|
+
outputTokens;
|
|
12782
|
+
reasoningTokens;
|
|
12783
|
+
transient = true;
|
|
12784
|
+
constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
|
|
12785
|
+
const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
|
|
12786
|
+
super(`dreamer provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
|
|
12787
|
+
this.fingerprint = fingerprint;
|
|
12788
|
+
this.outputTokens = outputTokens;
|
|
12789
|
+
this.reasoningTokens = reasoningTokens;
|
|
12790
|
+
this.name = "DreamerProviderOutputFailureError";
|
|
12791
|
+
}
|
|
12792
|
+
}
|
|
12793
|
+
function finiteTokenCount(value) {
|
|
12794
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
12795
|
+
}
|
|
12796
|
+
function completionShape(value) {
|
|
12797
|
+
if (!isRecord(value))
|
|
12798
|
+
return null;
|
|
12799
|
+
const info = isRecord(value.info) ? value.info : value;
|
|
12800
|
+
if (info.role !== "assistant")
|
|
12801
|
+
return null;
|
|
12802
|
+
const time = isRecord(info.time) ? info.time : null;
|
|
12803
|
+
const tokens = isRecord(info.tokens) ? info.tokens : null;
|
|
12804
|
+
return {
|
|
12805
|
+
createdAt: typeof time?.created === "number" ? time.created : 0,
|
|
12806
|
+
finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
|
|
12807
|
+
error: info.error,
|
|
12808
|
+
outputTokens: finiteTokenCount(tokens?.output),
|
|
12809
|
+
reasoningTokens: finiteTokenCount(tokens?.reasoning)
|
|
12810
|
+
};
|
|
12811
|
+
}
|
|
12812
|
+
function latestAssistantCompletion(messages) {
|
|
12813
|
+
if (!Array.isArray(messages))
|
|
12814
|
+
return null;
|
|
12815
|
+
let latest = null;
|
|
12816
|
+
for (const message of messages) {
|
|
12817
|
+
const completion = completionShape(message);
|
|
12818
|
+
if (completion && (!latest || completion.createdAt >= latest.createdAt))
|
|
12819
|
+
latest = completion;
|
|
12820
|
+
}
|
|
12821
|
+
return latest;
|
|
12822
|
+
}
|
|
12823
|
+
function providerOutputFailureFromInvalidManifest(messages, responseText) {
|
|
12824
|
+
const completion = latestAssistantCompletion(messages);
|
|
12825
|
+
if (completion?.finish?.toLowerCase() !== "stop")
|
|
12826
|
+
return null;
|
|
12827
|
+
if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
|
|
12828
|
+
return null;
|
|
12829
|
+
}
|
|
12830
|
+
const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
|
|
12831
|
+
if (!normalized)
|
|
12832
|
+
return null;
|
|
12833
|
+
const fingerprint = createHash2("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
12834
|
+
return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
|
|
12835
|
+
}
|
|
12836
|
+
|
|
12774
12837
|
// src/features/magic-context/mural/compress-cues-prompt.ts
|
|
12775
12838
|
var CUE_BUDGET_HIGH = 90;
|
|
12776
12839
|
var CUE_BUDGET_LOW = 50;
|
|
@@ -12943,7 +13006,7 @@ async function runCompressCues(args) {
|
|
|
12943
13006
|
chunks.push(candidates.slice(i, i + COMPRESS_CUES_CHUNK_SIZE));
|
|
12944
13007
|
}
|
|
12945
13008
|
const abortController = new AbortController;
|
|
12946
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
|
|
13009
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
12947
13010
|
try {
|
|
12948
13011
|
let consecutiveTimeouts = 0;
|
|
12949
13012
|
let timeoutStreakElapsedMs = [];
|
|
@@ -13038,7 +13101,14 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
13038
13101
|
const text = extractLatestAssistantText(messages);
|
|
13039
13102
|
if (!text)
|
|
13040
13103
|
throw new Error("compress-cues returned no output");
|
|
13041
|
-
|
|
13104
|
+
try {
|
|
13105
|
+
parseCuesManifest(text);
|
|
13106
|
+
} catch (error) {
|
|
13107
|
+
const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
|
|
13108
|
+
if (providerFailure)
|
|
13109
|
+
throw providerFailure;
|
|
13110
|
+
throw error;
|
|
13111
|
+
}
|
|
13042
13112
|
return text;
|
|
13043
13113
|
}
|
|
13044
13114
|
});
|
|
@@ -13046,7 +13116,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
13046
13116
|
} catch (error) {
|
|
13047
13117
|
const desc = describeError(error);
|
|
13048
13118
|
log(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
13049
|
-
if (signal.aborted)
|
|
13119
|
+
if (signal.aborted || error instanceof DreamerProviderOutputFailureError)
|
|
13050
13120
|
throw error;
|
|
13051
13121
|
return {
|
|
13052
13122
|
compressed: 0,
|
|
@@ -13154,7 +13224,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
|
|
|
13154
13224
|
log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
|
|
13155
13225
|
}
|
|
13156
13226
|
}
|
|
13157
|
-
const commandId = `mural-cues:${route.moduleCommandId}:${
|
|
13227
|
+
const commandId = `mural-cues:${route.moduleCommandId}:${createHash3("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
|
|
13158
13228
|
let response;
|
|
13159
13229
|
try {
|
|
13160
13230
|
response = await route.moduleClient.call({
|
|
@@ -13291,7 +13361,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
13291
13361
|
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, leaseKey, (reason) => {
|
|
13292
13362
|
log(`[dreamer] user-memories: lease lost (${reason}) — aborting`);
|
|
13293
13363
|
abortController.abort();
|
|
13294
|
-
});
|
|
13364
|
+
}, args.leaseAcquisition);
|
|
13295
13365
|
try {
|
|
13296
13366
|
const createResponse = await createChildSessionWithFence({
|
|
13297
13367
|
client: args.client,
|
|
@@ -13414,7 +13484,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
13414
13484
|
}
|
|
13415
13485
|
|
|
13416
13486
|
// src/features/magic-context/dreamer/classify.ts
|
|
13417
|
-
import { createHash as
|
|
13487
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
13418
13488
|
|
|
13419
13489
|
// src/plugin/rust-tool-backends.ts
|
|
13420
13490
|
function toolCallIdFromContext(context) {
|
|
@@ -13816,7 +13886,7 @@ async function runClassify(args) {
|
|
|
13816
13886
|
chunks.push(toClassify.slice(i, i + CLASSIFY_CHUNK_SIZE));
|
|
13817
13887
|
}
|
|
13818
13888
|
const abortController = new AbortController;
|
|
13819
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
|
|
13889
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
13820
13890
|
try {
|
|
13821
13891
|
for (let i = 0;i < chunks.length; i += 1) {
|
|
13822
13892
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
@@ -13896,7 +13966,14 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
13896
13966
|
const text = extractLatestAssistantText(messages);
|
|
13897
13967
|
if (!text)
|
|
13898
13968
|
throw new Error("classify returned no output");
|
|
13899
|
-
|
|
13969
|
+
try {
|
|
13970
|
+
parseClassifyManifest(text);
|
|
13971
|
+
} catch (error) {
|
|
13972
|
+
const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
|
|
13973
|
+
if (providerFailure)
|
|
13974
|
+
throw providerFailure;
|
|
13975
|
+
throw error;
|
|
13976
|
+
}
|
|
13900
13977
|
return text;
|
|
13901
13978
|
}
|
|
13902
13979
|
});
|
|
@@ -13907,7 +13984,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
13907
13984
|
const desc = describeError(failure);
|
|
13908
13985
|
log(`[dreamer] classify chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
13909
13986
|
recordInvocation(args, startedAt, { status: "failed", error: failure });
|
|
13910
|
-
if (moduleRoute || signal.aborted)
|
|
13987
|
+
if (moduleRoute || signal.aborted || failure instanceof DreamerProviderOutputFailureError)
|
|
13911
13988
|
throw failure;
|
|
13912
13989
|
return { classified: 0, changed: 0 };
|
|
13913
13990
|
} finally {
|
|
@@ -13936,7 +14013,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
13936
14013
|
v: 1,
|
|
13937
14014
|
session_id: args.moduleSessionId,
|
|
13938
14015
|
task: "classify",
|
|
13939
|
-
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${
|
|
14016
|
+
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash4("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
|
|
13940
14017
|
authority_generation: args.moduleAuthorityGeneration,
|
|
13941
14018
|
payload: {
|
|
13942
14019
|
prompt_body: prompt,
|
|
@@ -14632,7 +14709,7 @@ function throwIfAborted2(signal) {
|
|
|
14632
14709
|
}
|
|
14633
14710
|
|
|
14634
14711
|
// src/features/magic-context/smart-notes/compiler.ts
|
|
14635
|
-
import { createHash as
|
|
14712
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
14636
14713
|
|
|
14637
14714
|
// src/features/magic-context/smart-notes/sandbox-runner.ts
|
|
14638
14715
|
var asyncModulePromise = null;
|
|
@@ -15026,7 +15103,7 @@ function manifestAdvisoryWarnings(code, manifest) {
|
|
|
15026
15103
|
return warnings;
|
|
15027
15104
|
}
|
|
15028
15105
|
function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
|
|
15029
|
-
return
|
|
15106
|
+
return createHash5("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
|
|
15030
15107
|
}
|
|
15031
15108
|
function extractJsonObject(output) {
|
|
15032
15109
|
const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
@@ -15414,7 +15491,7 @@ async function evaluateSmartNotes(args) {
|
|
|
15414
15491
|
leaseAbortController.abort(new Error("Dream lease lost during smart notes"));
|
|
15415
15492
|
log("[dreamer] smart notes: lease lost — aborting");
|
|
15416
15493
|
args.onLeaseLost?.("smart notes");
|
|
15417
|
-
});
|
|
15494
|
+
}, args.leaseAcquisition);
|
|
15418
15495
|
let surfaced = 0;
|
|
15419
15496
|
let didWork = false;
|
|
15420
15497
|
try {
|
|
@@ -15855,7 +15932,7 @@ function enforceMaintainDocsProtectedRegions(args) {
|
|
|
15855
15932
|
}
|
|
15856
15933
|
|
|
15857
15934
|
// src/features/magic-context/dreamer/map-memories.ts
|
|
15858
|
-
import { createHash as
|
|
15935
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
15859
15936
|
|
|
15860
15937
|
// src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
15861
15938
|
import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
|
|
@@ -15972,7 +16049,7 @@ async function mapMemories(args) {
|
|
|
15972
16049
|
}
|
|
15973
16050
|
result.remaining = inputs.length;
|
|
15974
16051
|
const abortController = new AbortController;
|
|
15975
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
|
|
16052
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
15976
16053
|
try {
|
|
15977
16054
|
for (let i = 0;i < batches.length; i += 1) {
|
|
15978
16055
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
@@ -16116,7 +16193,7 @@ async function applyBatchMappings(args, batch, manifestText) {
|
|
|
16116
16193
|
memory_project: args.projectIdentity,
|
|
16117
16194
|
context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
|
|
16118
16195
|
authority_generation: args.moduleRoute.moduleAuthorityGeneration,
|
|
16119
|
-
command_id: `${args.moduleRoute.moduleCommandId}:${
|
|
16196
|
+
command_id: `${args.moduleRoute.moduleCommandId}:${createHash6("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
|
|
16120
16197
|
rows
|
|
16121
16198
|
}
|
|
16122
16199
|
}
|
|
@@ -16341,7 +16418,7 @@ async function promotePrimers(args) {
|
|
|
16341
16418
|
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => {
|
|
16342
16419
|
leaseLost = true;
|
|
16343
16420
|
log("[dreamer] primers: lease lost during promote-primers — aborting");
|
|
16344
|
-
});
|
|
16421
|
+
}, args.leaseAcquisition);
|
|
16345
16422
|
try {
|
|
16346
16423
|
assertLeaseHeld("prune start");
|
|
16347
16424
|
result.pruned = pruneExpiredPrimerCandidatesForProject(args.db, args.projectIdentity, Date.now(), PRIMER_CANDIDATE_TTL_MS);
|
|
@@ -16573,7 +16650,7 @@ async function refreshPrimers(args) {
|
|
|
16573
16650
|
if (primers.length === 0)
|
|
16574
16651
|
return result;
|
|
16575
16652
|
const abortController = new AbortController;
|
|
16576
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
|
|
16653
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
16577
16654
|
try {
|
|
16578
16655
|
for (let i = 0;i < primers.length; i += 1) {
|
|
16579
16656
|
const primer = primers[i];
|
|
@@ -17060,68 +17137,6 @@ function evaluateTaskGate(task, ctx) {
|
|
|
17060
17137
|
// src/features/magic-context/dreamer/verify.ts
|
|
17061
17138
|
import { createHash as createHash7 } from "node:crypto";
|
|
17062
17139
|
|
|
17063
|
-
// src/features/magic-context/dreamer/provider-output-failure.ts
|
|
17064
|
-
import { createHash as createHash6 } from "node:crypto";
|
|
17065
|
-
var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
|
|
17066
|
-
|
|
17067
|
-
class DreamerProviderOutputFailureError extends Error {
|
|
17068
|
-
fingerprint;
|
|
17069
|
-
outputTokens;
|
|
17070
|
-
reasoningTokens;
|
|
17071
|
-
transient = true;
|
|
17072
|
-
constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
|
|
17073
|
-
const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
|
|
17074
|
-
super(`verify provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
|
|
17075
|
-
this.fingerprint = fingerprint;
|
|
17076
|
-
this.outputTokens = outputTokens;
|
|
17077
|
-
this.reasoningTokens = reasoningTokens;
|
|
17078
|
-
this.name = "DreamerProviderOutputFailureError";
|
|
17079
|
-
}
|
|
17080
|
-
}
|
|
17081
|
-
function finiteTokenCount(value) {
|
|
17082
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
17083
|
-
}
|
|
17084
|
-
function completionShape(value) {
|
|
17085
|
-
if (!isRecord(value))
|
|
17086
|
-
return null;
|
|
17087
|
-
const info = isRecord(value.info) ? value.info : value;
|
|
17088
|
-
if (info.role !== "assistant")
|
|
17089
|
-
return null;
|
|
17090
|
-
const time = isRecord(info.time) ? info.time : null;
|
|
17091
|
-
const tokens = isRecord(info.tokens) ? info.tokens : null;
|
|
17092
|
-
return {
|
|
17093
|
-
createdAt: typeof time?.created === "number" ? time.created : 0,
|
|
17094
|
-
finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
|
|
17095
|
-
error: info.error,
|
|
17096
|
-
outputTokens: finiteTokenCount(tokens?.output),
|
|
17097
|
-
reasoningTokens: finiteTokenCount(tokens?.reasoning)
|
|
17098
|
-
};
|
|
17099
|
-
}
|
|
17100
|
-
function latestAssistantCompletion(messages) {
|
|
17101
|
-
if (!Array.isArray(messages))
|
|
17102
|
-
return null;
|
|
17103
|
-
let latest = null;
|
|
17104
|
-
for (const message of messages) {
|
|
17105
|
-
const completion = completionShape(message);
|
|
17106
|
-
if (completion && (!latest || completion.createdAt >= latest.createdAt))
|
|
17107
|
-
latest = completion;
|
|
17108
|
-
}
|
|
17109
|
-
return latest;
|
|
17110
|
-
}
|
|
17111
|
-
function providerOutputFailureFromInvalidManifest(messages, responseText) {
|
|
17112
|
-
const completion = latestAssistantCompletion(messages);
|
|
17113
|
-
if (completion?.finish?.toLowerCase() !== "stop")
|
|
17114
|
-
return null;
|
|
17115
|
-
if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
|
|
17116
|
-
return null;
|
|
17117
|
-
}
|
|
17118
|
-
const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
|
|
17119
|
-
if (!normalized)
|
|
17120
|
-
return null;
|
|
17121
|
-
const fingerprint = createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
17122
|
-
return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
|
|
17123
|
-
}
|
|
17124
|
-
|
|
17125
17140
|
// src/features/magic-context/dreamer/verify-gate.ts
|
|
17126
17141
|
import path4 from "node:path";
|
|
17127
17142
|
function minOf(values) {
|
|
@@ -17366,7 +17381,7 @@ async function runVerify(args) {
|
|
|
17366
17381
|
batches.push(gate.inScope.slice(i, i + VERIFY_BATCH_SIZE));
|
|
17367
17382
|
}
|
|
17368
17383
|
const abortController = new AbortController;
|
|
17369
|
-
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
|
|
17384
|
+
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
|
|
17370
17385
|
let consecutiveProviderFailures = 0;
|
|
17371
17386
|
let priorProviderFailureFingerprint = null;
|
|
17372
17387
|
let lastProviderFailure = null;
|
|
@@ -17702,6 +17717,9 @@ function createDreamTaskExecutor(deps) {
|
|
|
17702
17717
|
return async (config, ctx) => {
|
|
17703
17718
|
const { db, projectIdentity, holderId, leaseKey } = ctx;
|
|
17704
17719
|
const startedAt = Date.now();
|
|
17720
|
+
const leaseAcquisition = ctx.leaseAcquisition ?? acquireLeaseWithAcquisition(db, holderId, leaseKey) ?? (() => {
|
|
17721
|
+
throw new Error("Dream lease unavailable during executor setup");
|
|
17722
|
+
})();
|
|
17705
17723
|
const deadline = startedAt + config.timeoutMinutes * 60 * 1000;
|
|
17706
17724
|
const backlogAtStart = getDreamTaskBacklog(db, projectIdentity, config.task);
|
|
17707
17725
|
const reportProgress = (processed) => {
|
|
@@ -17719,7 +17737,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17719
17737
|
};
|
|
17720
17738
|
const parent = await resolveParentSessionId();
|
|
17721
17739
|
let moduleRoute;
|
|
17722
|
-
if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
|
|
17740
|
+
if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "classify-memories" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
|
|
17723
17741
|
try {
|
|
17724
17742
|
moduleRoute = await resolveDreamerModuleRoute({
|
|
17725
17743
|
db,
|
|
@@ -17733,6 +17751,9 @@ function createDreamTaskExecutor(deps) {
|
|
|
17733
17751
|
throw new DreamerModuleFailureError("authority.status", error);
|
|
17734
17752
|
}
|
|
17735
17753
|
}
|
|
17754
|
+
if (!leaseOwnershipMatches(db, holderId, leaseAcquisition.generation, leaseKey)) {
|
|
17755
|
+
throw new Error("Dream lease lost during executor setup");
|
|
17756
|
+
}
|
|
17736
17757
|
const recordRun = (status, error, extra) => {
|
|
17737
17758
|
try {
|
|
17738
17759
|
insertDreamRun(db, {
|
|
@@ -17805,6 +17826,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17805
17826
|
holderId,
|
|
17806
17827
|
leaseKey,
|
|
17807
17828
|
deadline,
|
|
17829
|
+
leaseAcquisition,
|
|
17808
17830
|
model: config.model ?? deps.mural.model ?? deps.dreamerModel,
|
|
17809
17831
|
fallbackModels: config.fallbackModels,
|
|
17810
17832
|
moduleRoute,
|
|
@@ -17828,6 +17850,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17828
17850
|
holderId,
|
|
17829
17851
|
leaseKey,
|
|
17830
17852
|
deadline,
|
|
17853
|
+
leaseAcquisition,
|
|
17831
17854
|
promotionThreshold: config.promotionThreshold ?? 3,
|
|
17832
17855
|
model: config.model,
|
|
17833
17856
|
fallbackModels: config.fallbackModels,
|
|
@@ -17847,6 +17870,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17847
17870
|
holderId,
|
|
17848
17871
|
leaseKey,
|
|
17849
17872
|
deadline,
|
|
17873
|
+
leaseAcquisition,
|
|
17850
17874
|
model: config.model,
|
|
17851
17875
|
fallbackModels: config.fallbackModels,
|
|
17852
17876
|
moduleRoute,
|
|
@@ -17872,6 +17896,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17872
17896
|
holderId,
|
|
17873
17897
|
leaseKey,
|
|
17874
17898
|
deadline,
|
|
17899
|
+
leaseAcquisition,
|
|
17875
17900
|
forceBroad: config.task === "verify-broad",
|
|
17876
17901
|
model: config.model,
|
|
17877
17902
|
fallbackModels: config.fallbackModels,
|
|
@@ -17905,40 +17930,15 @@ function createDreamTaskExecutor(deps) {
|
|
|
17905
17930
|
}
|
|
17906
17931
|
if (config.task === "classify-memories") {
|
|
17907
17932
|
let moduleArgs;
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
|
|
17916
|
-
|
|
17917
|
-
context_store_uuid: contextStoreUuid,
|
|
17918
|
-
project: projectIdentity,
|
|
17919
|
-
projectRoot: deps.sessionDirectory,
|
|
17920
|
-
domain: "memories"
|
|
17921
|
-
});
|
|
17922
|
-
} catch (error) {
|
|
17923
|
-
throw new ClassifyModuleFailureError("authority.status", error);
|
|
17924
|
-
}
|
|
17925
|
-
if (authority.authority?.state === "MODULE") {
|
|
17926
|
-
const generation = authority.authority.generation;
|
|
17927
|
-
if (typeof generation !== "number") {
|
|
17928
|
-
throw new ClassifyModuleFailureError("authority.status", new Error("response omitted generation"));
|
|
17929
|
-
}
|
|
17930
|
-
const moduleClient = {
|
|
17931
|
-
call: (callArgs) => moduleTransport.call(callArgs)
|
|
17932
|
-
};
|
|
17933
|
-
moduleArgs = {
|
|
17934
|
-
moduleClient,
|
|
17935
|
-
moduleSessionId: projectIdentity,
|
|
17936
|
-
moduleProjectRoot: deps.sessionDirectory,
|
|
17937
|
-
moduleContextStoreUuid: contextStoreUuid,
|
|
17938
|
-
moduleAuthorityGeneration: generation,
|
|
17939
|
-
moduleCommandId: `${startedAt}:${holderId}`
|
|
17940
|
-
};
|
|
17941
|
-
}
|
|
17933
|
+
if (moduleRoute) {
|
|
17934
|
+
moduleArgs = {
|
|
17935
|
+
moduleClient: moduleRoute.moduleClient,
|
|
17936
|
+
moduleSessionId: moduleRoute.moduleSessionId,
|
|
17937
|
+
moduleProjectRoot: moduleRoute.moduleProjectRoot,
|
|
17938
|
+
moduleContextStoreUuid: moduleRoute.moduleContextStoreUuid,
|
|
17939
|
+
moduleAuthorityGeneration: moduleRoute.moduleAuthorityGeneration,
|
|
17940
|
+
moduleCommandId: moduleRoute.moduleCommandId
|
|
17941
|
+
};
|
|
17942
17942
|
}
|
|
17943
17943
|
const result = await runClassify({
|
|
17944
17944
|
db,
|
|
@@ -17949,6 +17949,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17949
17949
|
holderId,
|
|
17950
17950
|
leaseKey,
|
|
17951
17951
|
deadline,
|
|
17952
|
+
leaseAcquisition,
|
|
17952
17953
|
model: config.model,
|
|
17953
17954
|
fallbackModels: config.fallbackModels,
|
|
17954
17955
|
...moduleArgs,
|
|
@@ -17972,6 +17973,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17972
17973
|
holderId,
|
|
17973
17974
|
leaseKey,
|
|
17974
17975
|
deadline,
|
|
17976
|
+
leaseAcquisition,
|
|
17975
17977
|
promotionThreshold: config.promotionThreshold ?? 2,
|
|
17976
17978
|
ensureProjectRegistered: deps.ensureProjectRegistered
|
|
17977
17979
|
});
|
|
@@ -17989,6 +17991,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17989
17991
|
holderId,
|
|
17990
17992
|
leaseKey,
|
|
17991
17993
|
deadline,
|
|
17994
|
+
leaseAcquisition,
|
|
17992
17995
|
model: config.model,
|
|
17993
17996
|
fallbackModels: config.fallbackModels,
|
|
17994
17997
|
language: config.language ?? deps.language,
|
|
@@ -18009,6 +18012,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
18009
18012
|
holderId,
|
|
18010
18013
|
leaseKey,
|
|
18011
18014
|
deadline,
|
|
18015
|
+
leaseAcquisition,
|
|
18012
18016
|
model: config.model,
|
|
18013
18017
|
fallbackModels: config.fallbackModels,
|
|
18014
18018
|
retinaHandoff: deps.retinaHandoff
|
|
@@ -18154,7 +18158,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
18154
18158
|
const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
|
|
18155
18159
|
leaseLost = true;
|
|
18156
18160
|
abortController.abort();
|
|
18157
|
-
});
|
|
18161
|
+
}, ctx.leaseAcquisition);
|
|
18158
18162
|
let childSessionId = null;
|
|
18159
18163
|
try {
|
|
18160
18164
|
const createResponse = await createChildSessionWithFence({
|
|
@@ -18344,7 +18348,7 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
18344
18348
|
const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
|
|
18345
18349
|
leaseLost = true;
|
|
18346
18350
|
abortController.abort();
|
|
18347
|
-
});
|
|
18351
|
+
}, ctx.leaseAcquisition);
|
|
18348
18352
|
let childSessionId = null;
|
|
18349
18353
|
try {
|
|
18350
18354
|
const createResponse = await createChildSessionWithFence({
|
|
@@ -18527,15 +18531,15 @@ async function runDomainGroup(deps, group, cb) {
|
|
|
18527
18531
|
const { db, projectIdentity, executor } = deps;
|
|
18528
18532
|
const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
|
|
18529
18533
|
const holderId = crypto.randomUUID();
|
|
18530
|
-
let
|
|
18531
|
-
if (!
|
|
18534
|
+
let acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
|
|
18535
|
+
if (!acquisition && cb?.leaseWaitMs) {
|
|
18532
18536
|
const deadline = Date.now() + cb.leaseWaitMs;
|
|
18533
|
-
while (!
|
|
18537
|
+
while (!acquisition && Date.now() < deadline) {
|
|
18534
18538
|
await new Promise((resolve3) => setTimeout(resolve3, LEASE_WAIT_POLL_MS));
|
|
18535
|
-
|
|
18539
|
+
acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
|
|
18536
18540
|
}
|
|
18537
18541
|
}
|
|
18538
|
-
if (!
|
|
18542
|
+
if (!acquisition) {
|
|
18539
18543
|
log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
|
|
18540
18544
|
for (const due of group)
|
|
18541
18545
|
cb?.onBusy?.(due.config.task);
|
|
@@ -18543,7 +18547,7 @@ async function runDomainGroup(deps, group, cb) {
|
|
|
18543
18547
|
}
|
|
18544
18548
|
try {
|
|
18545
18549
|
for (const due of [...group].sort((a, b) => compareTaskOrder(a.config.task, b.config.task))) {
|
|
18546
|
-
if (!
|
|
18550
|
+
if (!leaseOwnershipMatches(db, holderId, acquisition.generation, leaseKey)) {
|
|
18547
18551
|
log(`[dreamer] domain lease lost (${leaseKey}) — stopping remaining task(s)`);
|
|
18548
18552
|
break;
|
|
18549
18553
|
}
|
|
@@ -18562,7 +18566,13 @@ async function runDomainGroup(deps, group, cb) {
|
|
|
18562
18566
|
}
|
|
18563
18567
|
let outcome;
|
|
18564
18568
|
try {
|
|
18565
|
-
outcome = await executor(due.config, {
|
|
18569
|
+
outcome = await executor(due.config, {
|
|
18570
|
+
db,
|
|
18571
|
+
projectIdentity,
|
|
18572
|
+
holderId,
|
|
18573
|
+
leaseKey,
|
|
18574
|
+
leaseAcquisition: acquisition
|
|
18575
|
+
});
|
|
18566
18576
|
} catch (error) {
|
|
18567
18577
|
outcome = { status: "failed", transient: true, error: String(error) };
|
|
18568
18578
|
}
|
|
@@ -21087,14 +21097,15 @@ function createMagicContextCommandHandler(deps) {
|
|
|
21087
21097
|
const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
|
|
21088
21098
|
const isEmbedCommand = (command) => command === "ctx-embed";
|
|
21089
21099
|
const rustMode = deps.transformMode === "rust" && deps.rustModeModuleClient;
|
|
21090
|
-
const callRust = async (method, body) => {
|
|
21100
|
+
const callRust = async (method, body, timeoutMs) => {
|
|
21091
21101
|
if (!rustMode)
|
|
21092
21102
|
throw new Error("Rust module client is unavailable");
|
|
21093
21103
|
return moduleResponseValue(await rustMode.call({
|
|
21094
21104
|
sessionId: body.session_id,
|
|
21095
21105
|
projectRoot: deps.projectRoot ?? process.cwd(),
|
|
21096
21106
|
method,
|
|
21097
|
-
body
|
|
21107
|
+
body,
|
|
21108
|
+
...timeoutMs === undefined ? {} : { timeoutMs }
|
|
21098
21109
|
}));
|
|
21099
21110
|
};
|
|
21100
21111
|
return {
|
|
@@ -21239,7 +21250,7 @@ Starting wrapup…`, {});
|
|
|
21239
21250
|
session_id: sessionId,
|
|
21240
21251
|
keep,
|
|
21241
21252
|
command_id: rustCommandId("wrapup")
|
|
21242
|
-
});
|
|
21253
|
+
}, MAX_WRAPUP_REQUEST_BUDGET_MS);
|
|
21243
21254
|
result = formatRustOperationMessage("wrapup", value);
|
|
21244
21255
|
} catch (error) {
|
|
21245
21256
|
result = `## Magic Wrapup — Failed
|
|
@@ -21638,6 +21649,13 @@ var sessionLocks = new Map;
|
|
|
21638
21649
|
var incrementalTimers = new Map;
|
|
21639
21650
|
var pendingIncrementalKeys = new Set;
|
|
21640
21651
|
var completedIncrementalKeys = new Set;
|
|
21652
|
+
function clearCompletedIncrementalKeys(sessionId) {
|
|
21653
|
+
const prefix = `${sessionId}\x00`;
|
|
21654
|
+
for (const key of completedIncrementalKeys) {
|
|
21655
|
+
if (key.startsWith(prefix))
|
|
21656
|
+
completedIncrementalKeys.delete(key);
|
|
21657
|
+
}
|
|
21658
|
+
}
|
|
21641
21659
|
function defer(fn) {
|
|
21642
21660
|
const immediate = globalThis.setImmediate;
|
|
21643
21661
|
if (typeof immediate === "function") {
|
|
@@ -21752,14 +21770,12 @@ function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
|
|
|
21752
21770
|
function scheduleClearAndReindex(db, sessionId, readMessages) {
|
|
21753
21771
|
reconciledSessions.delete(sessionId);
|
|
21754
21772
|
reconciliationScheduledSessions.delete(sessionId);
|
|
21755
|
-
|
|
21756
|
-
for (const key of completedIncrementalKeys) {
|
|
21757
|
-
if (key.startsWith(prefix))
|
|
21758
|
-
completedIncrementalKeys.delete(key);
|
|
21759
|
-
}
|
|
21773
|
+
clearCompletedIncrementalKeys(sessionId);
|
|
21760
21774
|
scheduleAfterBootQuiet(() => {
|
|
21761
21775
|
defer(() => {
|
|
21762
21776
|
runWithSessionLock(sessionId, () => {
|
|
21777
|
+
reconciledSessions.delete(sessionId);
|
|
21778
|
+
clearCompletedIncrementalKeys(sessionId);
|
|
21763
21779
|
clearIndexedMessages(db, sessionId);
|
|
21764
21780
|
}).then(() => reconcileSessionIndex(db, sessionId, readMessages)).catch((error) => {
|
|
21765
21781
|
reconciledSessions.delete(sessionId);
|
|
@@ -22789,16 +22805,8 @@ function reconcileCompactionMode(args) {
|
|
|
22789
22805
|
notice: COMPACTION_ON_WRAPUP_SUGGESTION
|
|
22790
22806
|
};
|
|
22791
22807
|
}
|
|
22792
|
-
|
|
22793
|
-
|
|
22794
|
-
return {
|
|
22795
|
-
...NO_TRANSITION,
|
|
22796
|
-
recordToWrite: markerCleanup2.verified ? "off" : "off_cleanup_pending",
|
|
22797
|
-
notice: COMPACTION_OFF_FLIP_NOTICE,
|
|
22798
|
-
markerCleanup: markerCleanup2
|
|
22799
|
-
};
|
|
22800
|
-
}
|
|
22801
|
-
if (!args.compactionOff) {
|
|
22808
|
+
const completingOffNotice = stored === "off_notice_pending";
|
|
22809
|
+
if (!args.compactionOff && !completingOffNotice) {
|
|
22802
22810
|
if (stored === null || resolveCompactionModeRecord(stored) === "on") {
|
|
22803
22811
|
return stored === null ? { ...NO_TRANSITION, recordToWrite: "on" } : NO_TRANSITION;
|
|
22804
22812
|
}
|
|
@@ -22834,6 +22842,9 @@ function reconcileCompactionMode(args) {
|
|
|
22834
22842
|
markerCleanup: markerCleanup2
|
|
22835
22843
|
};
|
|
22836
22844
|
}
|
|
22845
|
+
if (!completingOffNotice) {
|
|
22846
|
+
setCompactionModeRecord(db, sessionId, "off_notice_pending");
|
|
22847
|
+
}
|
|
22837
22848
|
let clearedSomething = false;
|
|
22838
22849
|
const markerCleanup = cleanupOffMarkers(sessionId);
|
|
22839
22850
|
if (markerCleanup.removedRows > 0)
|
|
@@ -22871,10 +22882,8 @@ function reconcileCompactionMode(args) {
|
|
|
22871
22882
|
loggedUnverifiedMarkerCleanupRetry = true;
|
|
22872
22883
|
sessionLog(sessionId, "compaction-off transition could not verify complete marker cleanup; durable cleanup retry will run on the next pass");
|
|
22873
22884
|
}
|
|
22874
|
-
const notice = clearedSomething ? COMPACTION_OFF_FLIP_NOTICE : null;
|
|
22875
|
-
if (notice) {
|
|
22876
|
-
setCompactionModeRecord(db, sessionId, "off_notice_pending");
|
|
22877
|
-
} else if (!markerCleanup.verified) {
|
|
22885
|
+
const notice = clearedSomething || completingOffNotice ? COMPACTION_OFF_FLIP_NOTICE : null;
|
|
22886
|
+
if (!notice && !markerCleanup.verified) {
|
|
22878
22887
|
setCompactionModeRecord(db, sessionId, "off_cleanup_pending");
|
|
22879
22888
|
}
|
|
22880
22889
|
return {
|
|
@@ -23703,6 +23712,22 @@ function partIsAnthropicThinking(part) {
|
|
|
23703
23712
|
const type = part.type;
|
|
23704
23713
|
return type === "thinking" || type === "reasoning" || type === "redacted_thinking";
|
|
23705
23714
|
}
|
|
23715
|
+
function partEndsAnthropicAssistantRun(part) {
|
|
23716
|
+
if (!part || typeof part !== "object")
|
|
23717
|
+
return false;
|
|
23718
|
+
const value = part;
|
|
23719
|
+
if (value.type !== "tool" || value.providerExecuted === true || !value.state || typeof value.state !== "object") {
|
|
23720
|
+
return false;
|
|
23721
|
+
}
|
|
23722
|
+
const status = value.state.status;
|
|
23723
|
+
return status === "completed" || status === "error";
|
|
23724
|
+
}
|
|
23725
|
+
function partIsOpenCodeStepMetadata(part) {
|
|
23726
|
+
if (!part || typeof part !== "object")
|
|
23727
|
+
return false;
|
|
23728
|
+
const type = part.type;
|
|
23729
|
+
return type === "step-start" || type === "step-finish";
|
|
23730
|
+
}
|
|
23706
23731
|
function validateAnthropicReasoningRuns(messages) {
|
|
23707
23732
|
let index = 0;
|
|
23708
23733
|
while (index < messages.length) {
|
|
@@ -23718,7 +23743,10 @@ function validateAnthropicReasoningRuns(messages) {
|
|
|
23718
23743
|
thinkingBlocks += 1;
|
|
23719
23744
|
if (thinkingBlocks > 1 || sawOtherContent)
|
|
23720
23745
|
return false;
|
|
23721
|
-
} else {
|
|
23746
|
+
} else if (partEndsAnthropicAssistantRun(part)) {
|
|
23747
|
+
thinkingBlocks = 0;
|
|
23748
|
+
sawOtherContent = false;
|
|
23749
|
+
} else if (!partIsOpenCodeStepMetadata(part)) {
|
|
23722
23750
|
sawOtherContent = true;
|
|
23723
23751
|
}
|
|
23724
23752
|
}
|
|
@@ -24366,23 +24394,68 @@ function encodeOpenCodeMessagesToCk(messages) {
|
|
|
24366
24394
|
|
|
24367
24395
|
// src/hooks/magic-context/module-state-sync.ts
|
|
24368
24396
|
async function mirrorModuleCompartments(args) {
|
|
24369
|
-
const
|
|
24370
|
-
|
|
24371
|
-
|
|
24372
|
-
|
|
24373
|
-
|
|
24374
|
-
|
|
24375
|
-
|
|
24376
|
-
|
|
24377
|
-
|
|
24397
|
+
const authoritative = [];
|
|
24398
|
+
let afterSequence = -1;
|
|
24399
|
+
let maxSequence = null;
|
|
24400
|
+
for (;; ) {
|
|
24401
|
+
const published = await args.reader.getCompartmentsAfter(args.sessionId, afterSequence);
|
|
24402
|
+
if (!Number.isSafeInteger(published.max_sequence) || published.max_sequence < -1 || maxSequence !== null && published.max_sequence !== maxSequence) {
|
|
24403
|
+
throw new Error("module compartment mirror changed while its authoritative set was read");
|
|
24404
|
+
}
|
|
24405
|
+
maxSequence ??= published.max_sequence;
|
|
24406
|
+
let pageAdvanced = false;
|
|
24378
24407
|
for (const compartment of published.compartments) {
|
|
24379
|
-
if (!Number.
|
|
24380
|
-
|
|
24408
|
+
if (!Number.isSafeInteger(compartment.sequence) || compartment.sequence <= afterSequence || compartment.sequence > maxSequence || !Number.isSafeInteger(compartment.start_message) || !Number.isSafeInteger(compartment.end_message) || typeof compartment.start_message_id !== "string" || typeof compartment.end_message_id !== "string" || typeof compartment.title !== "string" || typeof compartment.content !== "string") {
|
|
24409
|
+
throw new Error("module compartment mirror returned an invalid authoritative row");
|
|
24381
24410
|
}
|
|
24382
|
-
|
|
24411
|
+
authoritative.push(compartment);
|
|
24412
|
+
afterSequence = compartment.sequence;
|
|
24413
|
+
pageAdvanced = true;
|
|
24414
|
+
}
|
|
24415
|
+
if (afterSequence >= maxSequence)
|
|
24416
|
+
break;
|
|
24417
|
+
if (!pageAdvanced) {
|
|
24418
|
+
throw new Error("module compartment mirror returned an incomplete authoritative set");
|
|
24419
|
+
}
|
|
24420
|
+
}
|
|
24421
|
+
const local = args.db.prepare("SELECT sequence, end_message FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(args.sessionId);
|
|
24422
|
+
let firstDifference = 0;
|
|
24423
|
+
while (firstDifference < local.length && firstDifference < authoritative.length && local[firstDifference]?.sequence === authoritative[firstDifference]?.sequence && local[firstDifference]?.end_message === authoritative[firstDifference]?.end_message) {
|
|
24424
|
+
firstDifference += 1;
|
|
24425
|
+
}
|
|
24426
|
+
const localDifference = local[firstDifference]?.sequence;
|
|
24427
|
+
const authoritativeDifference = authoritative[firstDifference]?.sequence;
|
|
24428
|
+
const divergentSequence = localDifference === undefined ? authoritativeDifference : authoritativeDifference === undefined ? localDifference : Math.min(localDifference, authoritativeDifference);
|
|
24429
|
+
const upsert = args.db.prepare(`INSERT INTO compartments
|
|
24430
|
+
(session_id, sequence, start_message, end_message, start_message_id, end_message_id,
|
|
24431
|
+
title, content, p1, p2, p3, p4, importance, episode_type, legacy, created_at, harness)
|
|
24432
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
24433
|
+
ON CONFLICT(session_id, sequence) DO UPDATE SET
|
|
24434
|
+
start_message = excluded.start_message,
|
|
24435
|
+
end_message = excluded.end_message,
|
|
24436
|
+
start_message_id = excluded.start_message_id,
|
|
24437
|
+
end_message_id = excluded.end_message_id,
|
|
24438
|
+
title = excluded.title,
|
|
24439
|
+
content = excluded.content,
|
|
24440
|
+
p1 = excluded.p1,
|
|
24441
|
+
p2 = excluded.p2,
|
|
24442
|
+
p3 = excluded.p3,
|
|
24443
|
+
p4 = excluded.p4,
|
|
24444
|
+
importance = excluded.importance,
|
|
24445
|
+
episode_type = excluded.episode_type,
|
|
24446
|
+
legacy = excluded.legacy,
|
|
24447
|
+
created_at = excluded.created_at,
|
|
24448
|
+
harness = excluded.harness`);
|
|
24449
|
+
const now = Date.now();
|
|
24450
|
+
args.db.transaction(() => {
|
|
24451
|
+
if (divergentSequence !== undefined) {
|
|
24452
|
+
args.db.prepare("DELETE FROM compartments WHERE session_id = ? AND sequence >= ?").run(args.sessionId, divergentSequence);
|
|
24453
|
+
}
|
|
24454
|
+
for (const compartment of authoritative) {
|
|
24455
|
+
upsert.run(args.sessionId, compartment.sequence, compartment.start_message, compartment.end_message, compartment.start_message_id, compartment.end_message_id, compartment.title, compartment.content, compartment.p1 ?? null, compartment.p2 ?? null, compartment.p3 ?? null, compartment.p4 ?? null, compartment.importance ?? 50, compartment.episode_type ?? null, compartment.legacy ?? (compartment.p1 ? 0 : 1), compartment.created_at ?? now, getHarness());
|
|
24383
24456
|
}
|
|
24384
24457
|
})();
|
|
24385
|
-
return
|
|
24458
|
+
return maxSequence;
|
|
24386
24459
|
}
|
|
24387
24460
|
function stableHash(value) {
|
|
24388
24461
|
return createHmac("sha256", "magic-context-shadow-watermark").update(value).digest("hex");
|
|
@@ -25002,7 +25075,7 @@ async function buildModuleStateSyncPayload(args) {
|
|
|
25002
25075
|
workspace,
|
|
25003
25076
|
nowMs: args.pass.nowMs
|
|
25004
25077
|
}) : [];
|
|
25005
|
-
const userProfile = includeUserProfile
|
|
25078
|
+
const userProfile = includeUserProfile ? getActiveUserMemories(args.pass.db).map((memory) => memory.content) : [];
|
|
25006
25079
|
const memoryMutations = memoryMutationsChanged && args.pass.projectPath ? getMemoryMutationsForRenderByProjects(args.pass.db, workspace.expandedIdentities, acked.memory_mutation_id, renderedMemoryIds).map((row) => ({
|
|
25007
25080
|
id: row.id,
|
|
25008
25081
|
project_path: row.projectPath,
|
|
@@ -25147,63 +25220,74 @@ function readAuthoritySeqMismatch(error) {
|
|
|
25147
25220
|
async function syncModuleState(args) {
|
|
25148
25221
|
let force = args.force;
|
|
25149
25222
|
const adoption = args.options?.authoritySeqAdoption ?? { used: false };
|
|
25150
|
-
|
|
25151
|
-
|
|
25152
|
-
|
|
25153
|
-
|
|
25154
|
-
|
|
25155
|
-
|
|
25156
|
-
})).state_sync_deltas === true;
|
|
25157
|
-
} catch {
|
|
25158
|
-
stateSyncDeltas = false;
|
|
25159
|
-
}
|
|
25160
|
-
}
|
|
25161
|
-
for (;; ) {
|
|
25162
|
-
const payload = await buildModuleStateSyncPayload({
|
|
25163
|
-
state: args.state,
|
|
25164
|
-
pass: args.pass,
|
|
25165
|
-
force,
|
|
25166
|
-
options: { ...args.options, stateSyncDeltas }
|
|
25167
|
-
});
|
|
25168
|
-
if (payload === null)
|
|
25169
|
-
return { status: "no_change" };
|
|
25170
|
-
if (payload === "m0_mutation" || payload === "mismatch" || payload === "unresolved" || payload === "seed_budget") {
|
|
25171
|
-
throw new Error(`module state sync ${payload}`);
|
|
25172
|
-
}
|
|
25173
|
-
try {
|
|
25174
|
-
const batches = payload.wireBatches ?? [payload];
|
|
25175
|
-
for (const batch of batches) {
|
|
25176
|
-
const response = await args.client.call({
|
|
25223
|
+
const resolveStateSyncDeltas = async (afterGenerationChange = false) => {
|
|
25224
|
+
let capability = afterGenerationChange ? undefined : args.options?.stateSyncDeltas;
|
|
25225
|
+
capability ??= args.client.getCachedStateSyncCapabilities?.()?.state_sync_deltas;
|
|
25226
|
+
if (capability === undefined && args.client.stateSyncCapabilities) {
|
|
25227
|
+
try {
|
|
25228
|
+
capability = (await args.client.stateSyncCapabilities({
|
|
25177
25229
|
sessionId: args.pass.sessionId,
|
|
25178
|
-
projectRoot: args.projectRoot
|
|
25179
|
-
|
|
25180
|
-
|
|
25181
|
-
|
|
25182
|
-
|
|
25230
|
+
projectRoot: args.projectRoot
|
|
25231
|
+
})).state_sync_deltas;
|
|
25232
|
+
} catch {
|
|
25233
|
+
capability = false;
|
|
25234
|
+
}
|
|
25235
|
+
}
|
|
25236
|
+
return capability === true;
|
|
25237
|
+
};
|
|
25238
|
+
let stateSyncDeltas = await resolveStateSyncDeltas();
|
|
25239
|
+
syncLoop:
|
|
25240
|
+
for (;; ) {
|
|
25241
|
+
const payload = await buildModuleStateSyncPayload({
|
|
25242
|
+
state: args.state,
|
|
25243
|
+
pass: args.pass,
|
|
25244
|
+
force,
|
|
25245
|
+
options: { ...args.options, stateSyncDeltas }
|
|
25246
|
+
});
|
|
25247
|
+
if (payload === null)
|
|
25248
|
+
return { status: "no_change" };
|
|
25249
|
+
if (payload === "m0_mutation" || payload === "mismatch" || payload === "unresolved" || payload === "seed_budget") {
|
|
25250
|
+
throw new Error(`module state sync ${payload}`);
|
|
25251
|
+
}
|
|
25252
|
+
try {
|
|
25253
|
+
const batches = payload.wireBatches ?? [payload];
|
|
25254
|
+
for (const batch of batches) {
|
|
25255
|
+
const response = await args.client.call({
|
|
25256
|
+
sessionId: args.pass.sessionId,
|
|
25257
|
+
projectRoot: args.projectRoot,
|
|
25258
|
+
method: "state_sync",
|
|
25259
|
+
body: {
|
|
25260
|
+
method: batch.method,
|
|
25261
|
+
...batch.params
|
|
25262
|
+
},
|
|
25263
|
+
generationSensitive: stateSyncDeltas
|
|
25264
|
+
});
|
|
25265
|
+
if (isModuleTransportGenerationChangedResult(response)) {
|
|
25266
|
+
stateSyncDeltas = await resolveStateSyncDeltas(true);
|
|
25267
|
+
continue syncLoop;
|
|
25268
|
+
}
|
|
25269
|
+
if (args.options?.authority === true && responseMemoriesSkipped(response) && !args.state.authorityMemorySyncSkipLogged) {
|
|
25270
|
+
args.state.authorityMemorySyncSkipLogged = true;
|
|
25271
|
+
sessionLog(args.pass.sessionId, "authority state sync skipped module-owned memory sections");
|
|
25183
25272
|
}
|
|
25184
|
-
});
|
|
25185
|
-
if (args.options?.authority === true && responseMemoriesSkipped(response) && !args.state.authorityMemorySyncSkipLogged) {
|
|
25186
|
-
args.state.authorityMemorySyncSkipLogged = true;
|
|
25187
|
-
sessionLog(args.pass.sessionId, "authority state sync skipped module-owned memory sections");
|
|
25188
25273
|
}
|
|
25274
|
+
} catch (error) {
|
|
25275
|
+
if (isHistorianCompartmentSyncBusy(error)) {
|
|
25276
|
+
return { status: "retry_busy" };
|
|
25277
|
+
}
|
|
25278
|
+
const durableSeq = args.options?.authority ? readAuthoritySeqMismatch(error) : null;
|
|
25279
|
+
if (durableSeq === null || adoption.used)
|
|
25280
|
+
throw error;
|
|
25281
|
+
adoption.used = true;
|
|
25282
|
+
args.state.lastAckedSeq = durableSeq;
|
|
25283
|
+
args.state.lastAckedWatermarks = null;
|
|
25284
|
+
force = true;
|
|
25285
|
+
continue;
|
|
25189
25286
|
}
|
|
25190
|
-
|
|
25191
|
-
|
|
25192
|
-
|
|
25193
|
-
}
|
|
25194
|
-
const durableSeq = args.options?.authority ? readAuthoritySeqMismatch(error) : null;
|
|
25195
|
-
if (durableSeq === null || adoption.used)
|
|
25196
|
-
throw error;
|
|
25197
|
-
adoption.used = true;
|
|
25198
|
-
args.state.lastAckedSeq = durableSeq;
|
|
25199
|
-
args.state.lastAckedWatermarks = null;
|
|
25200
|
-
force = true;
|
|
25201
|
-
continue;
|
|
25287
|
+
args.state.lastAckedWatermarks = payload.watermarks;
|
|
25288
|
+
args.state.lastAckedSeq += 1;
|
|
25289
|
+
return { status: "acked", watermarks: payload.watermarks };
|
|
25202
25290
|
}
|
|
25203
|
-
args.state.lastAckedWatermarks = payload.watermarks;
|
|
25204
|
-
args.state.lastAckedSeq += 1;
|
|
25205
|
-
return { status: "acked", watermarks: payload.watermarks };
|
|
25206
|
-
}
|
|
25207
25291
|
}
|
|
25208
25292
|
|
|
25209
25293
|
// src/hooks/magic-context/raw-fallback-context-limit.ts
|
|
@@ -27700,7 +27784,7 @@ var REASONING_IGNORED_PART_TYPES = new Set([
|
|
|
27700
27784
|
"compaction"
|
|
27701
27785
|
]);
|
|
27702
27786
|
var REASONING_PART_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
|
|
27703
|
-
function stripReasoningFromMergedAssistants(messages, providerID) {
|
|
27787
|
+
function stripReasoningFromMergedAssistants(messages, providerID, options) {
|
|
27704
27788
|
if (providerID !== "anthropic")
|
|
27705
27789
|
return 0;
|
|
27706
27790
|
let stripped = 0;
|
|
@@ -27716,6 +27800,10 @@ function stripReasoningFromMergedAssistants(messages, providerID) {
|
|
|
27716
27800
|
const firstInRun = prevRole !== "assistant";
|
|
27717
27801
|
if (firstInRun)
|
|
27718
27802
|
keptReasoningInRun = false;
|
|
27803
|
+
if (message === options?.mutationExemptMessage) {
|
|
27804
|
+
prevRole = role;
|
|
27805
|
+
continue;
|
|
27806
|
+
}
|
|
27719
27807
|
let keepIndex = -1;
|
|
27720
27808
|
if (firstInRun && !keptReasoningInRun) {
|
|
27721
27809
|
for (let i = 0;i < message.parts.length; i++) {
|
|
@@ -28810,11 +28898,21 @@ function finalizeMessageRepresentation(messages, resolvedProviderID, options) {
|
|
|
28810
28898
|
clearedParts = stripClearedReasoning(targetedMessages);
|
|
28811
28899
|
}
|
|
28812
28900
|
}
|
|
28813
|
-
const mergedReasoningParts = stripReasoningFromMergedAssistants(messages, resolvedProviderID
|
|
28901
|
+
const mergedReasoningParts = stripReasoningFromMergedAssistants(messages, resolvedProviderID, {
|
|
28902
|
+
mutationExemptMessage: options?.reasoningMutationExemptMessage
|
|
28903
|
+
});
|
|
28814
28904
|
return { clearedParts, mergedReasoningParts };
|
|
28815
28905
|
}
|
|
28816
28906
|
async function runPostTransformPhase(args) {
|
|
28817
28907
|
const compactionOff = args.compactionOff === true;
|
|
28908
|
+
let reasoningMutationExemptMessage;
|
|
28909
|
+
for (let index = args.messages.length - 1;index >= 0; index -= 1) {
|
|
28910
|
+
const message = args.messages[index];
|
|
28911
|
+
if (message.info.role !== "assistant")
|
|
28912
|
+
continue;
|
|
28913
|
+
reasoningMutationExemptMessage = message;
|
|
28914
|
+
break;
|
|
28915
|
+
}
|
|
28818
28916
|
const pendingMaterializationAtPassStart = args.pendingMaterializationSessions.has(args.sessionId);
|
|
28819
28917
|
const deferredMaterializationAtPassStart = args.deferredMaterializationSessions.has(args.sessionId);
|
|
28820
28918
|
const isExplicitFlush = pendingMaterializationAtPassStart;
|
|
@@ -28833,6 +28931,10 @@ async function runPostTransformPhase(args) {
|
|
|
28833
28931
|
state: args.sessionMeta,
|
|
28834
28932
|
projectPath: args.m0M1.projectPath,
|
|
28835
28933
|
projectDirectory: args.m0M1.projectDirectory,
|
|
28934
|
+
injectDocs: args.m0M1.injectDocs,
|
|
28935
|
+
muralEnabled: args.m0M1.muralEnabled,
|
|
28936
|
+
memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
|
|
28937
|
+
historyBudgetTokens: args.m0M1.historyBudgetTokens,
|
|
28836
28938
|
hardSignals: args.m0M1.hardSignals
|
|
28837
28939
|
}).value : false;
|
|
28838
28940
|
const bypassCompartmentGate = forceMaterialization || m0HardFoldThisPass;
|
|
@@ -29361,7 +29463,8 @@ async function runPostTransformPhase(args) {
|
|
|
29361
29463
|
const tFinalRepresentation = performance.now();
|
|
29362
29464
|
const finalRepresentation = finalizeMessageRepresentation(args.messages, args.resolvedProviderID, {
|
|
29363
29465
|
prependedMessageCount,
|
|
29364
|
-
reasoningMutatedMessages
|
|
29466
|
+
reasoningMutatedMessages,
|
|
29467
|
+
reasoningMutationExemptMessage
|
|
29365
29468
|
});
|
|
29366
29469
|
sessionLog(args.sessionId, `final representation: clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
|
|
29367
29470
|
logTransformTiming(args.sessionId, "finalizeMessageRepresentation", tFinalRepresentation, `clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
|
|
@@ -29403,6 +29506,15 @@ var RUST_PARK_RETRY_INTERVAL = 5;
|
|
|
29403
29506
|
var RUST_EMERGENCY_WALL_PCT = 95;
|
|
29404
29507
|
var RUST_PARK_PROBE_PRESSURE_BYPASS_PCT = 90;
|
|
29405
29508
|
var RUST_SEND_TIMEOUT_MS = 15000;
|
|
29509
|
+
var RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN = 4;
|
|
29510
|
+
function rawFallbackSerializedBytes(messages) {
|
|
29511
|
+
try {
|
|
29512
|
+
const serialized = JSON.stringify(messages);
|
|
29513
|
+
return typeof serialized === "string" ? Buffer.byteLength(serialized) : null;
|
|
29514
|
+
} catch {
|
|
29515
|
+
return null;
|
|
29516
|
+
}
|
|
29517
|
+
}
|
|
29406
29518
|
function isRecord3(value) {
|
|
29407
29519
|
return value !== null && typeof value === "object";
|
|
29408
29520
|
}
|
|
@@ -29635,6 +29747,19 @@ function responseValue(response) {
|
|
|
29635
29747
|
return response;
|
|
29636
29748
|
throw new Error("module transform returned a non-object response");
|
|
29637
29749
|
}
|
|
29750
|
+
function mirrorRustRenderedMemoryIds(args) {
|
|
29751
|
+
if (!("rendered_memory_ids" in args.response))
|
|
29752
|
+
return;
|
|
29753
|
+
const rawIds = args.response.rendered_memory_ids;
|
|
29754
|
+
if (!Array.isArray(rawIds) || rawIds.some((id) => typeof id !== "number" || !Number.isSafeInteger(id) || id <= 0)) {
|
|
29755
|
+
throw new Error("module transform returned an invalid rendered-memory manifest");
|
|
29756
|
+
}
|
|
29757
|
+
const serialized = JSON.stringify(rawIds);
|
|
29758
|
+
args.db.prepare(`UPDATE session_meta
|
|
29759
|
+
SET memory_block_ids = ?, memory_block_count = ?
|
|
29760
|
+
WHERE session_id = ?
|
|
29761
|
+
AND (COALESCE(memory_block_ids, '') <> ? OR COALESCE(memory_block_count, -1) <> ?)`).run(serialized, rawIds.length, args.sessionId, serialized, rawIds.length);
|
|
29762
|
+
}
|
|
29638
29763
|
function noteDeliveryPassIds(response) {
|
|
29639
29764
|
if (!Array.isArray(response.note_deliveries))
|
|
29640
29765
|
return [];
|
|
@@ -29983,8 +30108,10 @@ function buildTransformBody(args) {
|
|
|
29983
30108
|
model_key: args.modelKey,
|
|
29984
30109
|
provider_id: args.providerId,
|
|
29985
30110
|
tool_present: args.passInputs.tool_present === true,
|
|
30111
|
+
...typeof args.passInputs.todo_tool_present === "boolean" ? { todo_tool_present: args.passInputs.todo_tool_present } : {},
|
|
29986
30112
|
prompt_surface_preset: args.passInputs.prompt_surface_preset ?? "full",
|
|
29987
30113
|
prompt_surface_model_key: args.passInputs.prompt_surface_model_key,
|
|
30114
|
+
prompt_surface_config_identity: args.passInputs.prompt_surface_config_identity,
|
|
29988
30115
|
prompt_surface_tool_descriptions: args.passInputs.prompt_surface_tool_descriptions ?? {},
|
|
29989
30116
|
effective_execute_threshold: args.passInputs.effective_execute_threshold,
|
|
29990
30117
|
history_budget_tokens: args.passInputs.history_budget_tokens,
|
|
@@ -30007,6 +30134,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30007
30134
|
const states = new Map;
|
|
30008
30135
|
const wireCaches = new Map;
|
|
30009
30136
|
const scheduleLkgCapture = options.scheduleLkgCapture ?? ((capture) => setImmediate(capture));
|
|
30137
|
+
const rawFallbackEstimator = options.rawFallbackEstimatorForTests ?? estimateFinalWireInputTokens;
|
|
30010
30138
|
const timeoutMs = Math.max(1, options.moduleTimeoutMs ?? RUST_SEND_TIMEOUT_MS);
|
|
30011
30139
|
const logStage = (sessionId, stage, startedAt, timings, extra) => {
|
|
30012
30140
|
const elapsed = Math.max(0, performance.now() - startedAt);
|
|
@@ -30229,23 +30357,22 @@ function createRustModeTransform(deps, options) {
|
|
|
30229
30357
|
const serveRawFallback = (cause) => {
|
|
30230
30358
|
const contextLimit = resolvedContextLimit ?? (overflowState && overflowState.detectedContextLimit > 0 ? overflowState.detectedContextLimit : undefined);
|
|
30231
30359
|
if (contextLimit !== undefined) {
|
|
30360
|
+
let estimate;
|
|
30232
30361
|
try {
|
|
30233
|
-
|
|
30362
|
+
estimate = rawFallbackEstimator({
|
|
30234
30363
|
messages,
|
|
30235
30364
|
systemPromptTokens: sessionMeta.systemPromptTokens,
|
|
30236
30365
|
providerID: model?.providerID,
|
|
30237
30366
|
modelID: model?.modelID,
|
|
30238
30367
|
agentName: deps.getNotificationParams?.(sessionId)?.agent
|
|
30239
30368
|
});
|
|
30240
|
-
|
|
30241
|
-
|
|
30242
|
-
|
|
30243
|
-
|
|
30244
|
-
|
|
30245
|
-
}
|
|
30246
|
-
|
|
30247
|
-
if (error instanceof RawFallbackContextLimitError)
|
|
30248
|
-
throw error;
|
|
30369
|
+
} catch {}
|
|
30370
|
+
const rawBytes = rawFallbackSerializedBytes(messages);
|
|
30371
|
+
const proxyTokens = rawBytes === null ? contextLimit + 1 : Math.ceil(rawBytes / RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN);
|
|
30372
|
+
const refusalTokens = Math.max(estimate?.tokens ?? 0, proxyTokens);
|
|
30373
|
+
if (refusalTokens > contextLimit) {
|
|
30374
|
+
sessionLog(sessionId, `raw_fallback_over_context_limit estimated=${estimate?.tokens ?? "unavailable"} ` + `proxy_bytes=${rawBytes ?? "unavailable"} proxy_tokens=${proxyTokens} limit=${contextLimit}`);
|
|
30375
|
+
throw new RawFallbackContextLimitError(refusalTokens, contextLimit, { cause });
|
|
30249
30376
|
}
|
|
30250
30377
|
}
|
|
30251
30378
|
replaceMessagesInPlace(output, messages);
|
|
@@ -30319,7 +30446,9 @@ function createRustModeTransform(deps, options) {
|
|
|
30319
30446
|
}
|
|
30320
30447
|
const reduceAvailability = resolveCtxReduceAvailability(sessionId);
|
|
30321
30448
|
resolveTodowriteAvailabilityFromMessages(sessionId, messages);
|
|
30449
|
+
const todoAvailability = resolveTodowriteAvailability(sessionId);
|
|
30322
30450
|
const toolPresent = reduceAvailability.frozen && reduceAvailability.callable;
|
|
30451
|
+
const todoToolPresent = todoAvailability.frozen ? todoAvailability.callable : undefined;
|
|
30323
30452
|
try {
|
|
30324
30453
|
if (preflightError)
|
|
30325
30454
|
throw preflightError;
|
|
@@ -30353,8 +30482,10 @@ function createRustModeTransform(deps, options) {
|
|
|
30353
30482
|
system_prompt_hash: sessionMeta.systemPromptHash ?? "",
|
|
30354
30483
|
upgrade_state: readUpgradeState(deps.db, sessionId),
|
|
30355
30484
|
tool_present: toolPresent,
|
|
30485
|
+
todo_tool_present: todoToolPresent,
|
|
30356
30486
|
prompt_surface_preset: promptSurface.preset,
|
|
30357
30487
|
prompt_surface_model_key: modelKey,
|
|
30488
|
+
prompt_surface_config_identity: promptSurfaceConfigIdentity(deps.promptSurface),
|
|
30358
30489
|
prompt_surface_tool_descriptions: deps.promptSurface?.tool_descriptions ?? {},
|
|
30359
30490
|
protected_tags: deps.protectedTags ?? DEFAULT_PROTECTED_TAGS,
|
|
30360
30491
|
temporal_awareness: deps.experimentalTemporalAwareness === true,
|
|
@@ -30755,6 +30886,9 @@ function createRustModeTransform(deps, options) {
|
|
|
30755
30886
|
}
|
|
30756
30887
|
logStage(sessionId, "apply", applyStartedAt, timings);
|
|
30757
30888
|
const lkgSnapshotStartedAt = performance.now();
|
|
30889
|
+
if (cacheBustingPass) {
|
|
30890
|
+
dropSlot(sessionId, "lkg_cache_bust_pending_capture");
|
|
30891
|
+
}
|
|
30758
30892
|
const capturePlan = prepareRustCapture(state, sessionId, messages, pendingWireCache.rawContentSnapshots, response, rowVersion);
|
|
30759
30893
|
let captureMode = "async";
|
|
30760
30894
|
const captureFailed = (mode, error) => {
|
|
@@ -30804,6 +30938,11 @@ function createRustModeTransform(deps, options) {
|
|
|
30804
30938
|
}
|
|
30805
30939
|
throw error;
|
|
30806
30940
|
}
|
|
30941
|
+
try {
|
|
30942
|
+
mirrorRustRenderedMemoryIds({ db: deps.db, sessionId, response });
|
|
30943
|
+
} catch (error) {
|
|
30944
|
+
sessionLog(sessionId, "rust rendered-memory mirror write failed (ignored):", error);
|
|
30945
|
+
}
|
|
30807
30946
|
if (deliveryPassIds.length > 0) {
|
|
30808
30947
|
try {
|
|
30809
30948
|
await sendNoteDeliveryDisposition("transform.ack");
|
|
@@ -31360,16 +31499,6 @@ function createTransform(deps) {
|
|
|
31360
31499
|
sessionLog(sessionId, "transform skipped (internal magic-context child session)");
|
|
31361
31500
|
return;
|
|
31362
31501
|
}
|
|
31363
|
-
if (deps.transformMode === "rust") {
|
|
31364
|
-
if (!rustModeTransform) {
|
|
31365
|
-
sessionLog(sessionId, "rust transform unavailable; using raw passthrough");
|
|
31366
|
-
return;
|
|
31367
|
-
}
|
|
31368
|
-
await rustModeTransform.run(sessionId, messages, output, sessionMeta);
|
|
31369
|
-
return;
|
|
31370
|
-
}
|
|
31371
|
-
const reducedMode = sessionMeta.isSubagent;
|
|
31372
|
-
const fullFeatureMode = !reducedMode;
|
|
31373
31502
|
const compactionOff = deps.compactionOff === true;
|
|
31374
31503
|
try {
|
|
31375
31504
|
const transition = reconcileCompactionMode({
|
|
@@ -31411,6 +31540,18 @@ function createTransform(deps) {
|
|
|
31411
31540
|
passOutcome.record("compaction-mode-transition-failure");
|
|
31412
31541
|
sessionLog(sessionId, "compaction mode transition failed (retrying next pass):", error);
|
|
31413
31542
|
}
|
|
31543
|
+
if (deps.transformMode === "rust") {
|
|
31544
|
+
if (compactionOff)
|
|
31545
|
+
return;
|
|
31546
|
+
if (!rustModeTransform) {
|
|
31547
|
+
sessionLog(sessionId, "rust transform unavailable; using raw passthrough");
|
|
31548
|
+
return;
|
|
31549
|
+
}
|
|
31550
|
+
await rustModeTransform.run(sessionId, messages, output, sessionMeta);
|
|
31551
|
+
return;
|
|
31552
|
+
}
|
|
31553
|
+
const reducedMode = sessionMeta.isSubagent;
|
|
31554
|
+
const fullFeatureMode = !reducedMode;
|
|
31414
31555
|
const ctxReduceAvailability = resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
|
|
31415
31556
|
const ctxReduceCallable = ctxReduceAvailability.callable;
|
|
31416
31557
|
const todowriteAvailability = resolveTodowriteAvailabilityFromMessages(sessionId, messages);
|
|
@@ -33488,37 +33629,49 @@ function createSystemPromptHashHandler(deps) {
|
|
|
33488
33629
|
}
|
|
33489
33630
|
const isCacheBusting = deps.systemPromptRefreshSessions.has(sessionId);
|
|
33490
33631
|
const DATE_PATTERN = /Today's date: .+/;
|
|
33632
|
+
const DATE_PATTERN_ALL = /Today's date: .+/g;
|
|
33633
|
+
const liveSystemContent = output.system.join(`
|
|
33634
|
+
`);
|
|
33635
|
+
if (liveSystemContent.length === 0)
|
|
33636
|
+
return;
|
|
33637
|
+
const previousHash = sessionMetaEarly?.systemPromptHash ?? "";
|
|
33638
|
+
const hasPersistedHash = previousHash !== "" && previousHash !== "0";
|
|
33639
|
+
const dateElementIndexes = [];
|
|
33640
|
+
let currentDate;
|
|
33491
33641
|
for (let i = 0;i < output.system.length; i++) {
|
|
33492
33642
|
const match = output.system[i].match(DATE_PATTERN);
|
|
33493
33643
|
if (!match)
|
|
33494
33644
|
continue;
|
|
33495
|
-
|
|
33496
|
-
|
|
33497
|
-
|
|
33645
|
+
dateElementIndexes.push(i);
|
|
33646
|
+
currentDate ??= match[0];
|
|
33647
|
+
}
|
|
33648
|
+
const stickyDate = stickyDateBySession.get(sessionId);
|
|
33649
|
+
const stableCandidate = currentDate && stickyDate && currentDate !== stickyDate ? liveSystemContent.replace(DATE_PATTERN_ALL, stickyDate) : liveSystemContent;
|
|
33650
|
+
const stableCandidateHash = createHash14("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
|
|
33651
|
+
const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
|
|
33652
|
+
const dateMayAdvance = isCacheBusting || contentOrPresetChanged;
|
|
33653
|
+
if (currentDate && !stickyDate) {
|
|
33654
|
+
stickyDateBySession.set(sessionId, currentDate);
|
|
33655
|
+
} else if (currentDate && stickyDate && currentDate !== stickyDate) {
|
|
33656
|
+
if (dateMayAdvance) {
|
|
33498
33657
|
stickyDateBySession.set(sessionId, currentDate);
|
|
33499
|
-
|
|
33500
|
-
|
|
33501
|
-
|
|
33502
|
-
|
|
33503
|
-
} else {
|
|
33504
|
-
output.system[i] = output.system[i].replace(DATE_PATTERN, stickyDate);
|
|
33505
|
-
sessionLog(sessionId, `system prompt date frozen: real=${currentDate}, using=${stickyDate} (defer pass)`);
|
|
33658
|
+
sessionLog(sessionId, `system prompt date updated: ${stickyDate} → ${currentDate} (cache-busting pass)`);
|
|
33659
|
+
} else if (dateElementIndexes.length > 0) {
|
|
33660
|
+
for (const index of dateElementIndexes) {
|
|
33661
|
+
output.system[index] = output.system[index].replace(DATE_PATTERN_ALL, stickyDate);
|
|
33506
33662
|
}
|
|
33663
|
+
sessionLog(sessionId, `system prompt date frozen: real=${currentDate}, using=${stickyDate} (defer pass)`);
|
|
33507
33664
|
}
|
|
33508
|
-
break;
|
|
33509
33665
|
}
|
|
33510
33666
|
const systemContent = output.system.join(`
|
|
33511
33667
|
`);
|
|
33512
|
-
if (
|
|
33513
|
-
return;
|
|
33514
|
-
if (!availability.frozen)
|
|
33668
|
+
if (!availability.frozen || !modelKey)
|
|
33515
33669
|
return;
|
|
33516
33670
|
const currentHash = createHash14("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
|
|
33517
33671
|
if (!sessionMetaEarly) {
|
|
33518
33672
|
return;
|
|
33519
33673
|
}
|
|
33520
33674
|
const sessionMeta = sessionMetaEarly;
|
|
33521
|
-
const previousHash = sessionMeta.systemPromptHash;
|
|
33522
33675
|
if (previousHash !== "" && previousHash !== "0" && previousHash !== currentHash) {
|
|
33523
33676
|
sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${systemContent.length}), triggering flush`);
|
|
33524
33677
|
deps.historyRefreshSessions.add(sessionId);
|
|
@@ -33691,6 +33844,37 @@ function notifyMagicContextDisabled(client, reason) {
|
|
|
33691
33844
|
log("[magic-context] failed to show disabled toast:", error);
|
|
33692
33845
|
});
|
|
33693
33846
|
}
|
|
33847
|
+
function moduleNoteRowId(response, depth = 0) {
|
|
33848
|
+
if (depth > 4 || response === null || response === undefined)
|
|
33849
|
+
return null;
|
|
33850
|
+
if (typeof response === "string") {
|
|
33851
|
+
const match = response.match(/\b(?:smart\s+)?note\s+#(\d+)/i);
|
|
33852
|
+
return match ? Number(match[1]) : null;
|
|
33853
|
+
}
|
|
33854
|
+
if (Array.isArray(response)) {
|
|
33855
|
+
for (const item of response) {
|
|
33856
|
+
const id = moduleNoteRowId(item, depth + 1);
|
|
33857
|
+
if (id !== null)
|
|
33858
|
+
return id;
|
|
33859
|
+
}
|
|
33860
|
+
return null;
|
|
33861
|
+
}
|
|
33862
|
+
if (typeof response !== "object")
|
|
33863
|
+
return null;
|
|
33864
|
+
const record = response;
|
|
33865
|
+
return moduleNoteRowId(record.result, depth + 1) ?? moduleNoteRowId(record.content, depth + 1) ?? moduleNoteRowId(record.text, depth + 1);
|
|
33866
|
+
}
|
|
33867
|
+
function moduleNoteResponseIsError(response, depth = 0) {
|
|
33868
|
+
if (depth > 4 || response === null || typeof response !== "object")
|
|
33869
|
+
return false;
|
|
33870
|
+
if (Array.isArray(response)) {
|
|
33871
|
+
return response.some((item) => moduleNoteResponseIsError(item, depth + 1));
|
|
33872
|
+
}
|
|
33873
|
+
const record = response;
|
|
33874
|
+
if (record.isError === true || record.ok === false || record.error !== undefined)
|
|
33875
|
+
return true;
|
|
33876
|
+
return moduleNoteResponseIsError(record.result, depth + 1);
|
|
33877
|
+
}
|
|
33694
33878
|
function createMagicContextHook(deps) {
|
|
33695
33879
|
const contextUsageMap = new Map;
|
|
33696
33880
|
let db;
|
|
@@ -33965,6 +34149,7 @@ function createMagicContextHook(deps) {
|
|
|
33965
34149
|
autoEmbedAttemptedBySession.add(sessionId);
|
|
33966
34150
|
const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
|
|
33967
34151
|
(async () => {
|
|
34152
|
+
let completedDrainWithWork = false;
|
|
33968
34153
|
try {
|
|
33969
34154
|
await new Promise((resolve3) => setTimeout(resolve3, 0));
|
|
33970
34155
|
await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
|
|
@@ -33986,6 +34171,8 @@ function createMagicContextHook(deps) {
|
|
|
33986
34171
|
});
|
|
33987
34172
|
}
|
|
33988
34173
|
const summary = await executeEmbedHistory(sessionId);
|
|
34174
|
+
const completedCoverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
|
|
34175
|
+
completedDrainWithWork = completedCoverage.session.total - completedCoverage.session.embedded <= 0;
|
|
33989
34176
|
if (!isTuiConnected(sessionId)) {
|
|
33990
34177
|
await sendIgnoredMessage(deps.client, sessionId, summary, {
|
|
33991
34178
|
...notifyParams
|
|
@@ -33993,6 +34180,9 @@ function createMagicContextHook(deps) {
|
|
|
33993
34180
|
}
|
|
33994
34181
|
} catch (error) {
|
|
33995
34182
|
log("[magic-context] auto-embed drain failed:", error);
|
|
34183
|
+
} finally {
|
|
34184
|
+
if (!completedDrainWithWork)
|
|
34185
|
+
autoEmbedAttemptedBySession.delete(sessionId);
|
|
33996
34186
|
}
|
|
33997
34187
|
})();
|
|
33998
34188
|
};
|
|
@@ -34082,6 +34272,10 @@ function createMagicContextHook(deps) {
|
|
|
34082
34272
|
action,
|
|
34083
34273
|
content,
|
|
34084
34274
|
surfaceCondition,
|
|
34275
|
+
compiledProvider,
|
|
34276
|
+
compiledConfig,
|
|
34277
|
+
compiledAt,
|
|
34278
|
+
compileStatus,
|
|
34085
34279
|
filter,
|
|
34086
34280
|
limit,
|
|
34087
34281
|
offset,
|
|
@@ -34107,6 +34301,22 @@ function createMagicContextHook(deps) {
|
|
|
34107
34301
|
}
|
|
34108
34302
|
});
|
|
34109
34303
|
await syncModuleNotes();
|
|
34304
|
+
if (compileStatus && !moduleNoteResponseIsError(response)) {
|
|
34305
|
+
const moduleRowId = action === "write" ? moduleNoteRowId(response) : noteId ?? null;
|
|
34306
|
+
if (moduleRowId === null || !applyMirroredNoteCompileFields({
|
|
34307
|
+
db,
|
|
34308
|
+
moduleProject: memoryProject,
|
|
34309
|
+
moduleRowId,
|
|
34310
|
+
fields: {
|
|
34311
|
+
compiledProvider: compiledProvider ?? null,
|
|
34312
|
+
compiledConfig: compiledConfig ?? null,
|
|
34313
|
+
compiledAt: compiledAt ?? null,
|
|
34314
|
+
compileStatus
|
|
34315
|
+
}
|
|
34316
|
+
})) {
|
|
34317
|
+
throw new Error("Rust note was written but its host compilation metadata could not be mirrored");
|
|
34318
|
+
}
|
|
34319
|
+
}
|
|
34110
34320
|
return response;
|
|
34111
34321
|
},
|
|
34112
34322
|
memory: async ({
|
|
@@ -35417,7 +35627,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35417
35627
|
const db = getDb();
|
|
35418
35628
|
if (!db)
|
|
35419
35629
|
return { ok: false, error: "db unavailable" };
|
|
35420
|
-
const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-
|
|
35630
|
+
const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-a0g9b52q.js");
|
|
35421
35631
|
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
|
|
35422
35632
|
log(`[rpc] recomp requested for session ${sessionId}`);
|
|
35423
35633
|
const ctx = await buildManagedCtx(db);
|
|
@@ -35433,7 +35643,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35433
35643
|
const db = getDb();
|
|
35434
35644
|
if (!db)
|
|
35435
35645
|
return { ok: false, error: "db unavailable" };
|
|
35436
|
-
const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-
|
|
35646
|
+
const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-a0g9b52q.js");
|
|
35437
35647
|
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
|
|
35438
35648
|
log(`[rpc] session-upgrade requested for session ${sessionId}`);
|
|
35439
35649
|
const ctx = await buildManagedCtx(db);
|
|
@@ -35450,7 +35660,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35450
35660
|
if (!db)
|
|
35451
35661
|
return { ok: false, error: "db unavailable" };
|
|
35452
35662
|
try {
|
|
35453
|
-
const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-
|
|
35663
|
+
const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-df9tstzr.js");
|
|
35454
35664
|
updateSessionMeta2(db, sessionId, { upgradeRemindedAt: Date.now() });
|
|
35455
35665
|
return { ok: true };
|
|
35456
35666
|
} catch (error) {
|
|
@@ -36428,6 +36638,16 @@ class ProviderError extends Error {
|
|
|
36428
36638
|
|
|
36429
36639
|
// ../retina-local-fs/src/path-fence.ts
|
|
36430
36640
|
async function resolveAndFenceProviderPath(configuredPath, options) {
|
|
36641
|
+
const { home, dataDirectory } = await resolveFenceRoots(options);
|
|
36642
|
+
const expanded = configuredPath.startsWith("~/") ? join6(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
|
|
36643
|
+
const absolute = isAbsolute3(expanded) ? resolve3(expanded) : resolve3(options.cwd ?? process.cwd(), expanded);
|
|
36644
|
+
const canonical = await canonicalPath(absolute, options.allowMissing);
|
|
36645
|
+
if (isFencedPath(canonical, home, dataDirectory)) {
|
|
36646
|
+
throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
|
|
36647
|
+
}
|
|
36648
|
+
return canonical;
|
|
36649
|
+
}
|
|
36650
|
+
async function resolveFenceRoots(options) {
|
|
36431
36651
|
const configuredHomePath = resolve3(options.homeDirectory ?? process.env.HOME ?? homedir4());
|
|
36432
36652
|
let home;
|
|
36433
36653
|
try {
|
|
@@ -36435,13 +36655,9 @@ async function resolveAndFenceProviderPath(configuredPath, options) {
|
|
|
36435
36655
|
} catch (error) {
|
|
36436
36656
|
throw fsError(configuredHomePath, error);
|
|
36437
36657
|
}
|
|
36438
|
-
const
|
|
36439
|
-
const
|
|
36440
|
-
|
|
36441
|
-
if (isFencedPath(canonical, home)) {
|
|
36442
|
-
throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
|
|
36443
|
-
}
|
|
36444
|
-
return canonical;
|
|
36658
|
+
const configuredDataDirectory = resolve3(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join6(home, ".local", "share"));
|
|
36659
|
+
const dataDirectory = await canonicalPath(configuredDataDirectory, true);
|
|
36660
|
+
return { home, dataDirectory };
|
|
36445
36661
|
}
|
|
36446
36662
|
async function canonicalPath(path6, allowMissing) {
|
|
36447
36663
|
try {
|
|
@@ -36481,9 +36697,8 @@ async function canonicalPath(path6, allowMissing) {
|
|
|
36481
36697
|
}
|
|
36482
36698
|
}
|
|
36483
36699
|
}
|
|
36484
|
-
function isFencedPath(canonicalPath2, homeDirectory) {
|
|
36485
|
-
const
|
|
36486
|
-
const cortexkitRoot = join6(home, ".local", "share", "cortexkit");
|
|
36700
|
+
function isFencedPath(canonicalPath2, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join6(resolve3(homeDirectory), ".local", "share")) {
|
|
36701
|
+
const cortexkitRoot = join6(resolve3(dataDirectory), "cortexkit");
|
|
36487
36702
|
const relativeToCortexkit = relative(cortexkitRoot, canonicalPath2);
|
|
36488
36703
|
const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute3(relativeToCortexkit);
|
|
36489
36704
|
const parts = insideCortexkit ? relativeToCortexkit.split(sep) : [];
|
|
@@ -36492,10 +36707,11 @@ function isFencedPath(canonicalPath2, homeDirectory) {
|
|
|
36492
36707
|
const catalogDirectoryCarveIn = pathParts.includes("catalog");
|
|
36493
36708
|
const moduleBinCarveIn = parts.length >= 2 && parts[1] === "bin";
|
|
36494
36709
|
const catalogJsonCarveIn = name.endsWith(".json") && name.includes("catalog");
|
|
36495
|
-
|
|
36710
|
+
const rootWithoutCarveIns = insideCortexkit && (parts[0] === "run" || parts[0] === "magic-context");
|
|
36711
|
+
if (!rootWithoutCarveIns && (catalogDirectoryCarveIn || moduleBinCarveIn || catalogJsonCarveIn)) {
|
|
36496
36712
|
return false;
|
|
36497
36713
|
}
|
|
36498
|
-
const inFencedRoot = insideCortexkit && ["plexus", "claustrum", "staging"].includes(parts[0] ?? "");
|
|
36714
|
+
const inFencedRoot = insideCortexkit && ["plexus", "claustrum", "staging", "run", "magic-context"].includes(parts[0] ?? "");
|
|
36499
36715
|
const fencedBasename = name.includes("binding-key") || name.endsWith(".handle");
|
|
36500
36716
|
const plexusStore = insideCortexkit && parts[0] === "plexus" && name.startsWith("store.db");
|
|
36501
36717
|
return inFencedRoot || fencedBasename || plexusStore;
|
|
@@ -36645,6 +36861,9 @@ function invalid(message) {
|
|
|
36645
36861
|
var RETINA_LOCAL_FS_PROVIDER = "local-fs";
|
|
36646
36862
|
var VALUE = String.raw`(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+)`;
|
|
36647
36863
|
async function compileSurfaceCondition(surfaceCondition, options) {
|
|
36864
|
+
const plainReason = unsafeGrammarReason(surfaceCondition);
|
|
36865
|
+
if (plainReason)
|
|
36866
|
+
return { status: "plain", reason: plainReason };
|
|
36648
36867
|
const parsed = parseCondition(surfaceCondition, options.projectPath);
|
|
36649
36868
|
if (parsed === null)
|
|
36650
36869
|
return { status: "plain" };
|
|
@@ -36726,23 +36945,27 @@ function parseCondition(surfaceCondition, projectPath) {
|
|
|
36726
36945
|
return predicates.every((predicate) => predicate !== null) ? predicates : null;
|
|
36727
36946
|
}
|
|
36728
36947
|
function parseAtomicCondition(text, projectPath) {
|
|
36729
|
-
const fileContains = text.match(new RegExp(`^(?:when\\s+)?file\\s+(${VALUE})\\s+(no longer contains|contains)\\s+(
|
|
36948
|
+
const fileContains = text.match(new RegExp(`^(?:when\\s+)?file\\s+(${VALUE})\\s+(no longer contains|contains)\\s+(${VALUE})$`, "i"));
|
|
36730
36949
|
if (fileContains) {
|
|
36950
|
+
const path6 = unquote(fileContains[1]);
|
|
36731
36951
|
const needle = unquote(fileContains[3].trim());
|
|
36732
|
-
if (needle === null)
|
|
36952
|
+
if (path6 === null || needle === null)
|
|
36733
36953
|
return null;
|
|
36734
36954
|
return {
|
|
36735
36955
|
kind: "file_contains",
|
|
36736
|
-
path:
|
|
36956
|
+
path: path6,
|
|
36737
36957
|
needle,
|
|
36738
36958
|
...fileContains[2].toLowerCase() === "no longer contains" ? { absent: true } : {}
|
|
36739
36959
|
};
|
|
36740
36960
|
}
|
|
36741
36961
|
const commit = text.match(new RegExp(`^(?:when\\s+)?(?:repo(?:sitory)?\\s+)?(${VALUE})\\s+has\\s+a\\s+commit\\s+(?:after|newer than)\\s+([0-9a-f]{7,64})$`, "i"));
|
|
36742
36962
|
if (commit) {
|
|
36963
|
+
const repoPath = unquote(commit[1]);
|
|
36964
|
+
if (repoPath === null)
|
|
36965
|
+
return null;
|
|
36743
36966
|
return {
|
|
36744
36967
|
kind: "git_commit_after",
|
|
36745
|
-
repo_path:
|
|
36968
|
+
repo_path: repoPath,
|
|
36746
36969
|
sha: commit[2]
|
|
36747
36970
|
};
|
|
36748
36971
|
}
|
|
@@ -36762,16 +36985,22 @@ function parseAtomicCondition(text, projectPath) {
|
|
|
36762
36985
|
}
|
|
36763
36986
|
const mtime = text.match(new RegExp(`^(?:when\\s+)?(?:file\\s+)?(${VALUE})\\s+(changes|is rebuilt|mtime moves)$`, "i"));
|
|
36764
36987
|
if (mtime) {
|
|
36988
|
+
const path6 = unquote(mtime[1]);
|
|
36989
|
+
if (path6 === null)
|
|
36990
|
+
return null;
|
|
36765
36991
|
return {
|
|
36766
36992
|
kind: "mtime_after",
|
|
36767
|
-
path:
|
|
36993
|
+
path: path6
|
|
36768
36994
|
};
|
|
36769
36995
|
}
|
|
36770
36996
|
const pathExists = text.match(new RegExp(`^(?:when\\s+)?(?:path\\s+)?(${VALUE})\\s+(exists|is gone)$`, "i"));
|
|
36771
36997
|
if (pathExists) {
|
|
36998
|
+
const path6 = unquote(pathExists[1]);
|
|
36999
|
+
if (path6 === null)
|
|
37000
|
+
return null;
|
|
36772
37001
|
return {
|
|
36773
37002
|
kind: "path_exists",
|
|
36774
|
-
path:
|
|
37003
|
+
path: path6,
|
|
36775
37004
|
...pathExists[2].toLowerCase() === "is gone" ? { gone: true } : {}
|
|
36776
37005
|
};
|
|
36777
37006
|
}
|
|
@@ -36826,12 +37055,42 @@ function splitOrClauses(text) {
|
|
|
36826
37055
|
clauses.push(text.slice(start).trim());
|
|
36827
37056
|
return clauses.filter(Boolean);
|
|
36828
37057
|
}
|
|
37058
|
+
function unsafeGrammarReason(value) {
|
|
37059
|
+
let quote = null;
|
|
37060
|
+
let escaped = false;
|
|
37061
|
+
for (const character of value) {
|
|
37062
|
+
if (escaped) {
|
|
37063
|
+
escaped = false;
|
|
37064
|
+
continue;
|
|
37065
|
+
}
|
|
37066
|
+
if (quote && character === "\\") {
|
|
37067
|
+
escaped = true;
|
|
37068
|
+
continue;
|
|
37069
|
+
}
|
|
37070
|
+
if (character === '"' || character === "'") {
|
|
37071
|
+
quote = quote === character ? null : quote === null ? character : quote;
|
|
37072
|
+
}
|
|
37073
|
+
}
|
|
37074
|
+
if (quote !== null)
|
|
37075
|
+
return "unbalanced quote; leaving condition dreamer-evaluated";
|
|
37076
|
+
if (/\bcontains\s+no(?:\s|$)/i.test(value)) {
|
|
37077
|
+
return "ambiguous negation after contains; leaving condition dreamer-evaluated";
|
|
37078
|
+
}
|
|
37079
|
+
const temporalSuffix = new RegExp(`\\bcontains\\s+${VALUE}\\s+(?:since|until|after|before|when|while|for|as\\s+of)\\b`, "i");
|
|
37080
|
+
if (temporalSuffix.test(value)) {
|
|
37081
|
+
return "temporal suffix after contains; leaving condition dreamer-evaluated";
|
|
37082
|
+
}
|
|
37083
|
+
return null;
|
|
37084
|
+
}
|
|
36829
37085
|
function unquote(value) {
|
|
36830
|
-
if (value.length < 2)
|
|
36831
|
-
return value;
|
|
36832
37086
|
const quote = value[0];
|
|
36833
|
-
|
|
37087
|
+
const final = value.at(-1);
|
|
37088
|
+
const startsQuoted = quote === '"' || quote === "'";
|
|
37089
|
+
const endsQuoted = final === '"' || final === "'";
|
|
37090
|
+
if (!startsQuoted && !endsQuoted)
|
|
36834
37091
|
return value;
|
|
37092
|
+
if (!startsQuoted || final !== quote || value.length < 2)
|
|
37093
|
+
return null;
|
|
36835
37094
|
if (quote === '"') {
|
|
36836
37095
|
try {
|
|
36837
37096
|
const parsed = JSON.parse(value);
|
|
@@ -37026,8 +37285,15 @@ function createCtxNoteTool(deps) {
|
|
|
37026
37285
|
if (!rustNote || !projectIdentity) {
|
|
37027
37286
|
return "Error: Rust notes authority is active, but this module transport does not support ctx_note.";
|
|
37028
37287
|
}
|
|
37029
|
-
|
|
37030
|
-
|
|
37288
|
+
const surfaceCondition = args.surface_condition?.trim();
|
|
37289
|
+
let compilation;
|
|
37290
|
+
if ((action === "write" || action === "update") && surfaceCondition) {
|
|
37291
|
+
if (deps.rustToolBackends?.noteEvaluationAvailable?.(projectIdentity) !== true) {
|
|
37292
|
+
return "Error: Smart-note evaluation is unavailable for this Rust-authority project; the note was not written.";
|
|
37293
|
+
}
|
|
37294
|
+
compilation = await compileSurfaceCondition(surfaceCondition, {
|
|
37295
|
+
projectPath: toolContext.directory
|
|
37296
|
+
});
|
|
37031
37297
|
}
|
|
37032
37298
|
const commandId = toolCallIdFromContext(toolContext);
|
|
37033
37299
|
const request2 = {
|
|
@@ -37038,7 +37304,8 @@ function createCtxNoteTool(deps) {
|
|
|
37038
37304
|
memoryProject: projectIdentity,
|
|
37039
37305
|
action,
|
|
37040
37306
|
content: args.content,
|
|
37041
|
-
surfaceCondition
|
|
37307
|
+
surfaceCondition,
|
|
37308
|
+
...compilation ? conditionCompileStorageFields(compilation) : {},
|
|
37042
37309
|
filter: args.filter,
|
|
37043
37310
|
limit: args.limit,
|
|
37044
37311
|
offset: args.offset,
|
|
@@ -37046,9 +37313,13 @@ function createCtxNoteTool(deps) {
|
|
|
37046
37313
|
};
|
|
37047
37314
|
try {
|
|
37048
37315
|
const text = moduleNoteText(await rustNote(request2));
|
|
37049
|
-
if (text
|
|
37050
|
-
return
|
|
37051
|
-
|
|
37316
|
+
if (text === null) {
|
|
37317
|
+
return "Error: Rust module returned an invalid ctx_note response.";
|
|
37318
|
+
}
|
|
37319
|
+
if (compilation && !text.startsWith("Error:")) {
|
|
37320
|
+
return text + conditionCompileReplySuffix(compilation);
|
|
37321
|
+
}
|
|
37322
|
+
return text;
|
|
37052
37323
|
} catch (error) {
|
|
37053
37324
|
if (isRustAuthorityDrainingError(error)) {
|
|
37054
37325
|
return "Error: Rust notes authority is not ready; TypeScript fallback is disabled.";
|
|
@@ -38200,7 +38471,7 @@ var server = async (ctx) => {
|
|
|
38200
38471
|
{
|
|
38201
38472
|
const fence = getSchemaFenceRejection();
|
|
38202
38473
|
if (fence) {
|
|
38203
|
-
import("./conflict-warning-hook-
|
|
38474
|
+
import("./conflict-warning-hook-mt0ttc4x.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
|
|
38204
38475
|
}
|
|
38205
38476
|
}
|
|
38206
38477
|
if (conflictResult?.hasConflict) {
|
|
@@ -38221,7 +38492,7 @@ var server = async (ctx) => {
|
|
|
38221
38492
|
} = await import("./announcement-6c1g4es4.js");
|
|
38222
38493
|
if (shouldShowAnnouncement2()) {
|
|
38223
38494
|
setTimeout(() => {
|
|
38224
|
-
import("./conflict-warning-hook-
|
|
38495
|
+
import("./conflict-warning-hook-mt0ttc4x.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
|
|
38225
38496
|
}, 8000);
|
|
38226
38497
|
}
|
|
38227
38498
|
} catch {}
|
|
@@ -38273,6 +38544,7 @@ var server = async (ctx) => {
|
|
|
38273
38544
|
await magicContextRuntime.magicContext?.["command.execute.before"]?.(input, output);
|
|
38274
38545
|
},
|
|
38275
38546
|
"chat.message": async (input, _output) => {
|
|
38547
|
+
await preloadTokenizer();
|
|
38276
38548
|
const typed = input;
|
|
38277
38549
|
const provId = typed.model?.providerID;
|
|
38278
38550
|
const modId = typed.model?.modelID;
|