@cortexkit/opencode-magic-context 0.34.1 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/agents/magic-context-prompt.d.ts +2 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +3 -0
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +42 -1
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-fvpfvt0w.js → conflict-warning-hook-p2pmhvn7.js} +2 -1
- package/dist/features/magic-context/context-authority.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/provider-output-failure.d.ts +15 -0
- package/dist/features/magic-context/dreamer/provider-output-failure.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +9 -5
- package/dist/features/magic-context/dreamer/storage-task-schedule.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-gates.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-gate.d.ts +8 -2
- package/dist/features/magic-context/dreamer/verify-gate.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/fail-closed-block.d.ts +2 -0
- package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts +13 -5
- package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
- package/dist/features/magic-context/mural/cue-validation.d.ts +7 -7
- package/dist/features/magic-context/mural/cue-validation.d.ts.map +1 -1
- package/dist/features/magic-context/mural/storage-mural-cues.d.ts +17 -7
- package/dist/features/magic-context/mural/storage-mural-cues.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +21 -3
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +1 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -14
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts +16 -2
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +1 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +10 -3
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync.d.ts +1 -1
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-transport.d.ts +2 -1
- package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +5 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts +2 -0
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +22 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +19 -5
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-context-state.d.ts +1 -0
- package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +4 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index-0c9dmw9m.js +116 -0
- package/dist/{index-x8spt5wy.js → index-4anesz49.js} +849 -633
- package/dist/{index-dtas91s5.js → index-8aaadh98.js} +7 -119
- package/dist/{index-b563sga5.js → index-h8mk7vpa.js} +541 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1010 -840
- package/dist/plugin/hooks/create-session-hooks.d.ts +12 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +1 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts +4 -0
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-k72ejkkh.js → recomp-orchestrator-zc915ceq.js} +3 -2
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/prompt-surface-runtime.d.ts +43 -0
- package/dist/shared/prompt-surface-runtime.d.ts.map +1 -0
- package/dist/shared/prompt-surface.d.ts +49 -0
- package/dist/shared/prompt-surface.d.ts.map +1 -0
- package/dist/{storage-meta-session-xt41zbw4.js → storage-meta-session-53cjs6mr.js} +1 -1
- package/dist/tools/ctx-expand/tools.d.ts +1 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-memory/tools.d.ts +1 -0
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts +1 -0
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +1 -0
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts +1 -0
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tools/light-descriptions.d.ts +6 -0
- package/dist/tools/light-descriptions.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/agents/magic-context-prompt.test.ts +144 -0
- package/src/agents/magic-context-prompt.ts +53 -2
- package/src/config/index.test.ts +53 -0
- package/src/config/index.ts +4 -0
- package/src/config/project-security.test.ts +20 -0
- package/src/config/project-security.ts +23 -0
- package/src/config/schema/magic-context.test.ts +58 -0
- package/src/config/schema/magic-context.ts +61 -1
- package/src/shared/index.ts +2 -0
- package/src/shared/prompt-surface-a1-golden.md +458 -0
- package/src/shared/prompt-surface-runtime.test.ts +141 -0
- package/src/shared/prompt-surface-runtime.ts +250 -0
- package/src/shared/prompt-surface.test.ts +109 -0
- package/src/shared/prompt-surface.ts +138 -0
package/dist/index.js
CHANGED
|
@@ -85,11 +85,15 @@ import {
|
|
|
85
85
|
computeNormalizedHash,
|
|
86
86
|
computeWorkspaceEpochFingerprint,
|
|
87
87
|
contentSha256,
|
|
88
|
+
cortexKitProjectConfigBasePath,
|
|
89
|
+
cortexKitUserConfigBasePath,
|
|
88
90
|
cosineSimilarity,
|
|
89
91
|
countEmbeddedCommits,
|
|
90
92
|
countPrimerCandidatesForProject,
|
|
91
93
|
createChildSessionWithFence,
|
|
92
94
|
createPrimer,
|
|
95
|
+
createPromptSurfaceGuidanceEpochCache,
|
|
96
|
+
createPromptSurfaceRuntime,
|
|
93
97
|
deleteTagsByMessageId,
|
|
94
98
|
deleteUserMemoryCandidates,
|
|
95
99
|
deriveTagLoadFloor,
|
|
@@ -111,7 +115,6 @@ import {
|
|
|
111
115
|
ensureContextStoreUuid,
|
|
112
116
|
ensureMemoryEmbeddings,
|
|
113
117
|
escalationBands,
|
|
114
|
-
estimateTrueRawMessageTokens,
|
|
115
118
|
expandWorkspaceIdentitySetWithAliases,
|
|
116
119
|
exports_external,
|
|
117
120
|
extractLatestAssistantText,
|
|
@@ -138,6 +141,7 @@ import {
|
|
|
138
141
|
getDroppedTagsBySession,
|
|
139
142
|
getEmbeddingCoverageStatus,
|
|
140
143
|
getEmergencyInputSample,
|
|
144
|
+
getEmergencyRecoveryArmedAt,
|
|
141
145
|
getHistorianFailureState,
|
|
142
146
|
getLastCompartmentEndMessage,
|
|
143
147
|
getLastCompartmentEndMessageId,
|
|
@@ -219,7 +223,6 @@ import {
|
|
|
219
223
|
insertUserMemoryCandidates,
|
|
220
224
|
invalidateMemory,
|
|
221
225
|
invalidateProject,
|
|
222
|
-
invalidateTrueRawTokenCache,
|
|
223
226
|
isConsumerReconnectTransient,
|
|
224
227
|
isDatabasePersisted,
|
|
225
228
|
isEmbeddingEnabled,
|
|
@@ -240,6 +243,7 @@ import {
|
|
|
240
243
|
markProjectLoadUntrusted,
|
|
241
244
|
memoryNeedsCue,
|
|
242
245
|
mergeMemoryStats,
|
|
246
|
+
migrateMagicContextConfigLocations,
|
|
243
247
|
mustMaterialize,
|
|
244
248
|
nextDueAtMs,
|
|
245
249
|
nextOccurrence,
|
|
@@ -261,6 +265,7 @@ import {
|
|
|
261
265
|
prepareCompartmentInjection,
|
|
262
266
|
primerOccurrenceKey,
|
|
263
267
|
primerOccurrenceUtcDay,
|
|
268
|
+
promptSurfaceHashMaterial,
|
|
264
269
|
promptSyncWithValidatedOutputRetry,
|
|
265
270
|
pruneAutoSearchHintDecisions,
|
|
266
271
|
pruneExpiredUserMemoryCandidates,
|
|
@@ -279,6 +284,7 @@ import {
|
|
|
279
284
|
recordHighPressureNoEligibleHead,
|
|
280
285
|
recordMemoryMapping,
|
|
281
286
|
recordMemoryVerifications,
|
|
287
|
+
recordMuralCueRejection,
|
|
282
288
|
recordOverflowDetected,
|
|
283
289
|
recordSessionProjectIdentity,
|
|
284
290
|
recordToolDefinition,
|
|
@@ -307,10 +313,14 @@ import {
|
|
|
307
313
|
resetProtectedTailNoEligibleHead,
|
|
308
314
|
resolveCompactionModeRecord,
|
|
309
315
|
resolveGitTopLevel,
|
|
316
|
+
resolveLegacyConfigSources,
|
|
317
|
+
resolveLegacyConfigSourcesForHarness,
|
|
318
|
+
resolveModelConfigOrDefault,
|
|
310
319
|
resolveOpenCodeProtectedTailBoundary,
|
|
311
320
|
resolveProjectIdentity,
|
|
312
321
|
resolveProjectIdentityForSession,
|
|
313
322
|
resolveProjectIdentityStrict,
|
|
323
|
+
resolvePromptSurface,
|
|
314
324
|
resolveStoredPathWorkspaceIdentity,
|
|
315
325
|
resolveWorkspaceIdentitySet,
|
|
316
326
|
resolveWorkspaceShareCategories,
|
|
@@ -372,7 +382,7 @@ import {
|
|
|
372
382
|
upsertCommits,
|
|
373
383
|
verificationFileExists,
|
|
374
384
|
withContentLanguageDirective
|
|
375
|
-
} from "./index-
|
|
385
|
+
} from "./index-4anesz49.js";
|
|
376
386
|
import {
|
|
377
387
|
deriveHistorianChunkTokens,
|
|
378
388
|
deriveTriggerBudget,
|
|
@@ -409,6 +419,7 @@ import {
|
|
|
409
419
|
createToolDropTarget,
|
|
410
420
|
deleteIndexedMessage,
|
|
411
421
|
estimateTokens,
|
|
422
|
+
estimateTrueRawMessageTokens,
|
|
412
423
|
extractInMemoryMessageViews,
|
|
413
424
|
extractTexts,
|
|
414
425
|
extractToolCallObservation,
|
|
@@ -422,6 +433,7 @@ import {
|
|
|
422
433
|
hasMeaningfulUserText,
|
|
423
434
|
indexMessagesAfterOrdinal,
|
|
424
435
|
indexSingleMessage,
|
|
436
|
+
invalidateTrueRawTokenCache,
|
|
425
437
|
isEditTool,
|
|
426
438
|
isFilePart,
|
|
427
439
|
isMessageIndexReconciledThrough,
|
|
@@ -451,7 +463,7 @@ import {
|
|
|
451
463
|
textMentionsRecentCommit,
|
|
452
464
|
updateSessionMeta,
|
|
453
465
|
withRawSessionMessageCache
|
|
454
|
-
} from "./index-
|
|
466
|
+
} from "./index-h8mk7vpa.js";
|
|
455
467
|
import {
|
|
456
468
|
Database,
|
|
457
469
|
closeQuietly,
|
|
@@ -463,12 +475,14 @@ import {
|
|
|
463
475
|
} from "./index-fcyvznch.js";
|
|
464
476
|
import {
|
|
465
477
|
cleanupConflictWarnings,
|
|
466
|
-
detectConfigFile,
|
|
467
478
|
detectConflicts,
|
|
479
|
+
sendConflictWarning
|
|
480
|
+
} from "./index-8aaadh98.js";
|
|
481
|
+
import {
|
|
482
|
+
detectConfigFile,
|
|
468
483
|
parseJsonc,
|
|
469
|
-
sendConflictWarning,
|
|
470
484
|
stripJsonComments
|
|
471
|
-
} from "./index-
|
|
485
|
+
} from "./index-0c9dmw9m.js";
|
|
472
486
|
import {
|
|
473
487
|
ANNOUNCEMENT_FEATURES,
|
|
474
488
|
ANNOUNCEMENT_FOOTER,
|
|
@@ -8188,10 +8202,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
8188
8202
|
replacer = null;
|
|
8189
8203
|
indent = EMPTY;
|
|
8190
8204
|
};
|
|
8191
|
-
var
|
|
8205
|
+
var join = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
|
|
8192
8206
|
var join_content = (inside, value, gap) => {
|
|
8193
8207
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
8194
|
-
return
|
|
8208
|
+
return join(comment, inside, gap);
|
|
8195
8209
|
};
|
|
8196
8210
|
var stringify_string = (holder, key, value) => {
|
|
8197
8211
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -8213,13 +8227,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
8213
8227
|
if (i !== 0) {
|
|
8214
8228
|
inside += COMMA;
|
|
8215
8229
|
}
|
|
8216
|
-
const before =
|
|
8230
|
+
const before = join(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
8217
8231
|
inside += before || LF + deeper_gap;
|
|
8218
8232
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
8219
8233
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
8220
8234
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
8221
8235
|
}
|
|
8222
|
-
inside +=
|
|
8236
|
+
inside += join(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
8223
8237
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
8224
8238
|
};
|
|
8225
8239
|
var object_stringify = (value, gap) => {
|
|
@@ -8240,13 +8254,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
8240
8254
|
inside += COMMA;
|
|
8241
8255
|
}
|
|
8242
8256
|
first = false;
|
|
8243
|
-
const before =
|
|
8257
|
+
const before = join(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
8244
8258
|
inside += before || LF + deeper_gap;
|
|
8245
8259
|
inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
|
|
8246
8260
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
8247
8261
|
};
|
|
8248
8262
|
keys.forEach(iteratee);
|
|
8249
|
-
inside +=
|
|
8263
|
+
inside += join(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
8250
8264
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
8251
8265
|
};
|
|
8252
8266
|
function stringify(key, holder, gap) {
|
|
@@ -8514,7 +8528,7 @@ function buildHiddenAgentConfig(prompt, allowedTools, maxSteps, overrides, agent
|
|
|
8514
8528
|
}
|
|
8515
8529
|
|
|
8516
8530
|
// src/config/index.ts
|
|
8517
|
-
import { existsSync as
|
|
8531
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
8518
8532
|
|
|
8519
8533
|
// src/config/agent-disable.ts
|
|
8520
8534
|
var COMPACTION_ENABLED_PATH = `compaction${"."}enabled`;
|
|
@@ -8576,384 +8590,6 @@ function migrateLegacyAgentEnabledInMemory(rawConfig, warnings) {
|
|
|
8576
8590
|
return patched;
|
|
8577
8591
|
}
|
|
8578
8592
|
|
|
8579
|
-
// src/config/migrate-config-location.ts
|
|
8580
|
-
import {
|
|
8581
|
-
closeSync,
|
|
8582
|
-
existsSync,
|
|
8583
|
-
mkdirSync,
|
|
8584
|
-
openSync,
|
|
8585
|
-
readFileSync,
|
|
8586
|
-
renameSync,
|
|
8587
|
-
rmSync,
|
|
8588
|
-
statSync,
|
|
8589
|
-
unlinkSync,
|
|
8590
|
-
writeFileSync
|
|
8591
|
-
} from "node:fs";
|
|
8592
|
-
import { homedir } from "node:os";
|
|
8593
|
-
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
8594
|
-
var CONFIG_FILE_BASENAME = "magic-context";
|
|
8595
|
-
var MOVED_MARKER_SUFFIX = ".MOVED_READPLEASE";
|
|
8596
|
-
function homeDir() {
|
|
8597
|
-
if (process.platform === "win32") {
|
|
8598
|
-
return process.env.USERPROFILE || process.env.HOME || homedir();
|
|
8599
|
-
}
|
|
8600
|
-
return process.env.HOME || homedir();
|
|
8601
|
-
}
|
|
8602
|
-
function configHome() {
|
|
8603
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
8604
|
-
if (xdg && isAbsolute(xdg))
|
|
8605
|
-
return xdg;
|
|
8606
|
-
return join(homeDir(), ".config");
|
|
8607
|
-
}
|
|
8608
|
-
function cortexKitUserConfigBasePath() {
|
|
8609
|
-
return join(configHome(), "cortexkit", CONFIG_FILE_BASENAME);
|
|
8610
|
-
}
|
|
8611
|
-
function cortexKitProjectConfigBasePath(directory) {
|
|
8612
|
-
return join(directory, ".cortexkit", CONFIG_FILE_BASENAME);
|
|
8613
|
-
}
|
|
8614
|
-
function resolveCortexKitUserConfigPath() {
|
|
8615
|
-
return `${cortexKitUserConfigBasePath()}.jsonc`;
|
|
8616
|
-
}
|
|
8617
|
-
function resolveCortexKitProjectConfigPath(directory) {
|
|
8618
|
-
return `${cortexKitProjectConfigBasePath(directory)}.jsonc`;
|
|
8619
|
-
}
|
|
8620
|
-
function legacySourcesForBase(basePath, label) {
|
|
8621
|
-
return [
|
|
8622
|
-
{ path: `${basePath}.jsonc`, label: `${label} magic-context.jsonc` },
|
|
8623
|
-
{ path: `${basePath}.json`, label: `${label} magic-context.json` }
|
|
8624
|
-
];
|
|
8625
|
-
}
|
|
8626
|
-
function userScopeConfigPaths() {
|
|
8627
|
-
return new Set([
|
|
8628
|
-
`${cortexKitUserConfigBasePath()}.jsonc`,
|
|
8629
|
-
`${cortexKitUserConfigBasePath()}.json`,
|
|
8630
|
-
join(configHome(), "opencode", `${CONFIG_FILE_BASENAME}.jsonc`),
|
|
8631
|
-
join(configHome(), "opencode", `${CONFIG_FILE_BASENAME}.json`),
|
|
8632
|
-
join(homeDir(), ".pi", "agent", `${CONFIG_FILE_BASENAME}.jsonc`),
|
|
8633
|
-
join(homeDir(), ".pi", "agent", `${CONFIG_FILE_BASENAME}.json`)
|
|
8634
|
-
]);
|
|
8635
|
-
}
|
|
8636
|
-
function resolveLegacyConfigSources(directory) {
|
|
8637
|
-
const userPaths = userScopeConfigPaths();
|
|
8638
|
-
return {
|
|
8639
|
-
user: [
|
|
8640
|
-
...legacySourcesForBase(join(configHome(), "opencode", CONFIG_FILE_BASENAME), "OpenCode user"),
|
|
8641
|
-
...legacySourcesForBase(join(homeDir(), ".pi", "agent", CONFIG_FILE_BASENAME), "Pi user")
|
|
8642
|
-
],
|
|
8643
|
-
project: [
|
|
8644
|
-
...legacySourcesForBase(join(directory, CONFIG_FILE_BASENAME), "project root"),
|
|
8645
|
-
...legacySourcesForBase(join(directory, ".opencode", CONFIG_FILE_BASENAME), "OpenCode project"),
|
|
8646
|
-
...legacySourcesForBase(join(directory, ".pi", CONFIG_FILE_BASENAME), "Pi project")
|
|
8647
|
-
].filter((source) => !userPaths.has(source.path))
|
|
8648
|
-
};
|
|
8649
|
-
}
|
|
8650
|
-
function resolveLegacyConfigSourcesForHarness(directory, harness) {
|
|
8651
|
-
if (harness === "pi") {
|
|
8652
|
-
return {
|
|
8653
|
-
user: legacySourcesForBase(join(homeDir(), ".pi", "agent", CONFIG_FILE_BASENAME), "Pi user"),
|
|
8654
|
-
project: legacySourcesForBase(join(directory, ".pi", CONFIG_FILE_BASENAME), "Pi project")
|
|
8655
|
-
};
|
|
8656
|
-
}
|
|
8657
|
-
return {
|
|
8658
|
-
user: legacySourcesForBase(join(configHome(), "opencode", CONFIG_FILE_BASENAME), "OpenCode user"),
|
|
8659
|
-
project: [
|
|
8660
|
-
...legacySourcesForBase(join(directory, CONFIG_FILE_BASENAME), "project root"),
|
|
8661
|
-
...legacySourcesForBase(join(directory, ".opencode", CONFIG_FILE_BASENAME), "OpenCode project")
|
|
8662
|
-
]
|
|
8663
|
-
};
|
|
8664
|
-
}
|
|
8665
|
-
function stripJsoncForParse(input) {
|
|
8666
|
-
let out = "";
|
|
8667
|
-
let inString = false;
|
|
8668
|
-
let escaped = false;
|
|
8669
|
-
for (let i = 0;i < input.length; i++) {
|
|
8670
|
-
const ch = input[i];
|
|
8671
|
-
const next = input[i + 1];
|
|
8672
|
-
if (inString) {
|
|
8673
|
-
out += ch;
|
|
8674
|
-
if (escaped)
|
|
8675
|
-
escaped = false;
|
|
8676
|
-
else if (ch === "\\")
|
|
8677
|
-
escaped = true;
|
|
8678
|
-
else if (ch === '"')
|
|
8679
|
-
inString = false;
|
|
8680
|
-
continue;
|
|
8681
|
-
}
|
|
8682
|
-
if (ch === '"') {
|
|
8683
|
-
inString = true;
|
|
8684
|
-
out += ch;
|
|
8685
|
-
continue;
|
|
8686
|
-
}
|
|
8687
|
-
if (ch === "/" && next === "/") {
|
|
8688
|
-
while (i < input.length && input[i] !== `
|
|
8689
|
-
`)
|
|
8690
|
-
i++;
|
|
8691
|
-
out += `
|
|
8692
|
-
`;
|
|
8693
|
-
continue;
|
|
8694
|
-
}
|
|
8695
|
-
if (ch === "/" && next === "*") {
|
|
8696
|
-
i += 2;
|
|
8697
|
-
while (i < input.length && !(input[i] === "*" && input[i + 1] === "/"))
|
|
8698
|
-
i++;
|
|
8699
|
-
i++;
|
|
8700
|
-
out += " ";
|
|
8701
|
-
continue;
|
|
8702
|
-
}
|
|
8703
|
-
out += ch;
|
|
8704
|
-
}
|
|
8705
|
-
let withoutTrailingCommas = "";
|
|
8706
|
-
inString = false;
|
|
8707
|
-
escaped = false;
|
|
8708
|
-
for (let i = 0;i < out.length; i++) {
|
|
8709
|
-
const ch = out[i];
|
|
8710
|
-
if (inString) {
|
|
8711
|
-
withoutTrailingCommas += ch;
|
|
8712
|
-
if (escaped)
|
|
8713
|
-
escaped = false;
|
|
8714
|
-
else if (ch === "\\")
|
|
8715
|
-
escaped = true;
|
|
8716
|
-
else if (ch === '"')
|
|
8717
|
-
inString = false;
|
|
8718
|
-
continue;
|
|
8719
|
-
}
|
|
8720
|
-
if (ch === '"') {
|
|
8721
|
-
inString = true;
|
|
8722
|
-
withoutTrailingCommas += ch;
|
|
8723
|
-
continue;
|
|
8724
|
-
}
|
|
8725
|
-
if (ch === ",") {
|
|
8726
|
-
let j = i + 1;
|
|
8727
|
-
while (j < out.length && /\s/.test(out[j]))
|
|
8728
|
-
j++;
|
|
8729
|
-
if (out[j] === "}" || out[j] === "]")
|
|
8730
|
-
continue;
|
|
8731
|
-
}
|
|
8732
|
-
withoutTrailingCommas += ch;
|
|
8733
|
-
}
|
|
8734
|
-
return withoutTrailingCommas;
|
|
8735
|
-
}
|
|
8736
|
-
function sortJson(value) {
|
|
8737
|
-
if (Array.isArray(value))
|
|
8738
|
-
return value.map(sortJson);
|
|
8739
|
-
if (value && typeof value === "object") {
|
|
8740
|
-
const sorted = {};
|
|
8741
|
-
for (const key of Object.keys(value).sort()) {
|
|
8742
|
-
sorted[key] = sortJson(value[key]);
|
|
8743
|
-
}
|
|
8744
|
-
return sorted;
|
|
8745
|
-
}
|
|
8746
|
-
return value;
|
|
8747
|
-
}
|
|
8748
|
-
function normalizedJsoncSemantics(content) {
|
|
8749
|
-
return JSON.stringify(sortJson(JSON.parse(stripJsoncForParse(content))));
|
|
8750
|
-
}
|
|
8751
|
-
function fileSemanticsMatch(a, b) {
|
|
8752
|
-
try {
|
|
8753
|
-
return normalizedJsoncSemantics(a) === normalizedJsoncSemantics(b);
|
|
8754
|
-
} catch {
|
|
8755
|
-
return a === b;
|
|
8756
|
-
}
|
|
8757
|
-
}
|
|
8758
|
-
var CONFIG_LOCK_STALE_MS = 4000;
|
|
8759
|
-
function acquireConfigMigrationLock(lockDir) {
|
|
8760
|
-
for (let attempt = 0;attempt < 2; attempt++) {
|
|
8761
|
-
try {
|
|
8762
|
-
mkdirSync(lockDir, { recursive: false });
|
|
8763
|
-
return () => {
|
|
8764
|
-
try {
|
|
8765
|
-
rmSync(lockDir, { recursive: true, force: true });
|
|
8766
|
-
} catch {}
|
|
8767
|
-
};
|
|
8768
|
-
} catch (err) {
|
|
8769
|
-
const code = err?.code;
|
|
8770
|
-
if (code !== "EEXIST")
|
|
8771
|
-
throw err;
|
|
8772
|
-
try {
|
|
8773
|
-
const ageMs = Date.now() - statSync(lockDir).mtimeMs;
|
|
8774
|
-
if (ageMs > CONFIG_LOCK_STALE_MS) {
|
|
8775
|
-
rmSync(lockDir, { recursive: true, force: true });
|
|
8776
|
-
continue;
|
|
8777
|
-
}
|
|
8778
|
-
} catch {
|
|
8779
|
-
continue;
|
|
8780
|
-
}
|
|
8781
|
-
return null;
|
|
8782
|
-
}
|
|
8783
|
-
}
|
|
8784
|
-
return null;
|
|
8785
|
-
}
|
|
8786
|
-
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
8787
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
8788
|
-
const tmpPath = join(dirname(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
8789
|
-
let fd = null;
|
|
8790
|
-
try {
|
|
8791
|
-
fd = openSync(tmpPath, "wx", 384);
|
|
8792
|
-
writeFileSync(fd, readFileSync(sourcePath));
|
|
8793
|
-
closeSync(fd);
|
|
8794
|
-
fd = null;
|
|
8795
|
-
renameSync(tmpPath, targetPath);
|
|
8796
|
-
} catch (err) {
|
|
8797
|
-
if (fd !== null) {
|
|
8798
|
-
try {
|
|
8799
|
-
closeSync(fd);
|
|
8800
|
-
} catch {}
|
|
8801
|
-
}
|
|
8802
|
-
try {
|
|
8803
|
-
unlinkSync(tmpPath);
|
|
8804
|
-
} catch {}
|
|
8805
|
-
throw err;
|
|
8806
|
-
}
|
|
8807
|
-
}
|
|
8808
|
-
function atomicWriteConfigFile(targetPath, content) {
|
|
8809
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
8810
|
-
const tmpPath = join(dirname(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
8811
|
-
let fd = null;
|
|
8812
|
-
try {
|
|
8813
|
-
fd = openSync(tmpPath, "wx", 384);
|
|
8814
|
-
writeFileSync(fd, content);
|
|
8815
|
-
closeSync(fd);
|
|
8816
|
-
fd = null;
|
|
8817
|
-
renameSync(tmpPath, targetPath);
|
|
8818
|
-
} catch (err) {
|
|
8819
|
-
if (fd !== null) {
|
|
8820
|
-
try {
|
|
8821
|
-
closeSync(fd);
|
|
8822
|
-
} catch {}
|
|
8823
|
-
}
|
|
8824
|
-
try {
|
|
8825
|
-
unlinkSync(tmpPath);
|
|
8826
|
-
} catch {}
|
|
8827
|
-
throw err;
|
|
8828
|
-
}
|
|
8829
|
-
}
|
|
8830
|
-
function movedMarkerContent(targetPath, originalName, originalContent) {
|
|
8831
|
-
const header = [
|
|
8832
|
-
"// Magic Context configuration moved.",
|
|
8833
|
-
"//",
|
|
8834
|
-
"// Magic Context now reads its configuration from one shared CortexKit",
|
|
8835
|
-
"// location instead of a per-agent path. The settings that were in this",
|
|
8836
|
-
"// file have been moved to:",
|
|
8837
|
-
"//",
|
|
8838
|
-
`// ${targetPath}`,
|
|
8839
|
-
"//",
|
|
8840
|
-
"// Edit that file to change Magic Context settings. This location is no",
|
|
8841
|
-
"// longer read by Magic Context.",
|
|
8842
|
-
"//",
|
|
8843
|
-
`// To undo, rename this file back to "${originalName}" (and remove the`,
|
|
8844
|
-
"// CortexKit copy above if you want this location to take precedence).",
|
|
8845
|
-
"//",
|
|
8846
|
-
"// Your original settings are preserved below for reference.",
|
|
8847
|
-
"",
|
|
8848
|
-
""
|
|
8849
|
-
].join(`
|
|
8850
|
-
`);
|
|
8851
|
-
return `${header}${originalContent}`;
|
|
8852
|
-
}
|
|
8853
|
-
function markLegacySourcesMovedAside(sources, targetPath, logger) {
|
|
8854
|
-
const warnings = [];
|
|
8855
|
-
const info = logger?.info ?? logger?.log;
|
|
8856
|
-
for (const source of sources) {
|
|
8857
|
-
const markerPath = `${source.path}${MOVED_MARKER_SUFFIX}`;
|
|
8858
|
-
try {
|
|
8859
|
-
const original = readFileSync(source.path, "utf-8");
|
|
8860
|
-
atomicWriteConfigFile(markerPath, movedMarkerContent(targetPath, basename(source.path), original));
|
|
8861
|
-
unlinkSync(source.path);
|
|
8862
|
-
info?.(`Moved legacy Magic Context config ${source.path} aside to ${markerPath}; now reading ${targetPath}`);
|
|
8863
|
-
} catch (err) {
|
|
8864
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
8865
|
-
warnings.push(`Magic Context could not move legacy config ${source.path} aside (${msg}); it is now stale and ignored. Delete it manually — config is read from ${targetPath}.`);
|
|
8866
|
-
logger?.warn?.(`Could not move legacy Magic Context config ${source.path} aside (${msg}); reading ${targetPath}`);
|
|
8867
|
-
}
|
|
8868
|
-
}
|
|
8869
|
-
return warnings;
|
|
8870
|
-
}
|
|
8871
|
-
function visibleConfigMigrationWarning(scope, targetPath, paths, reason) {
|
|
8872
|
-
const uniquePaths = [...new Set([targetPath, ...paths])];
|
|
8873
|
-
return `Magic Context ${scope} config migration refused: ${reason}. ` + `Legacy and CortexKit config paths collapse to one file, but Magic Context will not overwrite or merge them automatically. ` + `Please consolidate manually into ${targetPath}. Paths: ${uniquePaths.join(" ; ")}`;
|
|
8874
|
-
}
|
|
8875
|
-
function migrateConfigFile(opts) {
|
|
8876
|
-
const warnings = [];
|
|
8877
|
-
const existingSources = opts.legacySources.filter((source) => existsSync(source.path));
|
|
8878
|
-
const info = opts.logger?.info ?? opts.logger?.log;
|
|
8879
|
-
if (existingSources.length === 0) {
|
|
8880
|
-
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
8881
|
-
}
|
|
8882
|
-
mkdirSync(dirname(opts.targetPath), { recursive: true });
|
|
8883
|
-
const release = acquireConfigMigrationLock(`${opts.targetPath}.lock`);
|
|
8884
|
-
if (!release) {
|
|
8885
|
-
warnings.push(`Config migration for ${opts.scope} skipped this run (another instance is migrating); will retry on next start.`);
|
|
8886
|
-
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
8887
|
-
}
|
|
8888
|
-
try {
|
|
8889
|
-
const sources = existingSources.map((source) => ({
|
|
8890
|
-
...source,
|
|
8891
|
-
content: readFileSync(source.path, "utf-8")
|
|
8892
|
-
}));
|
|
8893
|
-
if (existsSync(opts.targetPath)) {
|
|
8894
|
-
const targetContent = readFileSync(opts.targetPath, "utf-8");
|
|
8895
|
-
const differing2 = sources.filter((source) => !fileSemanticsMatch(source.content, targetContent));
|
|
8896
|
-
if (differing2.length > 0) {
|
|
8897
|
-
const message = visibleConfigMigrationWarning(opts.scope, opts.targetPath, differing2.map((source) => source.path), "the CortexKit target already exists with different settings");
|
|
8898
|
-
warnings.push(message);
|
|
8899
|
-
opts.logger?.warn?.(message);
|
|
8900
|
-
return { migrated: false, conflict: true, targetPath: opts.targetPath, warnings };
|
|
8901
|
-
}
|
|
8902
|
-
info?.(`Magic Context ${opts.scope} config already present at ${opts.targetPath}; legacy copies match`);
|
|
8903
|
-
warnings.push(...markLegacySourcesMovedAside(sources, opts.targetPath, opts.logger));
|
|
8904
|
-
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
8905
|
-
}
|
|
8906
|
-
const first = sources[0];
|
|
8907
|
-
const differing = sources.filter((source) => !fileSemanticsMatch(source.content, first.content));
|
|
8908
|
-
if (differing.length > 0) {
|
|
8909
|
-
const message = visibleConfigMigrationWarning(opts.scope, opts.targetPath, sources.map((source) => source.path), "multiple legacy sources have different settings");
|
|
8910
|
-
warnings.push(message);
|
|
8911
|
-
opts.logger?.warn?.(message);
|
|
8912
|
-
return { migrated: false, conflict: true, targetPath: opts.targetPath, warnings };
|
|
8913
|
-
}
|
|
8914
|
-
atomicCopyConfigFile(first.path, opts.targetPath);
|
|
8915
|
-
info?.(`Migrated Magic Context ${opts.scope} config from ${first.path} to ${opts.targetPath}`);
|
|
8916
|
-
warnings.push(...markLegacySourcesMovedAside(sources, opts.targetPath, opts.logger));
|
|
8917
|
-
return {
|
|
8918
|
-
migrated: true,
|
|
8919
|
-
conflict: false,
|
|
8920
|
-
sourcePath: first.path,
|
|
8921
|
-
targetPath: opts.targetPath,
|
|
8922
|
-
warnings
|
|
8923
|
-
};
|
|
8924
|
-
} catch (err) {
|
|
8925
|
-
const message = visibleConfigMigrationWarning(opts.scope, opts.targetPath, existingSources.map((source) => source.path), `migration failed (${err instanceof Error ? err.message : String(err)})`);
|
|
8926
|
-
warnings.push(message);
|
|
8927
|
-
opts.logger?.warn?.(message);
|
|
8928
|
-
return { migrated: false, conflict: true, targetPath: opts.targetPath, warnings };
|
|
8929
|
-
} finally {
|
|
8930
|
-
release();
|
|
8931
|
-
}
|
|
8932
|
-
}
|
|
8933
|
-
function migrateMagicContextConfigLocations(directory, logger) {
|
|
8934
|
-
const warnings = [];
|
|
8935
|
-
const legacy = resolveLegacyConfigSources(directory);
|
|
8936
|
-
try {
|
|
8937
|
-
warnings.push(...migrateConfigFile({
|
|
8938
|
-
scope: "user",
|
|
8939
|
-
targetPath: resolveCortexKitUserConfigPath(),
|
|
8940
|
-
legacySources: legacy.user,
|
|
8941
|
-
logger
|
|
8942
|
-
}).warnings);
|
|
8943
|
-
warnings.push(...migrateConfigFile({
|
|
8944
|
-
scope: "project",
|
|
8945
|
-
targetPath: resolveCortexKitProjectConfigPath(directory),
|
|
8946
|
-
legacySources: legacy.project,
|
|
8947
|
-
logger
|
|
8948
|
-
}).warnings);
|
|
8949
|
-
} catch (err) {
|
|
8950
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
8951
|
-
logger?.warn?.(`Magic Context config-location migration error (continuing): ${msg}`);
|
|
8952
|
-
warnings.push(`Magic Context config-location migration error: ${msg}`);
|
|
8953
|
-
}
|
|
8954
|
-
return warnings;
|
|
8955
|
-
}
|
|
8956
|
-
|
|
8957
8593
|
// src/config/migrate-dreamer-v2.ts
|
|
8958
8594
|
var OLD_VERIFY_TASK = "verify";
|
|
8959
8595
|
var OLD_CURATE_TASKS = ["consolidate", "archive-stale", "improve"];
|
|
@@ -9265,6 +8901,7 @@ function migrateLegacyExperimental(rawConfig, warnings) {
|
|
|
9265
8901
|
// src/config/project-security.ts
|
|
9266
8902
|
var HIDDEN_AGENT_KEYS = ["historian", "dreamer", "sidekick"];
|
|
9267
8903
|
var HISTORIAN_USER_ONLY_FIELDS = ["model", "fallback_models"];
|
|
8904
|
+
var PROMPT_SURFACE_USER_ONLY_FIELDS = ["guidance_override_path", "tool_descriptions"];
|
|
9268
8905
|
var AGENT_ESCALATION_FIELDS = ["prompt", "permission", "tools", "system_prompt"];
|
|
9269
8906
|
var EMBEDDING_DESTINATION_FIELDS = ["endpoint", "provider", "fallback_provider"];
|
|
9270
8907
|
var PERCENTAGE_THRESHOLD_REASON = "security: a repository may only raise compaction thresholds above the user's effective value; it cannot force earlier historian work or cloned-repo cost escalation.";
|
|
@@ -9400,6 +9037,19 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
9400
9037
|
delete storage.enforce_private_permissions;
|
|
9401
9038
|
warnings.push("Ignoring storage.enforce_private_permissions from project config (security: only user-level config may opt into externally managed shared storage permissions).");
|
|
9402
9039
|
}
|
|
9040
|
+
const promptSurface = projectRaw.prompt_surface;
|
|
9041
|
+
if (isPlainObject(promptSurface)) {
|
|
9042
|
+
const removed = [];
|
|
9043
|
+
for (const field of PROMPT_SURFACE_USER_ONLY_FIELDS) {
|
|
9044
|
+
if (field in promptSurface) {
|
|
9045
|
+
delete promptSurface[field];
|
|
9046
|
+
removed.push(field);
|
|
9047
|
+
}
|
|
9048
|
+
}
|
|
9049
|
+
if (removed.length > 0) {
|
|
9050
|
+
warnings.push(`Ignoring prompt_surface.${removed.join("/")} from project config (security: repositories may select prompt presets but only user config may provide guidance or tool-description text).`);
|
|
9051
|
+
}
|
|
9052
|
+
}
|
|
9403
9053
|
const pi = projectRaw.pi;
|
|
9404
9054
|
if (isPlainObject(pi) && "subagent_extensions" in pi) {
|
|
9405
9055
|
delete pi.subagent_extensions;
|
|
@@ -9647,13 +9297,13 @@ function resolveTransformMode(args) {
|
|
|
9647
9297
|
}
|
|
9648
9298
|
|
|
9649
9299
|
// src/config/variable.ts
|
|
9650
|
-
import { existsSync
|
|
9651
|
-
import { homedir
|
|
9652
|
-
import { dirname
|
|
9300
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
9301
|
+
import { homedir } from "node:os";
|
|
9302
|
+
import { dirname, isAbsolute, resolve } from "node:path";
|
|
9653
9303
|
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
9654
9304
|
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
9655
9305
|
function sensitiveFilePathReason(resolvedPath) {
|
|
9656
|
-
const home =
|
|
9306
|
+
const home = homedir();
|
|
9657
9307
|
const sensitiveDirs = [
|
|
9658
9308
|
{ dir: resolve(home, ".ssh"), label: "SSH keys" },
|
|
9659
9309
|
{ dir: resolve(home, ".aws"), label: "AWS credentials" },
|
|
@@ -9698,7 +9348,7 @@ function substituteConfigVariables(input) {
|
|
|
9698
9348
|
if (fileMatches.length === 0) {
|
|
9699
9349
|
return { text, warnings };
|
|
9700
9350
|
}
|
|
9701
|
-
const configDir = input.configPath ?
|
|
9351
|
+
const configDir = input.configPath ? dirname(input.configPath) : process.cwd();
|
|
9702
9352
|
let output = "";
|
|
9703
9353
|
let cursor = 0;
|
|
9704
9354
|
for (const match of fileMatches) {
|
|
@@ -9716,21 +9366,21 @@ function substituteConfigVariables(input) {
|
|
|
9716
9366
|
}
|
|
9717
9367
|
let filePath = rawPath.trim();
|
|
9718
9368
|
if (filePath.startsWith("~/")) {
|
|
9719
|
-
filePath = resolve(
|
|
9720
|
-
} else if (!
|
|
9369
|
+
filePath = resolve(homedir(), filePath.slice(2));
|
|
9370
|
+
} else if (!isAbsolute(filePath)) {
|
|
9721
9371
|
filePath = resolve(configDir, filePath);
|
|
9722
9372
|
}
|
|
9723
9373
|
const sensitiveReason = sensitiveFilePathReason(filePath);
|
|
9724
9374
|
if (sensitiveReason) {
|
|
9725
9375
|
warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
|
|
9726
9376
|
}
|
|
9727
|
-
if (!
|
|
9377
|
+
if (!existsSync(filePath)) {
|
|
9728
9378
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
9729
9379
|
continue;
|
|
9730
9380
|
}
|
|
9731
9381
|
let contents;
|
|
9732
9382
|
try {
|
|
9733
|
-
contents =
|
|
9383
|
+
contents = readFileSync(filePath, "utf-8").trim();
|
|
9734
9384
|
} catch (error) {
|
|
9735
9385
|
const message = error instanceof Error ? error.message : String(error);
|
|
9736
9386
|
warnings.push(`Failed to read file for ${token} (${filePath}): ${message}; using empty string`);
|
|
@@ -9750,15 +9400,15 @@ function getProjectConfigBasePath(directory) {
|
|
|
9750
9400
|
return cortexKitProjectConfigBasePath(directory);
|
|
9751
9401
|
}
|
|
9752
9402
|
function resolveLegacyReadFallback(sources) {
|
|
9753
|
-
return { source: sources.find((s) =>
|
|
9403
|
+
return { source: sources.find((s) => existsSync2(s.path)) ?? null };
|
|
9754
9404
|
}
|
|
9755
9405
|
function loadConfigFileDetailed(configPath, source) {
|
|
9756
|
-
if (!
|
|
9406
|
+
if (!existsSync2(configPath)) {
|
|
9757
9407
|
return null;
|
|
9758
9408
|
}
|
|
9759
9409
|
let rawText;
|
|
9760
9410
|
try {
|
|
9761
|
-
rawText =
|
|
9411
|
+
rawText = readFileSync2(configPath, "utf-8");
|
|
9762
9412
|
} catch (error) {
|
|
9763
9413
|
return {
|
|
9764
9414
|
config: {},
|
|
@@ -9917,9 +9567,6 @@ function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
9917
9567
|
configWarnings: [...preMigrationWarnings, ...warnings]
|
|
9918
9568
|
};
|
|
9919
9569
|
}
|
|
9920
|
-
function loadPluginConfig(directory) {
|
|
9921
|
-
return loadPluginConfigDetailed(directory).config;
|
|
9922
|
-
}
|
|
9923
9570
|
function hasUserTierSubcConfig(config) {
|
|
9924
9571
|
const subc = config?.subc;
|
|
9925
9572
|
if (typeof subc !== "object" || subc === null || Array.isArray(subc))
|
|
@@ -9975,8 +9622,8 @@ function loadPluginConfigDetailed(directory) {
|
|
|
9975
9622
|
const harnessLegacy = resolveLegacyConfigSourcesForHarness(directory, "opencode");
|
|
9976
9623
|
const userLegacyFallback = userDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.user) : { source: null };
|
|
9977
9624
|
const projectLegacyFallback = projectDetected.format === "none" ? resolveLegacyReadFallback(harnessLegacy.project) : { source: null };
|
|
9978
|
-
const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) =>
|
|
9979
|
-
const legacyProjectUnmigrated = projectDetected.format === "none" && !projectLegacyFallback.source && legacySources.project.some((source) =>
|
|
9625
|
+
const legacyUserUnmigrated = userDetected.format === "none" && !userLegacyFallback.source && legacySources.user.some((source) => existsSync2(source.path));
|
|
9626
|
+
const legacyProjectUnmigrated = projectDetected.format === "none" && !projectLegacyFallback.source && legacySources.project.some((source) => existsSync2(source.path));
|
|
9980
9627
|
const userLoaded = userDetected.format !== "none" ? loadConfigFileDetailed(userDetected.path, "user") : userLegacyFallback.source ? loadConfigFileDetailed(userLegacyFallback.source.path, "user") : null;
|
|
9981
9628
|
const projectLoaded = projectDetected.format !== "none" ? loadConfigFileDetailed(projectDetected.path, "project") : projectLegacyFallback.source ? loadConfigFileDetailed(projectLegacyFallback.source.path, "project") : null;
|
|
9982
9629
|
const allWarnings = [];
|
|
@@ -10048,6 +9695,7 @@ function loadPluginConfigDetailed(directory) {
|
|
|
10048
9695
|
};
|
|
10049
9696
|
return {
|
|
10050
9697
|
config,
|
|
9698
|
+
registrationPromptSurface: trustedBaseConfig.prompt_surface,
|
|
10051
9699
|
loadOutcome: combinedOutcome({ sources, substitutionFailures, recoveredTopLevelKeys }),
|
|
10052
9700
|
sources,
|
|
10053
9701
|
substitutionFailures,
|
|
@@ -10096,10 +9744,10 @@ function getMagicContextBuiltinCommands(compactionEnabled = true) {
|
|
|
10096
9744
|
}
|
|
10097
9745
|
|
|
10098
9746
|
// src/features/magic-context/dreamer/open-opencode-db.ts
|
|
10099
|
-
import { existsSync as
|
|
9747
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
10100
9748
|
function openOpenCodeDb() {
|
|
10101
9749
|
const dbPath = getOpenCodeDbPath();
|
|
10102
|
-
if (!
|
|
9750
|
+
if (!existsSync3(dbPath)) {
|
|
10103
9751
|
log(`[dreamer] OpenCode DB not found at ${dbPath} — skipping OpenCode history scan`);
|
|
10104
9752
|
return null;
|
|
10105
9753
|
}
|
|
@@ -10469,6 +10117,15 @@ function formatFailClosedBlockingProcesses(processes) {
|
|
|
10469
10117
|
}
|
|
10470
10118
|
function formatFailClosedBlockingMessage(reason) {
|
|
10471
10119
|
if (reason.kind === "migration_guard") {
|
|
10120
|
+
if (reason.unreadableFile) {
|
|
10121
|
+
const arm = reason.unreadableArm ?? "io";
|
|
10122
|
+
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.`;
|
|
10123
|
+
return [
|
|
10124
|
+
`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.`,
|
|
10125
|
+
recovery,
|
|
10126
|
+
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
10127
|
+
].join(" ");
|
|
10128
|
+
}
|
|
10472
10129
|
return [
|
|
10473
10130
|
`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.`,
|
|
10474
10131
|
"Restart the blocking process (it will pick up the new build and migrate on start), or shut it down and retry.",
|
|
@@ -10577,7 +10234,7 @@ function getLastHookInitFailure() {
|
|
|
10577
10234
|
|
|
10578
10235
|
// src/features/magic-context/session-project-backfill.ts
|
|
10579
10236
|
import { randomUUID } from "node:crypto";
|
|
10580
|
-
import { existsSync as
|
|
10237
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
10581
10238
|
var LEASE_TTL_MS = 10 * 60 * 1000;
|
|
10582
10239
|
var SESSION_PAGE_SIZE = 100;
|
|
10583
10240
|
var SESSION_QUERY_CHUNK_SIZE = 250;
|
|
@@ -10773,7 +10430,7 @@ async function runSessionProjectBackfill(db, source, options = {}) {
|
|
|
10773
10430
|
if (!session.directory) {
|
|
10774
10431
|
result.skippedEmptyDirectories += 1;
|
|
10775
10432
|
} else {
|
|
10776
|
-
const stillExists = existenceCache.get(session.directory) ??
|
|
10433
|
+
const stillExists = existenceCache.get(session.directory) ?? existsSync4(session.directory);
|
|
10777
10434
|
existenceCache.set(session.directory, stillExists);
|
|
10778
10435
|
if (!stillExists) {
|
|
10779
10436
|
result.skippedDeadDirectories += 1;
|
|
@@ -11198,45 +10855,45 @@ async function runDeferredV22Backfill(db, options = {}) {
|
|
|
11198
10855
|
}
|
|
11199
10856
|
|
|
11200
10857
|
// src/hooks/auto-update-checker/index.ts
|
|
11201
|
-
import { existsSync as
|
|
11202
|
-
import { dirname as
|
|
10858
|
+
import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync4, renameSync as renameSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
10859
|
+
import { dirname as dirname3, join as join3 } from "node:path";
|
|
11203
10860
|
|
|
11204
10861
|
// src/hooks/auto-update-checker/checker.ts
|
|
11205
10862
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
11206
10863
|
import { spawn } from "node:child_process";
|
|
11207
10864
|
import {
|
|
11208
10865
|
accessSync,
|
|
11209
|
-
existsSync as
|
|
10866
|
+
existsSync as existsSync5,
|
|
11210
10867
|
constants as fsConstants,
|
|
11211
|
-
readFileSync as
|
|
11212
|
-
renameSync
|
|
11213
|
-
statSync
|
|
11214
|
-
writeFileSync
|
|
10868
|
+
readFileSync as readFileSync3,
|
|
10869
|
+
renameSync,
|
|
10870
|
+
statSync,
|
|
10871
|
+
writeFileSync
|
|
11215
10872
|
} from "node:fs";
|
|
11216
|
-
import { dirname as
|
|
10873
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "node:path";
|
|
11217
10874
|
import { fileURLToPath } from "node:url";
|
|
11218
10875
|
|
|
11219
10876
|
// src/hooks/auto-update-checker/constants.ts
|
|
11220
|
-
import { homedir as
|
|
11221
|
-
import { join
|
|
10877
|
+
import { homedir as homedir2, platform } from "node:os";
|
|
10878
|
+
import { join } from "node:path";
|
|
11222
10879
|
var PACKAGE_NAME = "@cortexkit/opencode-magic-context";
|
|
11223
10880
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
11224
10881
|
var NPM_FETCH_TIMEOUT = 1e4;
|
|
11225
10882
|
function getOpenCodeCacheRoot() {
|
|
11226
10883
|
if (platform() === "win32") {
|
|
11227
|
-
return
|
|
10884
|
+
return join(process.env.LOCALAPPDATA ?? homedir2(), "opencode");
|
|
11228
10885
|
}
|
|
11229
|
-
return
|
|
10886
|
+
return join(homedir2(), ".cache", "opencode");
|
|
11230
10887
|
}
|
|
11231
10888
|
function getOpenCodeConfigRoot() {
|
|
11232
10889
|
if (platform() === "win32") {
|
|
11233
|
-
return
|
|
10890
|
+
return join(process.env.APPDATA ?? join(homedir2(), "AppData", "Roaming"), "opencode");
|
|
11234
10891
|
}
|
|
11235
|
-
return
|
|
10892
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(homedir2(), ".config"), "opencode");
|
|
11236
10893
|
}
|
|
11237
|
-
var CACHE_DIR =
|
|
11238
|
-
var USER_OPENCODE_CONFIG =
|
|
11239
|
-
var USER_OPENCODE_CONFIG_JSONC =
|
|
10894
|
+
var CACHE_DIR = join(getOpenCodeCacheRoot(), "packages");
|
|
10895
|
+
var USER_OPENCODE_CONFIG = join(getOpenCodeConfigRoot(), "opencode.json");
|
|
10896
|
+
var USER_OPENCODE_CONFIG_JSONC = join(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
11240
10897
|
|
|
11241
10898
|
// src/hooks/auto-update-checker/types.ts
|
|
11242
10899
|
var NpmPackageEnvelopeSchema = exports_external.object({
|
|
@@ -11297,17 +10954,17 @@ function extractChannel(version) {
|
|
|
11297
10954
|
}
|
|
11298
10955
|
function getSurfaceConfigPaths(directory, surface) {
|
|
11299
10956
|
const name = surface === "server" ? "opencode" : "tui";
|
|
11300
|
-
const globalDir =
|
|
10957
|
+
const globalDir = dirname2(USER_OPENCODE_CONFIG);
|
|
11301
10958
|
const dirs = [
|
|
11302
10959
|
globalDir,
|
|
11303
10960
|
directory,
|
|
11304
|
-
|
|
10961
|
+
join2(directory, ".opencode"),
|
|
11305
10962
|
process.env.OPENCODE_CONFIG_DIR
|
|
11306
10963
|
].filter((value) => Boolean(value));
|
|
11307
10964
|
const paths = [];
|
|
11308
10965
|
for (const dir of dirs) {
|
|
11309
10966
|
for (const extension of ["json", "jsonc"]) {
|
|
11310
|
-
const path2 =
|
|
10967
|
+
const path2 = join2(dir, `${name}.${extension}`);
|
|
11311
10968
|
if (!paths.includes(path2))
|
|
11312
10969
|
paths.push(path2);
|
|
11313
10970
|
}
|
|
@@ -11318,9 +10975,9 @@ function getWinningConfig(directory, surface) {
|
|
|
11318
10975
|
let winner = null;
|
|
11319
10976
|
for (const path2 of getSurfaceConfigPaths(directory, surface)) {
|
|
11320
10977
|
try {
|
|
11321
|
-
if (!
|
|
10978
|
+
if (!existsSync5(path2))
|
|
11322
10979
|
continue;
|
|
11323
|
-
const parsed = parseJsonConfig(
|
|
10980
|
+
const parsed = parseJsonConfig(readFileSync3(path2, "utf-8"));
|
|
11324
10981
|
const entries = getPluginEntries(parsed);
|
|
11325
10982
|
if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
|
|
11326
10983
|
if (winner) {
|
|
@@ -11343,24 +11000,24 @@ function resolvePathPluginSpec(spec, configPath) {
|
|
|
11343
11000
|
return spec.replace(/^file:\/\//, "");
|
|
11344
11001
|
}
|
|
11345
11002
|
}
|
|
11346
|
-
if (
|
|
11003
|
+
if (isAbsolute2(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
11347
11004
|
return spec;
|
|
11348
|
-
return resolve2(
|
|
11005
|
+
return resolve2(dirname2(configPath), spec);
|
|
11349
11006
|
}
|
|
11350
11007
|
function findPackageJsonUp(startPath) {
|
|
11351
11008
|
try {
|
|
11352
|
-
const stat =
|
|
11353
|
-
let dir = stat.isDirectory() ? startPath :
|
|
11009
|
+
const stat = statSync(startPath);
|
|
11010
|
+
let dir = stat.isDirectory() ? startPath : dirname2(startPath);
|
|
11354
11011
|
for (let i = 0;i < 10; i++) {
|
|
11355
|
-
const pkgPath =
|
|
11356
|
-
if (
|
|
11012
|
+
const pkgPath = join2(dir, "package.json");
|
|
11013
|
+
if (existsSync5(pkgPath)) {
|
|
11357
11014
|
try {
|
|
11358
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
11015
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync3(pkgPath, "utf-8")));
|
|
11359
11016
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
11360
11017
|
return pkgPath;
|
|
11361
11018
|
} catch {}
|
|
11362
11019
|
}
|
|
11363
|
-
const parent =
|
|
11020
|
+
const parent = dirname2(dir);
|
|
11364
11021
|
if (parent === dir)
|
|
11365
11022
|
break;
|
|
11366
11023
|
dir = parent;
|
|
@@ -11371,19 +11028,19 @@ function findPackageJsonUp(startPath) {
|
|
|
11371
11028
|
function getLocalDevPath(directory) {
|
|
11372
11029
|
for (const configPath of getConfigPaths(directory)) {
|
|
11373
11030
|
try {
|
|
11374
|
-
if (!
|
|
11031
|
+
if (!existsSync5(configPath))
|
|
11375
11032
|
continue;
|
|
11376
|
-
const rawConfig = parseJsonConfig(
|
|
11033
|
+
const rawConfig = parseJsonConfig(readFileSync3(configPath, "utf-8"));
|
|
11377
11034
|
const plugins = getPluginEntries(rawConfig);
|
|
11378
11035
|
for (const entry of plugins) {
|
|
11379
11036
|
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
|
|
11380
11037
|
continue;
|
|
11381
|
-
if (entry.startsWith("file://") || entry.startsWith(".") ||
|
|
11038
|
+
if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute2(entry)) {
|
|
11382
11039
|
const localPath = resolvePathPluginSpec(entry, configPath);
|
|
11383
11040
|
const pkgPath = findPackageJsonUp(localPath);
|
|
11384
11041
|
if (!pkgPath)
|
|
11385
11042
|
continue;
|
|
11386
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
11043
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync3(pkgPath, "utf-8")));
|
|
11387
11044
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
11388
11045
|
return localPath;
|
|
11389
11046
|
}
|
|
@@ -11400,7 +11057,7 @@ function getLocalDevVersion(directory) {
|
|
|
11400
11057
|
const pkgPath = findPackageJsonUp(localPath);
|
|
11401
11058
|
if (!pkgPath)
|
|
11402
11059
|
return null;
|
|
11403
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
11060
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync3(pkgPath, "utf-8")));
|
|
11404
11061
|
return pkg.success ? pkg.data.version ?? null : null;
|
|
11405
11062
|
} catch {
|
|
11406
11063
|
return null;
|
|
@@ -11408,7 +11065,7 @@ function getLocalDevVersion(directory) {
|
|
|
11408
11065
|
}
|
|
11409
11066
|
function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
|
|
11410
11067
|
try {
|
|
11411
|
-
return findPackageJsonUp(
|
|
11068
|
+
return findPackageJsonUp(dirname2(fileURLToPath(currentModuleUrl)));
|
|
11412
11069
|
} catch (err) {
|
|
11413
11070
|
warn(`[auto-update-checker] Failed to resolve runtime package path: ${String(err)}`);
|
|
11414
11071
|
return null;
|
|
@@ -11449,7 +11106,7 @@ function preflightConfigUpdates(paths, version) {
|
|
|
11449
11106
|
for (const path2 of paths) {
|
|
11450
11107
|
try {
|
|
11451
11108
|
accessSync(path2, fsConstants.W_OK);
|
|
11452
|
-
const original =
|
|
11109
|
+
const original = readFileSync3(path2, "utf-8");
|
|
11453
11110
|
const updated = configUpdateContent(original, version);
|
|
11454
11111
|
if (!updated)
|
|
11455
11112
|
return null;
|
|
@@ -11463,8 +11120,8 @@ function preflightConfigUpdates(paths, version) {
|
|
|
11463
11120
|
}
|
|
11464
11121
|
function writeConfig(path2, content) {
|
|
11465
11122
|
const tmp = `${path2}.mc-tmp-${process.pid}`;
|
|
11466
|
-
|
|
11467
|
-
|
|
11123
|
+
writeFileSync(tmp, content, "utf-8");
|
|
11124
|
+
renameSync(tmp, path2);
|
|
11468
11125
|
}
|
|
11469
11126
|
function restoreConfigs(snapshots) {
|
|
11470
11127
|
for (const snapshot of snapshots) {
|
|
@@ -11478,7 +11135,7 @@ function restoreConfigs(snapshots) {
|
|
|
11478
11135
|
function configsHaveSpec(paths, spec) {
|
|
11479
11136
|
return paths.every((path2) => {
|
|
11480
11137
|
try {
|
|
11481
|
-
const parsed = parseJsonConfig(
|
|
11138
|
+
const parsed = parseJsonConfig(readFileSync3(path2, "utf-8"));
|
|
11482
11139
|
return getPluginEntries(parsed).includes(spec);
|
|
11483
11140
|
} catch {
|
|
11484
11141
|
return false;
|
|
@@ -11534,8 +11191,8 @@ async function preparePluginUpdate(directory, _pluginInfo, version, options = {}
|
|
|
11534
11191
|
return null;
|
|
11535
11192
|
const spec = `${PACKAGE_NAME}@${version}`;
|
|
11536
11193
|
const globalServerPaths = [USER_OPENCODE_CONFIG, USER_OPENCODE_CONFIG_JSONC];
|
|
11537
|
-
const globalTuiPaths = globalServerPaths.map((path2) =>
|
|
11538
|
-
globalTuiPaths.push(...globalServerPaths.map((path2) =>
|
|
11194
|
+
const globalTuiPaths = globalServerPaths.map((path2) => join2(dirname2(path2), "tui.json"));
|
|
11195
|
+
globalTuiPaths.push(...globalServerPaths.map((path2) => join2(dirname2(path2), "tui.jsonc")));
|
|
11539
11196
|
const isGlobal = globalServerPaths.includes(paths[0]) && globalTuiPaths.includes(paths[1]);
|
|
11540
11197
|
if (isGlobal) {
|
|
11541
11198
|
const hostResult = await runHostPluginInstall(spec, options.signal, options.timeoutMs);
|
|
@@ -11568,9 +11225,9 @@ function getCachedVersion(_spec) {
|
|
|
11568
11225
|
const candidates = [getCurrentRuntimePackageJsonPath()].filter(isString);
|
|
11569
11226
|
for (const packageJsonPath of candidates) {
|
|
11570
11227
|
try {
|
|
11571
|
-
if (!
|
|
11228
|
+
if (!existsSync5(packageJsonPath))
|
|
11572
11229
|
continue;
|
|
11573
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
11230
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync3(packageJsonPath, "utf-8")));
|
|
11574
11231
|
if (pkg.success && pkg.data.version) {
|
|
11575
11232
|
if (!_spec)
|
|
11576
11233
|
cachedPackageVersion = pkg.data.version;
|
|
@@ -11668,20 +11325,20 @@ function claimCheckSlot(storageDir, intervalMs) {
|
|
|
11668
11325
|
if (!storageDir)
|
|
11669
11326
|
return true;
|
|
11670
11327
|
try {
|
|
11671
|
-
const file =
|
|
11672
|
-
if (
|
|
11328
|
+
const file = join3(storageDir, TIMESTAMP_FILENAME);
|
|
11329
|
+
if (existsSync6(file)) {
|
|
11673
11330
|
try {
|
|
11674
|
-
const raw = JSON.parse(
|
|
11331
|
+
const raw = JSON.parse(readFileSync4(file, "utf-8"));
|
|
11675
11332
|
const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
|
|
11676
11333
|
if (Number.isFinite(last) && Date.now() - last < intervalMs) {
|
|
11677
11334
|
return false;
|
|
11678
11335
|
}
|
|
11679
11336
|
} catch {}
|
|
11680
11337
|
}
|
|
11681
|
-
|
|
11338
|
+
mkdirSync(dirname3(file), { recursive: true });
|
|
11682
11339
|
const tmp = `${file}.tmp.${process.pid}`;
|
|
11683
|
-
|
|
11684
|
-
|
|
11340
|
+
writeFileSync2(tmp, JSON.stringify({ lastCheckedMs: Date.now() }), "utf-8");
|
|
11341
|
+
renameSync2(tmp, file);
|
|
11685
11342
|
return true;
|
|
11686
11343
|
} catch (err) {
|
|
11687
11344
|
warn2(`[auto-update-checker] Could not coordinate via timestamp file: ${String(err)}`);
|
|
@@ -11689,39 +11346,39 @@ function claimCheckSlot(storageDir, intervalMs) {
|
|
|
11689
11346
|
}
|
|
11690
11347
|
}
|
|
11691
11348
|
function pendingMarkerPath(storageDir) {
|
|
11692
|
-
return
|
|
11349
|
+
return join3(storageDir ?? getOpenCodeStorageDir(), PENDING_UPDATE_FILENAME);
|
|
11693
11350
|
}
|
|
11694
11351
|
function writePendingUpdateMarker(storageDir, update, version) {
|
|
11695
11352
|
try {
|
|
11696
|
-
const dir = storageDir ??
|
|
11697
|
-
|
|
11353
|
+
const dir = storageDir ?? dirname3(pendingMarkerPath(storageDir));
|
|
11354
|
+
mkdirSync(dir, { recursive: true });
|
|
11698
11355
|
const path2 = pendingMarkerPath(storageDir);
|
|
11699
11356
|
const temp = `${path2}.tmp.${process.pid}`;
|
|
11700
|
-
|
|
11357
|
+
writeFileSync2(temp, `${JSON.stringify({ spec: update.spec, version, configPaths: update.configPaths, writtenAt: Date.now() }, null, 2)}
|
|
11701
11358
|
`, "utf-8");
|
|
11702
|
-
|
|
11359
|
+
renameSync2(temp, path2);
|
|
11703
11360
|
} catch (err) {
|
|
11704
11361
|
warn2(`[auto-update-checker] Could not write pending update marker: ${String(err)}`);
|
|
11705
11362
|
}
|
|
11706
11363
|
}
|
|
11707
11364
|
function consumePendingUpdateMarker(storageDir, loadedVersion) {
|
|
11708
11365
|
const path2 = pendingMarkerPath(storageDir);
|
|
11709
|
-
if (!
|
|
11366
|
+
if (!existsSync6(path2))
|
|
11710
11367
|
return;
|
|
11711
11368
|
try {
|
|
11712
|
-
const marker = JSON.parse(
|
|
11369
|
+
const marker = JSON.parse(readFileSync4(path2, "utf-8"));
|
|
11713
11370
|
const age = Date.now() - (marker.writtenAt ?? 0);
|
|
11714
11371
|
const olderThanLoaded = typeof marker.version === "string" && typeof loadedVersion === "string" && (compareSemverCore(marker.version, loadedVersion) ?? 0) < 0;
|
|
11715
11372
|
if (marker.version === loadedVersion && marker.spec === `${PACKAGE_NAME}@${loadedVersion}` && Array.isArray(marker.configPaths) && marker.configPaths.length === 2) {
|
|
11716
|
-
|
|
11373
|
+
rmSync(path2, { force: true });
|
|
11717
11374
|
log(`[auto-update-checker] Pending update applied: ${marker.spec}`);
|
|
11718
11375
|
} else if (age > PENDING_UPDATE_MAX_AGE_MS || olderThanLoaded) {
|
|
11719
|
-
|
|
11376
|
+
rmSync(path2, { force: true });
|
|
11720
11377
|
warn2("[auto-update-checker] Discarded stale or mismatched pending update marker");
|
|
11721
11378
|
}
|
|
11722
11379
|
} catch (err) {
|
|
11723
11380
|
try {
|
|
11724
|
-
|
|
11381
|
+
rmSync(path2, { force: true });
|
|
11725
11382
|
} catch {}
|
|
11726
11383
|
warn2(`[auto-update-checker] Discarded corrupt pending update marker: ${String(err)}`);
|
|
11727
11384
|
}
|
|
@@ -11822,7 +11479,7 @@ function createLiveSessionState() {
|
|
|
11822
11479
|
|
|
11823
11480
|
// src/hooks/magic-context/module-transport.ts
|
|
11824
11481
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
11825
|
-
import { join as
|
|
11482
|
+
import { join as join4 } from "node:path";
|
|
11826
11483
|
var DEFAULT_MODULE_ID = "magic-context";
|
|
11827
11484
|
var CONNECT_BACKOFF_INITIAL_MS = 1000;
|
|
11828
11485
|
var CONNECT_BACKOFF_MAX_MS = 30000;
|
|
@@ -11832,7 +11489,7 @@ var SERIAL_LANE_MAX_WAITERS = 16;
|
|
|
11832
11489
|
var SERIAL_LANE_MIN_REMAINING_MS = 25;
|
|
11833
11490
|
var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
|
|
11834
11491
|
function getDefaultConnectionFile() {
|
|
11835
|
-
return
|
|
11492
|
+
return join4(getDataDir(), "cortexkit", "run", "subc-connection.json");
|
|
11836
11493
|
}
|
|
11837
11494
|
function errorChainSome(error, predicate) {
|
|
11838
11495
|
let current = error;
|
|
@@ -12100,6 +11757,14 @@ class SubcModuleTransport {
|
|
|
12100
11757
|
throw new Error("mirror.pull omitted page");
|
|
12101
11758
|
return { page: response.page };
|
|
12102
11759
|
}
|
|
11760
|
+
async deleteSession(sessionId, projectRoot) {
|
|
11761
|
+
await this.call({
|
|
11762
|
+
sessionId,
|
|
11763
|
+
projectRoot,
|
|
11764
|
+
method: "session.delete",
|
|
11765
|
+
body: { method: "session.delete", v: 1, session_id: sessionId }
|
|
11766
|
+
});
|
|
11767
|
+
}
|
|
12103
11768
|
closeSession(sessionId) {
|
|
12104
11769
|
const client = this.client;
|
|
12105
11770
|
const prefix = `${sessionId}\x00`;
|
|
@@ -12219,7 +11884,7 @@ class SubcModuleTransport {
|
|
|
12219
11884
|
}
|
|
12220
11885
|
|
|
12221
11886
|
// src/plugin/dream-timer.ts
|
|
12222
|
-
import { statSync as
|
|
11887
|
+
import { statSync as statSync3 } from "node:fs";
|
|
12223
11888
|
|
|
12224
11889
|
// src/features/magic-context/dreamer/storage-dream-state.ts
|
|
12225
11890
|
var getDreamStateStatements = new WeakMap;
|
|
@@ -12847,6 +12512,7 @@ function seedTaskScheduleState(db, projectPath, task, nextDueAt, lastRunAt, sche
|
|
|
12847
12512
|
db.prepare("INSERT INTO task_schedule_state (project_path, task, last_run_at, next_due_at, schedule, last_status, last_error, retry_count) VALUES (?, ?, ?, ?, ?, NULL, NULL, 0) ON CONFLICT(project_path, task) DO NOTHING").run(projectPath, task, lastRunAt, nextDueAt, schedule);
|
|
12848
12513
|
}
|
|
12849
12514
|
function writeTaskScheduleState(db, row) {
|
|
12515
|
+
const broadCycleUpdate = row.lastBroadRunAt === undefined ? "last_broad_run_at = task_schedule_state.last_broad_run_at" : "last_broad_run_at = excluded.last_broad_run_at";
|
|
12850
12516
|
db.prepare(`INSERT INTO task_schedule_state
|
|
12851
12517
|
(project_path, task, last_run_at, next_due_at, schedule, last_status, last_error, retry_count, last_checked_commit, last_broad_run_at, retrospective_watermark_ms)
|
|
12852
12518
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
@@ -12858,7 +12524,7 @@ function writeTaskScheduleState(db, row) {
|
|
|
12858
12524
|
last_error = excluded.last_error,
|
|
12859
12525
|
retry_count = excluded.retry_count,
|
|
12860
12526
|
last_checked_commit = COALESCE(excluded.last_checked_commit, task_schedule_state.last_checked_commit),
|
|
12861
|
-
|
|
12527
|
+
${broadCycleUpdate},
|
|
12862
12528
|
retrospective_watermark_ms = COALESCE(excluded.retrospective_watermark_ms, task_schedule_state.retrospective_watermark_ms)`).run(row.projectPath, row.task, row.lastRunAt, row.nextDueAt, row.schedule, row.lastStatus, row.lastError, row.retryCount, row.lastCheckedCommit ?? null, row.lastBroadRunAt ?? null, row.retrospectiveWatermarkMs ?? null);
|
|
12863
12529
|
}
|
|
12864
12530
|
function isRetrospectiveWindowProcessed(db, projectPath, windowKey) {
|
|
@@ -12870,8 +12536,8 @@ function recordRetrospectiveWindowProcessed(db, projectPath, windowKey) {
|
|
|
12870
12536
|
}
|
|
12871
12537
|
|
|
12872
12538
|
// src/features/magic-context/dreamer/task-executor.ts
|
|
12873
|
-
import { createHash as
|
|
12874
|
-
import { existsSync as
|
|
12539
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
12540
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
12875
12541
|
|
|
12876
12542
|
// src/agents/dreamer.ts
|
|
12877
12543
|
var DREAMER_AGENT = "dreamer";
|
|
@@ -12882,6 +12548,9 @@ var DREAMER_CLASSIFIER_AGENT = "dreamer-classifier";
|
|
|
12882
12548
|
var DREAMER_DOCS_AGENT = "dreamer-docs";
|
|
12883
12549
|
var DREAMER_REVIEWER_AGENT = "dreamer-reviewer";
|
|
12884
12550
|
|
|
12551
|
+
// src/features/magic-context/mural/compress-cues.ts
|
|
12552
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
12553
|
+
|
|
12885
12554
|
// src/features/magic-context/dreamer/manifest-parser.ts
|
|
12886
12555
|
function extractCompleteManifestBody(text, rootName) {
|
|
12887
12556
|
const escapedRoot = rootName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -12915,6 +12584,64 @@ function assertManifestCoversExactly(ids, expectedIds, rootName) {
|
|
|
12915
12584
|
}
|
|
12916
12585
|
}
|
|
12917
12586
|
|
|
12587
|
+
// src/features/magic-context/dreamer/module-apply.ts
|
|
12588
|
+
class DreamerModuleFailureError extends Error {
|
|
12589
|
+
transient = true;
|
|
12590
|
+
constructor(operation, cause) {
|
|
12591
|
+
super(`Rust dreamer ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
12592
|
+
this.name = "DreamerModuleFailureError";
|
|
12593
|
+
this.cause = cause;
|
|
12594
|
+
}
|
|
12595
|
+
}
|
|
12596
|
+
async function resolveDreamerModuleRoute(args) {
|
|
12597
|
+
const transport = args.transformMode === "ts" ? undefined : args.moduleClient;
|
|
12598
|
+
if (!transport?.authorityStatus)
|
|
12599
|
+
return;
|
|
12600
|
+
const contextStoreUuid = getContextStoreUuid(args.db);
|
|
12601
|
+
if (!contextStoreUuid)
|
|
12602
|
+
throw new Error("Rust dreamer requires a context store identity");
|
|
12603
|
+
const result = await transport.authorityStatus({
|
|
12604
|
+
context_store_uuid: contextStoreUuid,
|
|
12605
|
+
project: args.projectIdentity,
|
|
12606
|
+
projectRoot: args.projectRoot,
|
|
12607
|
+
domain: "memories"
|
|
12608
|
+
});
|
|
12609
|
+
if (result.authority?.state !== "MODULE")
|
|
12610
|
+
return;
|
|
12611
|
+
const generation = result.authority.generation;
|
|
12612
|
+
if (typeof generation !== "number")
|
|
12613
|
+
throw new Error("Rust authority status omitted generation");
|
|
12614
|
+
return {
|
|
12615
|
+
moduleClient: transport,
|
|
12616
|
+
moduleSessionId: args.projectIdentity,
|
|
12617
|
+
moduleProjectRoot: args.projectRoot,
|
|
12618
|
+
moduleContextStoreUuid: contextStoreUuid,
|
|
12619
|
+
moduleAuthorityGeneration: generation,
|
|
12620
|
+
moduleCommandId: args.commandId
|
|
12621
|
+
};
|
|
12622
|
+
}
|
|
12623
|
+
function getModuleMemoryIdentities(db, projectIdentity, contextIds) {
|
|
12624
|
+
if (contextIds.length === 0)
|
|
12625
|
+
return new Map;
|
|
12626
|
+
const placeholders = contextIds.map(() => "?").join(", ");
|
|
12627
|
+
const rows = db.prepare(`SELECT identity.context_row_id, identity.module_row_id, live.normalized_hash
|
|
12628
|
+
FROM mirror_identity identity
|
|
12629
|
+
LEFT JOIN mirror_live_memory_rows live
|
|
12630
|
+
ON live.module_project = identity.module_project
|
|
12631
|
+
AND live.module_row_id = identity.module_row_id
|
|
12632
|
+
WHERE identity.domain = 'memories' AND identity.module_project = ?
|
|
12633
|
+
AND identity.context_row_id IN (${placeholders})`).all(projectIdentity, ...contextIds);
|
|
12634
|
+
return new Map(rows.flatMap((row) => Number.isInteger(row.context_row_id) && Number.isInteger(row.module_row_id) && typeof row.normalized_hash === "string" ? [
|
|
12635
|
+
[
|
|
12636
|
+
row.context_row_id,
|
|
12637
|
+
{
|
|
12638
|
+
moduleId: row.module_row_id,
|
|
12639
|
+
normalizedHash: row.normalized_hash
|
|
12640
|
+
}
|
|
12641
|
+
]
|
|
12642
|
+
] : []));
|
|
12643
|
+
}
|
|
12644
|
+
|
|
12918
12645
|
// src/features/magic-context/mural/compress-cues-prompt.ts
|
|
12919
12646
|
var CUE_BUDGET_HIGH = 90;
|
|
12920
12647
|
var CUE_BUDGET_LOW = 50;
|
|
@@ -12986,7 +12713,7 @@ function hasBalancedParentheses(cue) {
|
|
|
12986
12713
|
}
|
|
12987
12714
|
return depth === 0;
|
|
12988
12715
|
}
|
|
12989
|
-
function validateCue(cue, importance) {
|
|
12716
|
+
function validateCue(cue, importance, ownId) {
|
|
12990
12717
|
const trimmed = cue.trim();
|
|
12991
12718
|
if (trimmed.length === 0)
|
|
12992
12719
|
return { reason: "empty" };
|
|
@@ -12994,8 +12721,9 @@ function validateCue(cue, importance) {
|
|
|
12994
12721
|
const length = [...trimmed].length;
|
|
12995
12722
|
if (length > budget)
|
|
12996
12723
|
return { reason: `over-budget ${length}>${budget}` };
|
|
12997
|
-
if (
|
|
12724
|
+
if (ownId !== undefined && new RegExp(`#${ownId}\\b`).test(trimmed)) {
|
|
12998
12725
|
return { reason: "leaked-id" };
|
|
12726
|
+
}
|
|
12999
12727
|
if (!hasBalancedParentheses(trimmed))
|
|
13000
12728
|
return { reason: "unbalanced-parens" };
|
|
13001
12729
|
const markers = trimmed.split("⊘").length - 1;
|
|
@@ -13011,6 +12739,7 @@ function validateCue(cue, importance) {
|
|
|
13011
12739
|
// src/features/magic-context/mural/compress-cues.ts
|
|
13012
12740
|
var COMPRESS_CUES_CHUNK_SIZE = 40;
|
|
13013
12741
|
var CHUNK_TIMEOUT_FLOOR_MS = 240000;
|
|
12742
|
+
var CUE_REJECTION_LATCH_THRESHOLD = 3;
|
|
13014
12743
|
var CONSECUTIVE_TIMEOUT_LIMIT = 2;
|
|
13015
12744
|
function toPromptMemory(candidate) {
|
|
13016
12745
|
const memory = candidate.memory;
|
|
@@ -13021,6 +12750,38 @@ function toPromptMemory(candidate) {
|
|
|
13021
12750
|
content: memory.content
|
|
13022
12751
|
};
|
|
13023
12752
|
}
|
|
12753
|
+
function stripOwnIdToken(value, ownId) {
|
|
12754
|
+
return value.replace(new RegExp(`#${ownId}\\b`, "g"), "");
|
|
12755
|
+
}
|
|
12756
|
+
function truncateCue(value, budget) {
|
|
12757
|
+
const trimmed = value.trim();
|
|
12758
|
+
const codepoints = [...trimmed];
|
|
12759
|
+
if (codepoints.length <= budget)
|
|
12760
|
+
return trimmed;
|
|
12761
|
+
const prefix = codepoints.slice(0, budget).join("");
|
|
12762
|
+
const boundary = prefix.search(/\s+\S*$/);
|
|
12763
|
+
return (boundary > 0 ? prefix.slice(0, boundary) : prefix).trim();
|
|
12764
|
+
}
|
|
12765
|
+
function sanitizeCue(value, candidate) {
|
|
12766
|
+
return truncateCue(stripOwnIdToken(value, candidate.memory.id), cueBudgetFor(candidate.memory.importance ?? 50));
|
|
12767
|
+
}
|
|
12768
|
+
function deterministicFallbackCue(candidate, lastCandidate) {
|
|
12769
|
+
const importance = candidate.memory.importance ?? 50;
|
|
12770
|
+
const budget = cueBudgetFor(importance);
|
|
12771
|
+
const sanitizedCandidate = sanitizeCue(lastCandidate, candidate);
|
|
12772
|
+
if (validateCue(sanitizedCandidate, importance, candidate.memory.id) === null) {
|
|
12773
|
+
return sanitizedCandidate;
|
|
12774
|
+
}
|
|
12775
|
+
const sourceSlice = sanitizeCue(candidate.memory.content, candidate);
|
|
12776
|
+
if (validateCue(sourceSlice, importance, candidate.memory.id) === null) {
|
|
12777
|
+
return sourceSlice;
|
|
12778
|
+
}
|
|
12779
|
+
const grammarSafe = truncateCue(sourceSlice.replaceAll("⊘", "").replace(/[()]/g, "").replace(/\b(?:must not|never|without|instead of|exclude|excludes)\b/gi, "").replace(/\s+/g, " "), budget);
|
|
12780
|
+
if (validateCue(grammarSafe, importance, candidate.memory.id) === null) {
|
|
12781
|
+
return grammarSafe;
|
|
12782
|
+
}
|
|
12783
|
+
return "memory";
|
|
12784
|
+
}
|
|
13024
12785
|
function selectCandidates(db, projectIdentity) {
|
|
13025
12786
|
const memories = getMemoriesByProject(db, projectIdentity, ["active", "permanent"]);
|
|
13026
12787
|
const cueState = getMuralCueState(db, memories.map((memory) => memory.id));
|
|
@@ -13152,7 +12913,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
13152
12913
|
return text;
|
|
13153
12914
|
}
|
|
13154
12915
|
});
|
|
13155
|
-
return applyCues(args, chunk, run.validated);
|
|
12916
|
+
return args.moduleRoute ? await applyCuesThroughModule(args, chunk, run.validated, signal) : applyCues(args, chunk, run.validated);
|
|
13156
12917
|
} catch (error) {
|
|
13157
12918
|
const desc = describeError(error);
|
|
13158
12919
|
log(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
@@ -13189,10 +12950,19 @@ function applyCues(args, chunk, manifestText) {
|
|
|
13189
12950
|
const candidate = byId.get(entry.id);
|
|
13190
12951
|
if (!candidate)
|
|
13191
12952
|
throw new Error(`cues manifest contains unknown id ${entry.id}`);
|
|
13192
|
-
const
|
|
12953
|
+
const importance = candidate.memory.importance ?? 50;
|
|
12954
|
+
const failure = validateCue(entry.cue, importance, candidate.memory.id);
|
|
13193
12955
|
if (failure) {
|
|
12956
|
+
const rejectionCount = recordMuralCueRejection(args.db, args.projectIdentity, entry.id, candidate.contentHash);
|
|
12957
|
+
if (rejectionCount >= CUE_REJECTION_LATCH_THRESHOLD) {
|
|
12958
|
+
const fallback = deterministicFallbackCue(candidate, entry.cue);
|
|
12959
|
+
setMuralCue(args.db, args.projectIdentity, entry.id, fallback, candidate.contentHash);
|
|
12960
|
+
compressed += 1;
|
|
12961
|
+
log(`[dreamer] compress-cues: fallback cue for memory ${entry.id} (${failure.reason}; ${rejectionCount} rejections; fallback)`);
|
|
12962
|
+
continue;
|
|
12963
|
+
}
|
|
13194
12964
|
skipped += 1;
|
|
13195
|
-
log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason})`);
|
|
12965
|
+
log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
|
|
13196
12966
|
continue;
|
|
13197
12967
|
}
|
|
13198
12968
|
setMuralCue(args.db, args.projectIdentity, entry.id, entry.cue.trim(), candidate.contentHash);
|
|
@@ -13201,6 +12971,111 @@ function applyCues(args, chunk, manifestText) {
|
|
|
13201
12971
|
});
|
|
13202
12972
|
return { compressed, skipped };
|
|
13203
12973
|
}
|
|
12974
|
+
async function applyCuesThroughModule(args, chunk, manifestText, signal) {
|
|
12975
|
+
const route = args.moduleRoute;
|
|
12976
|
+
if (!route)
|
|
12977
|
+
throw new Error("module cue apply called without a module route");
|
|
12978
|
+
const byId = new Map(chunk.map((candidate) => [candidate.memory.id, candidate]));
|
|
12979
|
+
const parsed = parseCuesManifest(manifestText);
|
|
12980
|
+
assertManifestCoversExactly(parsed.map((entry) => entry.id), new Set(byId.keys()), "cues");
|
|
12981
|
+
const state = getMuralCueState(args.db, chunk.map((candidate) => candidate.memory.id));
|
|
12982
|
+
const identities = getModuleMemoryIdentities(args.db, args.projectIdentity, chunk.map((candidate) => candidate.memory.id));
|
|
12983
|
+
const updates = [];
|
|
12984
|
+
for (const entry of parsed) {
|
|
12985
|
+
const candidate = byId.get(entry.id);
|
|
12986
|
+
if (!candidate)
|
|
12987
|
+
throw new Error(`cues manifest contains unknown id ${entry.id}`);
|
|
12988
|
+
const identity = identities.get(candidate.memory.id);
|
|
12989
|
+
if (!identity) {
|
|
12990
|
+
throw new Error(`module mirror identity missing for memory ${candidate.memory.id}`);
|
|
12991
|
+
}
|
|
12992
|
+
const failure = validateCue(entry.cue, candidate.memory.importance ?? 50, candidate.memory.id);
|
|
12993
|
+
if (!failure) {
|
|
12994
|
+
updates.push({
|
|
12995
|
+
contextId: candidate.memory.id,
|
|
12996
|
+
moduleId: identity.moduleId,
|
|
12997
|
+
contentHash: candidate.contentHash,
|
|
12998
|
+
cue: entry.cue.trim(),
|
|
12999
|
+
rejectionCount: 0,
|
|
13000
|
+
kind: "compressed"
|
|
13001
|
+
});
|
|
13002
|
+
continue;
|
|
13003
|
+
}
|
|
13004
|
+
const previous = state.get(candidate.memory.id);
|
|
13005
|
+
const rejectionCount = previous?.hash === candidate.contentHash ? (previous.rejectionCount ?? 0) + 1 : 1;
|
|
13006
|
+
if (rejectionCount >= CUE_REJECTION_LATCH_THRESHOLD) {
|
|
13007
|
+
updates.push({
|
|
13008
|
+
contextId: candidate.memory.id,
|
|
13009
|
+
moduleId: identity.moduleId,
|
|
13010
|
+
contentHash: candidate.contentHash,
|
|
13011
|
+
cue: deterministicFallbackCue(candidate, entry.cue),
|
|
13012
|
+
rejectionCount: 0,
|
|
13013
|
+
kind: "compressed"
|
|
13014
|
+
});
|
|
13015
|
+
log(`[dreamer] compress-cues: fallback cue for memory ${entry.id} (${failure.reason}; ${rejectionCount} rejections; fallback)`);
|
|
13016
|
+
} else {
|
|
13017
|
+
updates.push({
|
|
13018
|
+
contextId: candidate.memory.id,
|
|
13019
|
+
moduleId: identity.moduleId,
|
|
13020
|
+
contentHash: candidate.contentHash,
|
|
13021
|
+
cue: null,
|
|
13022
|
+
rejectionCount,
|
|
13023
|
+
kind: "skipped"
|
|
13024
|
+
});
|
|
13025
|
+
log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
|
|
13026
|
+
}
|
|
13027
|
+
}
|
|
13028
|
+
const commandId = `mural-cues:${route.moduleCommandId}:${createHash2("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
|
|
13029
|
+
let response;
|
|
13030
|
+
try {
|
|
13031
|
+
response = await route.moduleClient.call({
|
|
13032
|
+
sessionId: route.moduleSessionId,
|
|
13033
|
+
projectRoot: route.moduleProjectRoot,
|
|
13034
|
+
method: "memory.set_mural_cue",
|
|
13035
|
+
body: {
|
|
13036
|
+
name: "memory.set_mural_cue",
|
|
13037
|
+
arguments: {
|
|
13038
|
+
memory_project: args.projectIdentity,
|
|
13039
|
+
context_store_uuid: route.moduleContextStoreUuid,
|
|
13040
|
+
authority_generation: route.moduleAuthorityGeneration,
|
|
13041
|
+
command_id: commandId,
|
|
13042
|
+
rows: updates.map((update) => ({
|
|
13043
|
+
memory_id: update.moduleId,
|
|
13044
|
+
content_hash_at_prompt: update.contentHash,
|
|
13045
|
+
cue: update.cue,
|
|
13046
|
+
rejection_count: update.rejectionCount
|
|
13047
|
+
}))
|
|
13048
|
+
}
|
|
13049
|
+
},
|
|
13050
|
+
signal
|
|
13051
|
+
});
|
|
13052
|
+
} catch (error) {
|
|
13053
|
+
throw new DreamerModuleFailureError("mural cue apply", error);
|
|
13054
|
+
}
|
|
13055
|
+
const result = response?.result ?? response;
|
|
13056
|
+
if (!result || typeof result !== "object") {
|
|
13057
|
+
throw new Error("module returned invalid mural cue apply result");
|
|
13058
|
+
}
|
|
13059
|
+
const accepted = result.accepted;
|
|
13060
|
+
if (!Array.isArray(accepted) || !accepted.every((id) => Number.isInteger(id))) {
|
|
13061
|
+
throw new Error("module returned no mural cue acceptance list");
|
|
13062
|
+
}
|
|
13063
|
+
const acceptedIds = new Set(accepted);
|
|
13064
|
+
const rejected = result.rejected;
|
|
13065
|
+
const rejectedReasons = new Map;
|
|
13066
|
+
for (const row of Array.isArray(rejected) ? rejected : []) {
|
|
13067
|
+
const reason = row && typeof row === "object" && typeof row.reason === "string" ? row.reason : "unknown";
|
|
13068
|
+
rejectedReasons.set(reason, (rejectedReasons.get(reason) ?? 0) + 1);
|
|
13069
|
+
}
|
|
13070
|
+
if ([...rejectedReasons].some(([reason]) => reason !== "stale")) {
|
|
13071
|
+
throw new Error(`module rejected mural cues (${[...rejectedReasons].map(([reason, count]) => `${reason}=${count}`).join(", ")})`);
|
|
13072
|
+
}
|
|
13073
|
+
return updates.reduce((counts, update) => {
|
|
13074
|
+
if (acceptedIds.has(update.moduleId))
|
|
13075
|
+
counts[update.kind] += 1;
|
|
13076
|
+
return counts;
|
|
13077
|
+
}, { compressed: 0, skipped: 0 });
|
|
13078
|
+
}
|
|
13204
13079
|
|
|
13205
13080
|
// src/features/magic-context/user-memory/review-user-memories.ts
|
|
13206
13081
|
async function reviewUserMemories(args) {
|
|
@@ -13410,7 +13285,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
13410
13285
|
}
|
|
13411
13286
|
|
|
13412
13287
|
// src/features/magic-context/dreamer/classify.ts
|
|
13413
|
-
import { createHash as
|
|
13288
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
13414
13289
|
|
|
13415
13290
|
// src/plugin/rust-tool-backends.ts
|
|
13416
13291
|
function toolCallIdFromContext(context) {
|
|
@@ -13445,7 +13320,7 @@ function isRustAuthorityDrainingError(error) {
|
|
|
13445
13320
|
}
|
|
13446
13321
|
|
|
13447
13322
|
// src/shared/redaction.ts
|
|
13448
|
-
import { homedir as
|
|
13323
|
+
import { homedir as homedir3, userInfo } from "node:os";
|
|
13449
13324
|
function escapeRegex(value) {
|
|
13450
13325
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13451
13326
|
}
|
|
@@ -13494,7 +13369,7 @@ var SECRET_QUALIFIERS = new Set([
|
|
|
13494
13369
|
"azure"
|
|
13495
13370
|
]);
|
|
13496
13371
|
function sanitizePathString(value) {
|
|
13497
|
-
const home =
|
|
13372
|
+
const home = homedir3();
|
|
13498
13373
|
const username = userInfo().username;
|
|
13499
13374
|
let sanitized = value;
|
|
13500
13375
|
if (home) {
|
|
@@ -13696,64 +13571,6 @@ function parseClassifyManifest(text) {
|
|
|
13696
13571
|
return out;
|
|
13697
13572
|
}
|
|
13698
13573
|
|
|
13699
|
-
// src/features/magic-context/dreamer/module-apply.ts
|
|
13700
|
-
class DreamerModuleFailureError extends Error {
|
|
13701
|
-
transient = true;
|
|
13702
|
-
constructor(operation, cause) {
|
|
13703
|
-
super(`Rust dreamer ${operation} failed: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
13704
|
-
this.name = "DreamerModuleFailureError";
|
|
13705
|
-
this.cause = cause;
|
|
13706
|
-
}
|
|
13707
|
-
}
|
|
13708
|
-
async function resolveDreamerModuleRoute(args) {
|
|
13709
|
-
const transport = args.transformMode === "ts" ? undefined : args.moduleClient;
|
|
13710
|
-
if (!transport?.authorityStatus)
|
|
13711
|
-
return;
|
|
13712
|
-
const contextStoreUuid = getContextStoreUuid(args.db);
|
|
13713
|
-
if (!contextStoreUuid)
|
|
13714
|
-
throw new Error("Rust dreamer requires a context store identity");
|
|
13715
|
-
const result = await transport.authorityStatus({
|
|
13716
|
-
context_store_uuid: contextStoreUuid,
|
|
13717
|
-
project: args.projectIdentity,
|
|
13718
|
-
projectRoot: args.projectRoot,
|
|
13719
|
-
domain: "memories"
|
|
13720
|
-
});
|
|
13721
|
-
if (result.authority?.state !== "MODULE")
|
|
13722
|
-
return;
|
|
13723
|
-
const generation = result.authority.generation;
|
|
13724
|
-
if (typeof generation !== "number")
|
|
13725
|
-
throw new Error("Rust authority status omitted generation");
|
|
13726
|
-
return {
|
|
13727
|
-
moduleClient: transport,
|
|
13728
|
-
moduleSessionId: args.projectIdentity,
|
|
13729
|
-
moduleProjectRoot: args.projectRoot,
|
|
13730
|
-
moduleContextStoreUuid: contextStoreUuid,
|
|
13731
|
-
moduleAuthorityGeneration: generation,
|
|
13732
|
-
moduleCommandId: args.commandId
|
|
13733
|
-
};
|
|
13734
|
-
}
|
|
13735
|
-
function getModuleMemoryIdentities(db, projectIdentity, contextIds) {
|
|
13736
|
-
if (contextIds.length === 0)
|
|
13737
|
-
return new Map;
|
|
13738
|
-
const placeholders = contextIds.map(() => "?").join(", ");
|
|
13739
|
-
const rows = db.prepare(`SELECT identity.context_row_id, identity.module_row_id, live.normalized_hash
|
|
13740
|
-
FROM mirror_identity identity
|
|
13741
|
-
LEFT JOIN mirror_live_memory_rows live
|
|
13742
|
-
ON live.module_project = identity.module_project
|
|
13743
|
-
AND live.module_row_id = identity.module_row_id
|
|
13744
|
-
WHERE identity.domain = 'memories' AND identity.module_project = ?
|
|
13745
|
-
AND identity.context_row_id IN (${placeholders})`).all(projectIdentity, ...contextIds);
|
|
13746
|
-
return new Map(rows.flatMap((row) => Number.isInteger(row.context_row_id) && Number.isInteger(row.module_row_id) && typeof row.normalized_hash === "string" ? [
|
|
13747
|
-
[
|
|
13748
|
-
row.context_row_id,
|
|
13749
|
-
{
|
|
13750
|
-
moduleId: row.module_row_id,
|
|
13751
|
-
normalizedHash: row.normalized_hash
|
|
13752
|
-
}
|
|
13753
|
-
]
|
|
13754
|
-
] : []));
|
|
13755
|
-
}
|
|
13756
|
-
|
|
13757
13574
|
// src/features/magic-context/dreamer/classify.ts
|
|
13758
13575
|
var MIN_POOL_TO_CLASSIFY = 10;
|
|
13759
13576
|
var FULL_POOL_CEILING = 100;
|
|
@@ -13990,7 +13807,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
13990
13807
|
v: 1,
|
|
13991
13808
|
session_id: args.moduleSessionId,
|
|
13992
13809
|
task: "classify",
|
|
13993
|
-
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${
|
|
13810
|
+
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash3("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
|
|
13994
13811
|
authority_generation: args.moduleAuthorityGeneration,
|
|
13995
13812
|
payload: {
|
|
13996
13813
|
prompt_body: prompt,
|
|
@@ -14522,21 +14339,21 @@ function isSecretDeniedPath(repoRelativePath) {
|
|
|
14522
14339
|
const segments = normalized.split("/");
|
|
14523
14340
|
if (segments.includes(".git") || segments.includes("secrets"))
|
|
14524
14341
|
return true;
|
|
14525
|
-
const
|
|
14526
|
-
if (
|
|
14342
|
+
const basename = segments.at(-1) ?? "";
|
|
14343
|
+
if (basename === ".npmrc" || basename.startsWith(".env"))
|
|
14527
14344
|
return true;
|
|
14528
|
-
if (
|
|
14345
|
+
if (basename === ".pgpass" || basename === ".netrc")
|
|
14529
14346
|
return true;
|
|
14530
|
-
if (SECRET_KEY_EXTENSIONS.some((extension) =>
|
|
14347
|
+
if (SECRET_KEY_EXTENSIONS.some((extension) => basename.endsWith(extension)))
|
|
14531
14348
|
return true;
|
|
14532
|
-
if (
|
|
14349
|
+
if (basename === "id_rsa" || basename === "id_dsa" || basename === "id_ecdsa" || basename === "id_ed25519" || basename.startsWith("id_")) {
|
|
14533
14350
|
return true;
|
|
14534
14351
|
}
|
|
14535
|
-
if (segments.includes(".aws") &&
|
|
14352
|
+
if (segments.includes(".aws") && basename === "credentials")
|
|
14536
14353
|
return true;
|
|
14537
|
-
if (
|
|
14538
|
-
const serviceAccountJson =
|
|
14539
|
-
const gcloudCredentialJson = segments.includes("gcloud") && (
|
|
14354
|
+
if (basename.endsWith(".json")) {
|
|
14355
|
+
const serviceAccountJson = basename.includes("service-account") || basename.includes("service_account");
|
|
14356
|
+
const gcloudCredentialJson = segments.includes("gcloud") && (basename === "application_default_credentials.json" || basename.includes("credential") || segments.includes("legacy_credentials"));
|
|
14540
14357
|
if (serviceAccountJson || gcloudCredentialJson)
|
|
14541
14358
|
return true;
|
|
14542
14359
|
}
|
|
@@ -14686,7 +14503,7 @@ function throwIfAborted2(signal) {
|
|
|
14686
14503
|
}
|
|
14687
14504
|
|
|
14688
14505
|
// src/features/magic-context/smart-notes/compiler.ts
|
|
14689
|
-
import { createHash as
|
|
14506
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
14690
14507
|
|
|
14691
14508
|
// src/features/magic-context/smart-notes/sandbox-runner.ts
|
|
14692
14509
|
var asyncModulePromise = null;
|
|
@@ -15080,7 +14897,7 @@ function manifestAdvisoryWarnings(code, manifest) {
|
|
|
15080
14897
|
return warnings;
|
|
15081
14898
|
}
|
|
15082
14899
|
function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
|
|
15083
|
-
return
|
|
14900
|
+
return createHash4("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
|
|
15084
14901
|
}
|
|
15085
14902
|
function extractJsonObject(output) {
|
|
15086
14903
|
const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
@@ -15778,8 +15595,8 @@ Output exactly JSON: {"met": false}`;
|
|
|
15778
15595
|
}
|
|
15779
15596
|
|
|
15780
15597
|
// src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
15781
|
-
import { existsSync as
|
|
15782
|
-
import { join as
|
|
15598
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
|
|
15599
|
+
import { join as join5 } from "node:path";
|
|
15783
15600
|
|
|
15784
15601
|
// src/features/magic-context/dreamer/protected-regions.ts
|
|
15785
15602
|
var PROTECTED_START_TOKEN = "mc:protected START";
|
|
@@ -15880,10 +15697,10 @@ var MAINTAIN_DOCS_SNAPSHOT_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
|
15880
15697
|
function snapshotMaintainDocsFiles(docsDir) {
|
|
15881
15698
|
const snapshot = new Map;
|
|
15882
15699
|
for (const name of MAINTAIN_DOCS_SNAPSHOT_FILES) {
|
|
15883
|
-
const path3 =
|
|
15700
|
+
const path3 = join5(docsDir, name);
|
|
15884
15701
|
try {
|
|
15885
|
-
if (
|
|
15886
|
-
snapshot.set(name,
|
|
15702
|
+
if (existsSync7(path3)) {
|
|
15703
|
+
snapshot.set(name, readFileSync5(path3, "utf8"));
|
|
15887
15704
|
}
|
|
15888
15705
|
} catch {}
|
|
15889
15706
|
}
|
|
@@ -15891,14 +15708,14 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
15891
15708
|
}
|
|
15892
15709
|
function enforceMaintainDocsProtectedRegions(args) {
|
|
15893
15710
|
for (const [fileName, original] of args.snapshot) {
|
|
15894
|
-
const path3 =
|
|
15711
|
+
const path3 = join5(args.docsDir, fileName);
|
|
15895
15712
|
try {
|
|
15896
|
-
const current =
|
|
15713
|
+
const current = readFileSync5(path3, "utf8");
|
|
15897
15714
|
const { text, violated } = enforceProtectedRegions(original, current);
|
|
15898
15715
|
if (!violated) {
|
|
15899
15716
|
continue;
|
|
15900
15717
|
}
|
|
15901
|
-
|
|
15718
|
+
writeFileSync3(path3, text, "utf8");
|
|
15902
15719
|
log(`[dreamer] maintain-docs altered a protected region in ${fileName} — restored from pre-task snapshot`);
|
|
15903
15720
|
} catch (error) {
|
|
15904
15721
|
log(`[dreamer] maintain-docs protected-region enforcement failed for ${fileName}: ${error}`);
|
|
@@ -15907,10 +15724,10 @@ function enforceMaintainDocsProtectedRegions(args) {
|
|
|
15907
15724
|
}
|
|
15908
15725
|
|
|
15909
15726
|
// src/features/magic-context/dreamer/map-memories.ts
|
|
15910
|
-
import { createHash as
|
|
15727
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
15911
15728
|
|
|
15912
15729
|
// src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
15913
|
-
import { existsSync as
|
|
15730
|
+
import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
|
|
15914
15731
|
import path3 from "node:path";
|
|
15915
15732
|
var MAP_MEMORIES_SYSTEM_PROMPT = `You are a memory mapper for the magic-context system. You map project memories to the repository files that back them.
|
|
15916
15733
|
|
|
@@ -15948,7 +15765,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
15948
15765
|
if (!abs.startsWith(`${root}/`))
|
|
15949
15766
|
continue;
|
|
15950
15767
|
try {
|
|
15951
|
-
if (
|
|
15768
|
+
if (existsSync8(abs) && statSync2(abs).isFile())
|
|
15952
15769
|
found.add(rel);
|
|
15953
15770
|
} catch {}
|
|
15954
15771
|
if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
|
|
@@ -16168,7 +15985,7 @@ async function applyBatchMappings(args, batch, manifestText) {
|
|
|
16168
15985
|
memory_project: args.projectIdentity,
|
|
16169
15986
|
context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
|
|
16170
15987
|
authority_generation: args.moduleRoute.moduleAuthorityGeneration,
|
|
16171
|
-
command_id: `${args.moduleRoute.moduleCommandId}:${
|
|
15988
|
+
command_id: `${args.moduleRoute.moduleCommandId}:${createHash5("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
|
|
16172
15989
|
rows
|
|
16173
15990
|
}
|
|
16174
15991
|
}
|
|
@@ -16954,6 +16771,19 @@ function countUnverifiedMappedMemories(db, projectPath) {
|
|
|
16954
16771
|
AND v.verified_at = 0`).get(projectPath);
|
|
16955
16772
|
return row?.cnt ?? 0;
|
|
16956
16773
|
}
|
|
16774
|
+
function countBroadCycleCandidates(db, projectPath, cycleStartAt) {
|
|
16775
|
+
const row = db.prepare(`SELECT COUNT(*) AS cnt
|
|
16776
|
+
FROM memories m
|
|
16777
|
+
WHERE m.project_path = ?
|
|
16778
|
+
AND m.status IN ('active','permanent')
|
|
16779
|
+
AND (
|
|
16780
|
+
SELECT MAX(v.verified_at)
|
|
16781
|
+
FROM memory_verifications v
|
|
16782
|
+
WHERE v.memory_id = m.id
|
|
16783
|
+
AND v.file_path <> ''
|
|
16784
|
+
) < ?`).get(projectPath, cycleStartAt);
|
|
16785
|
+
return row?.cnt ?? 0;
|
|
16786
|
+
}
|
|
16957
16787
|
function countCueCandidates(db, projectPath) {
|
|
16958
16788
|
if (!hasMuralCueColumns(db))
|
|
16959
16789
|
return countActiveMemories(db, projectPath);
|
|
@@ -17009,7 +16839,9 @@ function getDreamTaskBacklog(db, projectPath, task, options = {}) {
|
|
|
17009
16839
|
}
|
|
17010
16840
|
case "verify-broad": {
|
|
17011
16841
|
const total = countMappedMemories(db, projectPath);
|
|
17012
|
-
|
|
16842
|
+
const cycleStartAt = getTaskScheduleState(db, projectPath, "verify-broad")?.lastBroadRunAt;
|
|
16843
|
+
const pending = cycleStartAt == null ? total : countBroadCycleCandidates(db, projectPath, cycleStartAt);
|
|
16844
|
+
return { pending, total };
|
|
17013
16845
|
}
|
|
17014
16846
|
case "curate": {
|
|
17015
16847
|
const total = countActiveMemories(db, projectPath);
|
|
@@ -17068,7 +16900,7 @@ function evaluateTaskGate(task, ctx) {
|
|
|
17068
16900
|
case "verify":
|
|
17069
16901
|
return countActiveMemories(db, project) > 0;
|
|
17070
16902
|
case "verify-broad":
|
|
17071
|
-
return countActiveMemories(db, project) > 0;
|
|
16903
|
+
return getTaskScheduleState(db, project, "verify-broad")?.lastBroadRunAt != null || countActiveMemories(db, project) > 0;
|
|
17072
16904
|
case "curate":
|
|
17073
16905
|
return countActiveMemories(db, project) > 0;
|
|
17074
16906
|
case "compress-cues":
|
|
@@ -17095,13 +16927,99 @@ function evaluateTaskGate(task, ctx) {
|
|
|
17095
16927
|
}
|
|
17096
16928
|
|
|
17097
16929
|
// src/features/magic-context/dreamer/verify.ts
|
|
17098
|
-
import { createHash as
|
|
16930
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
16931
|
+
|
|
16932
|
+
// src/features/magic-context/dreamer/provider-output-failure.ts
|
|
16933
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
16934
|
+
var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
|
|
16935
|
+
|
|
16936
|
+
class DreamerProviderOutputFailureError extends Error {
|
|
16937
|
+
fingerprint;
|
|
16938
|
+
outputTokens;
|
|
16939
|
+
reasoningTokens;
|
|
16940
|
+
transient = true;
|
|
16941
|
+
constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
|
|
16942
|
+
const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
|
|
16943
|
+
super(`verify provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
|
|
16944
|
+
this.fingerprint = fingerprint;
|
|
16945
|
+
this.outputTokens = outputTokens;
|
|
16946
|
+
this.reasoningTokens = reasoningTokens;
|
|
16947
|
+
this.name = "DreamerProviderOutputFailureError";
|
|
16948
|
+
}
|
|
16949
|
+
}
|
|
16950
|
+
function finiteTokenCount(value) {
|
|
16951
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
|
|
16952
|
+
}
|
|
16953
|
+
function completionShape(value) {
|
|
16954
|
+
if (!isRecord(value))
|
|
16955
|
+
return null;
|
|
16956
|
+
const info = isRecord(value.info) ? value.info : value;
|
|
16957
|
+
if (info.role !== "assistant")
|
|
16958
|
+
return null;
|
|
16959
|
+
const time = isRecord(info.time) ? info.time : null;
|
|
16960
|
+
const tokens = isRecord(info.tokens) ? info.tokens : null;
|
|
16961
|
+
return {
|
|
16962
|
+
createdAt: typeof time?.created === "number" ? time.created : 0,
|
|
16963
|
+
finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
|
|
16964
|
+
error: info.error,
|
|
16965
|
+
outputTokens: finiteTokenCount(tokens?.output),
|
|
16966
|
+
reasoningTokens: finiteTokenCount(tokens?.reasoning)
|
|
16967
|
+
};
|
|
16968
|
+
}
|
|
16969
|
+
function latestAssistantCompletion(messages) {
|
|
16970
|
+
if (!Array.isArray(messages))
|
|
16971
|
+
return null;
|
|
16972
|
+
let latest = null;
|
|
16973
|
+
for (const message of messages) {
|
|
16974
|
+
const completion = completionShape(message);
|
|
16975
|
+
if (completion && (!latest || completion.createdAt >= latest.createdAt))
|
|
16976
|
+
latest = completion;
|
|
16977
|
+
}
|
|
16978
|
+
return latest;
|
|
16979
|
+
}
|
|
16980
|
+
function providerOutputFailureFromInvalidManifest(messages, responseText) {
|
|
16981
|
+
const completion = latestAssistantCompletion(messages);
|
|
16982
|
+
if (completion?.finish?.toLowerCase() !== "stop")
|
|
16983
|
+
return null;
|
|
16984
|
+
if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
|
|
16985
|
+
return null;
|
|
16986
|
+
}
|
|
16987
|
+
const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
|
|
16988
|
+
if (!normalized)
|
|
16989
|
+
return null;
|
|
16990
|
+
const fingerprint = createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
16991
|
+
return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
|
|
16992
|
+
}
|
|
17099
16993
|
|
|
17100
16994
|
// src/features/magic-context/dreamer/verify-gate.ts
|
|
17101
16995
|
import path4 from "node:path";
|
|
17102
16996
|
function minOf(values) {
|
|
17103
16997
|
return values.reduce((acc, v) => v < acc ? v : acc, Number.POSITIVE_INFINITY);
|
|
17104
16998
|
}
|
|
16999
|
+
function ensureBroadCycleStart(args) {
|
|
17000
|
+
const current = getTaskScheduleState(args.db, args.projectIdentity, "verify-broad");
|
|
17001
|
+
if (current?.lastBroadRunAt != null && current.lastBroadRunAt > 0) {
|
|
17002
|
+
return current.lastBroadRunAt;
|
|
17003
|
+
}
|
|
17004
|
+
if (!current)
|
|
17005
|
+
return args.runStartedAt;
|
|
17006
|
+
if (!args.holderId || !args.leaseKey) {
|
|
17007
|
+
throw new Error("verify-broad cycle opening requires the task lease");
|
|
17008
|
+
}
|
|
17009
|
+
return runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
17010
|
+
const latest = getTaskScheduleState(args.db, args.projectIdentity, "verify-broad");
|
|
17011
|
+
if (!latest)
|
|
17012
|
+
return args.runStartedAt;
|
|
17013
|
+
if (latest.lastBroadRunAt != null && latest.lastBroadRunAt > 0) {
|
|
17014
|
+
return latest.lastBroadRunAt;
|
|
17015
|
+
}
|
|
17016
|
+
writeTaskScheduleState(args.db, {
|
|
17017
|
+
...latest,
|
|
17018
|
+
lastBroadRunAt: args.runStartedAt
|
|
17019
|
+
});
|
|
17020
|
+
return args.runStartedAt;
|
|
17021
|
+
});
|
|
17022
|
+
}
|
|
17105
17023
|
async function partitionVerifyScope(args) {
|
|
17106
17024
|
const runStartedAt = args.now ?? Date.now();
|
|
17107
17025
|
const active = getMemoriesByProject(args.db, args.projectIdentity);
|
|
@@ -17113,6 +17031,29 @@ async function partitionVerifyScope(args) {
|
|
|
17113
17031
|
content: m.content,
|
|
17114
17032
|
mappedFiles: verById.get(m.id)?.files ?? []
|
|
17115
17033
|
});
|
|
17034
|
+
if (args.forceBroad) {
|
|
17035
|
+
const broadCycleStartAt = ensureBroadCycleStart({
|
|
17036
|
+
db: args.db,
|
|
17037
|
+
projectIdentity: args.projectIdentity,
|
|
17038
|
+
holderId: args.holderId,
|
|
17039
|
+
leaseKey: args.leaseKey,
|
|
17040
|
+
runStartedAt
|
|
17041
|
+
});
|
|
17042
|
+
const broadCandidates = candidates.filter((m) => (verById.get(m.id)?.verifiedAt ?? 0) < broadCycleStartAt).sort((a, b) => {
|
|
17043
|
+
const verifiedAtA = verById.get(a.id)?.verifiedAt ?? 0;
|
|
17044
|
+
const verifiedAtB = verById.get(b.id)?.verifiedAt ?? 0;
|
|
17045
|
+
return verifiedAtA - verifiedAtB || a.id - b.id;
|
|
17046
|
+
});
|
|
17047
|
+
return {
|
|
17048
|
+
runStartedAt,
|
|
17049
|
+
mode: "broad",
|
|
17050
|
+
inScope: broadCandidates.map(toPrompt),
|
|
17051
|
+
inScopeIds: broadCandidates.map((m) => m.id),
|
|
17052
|
+
skippedIds: candidates.filter((m) => !broadCandidates.some((candidate) => candidate.id === m.id)).map((m) => m.id),
|
|
17053
|
+
broadCycleStartAt,
|
|
17054
|
+
reason: `broad cycle (${broadCandidates.length} remain; started ${broadCycleStartAt})`
|
|
17055
|
+
};
|
|
17056
|
+
}
|
|
17116
17057
|
if (candidates.length === 0) {
|
|
17117
17058
|
return {
|
|
17118
17059
|
runStartedAt,
|
|
@@ -17123,16 +17064,6 @@ async function partitionVerifyScope(args) {
|
|
|
17123
17064
|
reason: "no file-mapped memories in scope"
|
|
17124
17065
|
};
|
|
17125
17066
|
}
|
|
17126
|
-
if (args.forceBroad) {
|
|
17127
|
-
return {
|
|
17128
|
-
runStartedAt,
|
|
17129
|
-
mode: "broad",
|
|
17130
|
-
inScope: candidates.map(toPrompt),
|
|
17131
|
-
inScopeIds: candidates.map((m) => m.id),
|
|
17132
|
-
skippedIds: [],
|
|
17133
|
-
reason: "broad full-pool verification of file-mapped memories"
|
|
17134
|
-
};
|
|
17135
|
-
}
|
|
17136
17067
|
const allInScope = (mode, reason) => ({
|
|
17137
17068
|
runStartedAt,
|
|
17138
17069
|
mode,
|
|
@@ -17251,7 +17182,26 @@ function parseVerifyManifest(text) {
|
|
|
17251
17182
|
|
|
17252
17183
|
// src/features/magic-context/dreamer/verify.ts
|
|
17253
17184
|
var VERIFY_BATCH_SIZE = 50;
|
|
17185
|
+
var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
|
|
17186
|
+
function closeBroadCycle(args, cycleStartAt) {
|
|
17187
|
+
if (!args.forceBroad || cycleStartAt === undefined)
|
|
17188
|
+
return;
|
|
17189
|
+
if (!getTaskScheduleState(args.db, args.projectIdentity, "verify-broad"))
|
|
17190
|
+
return;
|
|
17191
|
+
runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
17192
|
+
const current = getTaskScheduleState(args.db, args.projectIdentity, "verify-broad");
|
|
17193
|
+
if (current?.lastBroadRunAt !== cycleStartAt)
|
|
17194
|
+
return;
|
|
17195
|
+
if (!current)
|
|
17196
|
+
return;
|
|
17197
|
+
writeTaskScheduleState(args.db, {
|
|
17198
|
+
...current,
|
|
17199
|
+
lastBroadRunAt: null
|
|
17200
|
+
});
|
|
17201
|
+
});
|
|
17202
|
+
}
|
|
17254
17203
|
async function runVerify(args) {
|
|
17204
|
+
const runStartedAt = Date.now();
|
|
17255
17205
|
const result = {
|
|
17256
17206
|
verified: 0,
|
|
17257
17207
|
updated: 0,
|
|
@@ -17266,20 +17216,29 @@ async function runVerify(args) {
|
|
|
17266
17216
|
db: args.db,
|
|
17267
17217
|
projectIdentity: args.projectIdentity,
|
|
17268
17218
|
projectDirectory: args.sessionDirectory,
|
|
17269
|
-
forceBroad: args.forceBroad
|
|
17219
|
+
forceBroad: args.forceBroad,
|
|
17220
|
+
now: runStartedAt,
|
|
17221
|
+
holderId: args.holderId,
|
|
17222
|
+
leaseKey: args.leaseKey
|
|
17270
17223
|
});
|
|
17271
17224
|
result.mode = gate.mode;
|
|
17225
|
+
result.broadCycleStartAt = gate.broadCycleStartAt;
|
|
17272
17226
|
result.inScope = gate.inScope.length;
|
|
17273
17227
|
result.remaining = gate.inScope.length;
|
|
17274
17228
|
log(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"} gate: mode=${gate.mode} in_scope=${gate.inScope.length} skipped=${gate.skippedIds.length} reason=${gate.reason}`);
|
|
17275
|
-
if (gate.inScope.length === 0)
|
|
17229
|
+
if (gate.inScope.length === 0) {
|
|
17230
|
+
closeBroadCycle(args, gate.broadCycleStartAt);
|
|
17276
17231
|
return result;
|
|
17232
|
+
}
|
|
17277
17233
|
const batches = [];
|
|
17278
17234
|
for (let i = 0;i < gate.inScope.length; i += VERIFY_BATCH_SIZE) {
|
|
17279
17235
|
batches.push(gate.inScope.slice(i, i + VERIFY_BATCH_SIZE));
|
|
17280
17236
|
}
|
|
17281
17237
|
const abortController = new AbortController;
|
|
17282
17238
|
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
|
|
17239
|
+
let consecutiveProviderFailures = 0;
|
|
17240
|
+
let priorProviderFailureFingerprint = null;
|
|
17241
|
+
let lastProviderFailure = null;
|
|
17283
17242
|
try {
|
|
17284
17243
|
for (let i = 0;i < batches.length; i += 1) {
|
|
17285
17244
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
@@ -17294,8 +17253,28 @@ async function runVerify(args) {
|
|
|
17294
17253
|
result.remaining -= counts.verified + counts.updated + counts.archived;
|
|
17295
17254
|
result.batches += 1;
|
|
17296
17255
|
args.onProgress?.(result.verified + result.updated + result.archived);
|
|
17256
|
+
if (counts.providerFailure) {
|
|
17257
|
+
lastProviderFailure = counts.providerFailure;
|
|
17258
|
+
if (counts.providerFailure.fingerprint === priorProviderFailureFingerprint) {
|
|
17259
|
+
consecutiveProviderFailures += 1;
|
|
17260
|
+
} else {
|
|
17261
|
+
priorProviderFailureFingerprint = counts.providerFailure.fingerprint;
|
|
17262
|
+
consecutiveProviderFailures = 1;
|
|
17263
|
+
}
|
|
17264
|
+
if (consecutiveProviderFailures >= IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT) {
|
|
17265
|
+
log(`[dreamer] verify run aborting after ${consecutiveProviderFailures} identical provider-failure batches`);
|
|
17266
|
+
throw counts.providerFailure;
|
|
17267
|
+
}
|
|
17268
|
+
} else {
|
|
17269
|
+
priorProviderFailureFingerprint = null;
|
|
17270
|
+
consecutiveProviderFailures = 0;
|
|
17271
|
+
}
|
|
17297
17272
|
}
|
|
17273
|
+
if (lastProviderFailure)
|
|
17274
|
+
throw lastProviderFailure;
|
|
17298
17275
|
result.complete = result.remaining === 0;
|
|
17276
|
+
if (result.complete)
|
|
17277
|
+
closeBroadCycle(args, gate.broadCycleStartAt);
|
|
17299
17278
|
log(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: verified=${result.verified} updated=${result.updated} archived=${result.archived} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}`);
|
|
17300
17279
|
return result;
|
|
17301
17280
|
} finally {
|
|
@@ -17350,7 +17329,14 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
17350
17329
|
const text = extractLatestAssistantText(messages);
|
|
17351
17330
|
if (!text)
|
|
17352
17331
|
throw new Error("verify returned no output");
|
|
17353
|
-
|
|
17332
|
+
try {
|
|
17333
|
+
parseVerifyManifest(text);
|
|
17334
|
+
} catch (error) {
|
|
17335
|
+
const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
|
|
17336
|
+
if (providerFailure)
|
|
17337
|
+
throw providerFailure;
|
|
17338
|
+
throw error;
|
|
17339
|
+
}
|
|
17354
17340
|
return text;
|
|
17355
17341
|
}
|
|
17356
17342
|
});
|
|
@@ -17358,11 +17344,12 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
17358
17344
|
return await applyVerifyManifest(args, batch, run.validated);
|
|
17359
17345
|
} catch (error) {
|
|
17360
17346
|
const desc = describeError(error);
|
|
17361
|
-
|
|
17347
|
+
const providerFailure = error instanceof DreamerProviderOutputFailureError ? error : undefined;
|
|
17348
|
+
log(`[dreamer] verify batch ${providerFailure ? "provider failure" : "failed"}: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
17362
17349
|
recordInvocation4(args, startedAt, { status: "failed", error });
|
|
17363
17350
|
if (error instanceof DreamerModuleFailureError || signal.aborted)
|
|
17364
17351
|
throw error;
|
|
17365
|
-
return { verified: 0, updated: 0, archived: 0 };
|
|
17352
|
+
return { verified: 0, updated: 0, archived: 0, providerFailure };
|
|
17366
17353
|
} finally {
|
|
17367
17354
|
if (agentSessionId && !shouldKeepSubagents()) {
|
|
17368
17355
|
await args.client.session.delete({
|
|
@@ -17434,7 +17421,7 @@ async function applyVerifyManifest(args, batch, manifestText) {
|
|
|
17434
17421
|
memory_project: args.projectIdentity,
|
|
17435
17422
|
context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
|
|
17436
17423
|
authority_generation: args.moduleRoute.moduleAuthorityGeneration,
|
|
17437
|
-
command_id: `${args.moduleRoute.moduleCommandId}:${
|
|
17424
|
+
command_id: `${args.moduleRoute.moduleCommandId}:${createHash7("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
|
|
17438
17425
|
rows
|
|
17439
17426
|
}
|
|
17440
17427
|
}
|
|
@@ -17629,7 +17616,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17629
17616
|
resultChars: 0,
|
|
17630
17617
|
...error ? { error } : {},
|
|
17631
17618
|
backlog: (() => {
|
|
17632
|
-
const end = getDreamTaskBacklog(db, projectIdentity, config.task);
|
|
17619
|
+
const end = extra?.backlogAfter ?? getDreamTaskBacklog(db, projectIdentity, config.task);
|
|
17633
17620
|
const processed = processedDreamTaskItems(backlogAtStart.pending, end.pending);
|
|
17634
17621
|
const value = {
|
|
17635
17622
|
pendingAtStart: backlogAtStart.pending,
|
|
@@ -17678,12 +17665,6 @@ function createDreamTaskExecutor(deps) {
|
|
|
17678
17665
|
recordRun("completed", null);
|
|
17679
17666
|
return { status: "completed" };
|
|
17680
17667
|
}
|
|
17681
|
-
if (moduleRoute) {
|
|
17682
|
-
const reason = "compress-cues parked: MODULE memory authority has no cue write facade";
|
|
17683
|
-
log(`[dreamer] compress-cues: skipped (${reason})`);
|
|
17684
|
-
recordRun("failed", reason);
|
|
17685
|
-
return { status: "failed", transient: true, error: reason };
|
|
17686
|
-
}
|
|
17687
17668
|
const result = await runCompressCues({
|
|
17688
17669
|
db,
|
|
17689
17670
|
client: deps.client,
|
|
@@ -17695,6 +17676,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
17695
17676
|
deadline,
|
|
17696
17677
|
model: config.model ?? deps.mural.model ?? deps.dreamerModel,
|
|
17697
17678
|
fallbackModels: config.fallbackModels,
|
|
17679
|
+
moduleRoute,
|
|
17698
17680
|
onProgress: (processed) => reportProgress(processed)
|
|
17699
17681
|
});
|
|
17700
17682
|
log(`[dreamer] compress-cues: compressed=${result.compressed} skipped=${result.skipped} chunks=${result.chunks} remaining=${result.remaining}`);
|
|
@@ -17764,19 +17746,31 @@ function createDreamTaskExecutor(deps) {
|
|
|
17764
17746
|
fallbackModels: config.fallbackModels,
|
|
17765
17747
|
language: config.language ?? deps.language,
|
|
17766
17748
|
moduleRoute,
|
|
17767
|
-
onProgress: (
|
|
17749
|
+
onProgress: (processed2) => reportProgress(processed2)
|
|
17768
17750
|
});
|
|
17751
|
+
const processed = result.verified + result.updated + result.archived;
|
|
17752
|
+
const broadProgress = config.task === "verify-broad" ? `verify-broad cycle ${result.broadCycleStartAt ?? "open"}: verified ${processed}, ${result.remaining} remain` : null;
|
|
17753
|
+
const backlogAfter = config.task === "verify-broad" ? { pending: result.remaining, total: backlogAtStart.total } : undefined;
|
|
17769
17754
|
if (!result.complete) {
|
|
17755
|
+
if (broadProgress && processed > 0) {
|
|
17756
|
+
recordRun("completed", broadProgress, {
|
|
17757
|
+
memoryChanges: computeMemoryDelta(memoryBefore),
|
|
17758
|
+
backlogAfter
|
|
17759
|
+
});
|
|
17760
|
+
return { status: "completed", error: broadProgress };
|
|
17761
|
+
}
|
|
17770
17762
|
const error = incompleteMessage(result.remaining);
|
|
17771
17763
|
recordRun("failed", error, {
|
|
17772
|
-
memoryChanges: computeMemoryDelta(memoryBefore)
|
|
17764
|
+
memoryChanges: computeMemoryDelta(memoryBefore),
|
|
17765
|
+
backlogAfter
|
|
17773
17766
|
});
|
|
17774
17767
|
return { status: "failed", transient: true, error };
|
|
17775
17768
|
}
|
|
17776
|
-
recordRun("completed",
|
|
17777
|
-
memoryChanges: computeMemoryDelta(memoryBefore)
|
|
17769
|
+
recordRun("completed", broadProgress, {
|
|
17770
|
+
memoryChanges: computeMemoryDelta(memoryBefore),
|
|
17771
|
+
backlogAfter
|
|
17778
17772
|
});
|
|
17779
|
-
return { status: "completed" };
|
|
17773
|
+
return broadProgress ? { status: "completed", error: broadProgress } : { status: "completed" };
|
|
17780
17774
|
}
|
|
17781
17775
|
if (config.task === "classify-memories") {
|
|
17782
17776
|
let moduleArgs;
|
|
@@ -17964,7 +17958,7 @@ function parseFrictionGateVerdict(verdict) {
|
|
|
17964
17958
|
}
|
|
17965
17959
|
function computeRetrospectiveWindowKey(flagged) {
|
|
17966
17960
|
const anchors = flagged.map((message) => `${message.sessionId}:${message.ts}`).sort().join("|");
|
|
17967
|
-
return
|
|
17961
|
+
return createHash8("sha256").update(anchors).digest("hex").slice(0, 32);
|
|
17968
17962
|
}
|
|
17969
17963
|
function renderFrictionWindow(messages, flaggedOrdinals, radius = 2) {
|
|
17970
17964
|
const flagged = new Set(flaggedOrdinals);
|
|
@@ -18197,8 +18191,8 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
18197
18191
|
const lastRunAt = getTaskScheduleState(db, projectIdentity, config.task)?.lastRunAt ?? null;
|
|
18198
18192
|
const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
|
|
18199
18193
|
const existingDocs = task === "maintain-docs" ? {
|
|
18200
|
-
architecture:
|
|
18201
|
-
structure:
|
|
18194
|
+
architecture: existsSync9(`${docsDir}/ARCHITECTURE.md`),
|
|
18195
|
+
structure: existsSync9(`${docsDir}/STRUCTURE.md`)
|
|
18202
18196
|
} : undefined;
|
|
18203
18197
|
const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
|
|
18204
18198
|
let curateMemories;
|
|
@@ -18911,7 +18905,7 @@ var startupJitters = new Map;
|
|
|
18911
18905
|
var nextStartupJitterSlot = 0;
|
|
18912
18906
|
function directoryStillExists(directory) {
|
|
18913
18907
|
try {
|
|
18914
|
-
return
|
|
18908
|
+
return statSync3(directory).isDirectory();
|
|
18915
18909
|
} catch {
|
|
18916
18910
|
return false;
|
|
18917
18911
|
}
|
|
@@ -19234,7 +19228,7 @@ function createDreamTimerModuleClient(moduleClient) {
|
|
|
19234
19228
|
}
|
|
19235
19229
|
|
|
19236
19230
|
// src/plugin/embedding-bootstrap-helpers.ts
|
|
19237
|
-
import { createHash as
|
|
19231
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
19238
19232
|
var EMBEDDING_AFFECTING_KEYS = new Set([
|
|
19239
19233
|
"embedding.api_key",
|
|
19240
19234
|
"embedding.endpoint",
|
|
@@ -19280,7 +19274,7 @@ var EMBEDDING_WARNING_TERMS = [
|
|
|
19280
19274
|
];
|
|
19281
19275
|
var loggedFailureSignatures = new Map;
|
|
19282
19276
|
function sha256Prefix(value, length = 16) {
|
|
19283
|
-
return
|
|
19277
|
+
return createHash9("sha256").update(value).digest("hex").slice(0, length);
|
|
19284
19278
|
}
|
|
19285
19279
|
function warningLooksEmbeddingRelated(message) {
|
|
19286
19280
|
const lower = message.toLowerCase();
|
|
@@ -19584,16 +19578,7 @@ function resolveCacheTtl(cacheTtl, modelKey) {
|
|
|
19584
19578
|
if (typeof cacheTtl === "string") {
|
|
19585
19579
|
return cacheTtl;
|
|
19586
19580
|
}
|
|
19587
|
-
|
|
19588
|
-
return cacheTtl[modelKey];
|
|
19589
|
-
}
|
|
19590
|
-
if (modelKey) {
|
|
19591
|
-
const bareModelId = modelKey.split("/").slice(1).join("/");
|
|
19592
|
-
if (bareModelId && typeof cacheTtl[bareModelId] === "string") {
|
|
19593
|
-
return cacheTtl[bareModelId];
|
|
19594
|
-
}
|
|
19595
|
-
}
|
|
19596
|
-
return cacheTtl.default ?? "5m";
|
|
19581
|
+
return resolveModelConfigOrDefault(cacheTtl, modelKey, cacheTtl.default ?? "5m");
|
|
19597
19582
|
}
|
|
19598
19583
|
var clampWarnSeen = new Set;
|
|
19599
19584
|
function isFinitePositive(v) {
|
|
@@ -22620,7 +22605,7 @@ function replayCavemanCompression(sessionId, db, targets, tags) {
|
|
|
22620
22605
|
}
|
|
22621
22606
|
|
|
22622
22607
|
// src/hooks/magic-context/compaction-off-transition.ts
|
|
22623
|
-
import { existsSync as
|
|
22608
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
22624
22609
|
var loggedUnverifiedMarkerCleanupRetry = false;
|
|
22625
22610
|
var COMPACTION_OFF_FLIP_NOTICE = [
|
|
22626
22611
|
"## Magic Context — compaction-off mode is now active",
|
|
@@ -22655,7 +22640,7 @@ function clearCachedM0Baseline(db, sessionId) {
|
|
|
22655
22640
|
return (result.changes ?? 0) > 0;
|
|
22656
22641
|
}
|
|
22657
22642
|
function cleanupOffMarkers(sessionId) {
|
|
22658
|
-
if (!
|
|
22643
|
+
if (!existsSync10(getOpenCodeDbPath())) {
|
|
22659
22644
|
return { verified: true, removedLineages: 0, removedRows: 0, retainedLineages: 0 };
|
|
22660
22645
|
}
|
|
22661
22646
|
return removeMcOwnedCompactionMarkers(sessionId, MARKER_SUMMARY_TEXT);
|
|
@@ -23749,7 +23734,7 @@ function createPassOutcome() {
|
|
|
23749
23734
|
}
|
|
23750
23735
|
|
|
23751
23736
|
// src/hooks/magic-context/rust-mode-transform.ts
|
|
23752
|
-
import { createHash as
|
|
23737
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
23753
23738
|
|
|
23754
23739
|
// src/hooks/magic-context/module-state-sync.ts
|
|
23755
23740
|
import { createHmac, randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -25087,6 +25072,121 @@ async function syncModuleState(args) {
|
|
|
25087
25072
|
}
|
|
25088
25073
|
}
|
|
25089
25074
|
|
|
25075
|
+
// src/hooks/magic-context/todo-view.ts
|
|
25076
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
25077
|
+
var TODO_STATUS_PENDING = "pending";
|
|
25078
|
+
var TODO_STATUS_IN_PROGRESS = "in_progress";
|
|
25079
|
+
var TODO_STATUS_COMPLETED = "completed";
|
|
25080
|
+
var TODO_STATUS_CANCELLED = "cancelled";
|
|
25081
|
+
var TODO_PRIORITY_HIGH = "high";
|
|
25082
|
+
var TODO_PRIORITY_MEDIUM = "medium";
|
|
25083
|
+
var TODO_PRIORITY_LOW = "low";
|
|
25084
|
+
var TODO_STATUSES = [
|
|
25085
|
+
TODO_STATUS_PENDING,
|
|
25086
|
+
TODO_STATUS_IN_PROGRESS,
|
|
25087
|
+
TODO_STATUS_COMPLETED,
|
|
25088
|
+
TODO_STATUS_CANCELLED
|
|
25089
|
+
];
|
|
25090
|
+
var TODO_PRIORITIES = [
|
|
25091
|
+
TODO_PRIORITY_HIGH,
|
|
25092
|
+
TODO_PRIORITY_MEDIUM,
|
|
25093
|
+
TODO_PRIORITY_LOW
|
|
25094
|
+
];
|
|
25095
|
+
var TODO_STATUS_SET = new Set(TODO_STATUSES);
|
|
25096
|
+
var TODO_PRIORITY_SET = new Set(TODO_PRIORITIES);
|
|
25097
|
+
var TERMINAL_STATUSES = new Set([
|
|
25098
|
+
TODO_STATUS_COMPLETED,
|
|
25099
|
+
TODO_STATUS_CANCELLED
|
|
25100
|
+
]);
|
|
25101
|
+
var TITLE_DONE_STATUSES = new Set([TODO_STATUS_COMPLETED]);
|
|
25102
|
+
var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
|
|
25103
|
+
function normalizeTodoStateJson(todos) {
|
|
25104
|
+
if (!Array.isArray(todos))
|
|
25105
|
+
return null;
|
|
25106
|
+
const normalized = [];
|
|
25107
|
+
for (const todo of todos) {
|
|
25108
|
+
if (!isTodoItem(todo))
|
|
25109
|
+
return null;
|
|
25110
|
+
normalized.push({
|
|
25111
|
+
content: todo.content,
|
|
25112
|
+
status: todo.status,
|
|
25113
|
+
priority: todo.priority ?? TODO_PRIORITY_MEDIUM
|
|
25114
|
+
});
|
|
25115
|
+
}
|
|
25116
|
+
return JSON.stringify(normalized);
|
|
25117
|
+
}
|
|
25118
|
+
function buildSyntheticTodoPart(stateJson) {
|
|
25119
|
+
const todos = parseTodoState(stateJson);
|
|
25120
|
+
if (todos === null || todos.length === 0)
|
|
25121
|
+
return null;
|
|
25122
|
+
if (todos.every((t) => TERMINAL_STATUSES.has(t.status)))
|
|
25123
|
+
return null;
|
|
25124
|
+
const callID = computeSyntheticCallId(stateJson);
|
|
25125
|
+
const activeCount = todos.filter((t) => !TITLE_DONE_STATUSES.has(t.status)).length;
|
|
25126
|
+
const output = JSON.stringify(todos, null, 2);
|
|
25127
|
+
const ts = 0;
|
|
25128
|
+
return {
|
|
25129
|
+
type: "tool",
|
|
25130
|
+
callID,
|
|
25131
|
+
tool: "todowrite",
|
|
25132
|
+
state: {
|
|
25133
|
+
status: "completed",
|
|
25134
|
+
input: { todos },
|
|
25135
|
+
output,
|
|
25136
|
+
title: `${activeCount} todos`,
|
|
25137
|
+
metadata: { todos, truncated: false },
|
|
25138
|
+
time: { start: ts, end: ts }
|
|
25139
|
+
},
|
|
25140
|
+
syntheticTodoMarker: true
|
|
25141
|
+
};
|
|
25142
|
+
}
|
|
25143
|
+
function computeSyntheticCallId(stateJson) {
|
|
25144
|
+
const hash = createHash11("sha256").update(stateJson).digest("hex").slice(0, 16);
|
|
25145
|
+
return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
|
|
25146
|
+
}
|
|
25147
|
+
function isSyntheticTodoPart(part) {
|
|
25148
|
+
if (part === null || typeof part !== "object")
|
|
25149
|
+
return false;
|
|
25150
|
+
const p = part;
|
|
25151
|
+
if (p.syntheticTodoMarker === true)
|
|
25152
|
+
return true;
|
|
25153
|
+
return p.type === "tool" && p.tool === "todowrite" && typeof p.callID === "string" && p.callID.startsWith(SYNTHETIC_CALL_ID_PREFIX);
|
|
25154
|
+
}
|
|
25155
|
+
function parseTodoState(stateJson) {
|
|
25156
|
+
if (stateJson.length === 0)
|
|
25157
|
+
return null;
|
|
25158
|
+
try {
|
|
25159
|
+
const parsed = JSON.parse(stateJson);
|
|
25160
|
+
if (!Array.isArray(parsed))
|
|
25161
|
+
return null;
|
|
25162
|
+
const result = [];
|
|
25163
|
+
for (const item of parsed) {
|
|
25164
|
+
if (!isTodoItem(item))
|
|
25165
|
+
return null;
|
|
25166
|
+
result.push({
|
|
25167
|
+
content: item.content,
|
|
25168
|
+
status: item.status,
|
|
25169
|
+
priority: item.priority ?? TODO_PRIORITY_MEDIUM
|
|
25170
|
+
});
|
|
25171
|
+
}
|
|
25172
|
+
return result;
|
|
25173
|
+
} catch {
|
|
25174
|
+
return null;
|
|
25175
|
+
}
|
|
25176
|
+
}
|
|
25177
|
+
function isTodoStatus(value) {
|
|
25178
|
+
return typeof value === "string" && TODO_STATUS_SET.has(value);
|
|
25179
|
+
}
|
|
25180
|
+
function isTodoPriority(value) {
|
|
25181
|
+
return typeof value === "string" && TODO_PRIORITY_SET.has(value);
|
|
25182
|
+
}
|
|
25183
|
+
function isTodoItem(value) {
|
|
25184
|
+
if (value === null || typeof value !== "object")
|
|
25185
|
+
return false;
|
|
25186
|
+
const todo = value;
|
|
25187
|
+
return typeof todo.content === "string" && isTodoStatus(todo.status) && (todo.priority === undefined || isTodoPriority(todo.priority));
|
|
25188
|
+
}
|
|
25189
|
+
|
|
25090
25190
|
// src/hooks/magic-context/transform-context-state.ts
|
|
25091
25191
|
function loadPersistedUsageWatermark(db, sessionId) {
|
|
25092
25192
|
const result = db.prepare("SELECT last_response_time FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
@@ -25110,7 +25210,8 @@ function loadContextUsage(contextUsageMap, db, sessionId) {
|
|
|
25110
25210
|
if (persisted) {
|
|
25111
25211
|
contextUsageMap.set(sessionId, {
|
|
25112
25212
|
...persisted,
|
|
25113
|
-
lastResponseTime: persistedLastResponseTime ?? persisted.updatedAt
|
|
25213
|
+
lastResponseTime: persistedLastResponseTime ?? persisted.updatedAt,
|
|
25214
|
+
hasUsageTokens: false
|
|
25114
25215
|
});
|
|
25115
25216
|
return persisted.usage;
|
|
25116
25217
|
}
|
|
@@ -25189,7 +25290,7 @@ function containsProbeVerbatim(text, probes) {
|
|
|
25189
25290
|
}
|
|
25190
25291
|
|
|
25191
25292
|
// src/features/magic-context/search-measurement.ts
|
|
25192
|
-
import { createHash as
|
|
25293
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
25193
25294
|
function resultId(result) {
|
|
25194
25295
|
switch (result.source) {
|
|
25195
25296
|
case "memory":
|
|
@@ -25276,7 +25377,7 @@ async function recordShadowMeasurement(args) {
|
|
|
25276
25377
|
}
|
|
25277
25378
|
}
|
|
25278
25379
|
function sha256(value) {
|
|
25279
|
-
return
|
|
25380
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
25280
25381
|
}
|
|
25281
25382
|
|
|
25282
25383
|
// src/features/magic-context/search.ts
|
|
@@ -27637,121 +27738,6 @@ function readFilePath(target) {
|
|
|
27637
27738
|
return null;
|
|
27638
27739
|
}
|
|
27639
27740
|
|
|
27640
|
-
// src/hooks/magic-context/todo-view.ts
|
|
27641
|
-
import { createHash as createHash10 } from "node:crypto";
|
|
27642
|
-
var TODO_STATUS_PENDING = "pending";
|
|
27643
|
-
var TODO_STATUS_IN_PROGRESS = "in_progress";
|
|
27644
|
-
var TODO_STATUS_COMPLETED = "completed";
|
|
27645
|
-
var TODO_STATUS_CANCELLED = "cancelled";
|
|
27646
|
-
var TODO_PRIORITY_HIGH = "high";
|
|
27647
|
-
var TODO_PRIORITY_MEDIUM = "medium";
|
|
27648
|
-
var TODO_PRIORITY_LOW = "low";
|
|
27649
|
-
var TODO_STATUSES = [
|
|
27650
|
-
TODO_STATUS_PENDING,
|
|
27651
|
-
TODO_STATUS_IN_PROGRESS,
|
|
27652
|
-
TODO_STATUS_COMPLETED,
|
|
27653
|
-
TODO_STATUS_CANCELLED
|
|
27654
|
-
];
|
|
27655
|
-
var TODO_PRIORITIES = [
|
|
27656
|
-
TODO_PRIORITY_HIGH,
|
|
27657
|
-
TODO_PRIORITY_MEDIUM,
|
|
27658
|
-
TODO_PRIORITY_LOW
|
|
27659
|
-
];
|
|
27660
|
-
var TODO_STATUS_SET = new Set(TODO_STATUSES);
|
|
27661
|
-
var TODO_PRIORITY_SET = new Set(TODO_PRIORITIES);
|
|
27662
|
-
var TERMINAL_STATUSES = new Set([
|
|
27663
|
-
TODO_STATUS_COMPLETED,
|
|
27664
|
-
TODO_STATUS_CANCELLED
|
|
27665
|
-
]);
|
|
27666
|
-
var TITLE_DONE_STATUSES = new Set([TODO_STATUS_COMPLETED]);
|
|
27667
|
-
var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
|
|
27668
|
-
function normalizeTodoStateJson(todos) {
|
|
27669
|
-
if (!Array.isArray(todos))
|
|
27670
|
-
return null;
|
|
27671
|
-
const normalized = [];
|
|
27672
|
-
for (const todo of todos) {
|
|
27673
|
-
if (!isTodoItem(todo))
|
|
27674
|
-
return null;
|
|
27675
|
-
normalized.push({
|
|
27676
|
-
content: todo.content,
|
|
27677
|
-
status: todo.status,
|
|
27678
|
-
priority: todo.priority ?? TODO_PRIORITY_MEDIUM
|
|
27679
|
-
});
|
|
27680
|
-
}
|
|
27681
|
-
return JSON.stringify(normalized);
|
|
27682
|
-
}
|
|
27683
|
-
function buildSyntheticTodoPart(stateJson) {
|
|
27684
|
-
const todos = parseTodoState(stateJson);
|
|
27685
|
-
if (todos === null || todos.length === 0)
|
|
27686
|
-
return null;
|
|
27687
|
-
if (todos.every((t) => TERMINAL_STATUSES.has(t.status)))
|
|
27688
|
-
return null;
|
|
27689
|
-
const callID = computeSyntheticCallId(stateJson);
|
|
27690
|
-
const activeCount = todos.filter((t) => !TITLE_DONE_STATUSES.has(t.status)).length;
|
|
27691
|
-
const output = JSON.stringify(todos, null, 2);
|
|
27692
|
-
const ts = 0;
|
|
27693
|
-
return {
|
|
27694
|
-
type: "tool",
|
|
27695
|
-
callID,
|
|
27696
|
-
tool: "todowrite",
|
|
27697
|
-
state: {
|
|
27698
|
-
status: "completed",
|
|
27699
|
-
input: { todos },
|
|
27700
|
-
output,
|
|
27701
|
-
title: `${activeCount} todos`,
|
|
27702
|
-
metadata: { todos, truncated: false },
|
|
27703
|
-
time: { start: ts, end: ts }
|
|
27704
|
-
},
|
|
27705
|
-
syntheticTodoMarker: true
|
|
27706
|
-
};
|
|
27707
|
-
}
|
|
27708
|
-
function computeSyntheticCallId(stateJson) {
|
|
27709
|
-
const hash = createHash10("sha256").update(stateJson).digest("hex").slice(0, 16);
|
|
27710
|
-
return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
|
|
27711
|
-
}
|
|
27712
|
-
function isSyntheticTodoPart(part) {
|
|
27713
|
-
if (part === null || typeof part !== "object")
|
|
27714
|
-
return false;
|
|
27715
|
-
const p = part;
|
|
27716
|
-
if (p.syntheticTodoMarker === true)
|
|
27717
|
-
return true;
|
|
27718
|
-
return p.type === "tool" && p.tool === "todowrite" && typeof p.callID === "string" && p.callID.startsWith(SYNTHETIC_CALL_ID_PREFIX);
|
|
27719
|
-
}
|
|
27720
|
-
function parseTodoState(stateJson) {
|
|
27721
|
-
if (stateJson.length === 0)
|
|
27722
|
-
return null;
|
|
27723
|
-
try {
|
|
27724
|
-
const parsed = JSON.parse(stateJson);
|
|
27725
|
-
if (!Array.isArray(parsed))
|
|
27726
|
-
return null;
|
|
27727
|
-
const result = [];
|
|
27728
|
-
for (const item of parsed) {
|
|
27729
|
-
if (!isTodoItem(item))
|
|
27730
|
-
return null;
|
|
27731
|
-
result.push({
|
|
27732
|
-
content: item.content,
|
|
27733
|
-
status: item.status,
|
|
27734
|
-
priority: item.priority ?? TODO_PRIORITY_MEDIUM
|
|
27735
|
-
});
|
|
27736
|
-
}
|
|
27737
|
-
return result;
|
|
27738
|
-
} catch {
|
|
27739
|
-
return null;
|
|
27740
|
-
}
|
|
27741
|
-
}
|
|
27742
|
-
function isTodoStatus(value) {
|
|
27743
|
-
return typeof value === "string" && TODO_STATUS_SET.has(value);
|
|
27744
|
-
}
|
|
27745
|
-
function isTodoPriority(value) {
|
|
27746
|
-
return typeof value === "string" && TODO_PRIORITY_SET.has(value);
|
|
27747
|
-
}
|
|
27748
|
-
function isTodoItem(value) {
|
|
27749
|
-
if (value === null || typeof value !== "object")
|
|
27750
|
-
return false;
|
|
27751
|
-
const todo = value;
|
|
27752
|
-
return typeof todo.content === "string" && isTodoStatus(todo.status) && (todo.priority === undefined || isTodoPriority(todo.priority));
|
|
27753
|
-
}
|
|
27754
|
-
|
|
27755
27741
|
// src/hooks/magic-context/tool-reclaim.ts
|
|
27756
27742
|
function buildSyntheticToolReclaimOps(input) {
|
|
27757
27743
|
const watermark = Math.max(0, input.watermark);
|
|
@@ -29265,7 +29251,9 @@ class MemoryAuthorityUnavailableError extends Error {
|
|
|
29265
29251
|
}
|
|
29266
29252
|
}
|
|
29267
29253
|
var RUST_FAILURE_PARK_THRESHOLD = 3;
|
|
29268
|
-
var
|
|
29254
|
+
var RUST_PARK_RETRY_INTERVAL = 5;
|
|
29255
|
+
var RUST_EMERGENCY_WALL_PCT = 95;
|
|
29256
|
+
var RUST_PARK_PROBE_PRESSURE_BYPASS_PCT = 90;
|
|
29269
29257
|
var RUST_SEND_TIMEOUT_MS = 15000;
|
|
29270
29258
|
function isRecord3(value) {
|
|
29271
29259
|
return value !== null && typeof value === "object";
|
|
@@ -29426,10 +29414,10 @@ function messageCacheSignature(message) {
|
|
|
29426
29414
|
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
29427
29415
|
const serializedParts = JSON.stringify(parts) ?? "null";
|
|
29428
29416
|
const serializedMessage = JSON.stringify(message) ?? "null";
|
|
29429
|
-
return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${
|
|
29417
|
+
return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash13("sha256").update(serializedMessage).digest("hex")}`;
|
|
29430
29418
|
}
|
|
29431
29419
|
function advanceWireFingerprint(previous, encoded) {
|
|
29432
|
-
return
|
|
29420
|
+
return createHash13("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
|
|
29433
29421
|
}
|
|
29434
29422
|
function buildWireFingerprint(encoded) {
|
|
29435
29423
|
let fingerprint = "rust-wire-v1";
|
|
@@ -29467,7 +29455,8 @@ function formatRustPassLog(args) {
|
|
|
29467
29455
|
const timings = args.timings ?? emptyRustPassTimings();
|
|
29468
29456
|
const measured = timings.prefixGuard + timings.ordinalResolve + timings.stateSync + timings.clone + timings.wireBuild + timings.transport + timings.apply + timings.lkgSnapshot;
|
|
29469
29457
|
const unattributed = Math.max(0, args.elapsedMs - measured);
|
|
29470
|
-
|
|
29458
|
+
const rowVersion = Number.isSafeInteger(args.rowVersion) ? args.rowVersion : 0;
|
|
29459
|
+
return `rust pass: decision=${args.decision} reason=${args.reason} served_from=${args.servedFrom} in=${args.inputCount} out=${args.outputCount} applied=${args.applied} row_version=${rowVersion} elapsed=${args.elapsedMs.toFixed(1)} ms module=${args.moduleElapsedMs.toFixed(1)} ms stages=prefix_guard:${timings.prefixGuard.toFixed(1)} ordinal_resolve:${timings.ordinalResolve.toFixed(1)} state_sync:${timings.stateSync.toFixed(1)} clone:${timings.clone.toFixed(1)} wire_build:${timings.wireBuild.toFixed(1)} wire_messages:${timings.wireMessages} transport:${timings.transport.toFixed(1)} transport_pages:${timings.transportPages} transport_bytes:${timings.transportBytes} apply:${timings.apply.toFixed(1)} lkg_snapshot:${timings.lkgSnapshot.toFixed(1)} other:${unattributed.toFixed(1)}`;
|
|
29471
29460
|
}
|
|
29472
29461
|
function isSyntheticUserMessage(message) {
|
|
29473
29462
|
if (!message || messageInfo2(message).role !== "user" || !Array.isArray(message.parts)) {
|
|
@@ -29599,6 +29588,19 @@ function passUsage(usage, limit) {
|
|
|
29599
29588
|
context_limit_tokens: limit
|
|
29600
29589
|
};
|
|
29601
29590
|
}
|
|
29591
|
+
function shouldDisarmRustEmergencyRecovery(input) {
|
|
29592
|
+
if (input.finalWireEstimate?.trusted === true && input.providerProvenLimitTokens > 0 && input.finalWireEstimate.tokens < input.providerProvenLimitTokens * 0.8) {
|
|
29593
|
+
return "trusted-final-wire";
|
|
29594
|
+
}
|
|
29595
|
+
if (!input.materialized || input.usagePercentage >= 80)
|
|
29596
|
+
return null;
|
|
29597
|
+
if (input.recoveryOrigin !== "provider_overflow")
|
|
29598
|
+
return "fresh-usage";
|
|
29599
|
+
if (input.usageEntry?.hasUsageTokens === true && (input.recoveryArmedAt === null || input.usageEntry.updatedAt > input.recoveryArmedAt)) {
|
|
29600
|
+
return "fresh-usage";
|
|
29601
|
+
}
|
|
29602
|
+
return null;
|
|
29603
|
+
}
|
|
29602
29604
|
function directiveTextOf(response) {
|
|
29603
29605
|
const directives = isRecord3(response.host_directives) ? response.host_directives : undefined;
|
|
29604
29606
|
const channel2 = isRecord3(directives?.channel2_nudge) ? directives.channel2_nudge : undefined;
|
|
@@ -29615,7 +29617,7 @@ function canonicalizeForChecksum(value) {
|
|
|
29615
29617
|
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalizeForChecksum(value[key])]));
|
|
29616
29618
|
}
|
|
29617
29619
|
function checksumSeedRows(rows) {
|
|
29618
|
-
return
|
|
29620
|
+
return createHash13("sha256").update(JSON.stringify(rows.map(canonicalizeForChecksum))).digest("hex");
|
|
29619
29621
|
}
|
|
29620
29622
|
function authoritySeedRows(db, projectPath, domain) {
|
|
29621
29623
|
const snapshots = domain === "memories" ? db.prepare("SELECT * FROM memories WHERE project_path = ? ORDER BY id ASC").all(projectPath) : db.prepare(`SELECT n.*
|
|
@@ -29756,6 +29758,35 @@ async function prepareRustMemoryAuthority(args) {
|
|
|
29756
29758
|
state.memoryAuthorityReady = true;
|
|
29757
29759
|
args.onProjectPrepared?.(projectPath);
|
|
29758
29760
|
}
|
|
29761
|
+
var TODO_HEAD_ANCHOR_ID2 = "__magic_context_todo_head__";
|
|
29762
|
+
function syntheticTodoAnchorFromNative(messages) {
|
|
29763
|
+
for (let index = 0;index < messages.length; index += 1) {
|
|
29764
|
+
const message = messages[index];
|
|
29765
|
+
if (!isRecord3(message) || !Array.isArray(message.parts))
|
|
29766
|
+
continue;
|
|
29767
|
+
const part = message.parts.find((candidate) => isRecord3(candidate) && candidate.syntheticTodoMarker === true);
|
|
29768
|
+
if (!isRecord3(part) || typeof part.callID !== "string")
|
|
29769
|
+
continue;
|
|
29770
|
+
const state = isRecord3(part.state) ? part.state : undefined;
|
|
29771
|
+
const input = state && isRecord3(state.input) ? state.input : undefined;
|
|
29772
|
+
const stateJson = normalizeTodoStateJson(input?.todos);
|
|
29773
|
+
if (stateJson === null || computeSyntheticCallId(stateJson) !== part.callID)
|
|
29774
|
+
continue;
|
|
29775
|
+
const previous = messages[index - 1];
|
|
29776
|
+
const previousInfo = isRecord3(previous) && isRecord3(previous.info) ? previous.info : undefined;
|
|
29777
|
+
const messageId2 = previousInfo && typeof previousInfo.id === "string" && previousInfo.id.length > 0 ? previousInfo.id : TODO_HEAD_ANCHOR_ID2;
|
|
29778
|
+
return { callId: part.callID, messageId: messageId2, stateJson };
|
|
29779
|
+
}
|
|
29780
|
+
return null;
|
|
29781
|
+
}
|
|
29782
|
+
function mirrorRustSyntheticTodoAnchor(args) {
|
|
29783
|
+
const anchor = syntheticTodoAnchorFromNative(args.messages);
|
|
29784
|
+
if (anchor) {
|
|
29785
|
+
setPersistedTodoSyntheticAnchor(args.db, args.sessionId, anchor.callId, anchor.messageId, anchor.stateJson);
|
|
29786
|
+
} else if (args.cacheBustingPass) {
|
|
29787
|
+
clearPersistedTodoSyntheticAnchor(args.db, args.sessionId);
|
|
29788
|
+
}
|
|
29789
|
+
}
|
|
29759
29790
|
function applyNativeMessagesVerbatim(output, response) {
|
|
29760
29791
|
const nativeMessages = response.native_messages;
|
|
29761
29792
|
if (typeof nativeMessages === "string") {
|
|
@@ -29809,6 +29840,9 @@ function buildTransformBody(args) {
|
|
|
29809
29840
|
model_key: args.modelKey,
|
|
29810
29841
|
provider_id: args.providerId,
|
|
29811
29842
|
tool_present: args.passInputs.tool_present === true,
|
|
29843
|
+
prompt_surface_preset: args.passInputs.prompt_surface_preset ?? "full",
|
|
29844
|
+
prompt_surface_model_key: args.passInputs.prompt_surface_model_key,
|
|
29845
|
+
prompt_surface_tool_descriptions: args.passInputs.prompt_surface_tool_descriptions ?? {},
|
|
29812
29846
|
effective_execute_threshold: args.passInputs.effective_execute_threshold,
|
|
29813
29847
|
history_budget_tokens: args.passInputs.history_budget_tokens,
|
|
29814
29848
|
clear_reasoning_age: args.passInputs.clear_reasoning_age,
|
|
@@ -29855,7 +29889,7 @@ function createRustModeTransform(deps, options) {
|
|
|
29855
29889
|
state.passesSincePark = 0;
|
|
29856
29890
|
state.warningSent = true;
|
|
29857
29891
|
const warning = "Rust Magic Context is unavailable for this session; retry after the module recovers.";
|
|
29858
|
-
sessionLog(sessionId,
|
|
29892
|
+
sessionLog(sessionId, `mc_rust_park_transition failure_passes=${state.consecutiveFailures} pass_count=${state.passCount} park_count=${state.parkCount}`);
|
|
29859
29893
|
options.notifyParked?.(sessionId, warning);
|
|
29860
29894
|
};
|
|
29861
29895
|
const resetOrdinalMemo = (state) => {
|
|
@@ -29988,6 +30022,7 @@ function createRustModeTransform(deps, options) {
|
|
|
29988
30022
|
let materializeReason = "none";
|
|
29989
30023
|
let servedFrom = "none";
|
|
29990
30024
|
let moduleElapsedMs = 0;
|
|
30025
|
+
let rowVersion = 0;
|
|
29991
30026
|
let appliedAt;
|
|
29992
30027
|
let emergencyFailClosed = false;
|
|
29993
30028
|
const passUsageSnapshot = loadContextUsage(deps.contextUsageMap, deps.db, sessionId);
|
|
@@ -30019,7 +30054,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30019
30054
|
} catch (error) {
|
|
30020
30055
|
preflightError ??= error;
|
|
30021
30056
|
}
|
|
30022
|
-
emergencyFailClosed = passUsageSnapshot.percentage >=
|
|
30057
|
+
emergencyFailClosed = passUsageSnapshot.percentage >= RUST_EMERGENCY_WALL_PCT && resolvedContextLimit !== undefined && resolvedContextLimit > 0;
|
|
30023
30058
|
if (overflowState) {
|
|
30024
30059
|
const detectedLimitMatchesModel = overflowState.detectedContextLimitModelKey === null || overflowState.detectedContextLimitModelKey === modelKey;
|
|
30025
30060
|
const hasProviderProof = overflowState.detectedContextLimit > 0 && detectedLimitMatchesModel || isProviderOverflowReconfirmed(sessionId);
|
|
@@ -30037,6 +30072,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30037
30072
|
applied,
|
|
30038
30073
|
elapsedMs,
|
|
30039
30074
|
moduleElapsedMs,
|
|
30075
|
+
rowVersion,
|
|
30040
30076
|
timings
|
|
30041
30077
|
}));
|
|
30042
30078
|
if (served) {
|
|
@@ -30056,6 +30092,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30056
30092
|
const timings2 = isRecord3(response.timings) ? response.timings : undefined;
|
|
30057
30093
|
const total = timings2?.total;
|
|
30058
30094
|
moduleElapsedMs = typeof total === "number" && Number.isFinite(total) ? total : 0;
|
|
30095
|
+
rowVersion = typeof response.row_version === "number" && Number.isSafeInteger(response.row_version) ? response.row_version : 0;
|
|
30059
30096
|
if (timings2 && moduleElapsedMs >= 1000) {
|
|
30060
30097
|
const detail = Object.entries(timings2).filter(([key, value]) => key !== "total" && typeof value === "number").map(([key, value]) => `${key}:${value.toFixed(1)}`).join(" ");
|
|
30061
30098
|
if (detail)
|
|
@@ -30064,7 +30101,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30064
30101
|
};
|
|
30065
30102
|
if (state.parked) {
|
|
30066
30103
|
state.passesSincePark += 1;
|
|
30067
|
-
if (!emergencyFailClosed && passUsageSnapshot.percentage <
|
|
30104
|
+
if (!emergencyFailClosed && passUsageSnapshot.percentage < RUST_PARK_PROBE_PRESSURE_BYPASS_PCT && state.passCount % RUST_PARK_RETRY_INTERVAL !== 0) {
|
|
30068
30105
|
decision = "parked";
|
|
30069
30106
|
const replayed = replayLastGood(sessionId, messages, output, sessionMeta.systemPromptTokens);
|
|
30070
30107
|
if (replayed) {
|
|
@@ -30078,6 +30115,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30078
30115
|
}
|
|
30079
30116
|
}
|
|
30080
30117
|
const reduceAvailability = resolveCtxReduceAvailability(sessionId);
|
|
30118
|
+
resolveTodowriteAvailabilityFromMessages(sessionId, messages);
|
|
30081
30119
|
const toolPresent = reduceAvailability.frozen && reduceAvailability.callable;
|
|
30082
30120
|
try {
|
|
30083
30121
|
if (preflightError)
|
|
@@ -30095,6 +30133,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30095
30133
|
const midTurn = isMidTurn(deps, sessionId);
|
|
30096
30134
|
const requestObservedAtMs = Date.now();
|
|
30097
30135
|
const recoveryNoHeadEscape = overflowState.needsEmergencyRecovery && loadProtectedTailMeta(deps.db, sessionId).recoveryNoEligibleHeadCount >= RECOVERY_NO_HEAD_LIMIT;
|
|
30136
|
+
const promptSurface = resolvePromptSurface(deps.promptSurface, modelKey ?? undefined);
|
|
30098
30137
|
const passInputs = {
|
|
30099
30138
|
now_ms: requestObservedAtMs,
|
|
30100
30139
|
model_key: modelKey,
|
|
@@ -30111,6 +30150,9 @@ function createRustModeTransform(deps, options) {
|
|
|
30111
30150
|
system_prompt_hash: sessionMeta.systemPromptHash ?? "",
|
|
30112
30151
|
upgrade_state: readUpgradeState(deps.db, sessionId),
|
|
30113
30152
|
tool_present: toolPresent,
|
|
30153
|
+
prompt_surface_preset: promptSurface.preset,
|
|
30154
|
+
prompt_surface_model_key: modelKey,
|
|
30155
|
+
prompt_surface_tool_descriptions: deps.promptSurface?.tool_descriptions ?? {},
|
|
30114
30156
|
protected_tags: deps.protectedTags ?? DEFAULT_PROTECTED_TAGS,
|
|
30115
30157
|
temporal_awareness: deps.experimentalTemporalAwareness === true,
|
|
30116
30158
|
channel2_nudge_state: getChannel2NudgeState(deps.db, sessionId),
|
|
@@ -30337,6 +30379,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30337
30379
|
const pages = buildPagedModuleTransformPayloads(body);
|
|
30338
30380
|
logStage(sessionId, "wireBuild", wireBuildStartedAt, timings, wireDelta ? `mode=tail_delta input=${encodedInput.length}` : "mode=full");
|
|
30339
30381
|
let response;
|
|
30382
|
+
let servedFinalWireEstimate;
|
|
30340
30383
|
for (const [index, page] of pages.entries()) {
|
|
30341
30384
|
timings.transportBytes += Buffer.byteLength(JSON.stringify(page));
|
|
30342
30385
|
const transportStartedAt = performance.now();
|
|
@@ -30469,6 +30512,9 @@ function createRustModeTransform(deps, options) {
|
|
|
30469
30512
|
});
|
|
30470
30513
|
}
|
|
30471
30514
|
};
|
|
30515
|
+
const explicitDecision = typeof response.decision === "string" || typeof response.action === "string" || typeof response.cache_bust === "boolean";
|
|
30516
|
+
const decisionUpper = decision.toUpperCase();
|
|
30517
|
+
const cacheBustingPass = response.cache_bust === true || decisionUpper === "HARD" || decisionUpper === "MIGRATE_HARD" || decisionUpper === "EXECUTE" || decisionUpper === "SOFT" || !explicitDecision;
|
|
30472
30518
|
let appliedMessages;
|
|
30473
30519
|
const applyStartedAt = performance.now();
|
|
30474
30520
|
try {
|
|
@@ -30484,11 +30530,25 @@ function createRustModeTransform(deps, options) {
|
|
|
30484
30530
|
if (typeof boundaryId === "string" && boundaryId.length > 0) {
|
|
30485
30531
|
assertNativeBoundary(appliedMessages, sessionId, boundaryId);
|
|
30486
30532
|
}
|
|
30533
|
+
if (!sessionMeta.isSubagent) {
|
|
30534
|
+
mirrorRustSyntheticTodoAnchor({
|
|
30535
|
+
db: deps.db,
|
|
30536
|
+
sessionId,
|
|
30537
|
+
messages: appliedMessages,
|
|
30538
|
+
cacheBustingPass
|
|
30539
|
+
});
|
|
30540
|
+
}
|
|
30541
|
+
if (passInputs.emergency_recovery_armed === true) {
|
|
30542
|
+
servedFinalWireEstimate = estimateFinalWireInputTokens({
|
|
30543
|
+
messages: appliedMessages,
|
|
30544
|
+
systemPromptTokens: sessionMeta.systemPromptTokens,
|
|
30545
|
+
providerID: model?.providerID,
|
|
30546
|
+
modelID: model?.modelID,
|
|
30547
|
+
agentName: deps.getNotificationParams?.(sessionId)?.agent
|
|
30548
|
+
});
|
|
30549
|
+
}
|
|
30487
30550
|
logStage(sessionId, "apply", applyStartedAt, timings);
|
|
30488
30551
|
const lkgSnapshotStartedAt = performance.now();
|
|
30489
|
-
const explicitDecision = typeof response.decision === "string" || typeof response.action === "string" || typeof response.cache_bust === "boolean";
|
|
30490
|
-
const decisionUpper = decision.toUpperCase();
|
|
30491
|
-
const cacheBustingPass = response.cache_bust === true || decisionUpper === "HARD" || decisionUpper === "MIGRATE_HARD" || decisionUpper === "EXECUTE" || decisionUpper === "SOFT" || !explicitDecision;
|
|
30492
30552
|
if (cacheBustingPass || !getSlot(sessionId)) {
|
|
30493
30553
|
const captured = captureRustResponse(sessionId, messages, response);
|
|
30494
30554
|
if (cacheBustingPass && !captured) {
|
|
@@ -30572,10 +30632,20 @@ function createRustModeTransform(deps, options) {
|
|
|
30572
30632
|
sessionLog(sessionId, "rust compartment mirror-back failed (ignored):", error);
|
|
30573
30633
|
}
|
|
30574
30634
|
}
|
|
30575
|
-
|
|
30635
|
+
const currentOverflowState = getOverflowState(deps.db, sessionId, modelKey);
|
|
30636
|
+
const disarmEvidence = currentOverflowState.needsEmergencyRecovery ? shouldDisarmRustEmergencyRecovery({
|
|
30637
|
+
materialized: materializeReason !== "none",
|
|
30638
|
+
usagePercentage: passUsageSnapshot.percentage,
|
|
30639
|
+
recoveryOrigin: currentOverflowState.emergencyRecoveryOrigin,
|
|
30640
|
+
recoveryArmedAt: getEmergencyRecoveryArmedAt(sessionId),
|
|
30641
|
+
usageEntry: deps.contextUsageMap.get(sessionId),
|
|
30642
|
+
finalWireEstimate: servedFinalWireEstimate,
|
|
30643
|
+
providerProvenLimitTokens: currentOverflowState.detectedContextLimit
|
|
30644
|
+
}) : null;
|
|
30645
|
+
if (disarmEvidence) {
|
|
30576
30646
|
try {
|
|
30577
30647
|
clearEmergencyRecovery(deps.db, sessionId);
|
|
30578
|
-
sessionLog(sessionId, `rust pass disarmed emergency recovery after ${materializeReason} at ${passUsageSnapshot.percentage.toFixed(1)}% usage`);
|
|
30648
|
+
sessionLog(sessionId, `rust pass disarmed emergency recovery via ${disarmEvidence} after ${materializeReason} at ${passUsageSnapshot.percentage.toFixed(1)}% usage`);
|
|
30579
30649
|
} catch {}
|
|
30580
30650
|
}
|
|
30581
30651
|
wireCaches.set(sessionId, pendingWireCache);
|
|
@@ -30586,6 +30656,7 @@ function createRustModeTransform(deps, options) {
|
|
|
30586
30656
|
sessionLog(sessionId, "rust transform wire invariant failed; LKG replay required", error);
|
|
30587
30657
|
}
|
|
30588
30658
|
if (emergencyFailClosed) {
|
|
30659
|
+
sessionLog(sessionId, "mc_rust_emergency_refusal before_lkg");
|
|
30589
30660
|
markFailure(sessionId, state, error);
|
|
30590
30661
|
finishPass(false, false);
|
|
30591
30662
|
throw new EmergencyFailClosedError("Rust Magic Context was unavailable at a provider-proven context limit", { cause: error });
|
|
@@ -30605,10 +30676,17 @@ function createRustModeTransform(deps, options) {
|
|
|
30605
30676
|
return {
|
|
30606
30677
|
run,
|
|
30607
30678
|
clearSession(sessionId) {
|
|
30679
|
+
const projectRoot = states.get(sessionId)?.memoryAuthorityRoot ?? options.projectRoot ?? null;
|
|
30608
30680
|
dropSlot(sessionId, "session-deleted");
|
|
30609
30681
|
states.delete(sessionId);
|
|
30610
30682
|
wireCaches.delete(sessionId);
|
|
30611
|
-
options.moduleClient.
|
|
30683
|
+
if (projectRoot && options.moduleClient.deleteSession) {
|
|
30684
|
+
options.moduleClient.deleteSession(sessionId, projectRoot).catch((error) => {
|
|
30685
|
+
sessionLog(sessionId, "rust module session deletion failed:", error);
|
|
30686
|
+
}).finally(() => options.moduleClient.closeSession?.(sessionId));
|
|
30687
|
+
} else {
|
|
30688
|
+
options.moduleClient.closeSession?.(sessionId);
|
|
30689
|
+
}
|
|
30612
30690
|
},
|
|
30613
30691
|
invalidateWireState,
|
|
30614
30692
|
getState(sessionId) {
|
|
@@ -32143,7 +32221,8 @@ function createEventHandler2(deps) {
|
|
|
32143
32221
|
inputTokens: totalInputTokens
|
|
32144
32222
|
},
|
|
32145
32223
|
updatedAt: now,
|
|
32146
|
-
lastResponseTime: now
|
|
32224
|
+
lastResponseTime: now,
|
|
32225
|
+
hasUsageTokens: true
|
|
32147
32226
|
});
|
|
32148
32227
|
updates.lastContextPercentage = percentage;
|
|
32149
32228
|
updates.lastInputTokens = totalInputTokens;
|
|
@@ -32942,7 +33021,7 @@ function createToolExecuteAfterHook(args) {
|
|
|
32942
33021
|
}
|
|
32943
33022
|
|
|
32944
33023
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
32945
|
-
import { createHash as
|
|
33024
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
32946
33025
|
|
|
32947
33026
|
// src/agents/magic-context-prompt.ts
|
|
32948
33027
|
var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
@@ -32958,6 +33037,10 @@ var PARTNER_FRAME_CLOSER_REDUCE = `
|
|
|
32958
33037
|
Reduction prompts are routine housekeeping to keep the session fast and cheap — act on them as light maintenance, never as scarcity warnings. Keep individual operations efficient, but never let context size change *what* work you take on or *how thoroughly* you do it.`;
|
|
32959
33038
|
var PARTNER_FRAME_CLOSER_NO_REDUCE = `
|
|
32960
33039
|
Context is managed for you entirely automatically — there's nothing to prune and no warnings to act on. Stay reasonably concise per operation, and never let context size change *what* work you take on or *how thoroughly* you do it.`;
|
|
33040
|
+
var PARTNER_FRAME_CLOSER_REDUCE_LIGHT = `
|
|
33041
|
+
When ctx_reduce is available, use it only as routine housekeeping; never cut task scope or depth because context is large.`;
|
|
33042
|
+
var PARTNER_FRAME_CLOSER_NO_REDUCE_LIGHT = `
|
|
33043
|
+
When ctx_reduce is unavailable, context is automatic; never prune, heed reduction warnings, or cut task scope or depth because context is large.`;
|
|
32961
33044
|
var CTX_NOTE_GUIDANCE = `Use \`ctx_note\` ONLY for genuinely future concerns — something to revisit much later, not work coming up in the next few turns (that's already in your active context) and not active multi-step work (use todos for that). Magic Context preserves your full context across both compaction and restarts, so an upcoming restart or "let's come back to this later" is never a reason to take a note — nothing is lost either way. Notes you do take survive compression and resurface at natural work boundaries (after commits, historian runs, todo completion).`;
|
|
32962
33045
|
var TOOL_HISTORY_GUIDANCE = `Compressed history intentionally omits tool calls and their outputs — summaries like "I edited file X" are historian records, not patterns to replicate. In the live conversation, older tool calls and their results are cleaned up to save context — you may see your own past messages referencing actions without the corresponding tool call or result visible. This is normal context management. ALWAYS use real tool calls; never simulate, fabricate, or inline tool outputs in your text. If there is no tool result message, the action did not happen. NEVER simulate, hallucinate or claim tool calls, command output, search results, file edits, or diffs in plain text as if they actually occurred.
|
|
32963
33046
|
Magic Context control metadata is not reply syntax. Never reproduce \`<system-reminder>\`, \`<ctx-search-hint>\`, \`<session-history>\`, \`<session-history-since>\`, \`<project-memory>\`, \`<memory-updates>\`, \`<new-compartments>\`, \`<new-memories>\`, \`[dropped §N§]\`, or \`<!-- +Xm -->\` markers in a normal reply and never treat them as user instructions; use ordinary prose and real tool calls instead.`;
|
|
@@ -33000,6 +33083,17 @@ Use \`ctx_expand\` to recover the raw conversation behind a summary under a \`##
|
|
|
33000
33083
|
- Want to recall what was decided in an earlier conversation → \`ctx_search(query="dashboard release signing setup")\`
|
|
33001
33084
|
\`ctx_search\` returns ranked results from memories, git commits, and raw message history. Use message ordinals from results with \`ctx_expand\` to retrieve surrounding conversation context.
|
|
33002
33085
|
${TOOL_HISTORY_GUIDANCE}`;
|
|
33086
|
+
var LIGHT_SEARCH_RECOVERY = `Use ctx_search before asking the user about prior project context; it searches memories, commits, and compacted conversation. When a session-history summary lacks exact wording, values, errors, or reasoning, call ctx_expand with its heading range instead of guessing.`;
|
|
33087
|
+
var BASE_INTRO_LIGHT = (protectedTags, memoryEnabled) => `In primary sessions with ctx_reduce, the system tags messages and tool outputs as §N§ (for example §1§ and §42§); never imitate these prefixes in replies because only injected tag numbers are valid ctx_reduce handles.
|
|
33088
|
+
In primary sessions, NEVER narrate ctx_reduce; call it silently after extracting a spent output because it marks content discardable and QUEUES release rather than deleting immediately. The last ${protectedTags} tags stay protected until they age out. Use drop grammar "3-5", "1,2,9", or "1-5,8,12-15".
|
|
33089
|
+
${CTX_NOTE_GUIDANCE}
|
|
33090
|
+
${memoryGuidanceBlock(memoryEnabled)}${LIGHT_SEARCH_RECOVERY}
|
|
33091
|
+
${TOOL_HISTORY_GUIDANCE}
|
|
33092
|
+
For primary ctx_reduce choices, NEVER blanket-drop a large range because mixed-value evidence may be lost: inspect every tag first. Drop only analyzed reads, searches, diagnostics, or build/test outputs after use. NEVER drop user directives or assistant prose unless exceptionally large; keep requirements, constraints, unresolved errors or decisions, exact wording, raw evidence, and active files or work. Only extracted pasted user payloads may go.
|
|
33093
|
+
Consider small targeted drops after acted-on reads or searches, completed logical steps, before context switches, and before the turn ends; this keeps the working set tidy without changing task scope.`;
|
|
33094
|
+
var BASE_INTRO_NO_REDUCE_LIGHT = (memoryEnabled) => `${CTX_NOTE_GUIDANCE}
|
|
33095
|
+
${memoryGuidanceBlock(memoryEnabled)}${LIGHT_SEARCH_RECOVERY}
|
|
33096
|
+
${TOOL_HISTORY_GUIDANCE}`;
|
|
33003
33097
|
var GENERIC_SECTION = `
|
|
33004
33098
|
### Reduction Triggers
|
|
33005
33099
|
- After reading files or search results you already acted on — drop raw outputs.
|
|
@@ -33016,21 +33110,27 @@ var GENERIC_SECTION = `
|
|
|
33016
33110
|
- Your current task requirements and constraints.
|
|
33017
33111
|
- Recent errors and unresolved decisions.
|
|
33018
33112
|
- Active work context and files being edited.`;
|
|
33113
|
+
var SMART_NOTE_GUIDANCE_LIGHT = `
|
|
33114
|
+
surface_condition creates a smart note checked nightly against external signals on ctx_note write.`;
|
|
33019
33115
|
var TEMPORAL_AWARENESS_GUIDANCE = `
|
|
33020
33116
|
**Temporal awareness**: User messages may be preceded by HTML comments like \`<!-- +12m -->\`, \`<!-- +2h 15m -->\`, or \`<!-- +3d 4h -->\` indicating time elapsed since the previous message's completion. Compartments in \`<session-history>\` carry \`start-date\` and \`end-date\` attributes (YYYY-MM-DD) showing real-time boundaries. Use these when reasoning about workflow pacing, log durations, build times, or how long ago something happened.`;
|
|
33021
33117
|
var SUBAGENT_REDUCE_INTRO = (protectedTags) => `Messages and tool outputs are tagged with §N§ identifiers (e.g., §1§, §42§).
|
|
33022
33118
|
Use \`ctx_reduce\` to drop tool outputs you have already finished with, keeping your working context lean. Syntax: "3-5", "1,2,9", or "1-5,8,12-15". The last ${protectedTags} tags are protected.
|
|
33023
33119
|
Drop silently — do not narrate it. NEVER drop large ranges blindly (e.g., "1-50"); review each tag first. Do not drop user or assistant text messages — only large tool outputs are worth dropping.
|
|
33024
33120
|
Older tool calls may show \`[dropped §N§]\` sentinels; that is normal context management, not a pattern to copy. ALWAYS make fresh real tool calls when you need data again; never fabricate or inline tool output.`;
|
|
33121
|
+
var SUBAGENT_REDUCE_INTRO_LIGHT = (protectedTags) => `In bounded subagent sessions, the system tags messages and tool outputs as §N§; use only those IDs in ctx_reduce drop ranges such as "3-5", "1,2,9", or "1-5,8,12-15". The last ${protectedTags} tags stay protected.
|
|
33122
|
+
When dropping, do it silently and NEVER choose a large range before reviewing every tag; drop only finished large tool outputs, never user or assistant messages.
|
|
33123
|
+
If older calls show [dropped §N§], never copy that system sentinel because it is not reply syntax; make a fresh real tool call and never fabricate or inline output.`;
|
|
33025
33124
|
var CAVEMAN_COMPRESSION_WARNING = `
|
|
33026
33125
|
**BEWARE**: History compression is on; older user AND assistant text — including your own earlier responses — has been deterministically rewritten in a terse caveman style (dropped articles, missing auxiliaries, \`//\` instead of connectives like \`because\`). This is automatic context compression that runs after the fact, not your actual prior wording or the user's. **DO NOT mimic this style in new turns.** Write fresh responses in normal prose. If you notice your output drifting into caveman cadence, that drift is in-context-learning bleeding from the compressed history — consciously revert to full sentences.`;
|
|
33027
|
-
function buildMagicContextSection(_agent, protectedTags, ctxReduceCallable = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language, memoryEnabled = true) {
|
|
33126
|
+
function buildMagicContextSection(_agent, protectedTags, ctxReduceCallable = true, dreamerEnabled = false, temporalAwarenessEnabled = false, cavemanTextCompressionEnabled = false, subagentMode = false, language, memoryEnabled = true, preset = "full", primaryOverride) {
|
|
33028
33127
|
if (subagentMode) {
|
|
33128
|
+
const intro = preset === "light" ? SUBAGENT_REDUCE_INTRO_LIGHT(protectedTags) : SUBAGENT_REDUCE_INTRO(protectedTags);
|
|
33029
33129
|
return `## Magic Context
|
|
33030
33130
|
|
|
33031
|
-
${
|
|
33131
|
+
${intro}`;
|
|
33032
33132
|
}
|
|
33033
|
-
const smartNoteGuidance = dreamerEnabled ? `
|
|
33133
|
+
const smartNoteGuidance = dreamerEnabled ? preset === "light" ? SMART_NOTE_GUIDANCE_LIGHT : `
|
|
33034
33134
|
When \`surface_condition\` is provided with \`write\`, the note becomes a project-scoped smart note.
|
|
33035
33135
|
The dreamer evaluates smart note conditions during nightly runs and surfaces them when conditions are met.
|
|
33036
33136
|
Example: \`ctx_note(action="write", content="Implement X because Y", surface_condition="When PR #42 is merged in this repo")\`` : "";
|
|
@@ -33040,13 +33140,32 @@ Example: \`ctx_note(action="write", content="Implement X because Y", surface_con
|
|
|
33040
33140
|
const languageGuidance = languageDirective ? `
|
|
33041
33141
|
|
|
33042
33142
|
${languageDirective}` : "";
|
|
33143
|
+
if (primaryOverride !== undefined) {
|
|
33144
|
+
return `${primaryOverride}${temporalGuidance}${cavemanWarning}${languageGuidance}`;
|
|
33145
|
+
}
|
|
33043
33146
|
if (!ctxReduceCallable) {
|
|
33147
|
+
if (preset === "light") {
|
|
33148
|
+
return `## Magic Context
|
|
33149
|
+
|
|
33150
|
+
${LONG_TERM_PARTNER_FRAME}
|
|
33151
|
+
${PARTNER_FRAME_CLOSER_NO_REDUCE_LIGHT}
|
|
33152
|
+
|
|
33153
|
+
${BASE_INTRO_NO_REDUCE_LIGHT(memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}${languageGuidance}`;
|
|
33154
|
+
}
|
|
33044
33155
|
return `## Magic Context
|
|
33045
33156
|
|
|
33046
33157
|
${LONG_TERM_PARTNER_FRAME}
|
|
33047
33158
|
${PARTNER_FRAME_CLOSER_NO_REDUCE}
|
|
33048
33159
|
|
|
33049
33160
|
${BASE_INTRO_NO_REDUCE(memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}${languageGuidance}`;
|
|
33161
|
+
}
|
|
33162
|
+
if (preset === "light") {
|
|
33163
|
+
return `## Magic Context
|
|
33164
|
+
|
|
33165
|
+
${LONG_TERM_PARTNER_FRAME}
|
|
33166
|
+
${PARTNER_FRAME_CLOSER_REDUCE_LIGHT}
|
|
33167
|
+
|
|
33168
|
+
${BASE_INTRO_LIGHT(protectedTags, memoryEnabled)}${smartNoteGuidance}${temporalGuidance}${cavemanWarning}${languageGuidance}`;
|
|
33050
33169
|
}
|
|
33051
33170
|
return `## Magic Context
|
|
33052
33171
|
|
|
@@ -33072,6 +33191,11 @@ function isMagicContextInternalAgent(systemPromptContent) {
|
|
|
33072
33191
|
return systemPromptContent.includes("You are Historian — the hippocampus of a long-running coding agent.") || systemPromptContent.includes("for the magic-context system") || systemPromptContent.includes("You are Sidekick, a focused memory-retrieval subagent for an AI coding assistant.");
|
|
33073
33192
|
}
|
|
33074
33193
|
function createSystemPromptHashHandler(deps) {
|
|
33194
|
+
const promptSurfaceRuntime = deps.promptSurfaceRuntime ?? createPromptSurfaceRuntime({
|
|
33195
|
+
userConfigDirectory: process.cwd(),
|
|
33196
|
+
warn: (message) => console.warn(`[magic-context] config warning: ${message}`)
|
|
33197
|
+
});
|
|
33198
|
+
const guidanceEpochs = createPromptSurfaceGuidanceEpochCache(promptSurfaceRuntime);
|
|
33075
33199
|
const stickyDateBySession = new Map;
|
|
33076
33200
|
const handler = async (input, output) => {
|
|
33077
33201
|
const sessionId = input.sessionID;
|
|
@@ -33109,10 +33233,14 @@ function createSystemPromptHashHandler(deps) {
|
|
|
33109
33233
|
const subagentReduceMode = isSubagentSession2 && ctxReduceCallable;
|
|
33110
33234
|
const effectiveCtxReduceEnabled = isSubagentSession2 ? false : ctxReduceCallable;
|
|
33111
33235
|
const skipGuidanceForDisabledSubagent = isSubagentSession2 && !ctxReduceCallable;
|
|
33236
|
+
const inputModel = input.model;
|
|
33237
|
+
const liveModel = inputModel?.providerID && inputModel.modelID ? { providerID: inputModel.providerID, modelID: inputModel.modelID } : deps.resolveModel?.(sessionId);
|
|
33238
|
+
const modelKey = liveModel?.providerID && liveModel.modelID ? `${liveModel.providerID}/${liveModel.modelID}` : undefined;
|
|
33239
|
+
const promptSurface = guidanceEpochs.resolve(sessionId, deps.promptSurface, modelKey);
|
|
33112
33240
|
const fullPrompt = output.system.join(`
|
|
33113
33241
|
`);
|
|
33114
33242
|
if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER) && !skipGuidanceForDisabledSubagent) {
|
|
33115
|
-
const guidance = buildMagicContextSection(null, deps.protectedTags, effectiveCtxReduceEnabled, deps.dreamerEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode, deps.language, deps.memoryEnabled !== false);
|
|
33243
|
+
const guidance = buildMagicContextSection(null, deps.protectedTags, effectiveCtxReduceEnabled, deps.dreamerEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode, deps.language, deps.memoryEnabled !== false, promptSurface.preset, promptSurface.primaryOverride);
|
|
33116
33244
|
output.system.push(guidance);
|
|
33117
33245
|
sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${isSubagentSession2}, subagentReduceMode=${subagentReduceMode})`);
|
|
33118
33246
|
}
|
|
@@ -33143,7 +33271,7 @@ function createSystemPromptHashHandler(deps) {
|
|
|
33143
33271
|
return;
|
|
33144
33272
|
if (!availability.frozen)
|
|
33145
33273
|
return;
|
|
33146
|
-
const currentHash =
|
|
33274
|
+
const currentHash = createHash14("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
|
|
33147
33275
|
if (!sessionMetaEarly) {
|
|
33148
33276
|
return;
|
|
33149
33277
|
}
|
|
@@ -33181,6 +33309,7 @@ function createSystemPromptHashHandler(deps) {
|
|
|
33181
33309
|
return {
|
|
33182
33310
|
handler,
|
|
33183
33311
|
clearSession: (sessionId) => {
|
|
33312
|
+
guidanceEpochs.clear(sessionId);
|
|
33184
33313
|
clearSystemPromptHashSession(sessionId, {
|
|
33185
33314
|
stickyDateBySession,
|
|
33186
33315
|
cachedDocsBySession: new Map
|
|
@@ -33335,11 +33464,13 @@ function createMagicContextHook(deps) {
|
|
|
33335
33464
|
const fence = getSchemaFenceRejection();
|
|
33336
33465
|
recordHookInitFailure({
|
|
33337
33466
|
type: "storage",
|
|
33338
|
-
reason: migration && blockingProcesses.length > 0 ? {
|
|
33467
|
+
reason: migration && (blockingProcesses.length > 0 || migration.unreadableFile) ? {
|
|
33339
33468
|
kind: "migration_guard",
|
|
33340
33469
|
persistedVersion: migration.persistedVersion,
|
|
33341
33470
|
supportedVersion: migration.supportedVersion,
|
|
33342
|
-
blockingProcesses
|
|
33471
|
+
blockingProcesses,
|
|
33472
|
+
...migration.unreadableFile ? { unreadableFile: migration.unreadableFile } : {},
|
|
33473
|
+
...migration.unreadableArm ? { unreadableArm: migration.unreadableArm } : {}
|
|
33343
33474
|
} : fence ? {
|
|
33344
33475
|
kind: "schema_fence",
|
|
33345
33476
|
persistedVersion: fence.persistedVersion,
|
|
@@ -33631,6 +33762,7 @@ function createMagicContextHook(deps) {
|
|
|
33631
33762
|
const client = {
|
|
33632
33763
|
call: (args) => transport.call(args),
|
|
33633
33764
|
stateSyncCapabilities: (args) => transport.stateSyncCapabilities(args),
|
|
33765
|
+
deleteSession: (sessionId, projectRoot) => transport.deleteSession(sessionId, projectRoot),
|
|
33634
33766
|
closeSession: (sessionId) => transport.closeSession(sessionId),
|
|
33635
33767
|
authorityStatus: (args) => transport.authorityStatus(args),
|
|
33636
33768
|
authorityPrepare: (args) => transport.authorityPrepare(args),
|
|
@@ -33659,6 +33791,23 @@ function createMagicContextHook(deps) {
|
|
|
33659
33791
|
return client;
|
|
33660
33792
|
})();
|
|
33661
33793
|
const rustModeModuleClient = deps.config.transform_mode === "rust" ? authorityRecoveryModuleClient : undefined;
|
|
33794
|
+
const syncModuleDomain = async (domain) => {
|
|
33795
|
+
if (!rustModeModuleClient?.mirrorPull)
|
|
33796
|
+
return;
|
|
33797
|
+
for (;; ) {
|
|
33798
|
+
const cursor = getMirrorCursor(db, domain);
|
|
33799
|
+
const response = await rustModeModuleClient.mirrorPull({
|
|
33800
|
+
domain,
|
|
33801
|
+
cursor,
|
|
33802
|
+
limit: 1000
|
|
33803
|
+
});
|
|
33804
|
+
const next = applyMirrorPage({ db, page: response.page });
|
|
33805
|
+
if (!response.page.has_more || next === cursor)
|
|
33806
|
+
break;
|
|
33807
|
+
}
|
|
33808
|
+
};
|
|
33809
|
+
const syncModuleNotes = () => syncModuleDomain("notes");
|
|
33810
|
+
const syncModuleMemories = () => syncModuleDomain("memories");
|
|
33662
33811
|
const rustToolBackends = deps.config.transform_mode === "rust" && rustModeModuleClient ? {
|
|
33663
33812
|
authorityState: async ({ projectPath: projectPath2, projectRoot, domain }) => {
|
|
33664
33813
|
if (!rustModeModuleClient.authorityStatus)
|
|
@@ -33683,7 +33832,7 @@ function createMagicContextHook(deps) {
|
|
|
33683
33832
|
command_id: commandId
|
|
33684
33833
|
}
|
|
33685
33834
|
}),
|
|
33686
|
-
note: ({
|
|
33835
|
+
note: async ({
|
|
33687
33836
|
commandId,
|
|
33688
33837
|
sessionId,
|
|
33689
33838
|
projectRoot,
|
|
@@ -33695,26 +33844,30 @@ function createMagicContextHook(deps) {
|
|
|
33695
33844
|
limit,
|
|
33696
33845
|
offset,
|
|
33697
33846
|
noteId
|
|
33698
|
-
}) =>
|
|
33699
|
-
|
|
33700
|
-
|
|
33701
|
-
|
|
33702
|
-
|
|
33703
|
-
|
|
33704
|
-
|
|
33705
|
-
|
|
33706
|
-
|
|
33707
|
-
|
|
33708
|
-
|
|
33709
|
-
|
|
33710
|
-
|
|
33711
|
-
|
|
33712
|
-
|
|
33713
|
-
|
|
33847
|
+
}) => {
|
|
33848
|
+
const response = await rustModeModuleClient.call({
|
|
33849
|
+
sessionId,
|
|
33850
|
+
projectRoot,
|
|
33851
|
+
method: "ctx_note",
|
|
33852
|
+
body: {
|
|
33853
|
+
name: "ctx_note",
|
|
33854
|
+
arguments: {
|
|
33855
|
+
...commandId ? { command_id: commandId } : {},
|
|
33856
|
+
action,
|
|
33857
|
+
content,
|
|
33858
|
+
memory_project: memoryProject,
|
|
33859
|
+
surface_condition: surfaceCondition,
|
|
33860
|
+
filter,
|
|
33861
|
+
limit,
|
|
33862
|
+
offset,
|
|
33863
|
+
note_id: noteId
|
|
33864
|
+
}
|
|
33714
33865
|
}
|
|
33715
|
-
}
|
|
33716
|
-
|
|
33717
|
-
|
|
33866
|
+
});
|
|
33867
|
+
await syncModuleNotes();
|
|
33868
|
+
return response;
|
|
33869
|
+
},
|
|
33870
|
+
memory: async ({
|
|
33718
33871
|
commandId,
|
|
33719
33872
|
sessionId,
|
|
33720
33873
|
projectRoot,
|
|
@@ -33724,23 +33877,27 @@ function createMagicContextHook(deps) {
|
|
|
33724
33877
|
category,
|
|
33725
33878
|
ids,
|
|
33726
33879
|
reason
|
|
33727
|
-
}) =>
|
|
33728
|
-
|
|
33729
|
-
|
|
33730
|
-
|
|
33731
|
-
|
|
33732
|
-
|
|
33733
|
-
|
|
33734
|
-
|
|
33735
|
-
|
|
33736
|
-
|
|
33737
|
-
|
|
33738
|
-
|
|
33739
|
-
|
|
33740
|
-
|
|
33880
|
+
}) => {
|
|
33881
|
+
const response = await rustModeModuleClient.call({
|
|
33882
|
+
sessionId,
|
|
33883
|
+
projectRoot,
|
|
33884
|
+
method: "ctx_memory",
|
|
33885
|
+
body: {
|
|
33886
|
+
name: "ctx_memory",
|
|
33887
|
+
arguments: {
|
|
33888
|
+
...commandId ? { command_id: commandId } : {},
|
|
33889
|
+
action,
|
|
33890
|
+
content,
|
|
33891
|
+
category,
|
|
33892
|
+
ids,
|
|
33893
|
+
reason,
|
|
33894
|
+
memory_project: memoryProject
|
|
33895
|
+
}
|
|
33741
33896
|
}
|
|
33742
|
-
}
|
|
33743
|
-
|
|
33897
|
+
});
|
|
33898
|
+
await syncModuleMemories();
|
|
33899
|
+
return response;
|
|
33900
|
+
},
|
|
33744
33901
|
noteEvaluationAvailable: (evaluationProjectPath) => getModuleNoteEvaluationBridge(evaluationProjectPath) !== undefined,
|
|
33745
33902
|
memorySync: (sessionId) => {
|
|
33746
33903
|
rustMemorySyncRequestedSessions.add(sessionId);
|
|
@@ -33751,21 +33908,6 @@ function createMagicContextHook(deps) {
|
|
|
33751
33908
|
return;
|
|
33752
33909
|
if (getModuleNoteEvaluationBridge(bridgeProjectPath))
|
|
33753
33910
|
return;
|
|
33754
|
-
const syncModuleNotes = async () => {
|
|
33755
|
-
for (;; ) {
|
|
33756
|
-
const cursor = getMirrorCursor(db, "notes");
|
|
33757
|
-
const response = await rustModeModuleClient.mirrorPull?.({
|
|
33758
|
-
domain: "notes",
|
|
33759
|
-
cursor,
|
|
33760
|
-
limit: 1000
|
|
33761
|
-
});
|
|
33762
|
-
if (!response)
|
|
33763
|
-
throw new Error("mirror.pull is unavailable for notes");
|
|
33764
|
-
const next = applyMirrorPage({ db, page: response.page });
|
|
33765
|
-
if (!response.page.has_more || next === cursor)
|
|
33766
|
-
break;
|
|
33767
|
-
}
|
|
33768
|
-
};
|
|
33769
33911
|
registerModuleNoteEvaluationBridge(bridgeProjectPath, {
|
|
33770
33912
|
sync: syncModuleNotes,
|
|
33771
33913
|
async evaluate({ contextNoteId, sessionId, verdict }) {
|
|
@@ -33873,6 +34015,7 @@ function createMagicContextHook(deps) {
|
|
|
33873
34015
|
} : undefined,
|
|
33874
34016
|
maybeAutoEmbedSession,
|
|
33875
34017
|
transformMode: deps.config.transform_mode,
|
|
34018
|
+
promptSurface: deps.config.prompt_surface,
|
|
33876
34019
|
rustModeModuleClient,
|
|
33877
34020
|
tsAuthorityRecoveryModuleClient: authorityRecoveryModuleClient,
|
|
33878
34021
|
rustMemorySyncRequestedSessions,
|
|
@@ -34054,6 +34197,9 @@ function createMagicContextHook(deps) {
|
|
|
34054
34197
|
dreamerEnabled: dreamerRunnable,
|
|
34055
34198
|
memoryEnabled: deps.config.memory?.enabled !== false,
|
|
34056
34199
|
language: deps.config.language,
|
|
34200
|
+
promptSurface: deps.config.prompt_surface,
|
|
34201
|
+
promptSurfaceRuntime: deps.promptSurfaceRuntime,
|
|
34202
|
+
resolveModel: resolveLiveModel,
|
|
34057
34203
|
historyRefreshSessions,
|
|
34058
34204
|
systemPromptRefreshSessions,
|
|
34059
34205
|
pendingMaterializationSessions,
|
|
@@ -34194,6 +34340,7 @@ async function createSessionHooksAsync(args) {
|
|
|
34194
34340
|
compactionHandler,
|
|
34195
34341
|
liveSessionState,
|
|
34196
34342
|
rustModeModuleClient: args.rustModeModuleClient,
|
|
34343
|
+
promptSurfaceRuntime: args.promptSurfaceRuntime,
|
|
34197
34344
|
config: buildMagicContextHookConfig(pluginConfig)
|
|
34198
34345
|
});
|
|
34199
34346
|
return {
|
|
@@ -35024,7 +35171,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35024
35171
|
const db = getDb();
|
|
35025
35172
|
if (!db)
|
|
35026
35173
|
return { ok: false, error: "db unavailable" };
|
|
35027
|
-
const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-
|
|
35174
|
+
const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-zc915ceq.js");
|
|
35028
35175
|
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-6njqewzk.js");
|
|
35029
35176
|
log(`[rpc] recomp requested for session ${sessionId}`);
|
|
35030
35177
|
const ctx = await buildManagedCtx(db);
|
|
@@ -35040,7 +35187,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35040
35187
|
const db = getDb();
|
|
35041
35188
|
if (!db)
|
|
35042
35189
|
return { ok: false, error: "db unavailable" };
|
|
35043
|
-
const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-
|
|
35190
|
+
const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-zc915ceq.js");
|
|
35044
35191
|
const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-6njqewzk.js");
|
|
35045
35192
|
log(`[rpc] session-upgrade requested for session ${sessionId}`);
|
|
35046
35193
|
const ctx = await buildManagedCtx(db);
|
|
@@ -35057,7 +35204,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
35057
35204
|
if (!db)
|
|
35058
35205
|
return { ok: false, error: "db unavailable" };
|
|
35059
35206
|
try {
|
|
35060
|
-
const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-
|
|
35207
|
+
const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-53cjs6mr.js");
|
|
35061
35208
|
updateSessionMeta2(db, sessionId, { upgradeRemindedAt: Date.now() });
|
|
35062
35209
|
return { ok: true };
|
|
35063
35210
|
} catch (error) {
|
|
@@ -36343,7 +36490,7 @@ Mark discardable once processed: large outputs you've summarized, repeated or re
|
|
|
36343
36490
|
Keep: user messages, unresolved errors, raw evidence you haven't extracted yet, and outputs whose exact wording may matter later.
|
|
36344
36491
|
Never blanket-mark large ranges (e.g. "1-50") — review what each tag holds first.`;
|
|
36345
36492
|
// src/tools/ctx-reduce/tools.ts
|
|
36346
|
-
import { createHash as
|
|
36493
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
36347
36494
|
import { tool as tool4 } from "@opencode-ai/plugin";
|
|
36348
36495
|
|
|
36349
36496
|
// src/features/magic-context/range-parser.ts
|
|
@@ -36413,11 +36560,11 @@ function createCtxReduceTool(deps) {
|
|
|
36413
36560
|
const stableId = `oc-${sessionId}-${callId}`;
|
|
36414
36561
|
if (Buffer.byteLength(stableId) <= 128)
|
|
36415
36562
|
return stableId;
|
|
36416
|
-
return `oc-${
|
|
36563
|
+
return `oc-${createHash15("sha256").update(stableId).digest("hex")}`;
|
|
36417
36564
|
}
|
|
36418
36565
|
fallbackCommandSequence += 1;
|
|
36419
36566
|
const monotonicId = `oc-${sessionId}-${fallbackCommandSequence}`;
|
|
36420
|
-
return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${
|
|
36567
|
+
return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash15("sha256").update(monotonicId).digest("hex")}`;
|
|
36421
36568
|
};
|
|
36422
36569
|
return tool4({
|
|
36423
36570
|
description: CTX_REDUCE_DESCRIPTION,
|
|
@@ -36813,10 +36960,23 @@ function createToolRegistry(args) {
|
|
|
36813
36960
|
rustToolBackends
|
|
36814
36961
|
}) : {}
|
|
36815
36962
|
};
|
|
36816
|
-
|
|
36963
|
+
const promptSurfaceRuntime = args.promptSurfaceRuntime ?? createPromptSurfaceRuntime({
|
|
36964
|
+
harness: "opencode",
|
|
36965
|
+
directory: ctx.directory,
|
|
36966
|
+
warn: (message) => console.warn(`[magic-context] config warning: ${message}`)
|
|
36967
|
+
});
|
|
36968
|
+
const registration = promptSurfaceRuntime.resolveRegistration(args.registrationPromptSurface ?? pluginConfig.prompt_surface);
|
|
36969
|
+
const surfacedTools = Object.fromEntries(Object.entries(allTools).map(([toolId, definition]) => [
|
|
36970
|
+
toolId,
|
|
36971
|
+
{
|
|
36972
|
+
...definition,
|
|
36973
|
+
description: registration.descriptionFor(toolId, definition.description ?? "")
|
|
36974
|
+
}
|
|
36975
|
+
]));
|
|
36976
|
+
for (const toolDefinition of Object.values(surfacedTools)) {
|
|
36817
36977
|
normalizeToolArgSchemas(toolDefinition);
|
|
36818
36978
|
}
|
|
36819
|
-
return
|
|
36979
|
+
return surfacedTools;
|
|
36820
36980
|
}
|
|
36821
36981
|
|
|
36822
36982
|
// src/shared/exit-abort-registry.ts
|
|
@@ -36844,15 +37004,15 @@ function unregisterExitAbort(controller) {
|
|
|
36844
37004
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
36845
37005
|
import {
|
|
36846
37006
|
chmodSync,
|
|
36847
|
-
mkdirSync as
|
|
37007
|
+
mkdirSync as mkdirSync2,
|
|
36848
37008
|
readdirSync,
|
|
36849
|
-
readFileSync as
|
|
36850
|
-
renameSync as
|
|
36851
|
-
rmSync as
|
|
36852
|
-
unlinkSync
|
|
36853
|
-
writeFileSync as
|
|
37009
|
+
readFileSync as readFileSync6,
|
|
37010
|
+
renameSync as renameSync3,
|
|
37011
|
+
rmSync as rmSync2,
|
|
37012
|
+
unlinkSync,
|
|
37013
|
+
writeFileSync as writeFileSync4
|
|
36854
37014
|
} from "node:fs";
|
|
36855
|
-
import { dirname as
|
|
37015
|
+
import { dirname as dirname4 } from "node:path";
|
|
36856
37016
|
var MAX_BODY_BYTES = 1048576;
|
|
36857
37017
|
var WS_AUTH_TIMEOUT_MS = 5000;
|
|
36858
37018
|
var WS_CLOSE_UNAUTHORIZED = 4401;
|
|
@@ -36926,28 +37086,28 @@ class MagicContextRpcServer {
|
|
|
36926
37086
|
this.port = server.port ?? 0;
|
|
36927
37087
|
try {
|
|
36928
37088
|
this.warnIfOtherLiveInstance();
|
|
36929
|
-
const dir =
|
|
37089
|
+
const dir = dirname4(this.portFilePath);
|
|
36930
37090
|
const enforcePrivatePermissions = shouldEnforcePrivateStoragePermissions();
|
|
36931
37091
|
if (enforcePrivatePermissions) {
|
|
36932
|
-
|
|
37092
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
36933
37093
|
try {
|
|
36934
37094
|
chmodSync(dir, 448);
|
|
36935
37095
|
} catch {}
|
|
36936
37096
|
} else {
|
|
36937
|
-
|
|
37097
|
+
mkdirSync2(dir, { recursive: true });
|
|
36938
37098
|
}
|
|
36939
37099
|
const tmpPath = `${this.portFilePath}.tmp`;
|
|
36940
37100
|
try {
|
|
36941
|
-
|
|
37101
|
+
rmSync2(tmpPath, { force: true });
|
|
36942
37102
|
} catch {}
|
|
36943
|
-
|
|
37103
|
+
writeFileSync4(tmpPath, JSON.stringify({
|
|
36944
37104
|
port: this.port,
|
|
36945
37105
|
pid: process.pid,
|
|
36946
37106
|
started_at: this.startedAt,
|
|
36947
37107
|
token: this.token,
|
|
36948
37108
|
instance_id: this.instanceId
|
|
36949
37109
|
}), enforcePrivatePermissions ? { encoding: "utf-8", mode: 384 } : { encoding: "utf-8" });
|
|
36950
|
-
|
|
37110
|
+
renameSync3(tmpPath, this.portFilePath);
|
|
36951
37111
|
if (enforcePrivatePermissions) {
|
|
36952
37112
|
try {
|
|
36953
37113
|
chmodSync(this.portFilePath, 384);
|
|
@@ -36974,7 +37134,7 @@ class MagicContextRpcServer {
|
|
|
36974
37134
|
this.server = null;
|
|
36975
37135
|
}
|
|
36976
37136
|
try {
|
|
36977
|
-
|
|
37137
|
+
unlinkSync(this.portFilePath);
|
|
36978
37138
|
} catch {}
|
|
36979
37139
|
}
|
|
36980
37140
|
warnIfOtherLiveInstance() {
|
|
@@ -36982,7 +37142,7 @@ class MagicContextRpcServer {
|
|
|
36982
37142
|
for (const entry of readdirSync(this.portDir)) {
|
|
36983
37143
|
if (!entry.startsWith("port-") || !entry.endsWith(".json"))
|
|
36984
37144
|
continue;
|
|
36985
|
-
const record = parseRpcPortFile(
|
|
37145
|
+
const record = parseRpcPortFile(readFileSync6(`${this.portDir}/${entry}`, "utf-8"));
|
|
36986
37146
|
if (!record || record.pid === process.pid || !isPidAlive(record.pid))
|
|
36987
37147
|
continue;
|
|
36988
37148
|
log(`[rpc] another Magic Context RPC server is active for this project (pid ${record.pid}, port ${record.port}); starting separate instance on a new port`);
|
|
@@ -37122,7 +37282,13 @@ var server = async (ctx) => {
|
|
|
37122
37282
|
warn: (m) => log(`[magic-context] ${m}`),
|
|
37123
37283
|
info: (m) => log(`[magic-context] ${m}`)
|
|
37124
37284
|
});
|
|
37125
|
-
const
|
|
37285
|
+
const loadedPluginConfig = loadPluginConfigDetailed(ctx.directory);
|
|
37286
|
+
const pluginConfig = loadedPluginConfig.config;
|
|
37287
|
+
const promptSurfaceRuntime = createPromptSurfaceRuntime({
|
|
37288
|
+
harness: "opencode",
|
|
37289
|
+
directory: ctx.directory,
|
|
37290
|
+
warn: (message) => log(`[magic-context] config warning: ${message}`)
|
|
37291
|
+
});
|
|
37126
37292
|
if (configMigrationWarnings.length > 0) {
|
|
37127
37293
|
pluginConfig.configWarnings = [
|
|
37128
37294
|
...configMigrationWarnings,
|
|
@@ -37182,7 +37348,8 @@ var server = async (ctx) => {
|
|
|
37182
37348
|
ctx,
|
|
37183
37349
|
pluginConfig,
|
|
37184
37350
|
liveSessionState,
|
|
37185
|
-
rustModeModuleClient
|
|
37351
|
+
rustModeModuleClient,
|
|
37352
|
+
promptSurfaceRuntime
|
|
37186
37353
|
});
|
|
37187
37354
|
const magicContextRuntime = {
|
|
37188
37355
|
magicContext: hooks.magicContext,
|
|
@@ -37207,7 +37374,8 @@ var server = async (ctx) => {
|
|
|
37207
37374
|
ctx,
|
|
37208
37375
|
pluginConfig,
|
|
37209
37376
|
liveSessionState,
|
|
37210
|
-
rustModeModuleClient
|
|
37377
|
+
rustModeModuleClient,
|
|
37378
|
+
promptSurfaceRuntime
|
|
37211
37379
|
});
|
|
37212
37380
|
if (!reopened.magicContext)
|
|
37213
37381
|
return false;
|
|
@@ -37224,7 +37392,9 @@ var server = async (ctx) => {
|
|
|
37224
37392
|
const tools5 = createToolRegistry({
|
|
37225
37393
|
ctx,
|
|
37226
37394
|
pluginConfig,
|
|
37227
|
-
rustToolBackends: magicContextRuntime.rustToolBackends
|
|
37395
|
+
rustToolBackends: magicContextRuntime.rustToolBackends,
|
|
37396
|
+
promptSurfaceRuntime,
|
|
37397
|
+
registrationPromptSurface: loadedPluginConfig.registrationPromptSurface
|
|
37228
37398
|
});
|
|
37229
37399
|
if (pluginConfig.enabled && magicContextRuntime.magicContext) {
|
|
37230
37400
|
try {
|
|
@@ -37330,7 +37500,7 @@ var server = async (ctx) => {
|
|
|
37330
37500
|
{
|
|
37331
37501
|
const fence = getSchemaFenceRejection();
|
|
37332
37502
|
if (fence) {
|
|
37333
|
-
import("./conflict-warning-hook-
|
|
37503
|
+
import("./conflict-warning-hook-p2pmhvn7.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
|
|
37334
37504
|
}
|
|
37335
37505
|
}
|
|
37336
37506
|
if (conflictResult?.hasConflict) {
|
|
@@ -37351,7 +37521,7 @@ var server = async (ctx) => {
|
|
|
37351
37521
|
} = await import("./announcement-gms2nhya.js");
|
|
37352
37522
|
if (shouldShowAnnouncement2()) {
|
|
37353
37523
|
setTimeout(() => {
|
|
37354
|
-
import("./conflict-warning-hook-
|
|
37524
|
+
import("./conflict-warning-hook-p2pmhvn7.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
|
|
37355
37525
|
}, 8000);
|
|
37356
37526
|
}
|
|
37357
37527
|
} catch {}
|