@cortexkit/opencode-magic-context 0.33.1 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/agent-disable.d.ts +22 -0
- package/dist/config/agent-disable.d.ts.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +7 -0
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +82 -2
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/config/transform-mode.d.ts +2 -0
- package/dist/config/transform-mode.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-n48c783v.js → conflict-warning-hook-fvpfvt0w.js} +1 -1
- package/dist/{derive-budgets-e9j09sjr.js → derive-budgets-9crp0cvd.js} +1 -1
- package/dist/features/builtin-commands/commands.d.ts +1 -1
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts +57 -0
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/fail-closed-block.d.ts +10 -0
- package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commit-embeddings.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/storage-git-commits.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +7 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +2 -6
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/storage-memory-embeddings.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.map +1 -1
- package/dist/features/magic-context/mural/render-mural.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts +8 -1
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/schema-fence-probe.d.ts +28 -0
- package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -0
- package/dist/features/magic-context/sidekick/agent.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +35 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +38 -4
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts +1 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts.map +1 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts +1 -0
- package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
- package/dist/hooks/magic-context/child-session-spawn.d.ts +26 -0
- package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -0
- package/dist/hooks/magic-context/command-handler.d.ts +2 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-off-transition.d.ts +96 -0
- package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -0
- 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-mapping.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +12 -5
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +47 -1
- package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-drop.d.ts +2 -2
- package/dist/hooks/magic-context/event-handler.d.ts +7 -0
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +13 -21
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +1 -0
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +11 -1
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +9 -0
- package/dist/hooks/magic-context/inject-compartments.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-db.d.ts.map +1 -1
- 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 +3 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts +20 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -0
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +30 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +27 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-ey1bc14z.js → index-b563sga5.js} +7 -264
- package/dist/{index-y1c9tcm3.js → index-cn960ffd.js} +101 -20
- package/dist/{index-xyaekybw.js → index-dtas91s5.js} +6 -4
- package/dist/index-fcyvznch.js +279 -0
- package/dist/{index-63dq2g4d.js → index-ry8rh8cv.js} +138 -24
- package/dist/{index-c2gahrks.js → index-s0mdn690.js} +1599 -892
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1292 -623
- package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +11 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +10 -0
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +3 -7
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts +8 -0
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-2yb2hfh2.js → recomp-orchestrator-8e82vmvb.js} +6 -4
- package/dist/send-session-notification-6njqewzk.js +20 -0
- package/dist/shared/conflict-detector.d.ts +38 -1
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/conflict-fixer.d.ts +18 -1
- package/dist/shared/conflict-fixer.d.ts.map +1 -1
- package/dist/shared/context-limit-provenance.d.ts +3 -0
- package/dist/shared/context-limit-provenance.d.ts.map +1 -0
- package/dist/shared/escalation-bands.d.ts +9 -0
- package/dist/shared/escalation-bands.d.ts.map +1 -0
- package/dist/shared/format-threshold.d.ts +1 -1
- package/dist/shared/models-dev-cache.d.ts +29 -3
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +46 -1
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/storage-permissions.d.ts +5 -0
- package/dist/shared/storage-permissions.d.ts.map +1 -0
- package/dist/{storage-meta-session-td6bwtky.js → storage-meta-session-xt41zbw4.js} +2 -1
- package/dist/tui/compaction-off.d.ts +13 -0
- package/dist/tui/compaction-off.d.ts.map +1 -0
- package/dist/tui/data/context-db.d.ts.map +1 -1
- package/dist/tui-compiled/compaction-off.d.ts +13 -0
- package/dist/tui-compiled/compaction-off.d.ts.map +1 -0
- package/dist/tui-compiled/data/context-db.d.ts.map +1 -1
- package/package.json +7 -2
- package/src/agents/dreamer.ts +68 -0
- package/src/agents/hidden-agent-registrations.ts +331 -0
- package/src/agents/historian.ts +3 -0
- package/src/agents/language-directive.test.ts +138 -0
- package/src/agents/language-directive.ts +121 -0
- package/src/agents/magic-context-prompt.language.test.ts +35 -0
- package/src/agents/magic-context-prompt.test.ts +292 -0
- package/src/agents/magic-context-prompt.ts +182 -0
- package/src/agents/permissions.test.ts +252 -0
- package/src/agents/permissions.ts +186 -0
- package/src/agents/sidekick.ts +1 -0
- package/src/agents/smart-note-compiler.ts +1 -0
- package/src/config/agent-disable.ts +106 -0
- package/src/config/compaction-accessor-guard.test.ts +82 -0
- package/src/config/compaction-backcompat.test.ts +52 -0
- package/src/config/index.test.ts +904 -0
- package/src/config/index.ts +601 -0
- package/src/config/migrate-config-location.test.ts +332 -0
- package/src/config/migrate-config-location.ts +635 -0
- package/src/config/migrate-dreamer-v2.test.ts +287 -0
- package/src/config/migrate-dreamer-v2.ts +336 -0
- package/src/config/migrate-experimental.ts +159 -0
- package/src/config/project-security.test.ts +366 -0
- package/src/config/project-security.ts +588 -0
- package/src/config/prune-config-leaf.test.ts +78 -0
- package/src/config/prune-config-leaf.ts +68 -0
- package/src/config/removed-config-keys.test.ts +116 -0
- package/src/config/schema/agent-overrides.ts +45 -0
- package/src/config/schema/magic-context.test.ts +358 -0
- package/src/config/schema/magic-context.ts +1002 -0
- package/src/config/transform-mode.test.ts +62 -0
- package/src/config/transform-mode.ts +34 -0
- package/src/config/variable.test.ts +323 -0
- package/src/config/variable.ts +192 -0
- package/src/features/magic-context/defaults.ts +1 -0
- package/src/features/magic-context/dreamer/cron.ts +243 -0
- package/src/features/magic-context/dreamer/task-registry.ts +104 -0
- package/src/shared/conflict-detector.test.ts +121 -0
- package/src/shared/conflict-detector.ts +50 -3
- package/src/shared/conflict-fixer.test.ts +309 -0
- package/src/shared/conflict-fixer.ts +82 -5
- package/src/shared/context-limit-provenance.ts +6 -0
- package/src/shared/escalation-bands.test.ts +23 -0
- package/src/shared/escalation-bands.ts +18 -0
- package/src/shared/format-threshold.ts +1 -1
- package/src/shared/models-dev-cache.test.ts +171 -0
- package/src/shared/models-dev-cache.ts +195 -38
- package/src/shared/rpc-server.ts +27 -18
- package/src/shared/rpc-types.ts +46 -1
- package/src/shared/storage-permissions.ts +20 -0
- package/src/tui/compaction-off.test.ts +56 -0
- package/src/tui/compaction-off.ts +29 -0
- package/src/tui/data/context-db.ts +6 -0
- package/src/tui/index.tsx +113 -65
- package/src/tui/slots/sidebar-content.tsx +139 -83
- package/src/tui-compiled/compaction-off.ts +29 -0
- package/src/tui-compiled/data/context-db.ts +6 -0
- package/src/tui-compiled/index.tsx +558 -455
- package/src/tui-compiled/slots/sidebar-content.tsx +237 -161
- package/dist/send-session-notification-tghq9gnh.js +0 -11
- /package/dist/{index-v7fmc1s2.js → index-ygcng9t8.js} +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deriveTriggerBudget,
|
|
3
|
-
modelSupportsVision
|
|
4
|
-
|
|
3
|
+
modelSupportsVision,
|
|
4
|
+
piModelRefToCanonical,
|
|
5
|
+
shouldEnforcePrivateStoragePermissions
|
|
6
|
+
} from "./index-ry8rh8cv.js";
|
|
5
7
|
import {
|
|
6
8
|
parseProviderModel
|
|
7
9
|
} from "./index-td9depx5.js";
|
|
@@ -9,18 +11,15 @@ import {
|
|
|
9
11
|
describeError,
|
|
10
12
|
getErrorMessage,
|
|
11
13
|
sendIgnoredMessage
|
|
12
|
-
} from "./index-
|
|
14
|
+
} from "./index-cn960ffd.js";
|
|
13
15
|
import {
|
|
14
|
-
Database,
|
|
15
16
|
clearCachedM0M1,
|
|
16
17
|
clearCompressionDepth,
|
|
17
18
|
clearCompressionDepthRange,
|
|
18
|
-
closeQuietly,
|
|
19
19
|
ensureSessionMetaRow,
|
|
20
20
|
estimateTokens,
|
|
21
21
|
getCachedAbsoluteMessageCount,
|
|
22
22
|
getLegacyProtectedTailStartOrdinal,
|
|
23
|
-
getMessageTimesFromOpenCodeDb,
|
|
24
23
|
getRawSessionMessageCount,
|
|
25
24
|
getRawSessionTagKeysThrough,
|
|
26
25
|
hasMeaningfulUserText,
|
|
@@ -29,9 +28,17 @@ import {
|
|
|
29
28
|
persistCachedM0,
|
|
30
29
|
readRawSessionMessages,
|
|
31
30
|
readSessionChunk,
|
|
32
|
-
updateSessionMeta
|
|
31
|
+
updateSessionMeta
|
|
32
|
+
} from "./index-b563sga5.js";
|
|
33
|
+
import {
|
|
34
|
+
Database,
|
|
35
|
+
closeQuietly,
|
|
36
|
+
getMessageTimesFromOpenCodeDb,
|
|
33
37
|
withPrivilegedWriter
|
|
34
|
-
} from "./index-
|
|
38
|
+
} from "./index-fcyvznch.js";
|
|
39
|
+
import {
|
|
40
|
+
pushNotification
|
|
41
|
+
} from "./index-d62ypazr.js";
|
|
35
42
|
import {
|
|
36
43
|
log,
|
|
37
44
|
sessionLog
|
|
@@ -372,462 +379,95 @@ function buildPrimaryLanguageDirective(language) {
|
|
|
372
379
|
return "";
|
|
373
380
|
return `Use ${target} for your natural-language replies to the user unless the user explicitly asks for another language. Keep code, identifiers, file paths, commands, logs, and quoted text verbatim.`;
|
|
374
381
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
/context size has been exceeded/i
|
|
397
|
-
];
|
|
398
|
-
var LIMIT_EXTRACTION_PATTERNS = [
|
|
399
|
-
/maximum prompt length is (\d+)/i,
|
|
400
|
-
/maximum context length is (\d+) tokens?/i,
|
|
401
|
-
/context length is only (\d+) tokens?/i,
|
|
402
|
-
/exceeds the limit of (\d+)/i,
|
|
403
|
-
/too large for model with (\d+) maximum context length/i,
|
|
404
|
-
/context size.*(\d+) tokens?/i,
|
|
405
|
-
/exceeds? the context length of (\d+)/i,
|
|
406
|
-
/>\s*(\d+)\s*(?:tokens?\s*)?(?:maximum|max|limit)\b/i,
|
|
407
|
-
/max(?:imum)?.*context.*?(\d+)/i
|
|
408
|
-
];
|
|
409
|
-
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
410
|
-
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
411
|
-
function extractErrorMessage(error) {
|
|
412
|
-
if (!error)
|
|
413
|
-
return "";
|
|
414
|
-
if (typeof error === "string")
|
|
415
|
-
return error;
|
|
416
|
-
if (typeof error === "object") {
|
|
417
|
-
const obj = error;
|
|
418
|
-
const nested = obj.error;
|
|
419
|
-
if (nested && typeof nested.message === "string" && nested.message.length > 0) {
|
|
420
|
-
return nested.message;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
if (error instanceof Error)
|
|
424
|
-
return error.message;
|
|
425
|
-
if (typeof error === "object") {
|
|
426
|
-
const obj = error;
|
|
427
|
-
if (typeof obj.message === "string")
|
|
428
|
-
return obj.message;
|
|
429
|
-
if (typeof obj.responseBody === "string")
|
|
430
|
-
return obj.responseBody;
|
|
431
|
-
try {
|
|
432
|
-
return JSON.stringify(error);
|
|
433
|
-
} catch {
|
|
434
|
-
return String(error);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
return String(error);
|
|
382
|
+
|
|
383
|
+
// src/features/magic-context/storage-db.ts
|
|
384
|
+
import {
|
|
385
|
+
chmodSync,
|
|
386
|
+
copyFileSync,
|
|
387
|
+
cpSync,
|
|
388
|
+
existsSync as existsSync3,
|
|
389
|
+
mkdirSync,
|
|
390
|
+
mkdtempSync,
|
|
391
|
+
readdirSync,
|
|
392
|
+
readFileSync,
|
|
393
|
+
unlinkSync
|
|
394
|
+
} from "node:fs";
|
|
395
|
+
import { basename, dirname, join as join3 } from "node:path";
|
|
396
|
+
|
|
397
|
+
// src/plugin/boot-quiet.ts
|
|
398
|
+
var BOOT_QUIET_MS = 120000;
|
|
399
|
+
var bootQuietUntilMs = 0;
|
|
400
|
+
function beginBootQuietPeriod(now = Date.now()) {
|
|
401
|
+
if (bootQuietUntilMs === 0)
|
|
402
|
+
bootQuietUntilMs = now + BOOT_QUIET_MS;
|
|
438
403
|
}
|
|
439
|
-
function
|
|
440
|
-
|
|
441
|
-
if (!message) {
|
|
442
|
-
return { isOverflow: false };
|
|
443
|
-
}
|
|
444
|
-
const hasStatus413 = /\b413\b/.test(message) && /(entity|payload|context|prompt)/i.test(message);
|
|
445
|
-
let matched;
|
|
446
|
-
for (const pattern of OVERFLOW_PATTERNS) {
|
|
447
|
-
if (pattern.test(message)) {
|
|
448
|
-
matched = pattern;
|
|
449
|
-
break;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
if (!matched && !hasStatus413) {
|
|
453
|
-
return { isOverflow: false };
|
|
454
|
-
}
|
|
455
|
-
const reportedLimit = parseReportedLimit(message);
|
|
456
|
-
return {
|
|
457
|
-
isOverflow: true,
|
|
458
|
-
reportedLimit,
|
|
459
|
-
matchedPattern: matched?.source
|
|
460
|
-
};
|
|
404
|
+
function bootQuietRemainingMs(now = Date.now()) {
|
|
405
|
+
return Math.max(0, bootQuietUntilMs - now);
|
|
461
406
|
}
|
|
462
|
-
function
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const match = message.match(pattern);
|
|
467
|
-
if (!match)
|
|
468
|
-
continue;
|
|
469
|
-
const raw = match[1];
|
|
470
|
-
if (!raw)
|
|
471
|
-
continue;
|
|
472
|
-
const value = Number.parseInt(raw, 10);
|
|
473
|
-
if (!Number.isFinite(value))
|
|
474
|
-
continue;
|
|
475
|
-
if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
|
|
476
|
-
continue;
|
|
477
|
-
return value;
|
|
478
|
-
}
|
|
479
|
-
return;
|
|
407
|
+
function scheduleAfterBootQuiet(task, additionalDelayMs = 0) {
|
|
408
|
+
const timer = setTimeout(task, bootQuietRemainingMs() + Math.max(0, additionalDelayMs));
|
|
409
|
+
timer.unref?.();
|
|
410
|
+
return timer;
|
|
480
411
|
}
|
|
481
412
|
|
|
482
|
-
// src/shared/
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
413
|
+
// src/shared/rpc-utils.ts
|
|
414
|
+
import { createHash } from "node:crypto";
|
|
415
|
+
import { join } from "node:path";
|
|
416
|
+
function projectHash(directory) {
|
|
417
|
+
const normalized = directory.replace(/\/+$/, "");
|
|
418
|
+
return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
486
419
|
}
|
|
487
|
-
function
|
|
488
|
-
|
|
489
|
-
return error;
|
|
490
|
-
if (error instanceof Error)
|
|
491
|
-
return error.message;
|
|
492
|
-
if (typeof error === "object" && error !== null) {
|
|
493
|
-
const obj = error;
|
|
494
|
-
if (typeof obj.message === "string")
|
|
495
|
-
return obj.message;
|
|
496
|
-
}
|
|
497
|
-
try {
|
|
498
|
-
return JSON.stringify(error);
|
|
499
|
-
} catch (_error) {
|
|
500
|
-
return String(error);
|
|
501
|
-
}
|
|
420
|
+
function rpcPortDir(storageDir, directory) {
|
|
421
|
+
return join(storageDir, "rpc", projectHash(directory));
|
|
502
422
|
}
|
|
503
|
-
function
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
if (typeof error === "object" && error !== null) {
|
|
507
|
-
const errObj = error;
|
|
508
|
-
if (errObj.name === "ProviderModelNotFoundError" && typeof errObj.data === "object" && errObj.data !== null) {
|
|
509
|
-
const data = errObj.data;
|
|
510
|
-
const suggestions = data.suggestions;
|
|
511
|
-
if (Array.isArray(suggestions) && typeof suggestions[0] === "string") {
|
|
512
|
-
return {
|
|
513
|
-
providerID: String(data.providerID ?? ""),
|
|
514
|
-
modelID: String(data.modelID ?? ""),
|
|
515
|
-
suggestion: suggestions[0]
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
for (const key of ["data", "error", "cause"]) {
|
|
520
|
-
const nested = errObj[key];
|
|
521
|
-
if (nested && typeof nested === "object") {
|
|
522
|
-
const result = parseModelSuggestion(nested);
|
|
523
|
-
if (result)
|
|
524
|
-
return result;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
const message = extractMessage(error);
|
|
529
|
-
const modelMatch = message.match(/model not found:\s*([^/\s]+)\s*\/\s*([^.,\s]+)/i);
|
|
530
|
-
const suggestionMatch = message.match(/did you mean:\s*([^,?]+)/i);
|
|
531
|
-
if (!modelMatch || !suggestionMatch) {
|
|
532
|
-
return null;
|
|
533
|
-
}
|
|
534
|
-
return {
|
|
535
|
-
providerID: modelMatch[1].trim(),
|
|
536
|
-
modelID: modelMatch[2].trim(),
|
|
537
|
-
suggestion: suggestionMatch[1].trim()
|
|
538
|
-
};
|
|
423
|
+
function rpcPortFilePath(storageDir, directory, pid = process.pid, instanceId) {
|
|
424
|
+
const suffix = instanceId ? `-${instanceId}` : "";
|
|
425
|
+
return join(rpcPortDir(storageDir, directory), `port-${pid}${suffix}.json`);
|
|
539
426
|
}
|
|
540
|
-
|
|
541
|
-
if (
|
|
542
|
-
|
|
543
|
-
}
|
|
544
|
-
const controller = new AbortController;
|
|
545
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
546
|
-
const onExternalAbort = () => controller.abort();
|
|
547
|
-
signal?.addEventListener("abort", onExternalAbort);
|
|
548
|
-
try {
|
|
549
|
-
await client.session.prompt({
|
|
550
|
-
...args,
|
|
551
|
-
signal: controller.signal
|
|
552
|
-
});
|
|
553
|
-
} catch (error) {
|
|
554
|
-
if (signal?.aborted) {
|
|
555
|
-
await abortChildRun(client, args.path.id);
|
|
556
|
-
throw new Error("prompt aborted by external signal");
|
|
557
|
-
}
|
|
558
|
-
if (controller.signal.aborted) {
|
|
559
|
-
await abortChildRun(client, args.path.id);
|
|
560
|
-
throw new Error(`prompt timed out after ${timeoutMs}ms`);
|
|
561
|
-
}
|
|
562
|
-
throw error;
|
|
563
|
-
} finally {
|
|
564
|
-
clearTimeout(timeout);
|
|
565
|
-
signal?.removeEventListener("abort", onExternalAbort);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
async function abortChildRun(client, sessionId) {
|
|
427
|
+
function isPidAlive(pid) {
|
|
428
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
429
|
+
return false;
|
|
569
430
|
try {
|
|
570
|
-
|
|
571
|
-
client.session.abort({ path: { id: sessionId } }),
|
|
572
|
-
new Promise((resolve) => setTimeout(resolve, ABORT_CALL_TIMEOUT_MS))
|
|
573
|
-
]);
|
|
574
|
-
} catch (error) {
|
|
575
|
-
log(`[model-retry] child session abort failed for ${sessionId}: ${String(error)}`);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
function isNonRetryable(error, externalSignal) {
|
|
579
|
-
if (externalSignal?.aborted)
|
|
580
|
-
return true;
|
|
581
|
-
if (error instanceof Error) {
|
|
582
|
-
if (error.name === "AbortError")
|
|
583
|
-
return true;
|
|
584
|
-
if (error.message === "prompt aborted by external signal")
|
|
585
|
-
return true;
|
|
586
|
-
if (/^prompt timed out after \d+ms$/.test(error.message))
|
|
587
|
-
return true;
|
|
588
|
-
}
|
|
589
|
-
if (detectOverflow(error).isOverflow)
|
|
431
|
+
process.kill(pid, 0);
|
|
590
432
|
return true;
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
function shortErr(error) {
|
|
594
|
-
if (error instanceof Error) {
|
|
595
|
-
return error.name && error.name !== "Error" ? `${error.name}: ${error.message}` : error.message;
|
|
596
|
-
}
|
|
597
|
-
return extractMessage(error);
|
|
598
|
-
}
|
|
599
|
-
async function attemptOnce(client, args, timeoutMs, signal, callContext, label) {
|
|
600
|
-
const originalBody = { ...args.body };
|
|
601
|
-
const attemptArgs = copyPromptArgs(args, originalBody);
|
|
602
|
-
try {
|
|
603
|
-
await promptWithTimeout(client, attemptArgs, timeoutMs, signal);
|
|
604
|
-
return;
|
|
605
|
-
} catch (error) {
|
|
606
|
-
if (isNonRetryable(error, signal))
|
|
607
|
-
throw error;
|
|
608
|
-
const suggestion = parseModelSuggestion(error);
|
|
609
|
-
if (!suggestion || !originalBody.model) {
|
|
610
|
-
throw error;
|
|
611
|
-
}
|
|
612
|
-
log(`[${callContext}] ${label}: model not found, retrying with suggestion`, {
|
|
613
|
-
original: `${suggestion.providerID}/${suggestion.modelID}`,
|
|
614
|
-
suggested: suggestion.suggestion
|
|
615
|
-
});
|
|
616
|
-
await promptWithTimeout(client, copyPromptArgs(args, {
|
|
617
|
-
...originalBody,
|
|
618
|
-
model: {
|
|
619
|
-
providerID: suggestion.providerID,
|
|
620
|
-
modelID: suggestion.suggestion
|
|
621
|
-
}
|
|
622
|
-
}), timeoutMs, signal);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
|
|
626
|
-
const timeoutMs = options.timeoutMs ?? 300000;
|
|
627
|
-
const callContext = options.callContext ?? "subagent";
|
|
628
|
-
const fallbacks = options.fallbackModels ?? [];
|
|
629
|
-
const baseBody = { ...args.body };
|
|
630
|
-
const baseArgs = copyPromptArgs(args, baseBody);
|
|
631
|
-
const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
|
|
632
|
-
let lastError = null;
|
|
633
|
-
try {
|
|
634
|
-
await attemptOnce(client, baseArgs, timeoutMs, options.signal, callContext, explicitPrimaryLabel);
|
|
635
|
-
return;
|
|
636
|
-
} catch (error) {
|
|
637
|
-
lastError = error;
|
|
638
|
-
if (isNonRetryable(error, options.signal))
|
|
639
|
-
throw error;
|
|
640
|
-
if (fallbacks.length === 0) {
|
|
641
|
-
throw error;
|
|
642
|
-
}
|
|
643
|
-
log(`[${callContext}] primary (${explicitPrimaryLabel}) failed: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
|
|
644
|
-
}
|
|
645
|
-
for (let i = 0;i < fallbacks.length; i += 1) {
|
|
646
|
-
const parsed = parseProviderModel(fallbacks[i]);
|
|
647
|
-
if (!parsed) {
|
|
648
|
-
log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
|
|
649
|
-
continue;
|
|
650
|
-
}
|
|
651
|
-
const label = `${parsed.providerID}/${parsed.modelID}`;
|
|
652
|
-
const attemptArgs = copyPromptArgs(baseArgs, {
|
|
653
|
-
...baseBody,
|
|
654
|
-
model: parsed
|
|
655
|
-
});
|
|
656
|
-
try {
|
|
657
|
-
await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
|
|
658
|
-
log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
|
|
659
|
-
return;
|
|
660
|
-
} catch (error) {
|
|
661
|
-
lastError = error;
|
|
662
|
-
if (isNonRetryable(error, options.signal))
|
|
663
|
-
throw error;
|
|
664
|
-
const remaining = fallbacks.length - i - 1;
|
|
665
|
-
if (remaining > 0) {
|
|
666
|
-
log(`[${callContext}] ${label} failed: ${shortErr(error)}; ${remaining} fallback(s) left`);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
433
|
+
} catch (err) {
|
|
434
|
+
return err.code === "EPERM";
|
|
669
435
|
}
|
|
670
|
-
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; last error: ${shortErr(lastError)}`);
|
|
671
|
-
throw lastError ?? new Error("All fallback models failed");
|
|
672
436
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
}
|
|
679
|
-
async function promptSyncWithValidatedOutputRetry(client, args, options) {
|
|
680
|
-
const timeoutMs = options.timeoutMs ?? 300000;
|
|
681
|
-
const callContext = options.callContext ?? "subagent";
|
|
682
|
-
const fallbacks = options.fallbackModels ?? [];
|
|
683
|
-
const baseBody = { ...args.body };
|
|
684
|
-
const baseArgs = copyPromptArgs(args, baseBody);
|
|
685
|
-
const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
|
|
686
|
-
const totalAttempts = fallbacks.length + 1;
|
|
687
|
-
let firstError = null;
|
|
688
|
-
let lastError = null;
|
|
689
|
-
try {
|
|
690
|
-
return await attemptAndValidate(client, baseArgs, timeoutMs, options.signal, callContext, {
|
|
691
|
-
label: explicitPrimaryLabel,
|
|
692
|
-
attemptIndex: 0,
|
|
693
|
-
isFallback: false,
|
|
694
|
-
totalAttempts,
|
|
695
|
-
model: baseBody.model
|
|
696
|
-
}, options);
|
|
697
|
-
} catch (error) {
|
|
698
|
-
firstError = error;
|
|
699
|
-
lastError = error;
|
|
700
|
-
if (isNonRetryable(error, options.signal))
|
|
701
|
-
throw error;
|
|
702
|
-
if (fallbacks.length === 0) {
|
|
703
|
-
throw error;
|
|
704
|
-
}
|
|
705
|
-
log(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
|
|
706
|
-
}
|
|
707
|
-
for (let i = 0;i < fallbacks.length; i += 1) {
|
|
708
|
-
const parsed = parseProviderModel(fallbacks[i]);
|
|
709
|
-
if (!parsed) {
|
|
710
|
-
log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
|
|
711
|
-
continue;
|
|
712
|
-
}
|
|
713
|
-
const label = `${parsed.providerID}/${parsed.modelID}`;
|
|
714
|
-
const attemptArgs = copyPromptArgs(baseArgs, {
|
|
715
|
-
...baseBody,
|
|
716
|
-
model: parsed
|
|
717
|
-
});
|
|
718
|
-
const attempt = {
|
|
719
|
-
label,
|
|
720
|
-
attemptIndex: i + 1,
|
|
721
|
-
isFallback: true,
|
|
722
|
-
totalAttempts,
|
|
723
|
-
model: parsed
|
|
724
|
-
};
|
|
437
|
+
function parseRpcPortFile(content, fallbackPid = 0) {
|
|
438
|
+
const trimmed = content.trim();
|
|
439
|
+
if (!trimmed)
|
|
440
|
+
return null;
|
|
441
|
+
if (trimmed.startsWith("{")) {
|
|
725
442
|
try {
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
|
|
742
|
-
throw firstError ?? lastError ?? new Error("All fallback models failed validation");
|
|
743
|
-
}
|
|
744
|
-
// src/shared/normalize-sdk-response.ts
|
|
745
|
-
function normalizeSDKResponse(response, fallback, options) {
|
|
746
|
-
if (response === null || response === undefined) {
|
|
747
|
-
return fallback;
|
|
748
|
-
}
|
|
749
|
-
if (Array.isArray(response)) {
|
|
750
|
-
return response;
|
|
751
|
-
}
|
|
752
|
-
if (typeof response === "object" && "data" in response) {
|
|
753
|
-
const data = response.data;
|
|
754
|
-
if (data !== null && data !== undefined) {
|
|
755
|
-
return data;
|
|
756
|
-
}
|
|
757
|
-
if (options?.preferResponseOnMissingData === true) {
|
|
758
|
-
return response;
|
|
443
|
+
const parsed = JSON.parse(trimmed);
|
|
444
|
+
const port2 = Number(parsed.port);
|
|
445
|
+
const pid = Number(parsed.pid);
|
|
446
|
+
const startedAt = Number(parsed.started_at);
|
|
447
|
+
if (!isValidPort(port2) || !Number.isInteger(pid) || pid <= 0)
|
|
448
|
+
return null;
|
|
449
|
+
return {
|
|
450
|
+
port: port2,
|
|
451
|
+
pid,
|
|
452
|
+
started_at: Number.isFinite(startedAt) ? startedAt : 0,
|
|
453
|
+
token: typeof parsed.token === "string" ? parsed.token : undefined,
|
|
454
|
+
instance_id: typeof parsed.instance_id === "string" ? parsed.instance_id : undefined
|
|
455
|
+
};
|
|
456
|
+
} catch {
|
|
457
|
+
return null;
|
|
759
458
|
}
|
|
760
|
-
return fallback;
|
|
761
|
-
}
|
|
762
|
-
if (options?.preferResponseOnMissingData === true) {
|
|
763
|
-
return response;
|
|
764
459
|
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
// src/shared/assistant-message-extractor.ts
|
|
768
|
-
function asSessionMessage(value) {
|
|
769
|
-
if (!isRecord(value))
|
|
460
|
+
const port = Number.parseInt(trimmed, 10);
|
|
461
|
+
if (!isValidPort(port))
|
|
770
462
|
return null;
|
|
771
|
-
|
|
772
|
-
const parts = value.parts;
|
|
773
|
-
return {
|
|
774
|
-
info: isRecord(info) ? {
|
|
775
|
-
role: typeof info.role === "string" ? info.role : undefined,
|
|
776
|
-
time: isRecord(info.time) ? {
|
|
777
|
-
created: typeof info.time.created === "number" ? info.time.created : undefined
|
|
778
|
-
} : undefined
|
|
779
|
-
} : undefined,
|
|
780
|
-
parts
|
|
781
|
-
};
|
|
463
|
+
return { port, pid: fallbackPid, started_at: 0 };
|
|
782
464
|
}
|
|
783
|
-
function
|
|
784
|
-
return
|
|
785
|
-
}
|
|
786
|
-
function getTextParts(message) {
|
|
787
|
-
if (!Array.isArray(message.parts))
|
|
788
|
-
return [];
|
|
789
|
-
return message.parts.filter((part) => isRecord(part)).map((part) => ({
|
|
790
|
-
type: typeof part.type === "string" ? part.type : undefined,
|
|
791
|
-
text: typeof part.text === "string" ? part.text : undefined
|
|
792
|
-
})).filter((part) => part.type === "text" && Boolean(part.text));
|
|
793
|
-
}
|
|
794
|
-
function extractLatestAssistantText(messages) {
|
|
795
|
-
if (!Array.isArray(messages) || messages.length === 0)
|
|
796
|
-
return null;
|
|
797
|
-
const assistantMessages = messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a));
|
|
798
|
-
const latest = assistantMessages[0];
|
|
799
|
-
if (!latest)
|
|
800
|
-
return null;
|
|
801
|
-
return getTextParts(latest).map((part) => part.text).join(`
|
|
802
|
-
`) || null;
|
|
803
|
-
}
|
|
804
|
-
function hasLengthCappedOutput(value) {
|
|
805
|
-
if (Array.isArray(value))
|
|
806
|
-
return value.some((item) => hasLengthCappedOutput(item));
|
|
807
|
-
if (!isRecord(value))
|
|
808
|
-
return false;
|
|
809
|
-
if (value.length_capped === true || value.lengthCapped === true)
|
|
810
|
-
return true;
|
|
811
|
-
const finishReason = value.finish_reason ?? value.finishReason;
|
|
812
|
-
if (typeof finishReason === "string") {
|
|
813
|
-
const normalized = finishReason.toLowerCase();
|
|
814
|
-
if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
|
|
815
|
-
return true;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
return Object.values(value).some((item) => hasLengthCappedOutput(item));
|
|
465
|
+
function isValidPort(port) {
|
|
466
|
+
return Number.isInteger(port) && port > 0 && port <= 65535;
|
|
819
467
|
}
|
|
820
468
|
|
|
821
|
-
// src/shared/keep-subagents.ts
|
|
822
|
-
var keepSubagents = false;
|
|
823
|
-
function setKeepSubagents(value) {
|
|
824
|
-
keepSubagents = value === true;
|
|
825
|
-
}
|
|
826
|
-
function shouldKeepSubagents() {
|
|
827
|
-
return keepSubagents;
|
|
828
|
-
}
|
|
829
469
|
// src/features/magic-context/context-authority.ts
|
|
830
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
470
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
831
471
|
var AUTHORITY_DOMAINS = ["memories", "notes"];
|
|
832
472
|
var moduleNoteEvaluationBridges = new Map;
|
|
833
473
|
function registerModuleNoteEvaluationBridge(projectPath, bridge) {
|
|
@@ -959,7 +599,7 @@ function checksumAuthoritySeedRows(rows) {
|
|
|
959
599
|
const rightId = seedSourceRowId(right) ?? Number.MAX_SAFE_INTEGER;
|
|
960
600
|
return leftId - rightId;
|
|
961
601
|
});
|
|
962
|
-
return
|
|
602
|
+
return createHash2("sha256").update(JSON.stringify(ordered.map(canonicalizeSeedValue))).digest("hex");
|
|
963
603
|
}
|
|
964
604
|
function maxDomainRowId(db, domain, projectPath) {
|
|
965
605
|
const row = domain === "memories" ? db.prepare("SELECT COALESCE(MAX(rowid), 0) AS max_rowid FROM memories WHERE project_path = ?").get(projectPath) : db.prepare(`SELECT COALESCE(MAX(n.rowid), 0) AS max_rowid
|
|
@@ -1047,10 +687,14 @@ async function prepareAuthority(args) {
|
|
|
1047
687
|
domain,
|
|
1048
688
|
rows: page
|
|
1049
689
|
});
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1052
|
-
sourceRowId
|
|
1053
|
-
|
|
690
|
+
const identityByModuleRowId = new Map;
|
|
691
|
+
for (const [index, moduleRowId] of (seedResponse.module_row_ids ?? []).entries()) {
|
|
692
|
+
const sourceRowId = seedSourceRowId(page[index]);
|
|
693
|
+
if (sourceRowId === null)
|
|
694
|
+
continue;
|
|
695
|
+
identityByModuleRowId.set(moduleRowId, { moduleRowId, sourceRowId });
|
|
696
|
+
}
|
|
697
|
+
const identities = [...identityByModuleRowId.values()];
|
|
1054
698
|
if (identities.length > 0) {
|
|
1055
699
|
args.db.transaction(() => {
|
|
1056
700
|
for (const identity of identities) {
|
|
@@ -1951,6 +1595,7 @@ function pullMemoryMirrorOnce(args) {
|
|
|
1951
1595
|
mirrorFlights.set(args.module, flight);
|
|
1952
1596
|
return flight;
|
|
1953
1597
|
}
|
|
1598
|
+
|
|
1954
1599
|
// src/hooks/magic-context/compartment-parser.ts
|
|
1955
1600
|
var COMPARTMENT_REGEX = /<compartment\s+([^>]*?)\s*>(.*?)<\/compartment>/gs;
|
|
1956
1601
|
var ATTR_START_REGEX = /\bstart="(\d+)"/;
|
|
@@ -2221,7 +1866,7 @@ function healMissingMemoryBlockIds(db, columns) {
|
|
|
2221
1866
|
}
|
|
2222
1867
|
|
|
2223
1868
|
// src/features/magic-context/workspaces.ts
|
|
2224
|
-
import { createHash as
|
|
1869
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
2225
1870
|
|
|
2226
1871
|
// src/features/magic-context/memory/constants.ts
|
|
2227
1872
|
var V2_MEMORY_CATEGORIES = [
|
|
@@ -2275,7 +1920,7 @@ var CATEGORY_DEFAULT_TTL = {
|
|
|
2275
1920
|
|
|
2276
1921
|
// src/features/magic-context/memory/project-identity.ts
|
|
2277
1922
|
import { execFileSync } from "node:child_process";
|
|
2278
|
-
import { createHash as
|
|
1923
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
2279
1924
|
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
2280
1925
|
import { homedir } from "node:os";
|
|
2281
1926
|
import path from "node:path";
|
|
@@ -2290,6 +1935,7 @@ var dubiousOwnershipLoggedDirectories = new Set;
|
|
|
2290
1935
|
var dubiousOwnershipWarnedDirectories = new Set;
|
|
2291
1936
|
var transientGitIdentityReuseLoggedDirectories = new Set;
|
|
2292
1937
|
var execFileSyncForIdentity = execFileSync;
|
|
1938
|
+
var userHomeDirectoryForIdentity = () => homedir();
|
|
2293
1939
|
var nowMs = () => Date.now();
|
|
2294
1940
|
|
|
2295
1941
|
class ProjectIdentityError extends Error {
|
|
@@ -2343,7 +1989,7 @@ function getErrorStderr(error) {
|
|
|
2343
1989
|
}
|
|
2344
1990
|
function directoryFallback(directory) {
|
|
2345
1991
|
const canonical = path.resolve(directory);
|
|
2346
|
-
const hash =
|
|
1992
|
+
const hash = createHash3("md5").update(canonical, "utf8").digest("hex").slice(0, 12);
|
|
2347
1993
|
return `dir:${hash}`;
|
|
2348
1994
|
}
|
|
2349
1995
|
function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
|
|
@@ -2494,9 +2140,12 @@ function takeDubiousOwnershipProjectIdentityWarning(directory) {
|
|
|
2494
2140
|
dubiousOwnershipWarnedDirectories.add(canonical);
|
|
2495
2141
|
return formatDubiousOwnershipWarning(canonical);
|
|
2496
2142
|
}
|
|
2143
|
+
function canonicalUserHomeDirectory() {
|
|
2144
|
+
return realpathSync.native(userHomeDirectoryForIdentity());
|
|
2145
|
+
}
|
|
2497
2146
|
function isUserHomeDirectory(directory) {
|
|
2498
2147
|
try {
|
|
2499
|
-
return realpathSync.native(path.resolve(directory)) ===
|
|
2148
|
+
return realpathSync.native(path.resolve(directory)) === canonicalUserHomeDirectory();
|
|
2500
2149
|
} catch {
|
|
2501
2150
|
return false;
|
|
2502
2151
|
}
|
|
@@ -2565,22 +2214,52 @@ function hasGitDir(canonical) {
|
|
|
2565
2214
|
return false;
|
|
2566
2215
|
}
|
|
2567
2216
|
}
|
|
2568
|
-
function
|
|
2217
|
+
function gitRootInAncestorChain(startDirectory) {
|
|
2569
2218
|
let current = startDirectory;
|
|
2570
2219
|
while (true) {
|
|
2571
2220
|
if (existsSync(path.join(current, ".git"))) {
|
|
2572
|
-
|
|
2221
|
+
try {
|
|
2222
|
+
return realpathSync.native(current);
|
|
2223
|
+
} catch {
|
|
2224
|
+
return path.resolve(current);
|
|
2225
|
+
}
|
|
2573
2226
|
}
|
|
2574
2227
|
const parent = path.dirname(current);
|
|
2575
2228
|
if (parent === current) {
|
|
2576
|
-
return
|
|
2229
|
+
return null;
|
|
2577
2230
|
}
|
|
2578
2231
|
current = parent;
|
|
2579
2232
|
}
|
|
2580
2233
|
}
|
|
2581
|
-
function
|
|
2582
|
-
|
|
2583
|
-
|
|
2234
|
+
function hasGitDirInAncestorChain(startDirectory) {
|
|
2235
|
+
return gitRootInAncestorChain(startDirectory) !== null;
|
|
2236
|
+
}
|
|
2237
|
+
function gitRootDirectory(canonical) {
|
|
2238
|
+
const direct = gitRootInAncestorChain(canonical);
|
|
2239
|
+
if (direct)
|
|
2240
|
+
return direct;
|
|
2241
|
+
try {
|
|
2242
|
+
const realCanonical = realpathSync.native(canonical);
|
|
2243
|
+
return realCanonical === canonical ? null : gitRootInAncestorChain(realCanonical);
|
|
2244
|
+
} catch {
|
|
2245
|
+
return null;
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
function resolveProjectIdentityForSession(directory, allowHomeProject = false) {
|
|
2249
|
+
const canonicalHome = canonicalUserHomeDirectory();
|
|
2250
|
+
const canonicalDirectory = (() => {
|
|
2251
|
+
try {
|
|
2252
|
+
return realpathSync.native(path.resolve(directory));
|
|
2253
|
+
} catch {
|
|
2254
|
+
return path.resolve(directory);
|
|
2255
|
+
}
|
|
2256
|
+
})();
|
|
2257
|
+
const inheritsHomeRepository = gitRootDirectory(canonicalDirectory) === canonicalHome;
|
|
2258
|
+
if (canonicalDirectory === canonicalHome || inheritsHomeRepository) {
|
|
2259
|
+
if (!allowHomeProject)
|
|
2260
|
+
return;
|
|
2261
|
+
return directoryFallback(canonicalHome);
|
|
2262
|
+
}
|
|
2584
2263
|
return resolveProjectIdentityOrFallback(directory);
|
|
2585
2264
|
}
|
|
2586
2265
|
function normalizeStoredProjectPath(rawOrStored) {
|
|
@@ -2782,7 +2461,7 @@ function computeWorkspaceEpochFingerprint(db, identities) {
|
|
|
2782
2461
|
const canonical = uniqueSorted(identities.filter((identity) => identity.length > 0));
|
|
2783
2462
|
const epochs = getEpochMap(db, canonical);
|
|
2784
2463
|
const shareCategories = selectWorkspaceShareCategories(db, canonical);
|
|
2785
|
-
const hash =
|
|
2464
|
+
const hash = createHash4("sha256");
|
|
2786
2465
|
hash.update("share_categories", "utf8");
|
|
2787
2466
|
hash.update("\x00");
|
|
2788
2467
|
hash.update(shareCategories === null ? "NO_WORKSPACE" : JSON.stringify(shareCategories), "utf8");
|
|
@@ -4869,6 +4548,33 @@ var MIGRATIONS = [
|
|
|
4869
4548
|
up(db) {
|
|
4870
4549
|
installLatestAuthorityTriggers(db);
|
|
4871
4550
|
}
|
|
4551
|
+
},
|
|
4552
|
+
{
|
|
4553
|
+
version: 72,
|
|
4554
|
+
description: "add per-session compaction mode record column (issue #266)",
|
|
4555
|
+
up(db) {
|
|
4556
|
+
if (tableExists2(db, "session_meta")) {
|
|
4557
|
+
ensureColumn(db, "session_meta", "compaction_mode_record", "TEXT");
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
},
|
|
4561
|
+
{
|
|
4562
|
+
version: 73,
|
|
4563
|
+
description: "persist the last successful todowrite permission verdict",
|
|
4564
|
+
up(db) {
|
|
4565
|
+
if (tableExists2(db, "session_meta")) {
|
|
4566
|
+
ensureColumn(db, "session_meta", "todo_permission_denied", "INTEGER NOT NULL DEFAULT 2");
|
|
4567
|
+
}
|
|
4568
|
+
}
|
|
4569
|
+
},
|
|
4570
|
+
{
|
|
4571
|
+
version: 74,
|
|
4572
|
+
description: "persist detected context-limit provenance",
|
|
4573
|
+
up(db) {
|
|
4574
|
+
if (tableExists2(db, "session_meta")) {
|
|
4575
|
+
ensureColumn(db, "session_meta", "detected_context_limit_provenance", "TEXT NOT NULL DEFAULT 'unknown'");
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4872
4578
|
}
|
|
4873
4579
|
];
|
|
4874
4580
|
var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
|
|
@@ -4978,151 +4684,6 @@ async function runMigrationsWithRetry(db, options = {}) {
|
|
|
4978
4684
|
}
|
|
4979
4685
|
}
|
|
4980
4686
|
}
|
|
4981
|
-
// src/features/magic-context/project-docs-hash.ts
|
|
4982
|
-
import { createHash as createHash4 } from "node:crypto";
|
|
4983
|
-
import { lstatSync, readFileSync, statSync as statSync2 } from "node:fs";
|
|
4984
|
-
import path2 from "node:path";
|
|
4985
|
-
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
4986
|
-
var PROJECT_DOCS_DELIMITER = `
|
|
4987
|
-
|
|
4988
|
-
---
|
|
4989
|
-
|
|
4990
|
-
`;
|
|
4991
|
-
var MAX_PROJECT_DOC_BYTES = 256 * 1024;
|
|
4992
|
-
var docsCache = new Map;
|
|
4993
|
-
function canonicalizeDocContent(raw) {
|
|
4994
|
-
return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
|
|
4995
|
-
`).split(`
|
|
4996
|
-
`).map((line) => line.replace(/[ \t]+$/, "")).join(`
|
|
4997
|
-
`).replace(/\n+$/, "");
|
|
4998
|
-
}
|
|
4999
|
-
function fingerprintFile(filePath) {
|
|
5000
|
-
try {
|
|
5001
|
-
const stat = lstatSync(filePath);
|
|
5002
|
-
const isReadableDoc = stat.isFile() && stat.size <= MAX_PROJECT_DOC_BYTES;
|
|
5003
|
-
return {
|
|
5004
|
-
exists: isReadableDoc,
|
|
5005
|
-
mtimeMs: stat.mtimeMs,
|
|
5006
|
-
size: stat.size
|
|
5007
|
-
};
|
|
5008
|
-
} catch {
|
|
5009
|
-
return { exists: false, mtimeMs: 0, size: 0 };
|
|
5010
|
-
}
|
|
5011
|
-
}
|
|
5012
|
-
function readDirectoryMtimeMs(projectDirectory) {
|
|
5013
|
-
try {
|
|
5014
|
-
return statSync2(projectDirectory).mtimeMs;
|
|
5015
|
-
} catch {
|
|
5016
|
-
return 0;
|
|
5017
|
-
}
|
|
5018
|
-
}
|
|
5019
|
-
function fingerprintsEqual(a, b) {
|
|
5020
|
-
return a?.exists === b.exists && a.mtimeMs === b.mtimeMs && a.size === b.size;
|
|
5021
|
-
}
|
|
5022
|
-
function cacheFilesEqual(cachedFiles, currentFiles) {
|
|
5023
|
-
for (const [filePath, current] of currentFiles) {
|
|
5024
|
-
if (!fingerprintsEqual(cachedFiles.get(filePath), current)) {
|
|
5025
|
-
return false;
|
|
5026
|
-
}
|
|
5027
|
-
}
|
|
5028
|
-
return true;
|
|
5029
|
-
}
|
|
5030
|
-
function readCurrentFingerprints(projectDirectory) {
|
|
5031
|
-
const files = new Map;
|
|
5032
|
-
for (const filename of PROJECT_DOC_FILES) {
|
|
5033
|
-
const filePath = path2.join(projectDirectory, filename);
|
|
5034
|
-
files.set(filePath, fingerprintFile(filePath));
|
|
5035
|
-
}
|
|
5036
|
-
return { directoryMtimeMs: readDirectoryMtimeMs(projectDirectory), files };
|
|
5037
|
-
}
|
|
5038
|
-
function readCanonicalPieces(projectDirectory, files) {
|
|
5039
|
-
const hashPieces = [];
|
|
5040
|
-
const renderedSections = [];
|
|
5041
|
-
for (const filename of PROJECT_DOC_FILES) {
|
|
5042
|
-
const filePath = path2.join(projectDirectory, filename);
|
|
5043
|
-
const fingerprint = files.get(filePath);
|
|
5044
|
-
if (!fingerprint?.exists) {
|
|
5045
|
-
continue;
|
|
5046
|
-
}
|
|
5047
|
-
let safeToRead = false;
|
|
5048
|
-
try {
|
|
5049
|
-
const st = lstatSync(filePath);
|
|
5050
|
-
safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
|
|
5051
|
-
} catch {
|
|
5052
|
-
safeToRead = false;
|
|
5053
|
-
}
|
|
5054
|
-
if (!safeToRead) {
|
|
5055
|
-
continue;
|
|
5056
|
-
}
|
|
5057
|
-
const canonicalContent = canonicalizeDocContent(readFileSync(filePath, "utf8"));
|
|
5058
|
-
hashPieces.push(`file:${filename}
|
|
5059
|
-
${canonicalContent}`);
|
|
5060
|
-
renderedSections.push(`<file name="${escapeXmlAttr(filename)}">
|
|
5061
|
-
${escapeXmlContent(canonicalContent)}
|
|
5062
|
-
</file>`);
|
|
5063
|
-
}
|
|
5064
|
-
return { hashPieces, renderedSections };
|
|
5065
|
-
}
|
|
5066
|
-
function buildRenderedBlock(renderedSections) {
|
|
5067
|
-
if (renderedSections.length === 0) {
|
|
5068
|
-
return "";
|
|
5069
|
-
}
|
|
5070
|
-
return `<project-docs>
|
|
5071
|
-
${renderedSections.join(`
|
|
5072
|
-
|
|
5073
|
-
`)}
|
|
5074
|
-
</project-docs>`;
|
|
5075
|
-
}
|
|
5076
|
-
function hashCanonicalPieces(hashPieces) {
|
|
5077
|
-
if (hashPieces.length === 0) {
|
|
5078
|
-
return "";
|
|
5079
|
-
}
|
|
5080
|
-
return createHash4("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
|
|
5081
|
-
}
|
|
5082
|
-
function readProjectDocsCanonical(projectDirectory) {
|
|
5083
|
-
const canonicalDirectory = path2.resolve(projectDirectory);
|
|
5084
|
-
const current = readCurrentFingerprints(canonicalDirectory);
|
|
5085
|
-
const cached = docsCache.get(canonicalDirectory);
|
|
5086
|
-
if (cached && cacheFilesEqual(cached.files, current.files)) {
|
|
5087
|
-
cached.directoryMtimeMs = current.directoryMtimeMs;
|
|
5088
|
-
return {
|
|
5089
|
-
renderedBlock: cached.cachedRendered,
|
|
5090
|
-
canonicalHash: cached.cachedHash
|
|
5091
|
-
};
|
|
5092
|
-
}
|
|
5093
|
-
const { hashPieces, renderedSections } = readCanonicalPieces(canonicalDirectory, current.files);
|
|
5094
|
-
const canonicalHash = hashCanonicalPieces(hashPieces);
|
|
5095
|
-
const renderedBlock = buildRenderedBlock(renderedSections);
|
|
5096
|
-
docsCache.set(canonicalDirectory, {
|
|
5097
|
-
directoryMtimeMs: current.directoryMtimeMs,
|
|
5098
|
-
files: current.files,
|
|
5099
|
-
cachedHash: canonicalHash,
|
|
5100
|
-
cachedRendered: renderedBlock
|
|
5101
|
-
});
|
|
5102
|
-
return { renderedBlock, canonicalHash };
|
|
5103
|
-
}
|
|
5104
|
-
function computeProjectDocsHash(projectDirectory) {
|
|
5105
|
-
return readProjectDocsCanonical(projectDirectory).canonicalHash;
|
|
5106
|
-
}
|
|
5107
|
-
// src/features/magic-context/storage-db.ts
|
|
5108
|
-
import { chmodSync, copyFileSync, cpSync, existsSync as existsSync3, mkdirSync, mkdtempSync } from "node:fs";
|
|
5109
|
-
import { dirname, join as join2 } from "node:path";
|
|
5110
|
-
|
|
5111
|
-
// src/plugin/boot-quiet.ts
|
|
5112
|
-
var BOOT_QUIET_MS = 120000;
|
|
5113
|
-
var bootQuietUntilMs = 0;
|
|
5114
|
-
function beginBootQuietPeriod(now = Date.now()) {
|
|
5115
|
-
if (bootQuietUntilMs === 0)
|
|
5116
|
-
bootQuietUntilMs = now + BOOT_QUIET_MS;
|
|
5117
|
-
}
|
|
5118
|
-
function bootQuietRemainingMs(now = Date.now()) {
|
|
5119
|
-
return Math.max(0, bootQuietUntilMs - now);
|
|
5120
|
-
}
|
|
5121
|
-
function scheduleAfterBootQuiet(task, additionalDelayMs = 0) {
|
|
5122
|
-
const timer = setTimeout(task, bootQuietRemainingMs() + Math.max(0, additionalDelayMs));
|
|
5123
|
-
timer.unref?.();
|
|
5124
|
-
return timer;
|
|
5125
|
-
}
|
|
5126
4687
|
|
|
5127
4688
|
// src/features/magic-context/tool-definition-tokens.ts
|
|
5128
4689
|
import { createHash as createHash5 } from "node:crypto";
|
|
@@ -5236,11 +4797,11 @@ function getMeasuredToolDefinitionTokens(providerID, modelID, agentName) {
|
|
|
5236
4797
|
|
|
5237
4798
|
// src/features/magic-context/tool-owner-backfill.ts
|
|
5238
4799
|
import { existsSync as existsSync2 } from "node:fs";
|
|
5239
|
-
import { join } from "node:path";
|
|
4800
|
+
import { join as join2 } from "node:path";
|
|
5240
4801
|
var LEASE_DURATION_MS = 5 * 60 * 1000;
|
|
5241
4802
|
var LEASE_RENEWAL_MS = 60 * 1000;
|
|
5242
4803
|
function resolveOpencodeDbPath() {
|
|
5243
|
-
return
|
|
4804
|
+
return join2(getDataDir(), "opencode", "opencode.db");
|
|
5244
4805
|
}
|
|
5245
4806
|
function ensureBackfillStateTable(db) {
|
|
5246
4807
|
db.exec(`
|
|
@@ -5495,30 +5056,40 @@ var persistenceByDatabase = new WeakMap;
|
|
|
5495
5056
|
var persistenceErrorByDatabase = new WeakMap;
|
|
5496
5057
|
var pathByDatabase = new WeakMap;
|
|
5497
5058
|
var lastSchemaFenceRejection = null;
|
|
5059
|
+
var lastMigrationOnOpenRefusal = null;
|
|
5498
5060
|
function getSchemaFenceRejection() {
|
|
5499
5061
|
return lastSchemaFenceRejection;
|
|
5500
5062
|
}
|
|
5501
|
-
|
|
5063
|
+
function getMigrationOnOpenRefusal() {
|
|
5064
|
+
return lastMigrationOnOpenRefusal;
|
|
5065
|
+
}
|
|
5066
|
+
var LATEST_SUPPORTED_VERSION = 74;
|
|
5502
5067
|
var PERMISSIONS_ENFORCEABLE = process.platform !== "win32";
|
|
5068
|
+
var defaultStoragePermissionFs = { chmodSync, mkdirSync };
|
|
5069
|
+
var storagePermissionFs = defaultStoragePermissionFs;
|
|
5503
5070
|
function ensureSecureStorageDir(dir) {
|
|
5504
|
-
|
|
5071
|
+
if (!shouldEnforcePrivateStoragePermissions()) {
|
|
5072
|
+
storagePermissionFs.mkdirSync(dir, { recursive: true });
|
|
5073
|
+
return;
|
|
5074
|
+
}
|
|
5075
|
+
storagePermissionFs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
5505
5076
|
if (!PERMISSIONS_ENFORCEABLE)
|
|
5506
5077
|
return;
|
|
5507
5078
|
try {
|
|
5508
|
-
chmodSync(dir, 448);
|
|
5079
|
+
storagePermissionFs.chmodSync(dir, 448);
|
|
5509
5080
|
} catch (error) {
|
|
5510
5081
|
log(`[magic-context] could not restrict storage dir permissions on ${dir}: ${getErrorMessage(error)}`);
|
|
5511
5082
|
}
|
|
5512
5083
|
}
|
|
5513
5084
|
function restrictDatabaseFilePermissions(dbPath) {
|
|
5514
|
-
if (!PERMISSIONS_ENFORCEABLE)
|
|
5085
|
+
if (!PERMISSIONS_ENFORCEABLE || !shouldEnforcePrivateStoragePermissions())
|
|
5515
5086
|
return;
|
|
5516
5087
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
5517
5088
|
const file = `${dbPath}${suffix}`;
|
|
5518
5089
|
if (!existsSync3(file))
|
|
5519
5090
|
continue;
|
|
5520
5091
|
try {
|
|
5521
|
-
chmodSync(file, 384);
|
|
5092
|
+
storagePermissionFs.chmodSync(file, 384);
|
|
5522
5093
|
} catch (error) {
|
|
5523
5094
|
log(`[magic-context] could not restrict DB file permissions on ${file}: ${getErrorMessage(error)}`);
|
|
5524
5095
|
}
|
|
@@ -5530,12 +5101,12 @@ function resolveDatabasePath(dbPathOverride) {
|
|
|
5530
5101
|
}
|
|
5531
5102
|
const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
|
|
5532
5103
|
if (testDataDir && !process.env.XDG_DATA_HOME) {
|
|
5533
|
-
const dbDir2 =
|
|
5534
|
-
return { dbDir: dbDir2, dbPath:
|
|
5104
|
+
const dbDir2 = join3(testDataDir, "cortexkit", "magic-context");
|
|
5105
|
+
return { dbDir: dbDir2, dbPath: join3(dbDir2, "context.db") };
|
|
5535
5106
|
}
|
|
5536
5107
|
if (false) {}
|
|
5537
5108
|
const dbDir = getMagicContextStorageDir();
|
|
5538
|
-
return { dbDir, dbPath:
|
|
5109
|
+
return { dbDir, dbPath: join3(dbDir, "context.db") };
|
|
5539
5110
|
}
|
|
5540
5111
|
function getDatabasePath(db) {
|
|
5541
5112
|
return pathByDatabase.get(db) ?? null;
|
|
@@ -5544,7 +5115,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
5544
5115
|
if (existsSync3(targetDbPath))
|
|
5545
5116
|
return;
|
|
5546
5117
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
5547
|
-
const legacyDbPath =
|
|
5118
|
+
const legacyDbPath = join3(legacyDir, "context.db");
|
|
5548
5119
|
if (!existsSync3(legacyDbPath))
|
|
5549
5120
|
return;
|
|
5550
5121
|
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
@@ -5561,7 +5132,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
5561
5132
|
}
|
|
5562
5133
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
5563
5134
|
const src = `${legacyDbPath}${suffix}`;
|
|
5564
|
-
const dst =
|
|
5135
|
+
const dst = join3(targetDbDir, `context.db${suffix}`);
|
|
5565
5136
|
if (existsSync3(src)) {
|
|
5566
5137
|
try {
|
|
5567
5138
|
copyFileSync(src, dst);
|
|
@@ -5570,8 +5141,8 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
5570
5141
|
}
|
|
5571
5142
|
}
|
|
5572
5143
|
}
|
|
5573
|
-
const legacyModelsDir =
|
|
5574
|
-
const targetModelsDir =
|
|
5144
|
+
const legacyModelsDir = join3(legacyDir, "models");
|
|
5145
|
+
const targetModelsDir = join3(targetDbDir, "models");
|
|
5575
5146
|
if (existsSync3(legacyModelsDir) && !existsSync3(targetModelsDir)) {
|
|
5576
5147
|
try {
|
|
5577
5148
|
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
@@ -5588,6 +5159,9 @@ function getPersistedSchemaVersion(db) {
|
|
|
5588
5159
|
const row = db.prepare("SELECT MAX(version) AS version FROM schema_migrations").get();
|
|
5589
5160
|
return row?.version ?? 0;
|
|
5590
5161
|
}
|
|
5162
|
+
function formatSchemaFenceBootLog(persistedVersion, supportedVersion) {
|
|
5163
|
+
return `[magic-context] storage schema at boot: database=v${persistedVersion}, supported_fence=v${supportedVersion}`;
|
|
5164
|
+
}
|
|
5591
5165
|
function getRuntimeLatestSupportedVersion(options) {
|
|
5592
5166
|
if (options?.latestSupportedVersion !== undefined) {
|
|
5593
5167
|
return options.latestSupportedVersion;
|
|
@@ -5604,12 +5178,109 @@ function getRuntimeLatestSupportedVersion(options) {
|
|
|
5604
5178
|
function enforceSchemaFence(db, dbPath, latestSupportedVersion) {
|
|
5605
5179
|
const persistedVersion = getPersistedSchemaVersion(db);
|
|
5606
5180
|
if (persistedVersion <= latestSupportedVersion) {
|
|
5181
|
+
lastSchemaFenceRejection = null;
|
|
5607
5182
|
return true;
|
|
5608
5183
|
}
|
|
5609
5184
|
lastSchemaFenceRejection = { persistedVersion, supportedVersion: latestSupportedVersion };
|
|
5610
5185
|
log(`[magic-context] storage fatal: refusing to open ${dbPath}; database schema v${persistedVersion} is newer than this binary supports (max v${latestSupportedVersion}). A pinned or stale plugin is likely sharing this database with a newer instance; update or unpin Magic Context with 'npx @cortexkit/magic-context@latest doctor --force', then restart.`);
|
|
5611
5186
|
return false;
|
|
5612
5187
|
}
|
|
5188
|
+
function unreadableDiscovery(path2) {
|
|
5189
|
+
return {
|
|
5190
|
+
state: "unreadable",
|
|
5191
|
+
serverPids: [],
|
|
5192
|
+
staleFiles: [],
|
|
5193
|
+
unreadableFile: path2
|
|
5194
|
+
};
|
|
5195
|
+
}
|
|
5196
|
+
function inspectRpcServerDiscovery(storageDir) {
|
|
5197
|
+
const rpcRoot = join3(storageDir, "rpc");
|
|
5198
|
+
let projectEntries;
|
|
5199
|
+
try {
|
|
5200
|
+
projectEntries = readdirSync(rpcRoot, { withFileTypes: true });
|
|
5201
|
+
} catch (error) {
|
|
5202
|
+
if (error.code === "ENOENT") {
|
|
5203
|
+
return { state: "absent", serverPids: [], staleFiles: [] };
|
|
5204
|
+
}
|
|
5205
|
+
return unreadableDiscovery(rpcRoot);
|
|
5206
|
+
}
|
|
5207
|
+
const portFiles = [];
|
|
5208
|
+
for (const projectEntry of projectEntries) {
|
|
5209
|
+
if (!projectEntry.isDirectory())
|
|
5210
|
+
continue;
|
|
5211
|
+
const projectDir = join3(rpcRoot, projectEntry.name);
|
|
5212
|
+
let entries;
|
|
5213
|
+
try {
|
|
5214
|
+
entries = readdirSync(projectDir);
|
|
5215
|
+
} catch {
|
|
5216
|
+
return unreadableDiscovery(projectDir);
|
|
5217
|
+
}
|
|
5218
|
+
for (const entry of entries) {
|
|
5219
|
+
if (entry === "port" || entry.startsWith("port-") && entry.endsWith(".json")) {
|
|
5220
|
+
portFiles.push(join3(projectDir, entry));
|
|
5221
|
+
}
|
|
5222
|
+
}
|
|
5223
|
+
}
|
|
5224
|
+
if (portFiles.length === 0) {
|
|
5225
|
+
return { state: "absent", serverPids: [], staleFiles: [] };
|
|
5226
|
+
}
|
|
5227
|
+
const pids = new Set;
|
|
5228
|
+
const staleFiles = [];
|
|
5229
|
+
for (const portFile of portFiles) {
|
|
5230
|
+
let raw;
|
|
5231
|
+
try {
|
|
5232
|
+
raw = readFileSync(portFile, "utf8");
|
|
5233
|
+
} catch {
|
|
5234
|
+
return unreadableDiscovery(portFile);
|
|
5235
|
+
}
|
|
5236
|
+
const filename = basename(portFile);
|
|
5237
|
+
const pidFromName = /^port-(\d+)/.exec(filename)?.[1];
|
|
5238
|
+
const record = parseRpcPortFile(raw, pidFromName ? Number(pidFromName) : 0);
|
|
5239
|
+
if (!record || !Number.isInteger(record.pid) || record.pid <= 0) {
|
|
5240
|
+
return unreadableDiscovery(portFile);
|
|
5241
|
+
}
|
|
5242
|
+
if (isPidAlive(record.pid))
|
|
5243
|
+
pids.add(record.pid);
|
|
5244
|
+
else
|
|
5245
|
+
staleFiles.push(portFile);
|
|
5246
|
+
}
|
|
5247
|
+
const serverPids = [...pids].sort((a, b) => a - b);
|
|
5248
|
+
if (serverPids.length > 0) {
|
|
5249
|
+
return { state: "live", serverPids, staleFiles };
|
|
5250
|
+
}
|
|
5251
|
+
for (const staleFile of staleFiles) {
|
|
5252
|
+
try {
|
|
5253
|
+
unlinkSync(staleFile);
|
|
5254
|
+
} catch {
|
|
5255
|
+
return unreadableDiscovery(staleFile);
|
|
5256
|
+
}
|
|
5257
|
+
}
|
|
5258
|
+
return { state: "stale", serverPids: [], staleFiles };
|
|
5259
|
+
}
|
|
5260
|
+
function enforceMigrationOnOpenGuard(db, dbPath, dbDir, latestSupportedVersion) {
|
|
5261
|
+
const persistedVersion = getPersistedSchemaVersion(db);
|
|
5262
|
+
if (persistedVersion >= latestSupportedVersion) {
|
|
5263
|
+
lastMigrationOnOpenRefusal = null;
|
|
5264
|
+
return true;
|
|
5265
|
+
}
|
|
5266
|
+
const discovery = inspectRpcServerDiscovery(dbDir);
|
|
5267
|
+
if (discovery.state === "absent" || discovery.state === "stale") {
|
|
5268
|
+
lastMigrationOnOpenRefusal = null;
|
|
5269
|
+
return true;
|
|
5270
|
+
}
|
|
5271
|
+
lastMigrationOnOpenRefusal = {
|
|
5272
|
+
persistedVersion,
|
|
5273
|
+
supportedVersion: latestSupportedVersion,
|
|
5274
|
+
serverPids: discovery.serverPids,
|
|
5275
|
+
...discovery.unreadableFile ? { unreadableFile: discovery.unreadableFile } : {}
|
|
5276
|
+
};
|
|
5277
|
+
if (discovery.state === "unreadable") {
|
|
5278
|
+
log(`[magic-context] storage fatal: refusing to migrate ${dbPath} from schema v${persistedVersion} to v${latestSupportedVersion} because RPC discovery file ${discovery.unreadableFile ?? "<unknown>"} is unreadable or invalid, so the absence of a live OpenCode server cannot be proven. Restart OpenCode, remove or repair the named discovery file, then retry this process.`);
|
|
5279
|
+
} else {
|
|
5280
|
+
log(`[magic-context] storage fatal: refusing to migrate ${dbPath} from schema v${persistedVersion} to v${latestSupportedVersion} while live OpenCode server PID(s) ${discovery.serverPids.join(", ")} may still use the old plugin build. Restart OpenCode, then retry this process.`);
|
|
5281
|
+
}
|
|
5282
|
+
return false;
|
|
5283
|
+
}
|
|
5613
5284
|
var sqlitePragmaConfig = {
|
|
5614
5285
|
cacheSizeMb: 64,
|
|
5615
5286
|
mmapSizeMb: 0
|
|
@@ -5654,6 +5325,9 @@ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion)
|
|
|
5654
5325
|
pathByDatabase.set(db, dbPath);
|
|
5655
5326
|
persistenceByDatabase.set(db, true);
|
|
5656
5327
|
persistenceErrorByDatabase.delete(db);
|
|
5328
|
+
if (!explicitDbPath) {
|
|
5329
|
+
log(formatSchemaFenceBootLog(getPersistedSchemaVersion(db), latestSupportedVersion));
|
|
5330
|
+
}
|
|
5657
5331
|
return db;
|
|
5658
5332
|
}
|
|
5659
5333
|
function initializeDatabase(db) {
|
|
@@ -6254,12 +5928,14 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
6254
5928
|
note_nudge_anchors TEXT NOT NULL DEFAULT '[]',
|
|
6255
5929
|
auto_search_hint_decisions TEXT NOT NULL DEFAULT '[]',
|
|
6256
5930
|
last_todo_state TEXT DEFAULT '',
|
|
5931
|
+
todo_permission_denied INTEGER NOT NULL DEFAULT 2,
|
|
6257
5932
|
todo_synthetic_call_id TEXT DEFAULT '',
|
|
6258
5933
|
todo_synthetic_anchor_message_id TEXT DEFAULT '',
|
|
6259
5934
|
todo_synthetic_state_json TEXT DEFAULT '',
|
|
6260
5935
|
is_subagent INTEGER DEFAULT 0,
|
|
6261
5936
|
last_context_percentage REAL DEFAULT 0,
|
|
6262
5937
|
last_input_tokens INTEGER DEFAULT 0,
|
|
5938
|
+
detected_context_limit_provenance TEXT NOT NULL DEFAULT 'unknown',
|
|
6263
5939
|
observed_safe_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
6264
5940
|
cache_alert_sent INTEGER NOT NULL DEFAULT 0,
|
|
6265
5941
|
times_execute_threshold_reached INTEGER DEFAULT 0,
|
|
@@ -6314,6 +5990,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
6314
5990
|
emergency_drain_active INTEGER NOT NULL DEFAULT 0,
|
|
6315
5991
|
historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
|
|
6316
5992
|
wrapup_in_progress_state TEXT,
|
|
5993
|
+
compaction_mode_record TEXT,
|
|
6317
5994
|
cached_m0_materialized_at INTEGER,
|
|
6318
5995
|
cached_m0_session_facts_version INTEGER,
|
|
6319
5996
|
cached_m0_upgrade_state TEXT,
|
|
@@ -6513,6 +6190,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
6513
6190
|
ensureColumn(db, "session_meta", "note_nudge_anchors", "TEXT NOT NULL DEFAULT '[]'");
|
|
6514
6191
|
ensureColumn(db, "session_meta", "auto_search_hint_decisions", "TEXT NOT NULL DEFAULT '[]'");
|
|
6515
6192
|
ensureColumn(db, "session_meta", "last_todo_state", "TEXT DEFAULT ''");
|
|
6193
|
+
ensureColumn(db, "session_meta", "todo_permission_denied", "INTEGER NOT NULL DEFAULT 2");
|
|
6516
6194
|
ensureColumn(db, "session_meta", "todo_synthetic_call_id", "TEXT DEFAULT ''");
|
|
6517
6195
|
ensureColumn(db, "session_meta", "todo_synthetic_anchor_message_id", "TEXT DEFAULT ''");
|
|
6518
6196
|
ensureColumn(db, "session_meta", "todo_synthetic_state_json", "TEXT DEFAULT ''");
|
|
@@ -6569,6 +6247,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
6569
6247
|
ensureColumn(db, "session_meta", "recomp_partial_range_end", "INTEGER DEFAULT 0");
|
|
6570
6248
|
ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
|
|
6571
6249
|
ensureColumn(db, "session_meta", "detected_context_limit_model_key", "TEXT");
|
|
6250
|
+
ensureColumn(db, "session_meta", "detected_context_limit_provenance", "TEXT NOT NULL DEFAULT 'unknown'");
|
|
6572
6251
|
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
6573
6252
|
ensureColumn(db, "session_meta", "emergency_recovery_origin", "TEXT DEFAULT ''");
|
|
6574
6253
|
ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
|
|
@@ -6619,6 +6298,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
6619
6298
|
ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
|
|
6620
6299
|
ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
|
|
6621
6300
|
ensureColumn(db, "session_meta", "wrapup_in_progress_state", "TEXT");
|
|
6301
|
+
ensureColumn(db, "session_meta", "compaction_mode_record", "TEXT");
|
|
6622
6302
|
ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
|
|
6623
6303
|
ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
|
|
6624
6304
|
ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
|
|
@@ -6758,6 +6438,8 @@ function openDatabase(dbPathOrOptions) {
|
|
|
6758
6438
|
const explicitDbPath = options?.dbPath !== undefined;
|
|
6759
6439
|
const { dbDir, dbPath } = resolveDatabasePath(options?.dbPath);
|
|
6760
6440
|
const latestSupportedVersion = getRuntimeLatestSupportedVersion(options);
|
|
6441
|
+
lastSchemaFenceRejection = null;
|
|
6442
|
+
lastMigrationOnOpenRefusal = null;
|
|
6761
6443
|
const existing = databases.get(dbPath);
|
|
6762
6444
|
if (existing) {
|
|
6763
6445
|
if (!enforceSchemaFence(existing, dbPath, latestSupportedVersion)) {
|
|
@@ -6779,6 +6461,10 @@ function openDatabase(dbPathOrOptions) {
|
|
|
6779
6461
|
closeQuietly(db);
|
|
6780
6462
|
return null;
|
|
6781
6463
|
}
|
|
6464
|
+
if (!enforceMigrationOnOpenGuard(db, dbPath, dbDir, latestSupportedVersion)) {
|
|
6465
|
+
closeQuietly(db);
|
|
6466
|
+
return null;
|
|
6467
|
+
}
|
|
6782
6468
|
initializeDatabase(db);
|
|
6783
6469
|
runMigrations(db);
|
|
6784
6470
|
ensureContextStoreUuid(db);
|
|
@@ -6794,6 +6480,8 @@ async function openDatabaseAsync(dbPathOrOptions) {
|
|
|
6794
6480
|
const explicitDbPath = options?.dbPath !== undefined;
|
|
6795
6481
|
const { dbDir, dbPath } = resolveDatabasePath(options?.dbPath);
|
|
6796
6482
|
const latestSupportedVersion = getRuntimeLatestSupportedVersion(options);
|
|
6483
|
+
lastSchemaFenceRejection = null;
|
|
6484
|
+
lastMigrationOnOpenRefusal = null;
|
|
6797
6485
|
const existing = databases.get(dbPath);
|
|
6798
6486
|
if (existing) {
|
|
6799
6487
|
if (!enforceSchemaFence(existing, dbPath, latestSupportedVersion))
|
|
@@ -6817,6 +6505,10 @@ async function openDatabaseAsync(dbPathOrOptions) {
|
|
|
6817
6505
|
closeQuietly(db);
|
|
6818
6506
|
return null;
|
|
6819
6507
|
}
|
|
6508
|
+
if (!enforceMigrationOnOpenGuard(db, dbPath, dbDir, latestSupportedVersion)) {
|
|
6509
|
+
closeQuietly(db);
|
|
6510
|
+
return null;
|
|
6511
|
+
}
|
|
6820
6512
|
initializeDatabase(db);
|
|
6821
6513
|
await runMigrationsWithRetry(db);
|
|
6822
6514
|
ensureContextStoreUuid(db);
|
|
@@ -6847,11 +6539,188 @@ function getDatabasePersistenceError(db) {
|
|
|
6847
6539
|
return null;
|
|
6848
6540
|
return persistenceErrorByDatabase.get(db) ?? null;
|
|
6849
6541
|
}
|
|
6850
|
-
|
|
6542
|
+
|
|
6543
|
+
// src/features/magic-context/schema-fence-probe.ts
|
|
6544
|
+
var STALE_CHILD_SPAWN_FAILURE = "stale_schema_fence";
|
|
6545
|
+
var STALE_CHILD_SPAWN_LATCH_THRESHOLD = 2;
|
|
6546
|
+
var state = {
|
|
6547
|
+
consecutiveFailures: 0,
|
|
6548
|
+
totalFailures: 0,
|
|
6549
|
+
latched: false,
|
|
6550
|
+
noticeEmitted: false,
|
|
6551
|
+
failure: null
|
|
6552
|
+
};
|
|
6553
|
+
function recordStaleFence(persistedVersion, supportedVersion) {
|
|
6554
|
+
state.consecutiveFailures += 1;
|
|
6555
|
+
state.totalFailures += 1;
|
|
6556
|
+
const latched = state.consecutiveFailures >= STALE_CHILD_SPAWN_LATCH_THRESHOLD;
|
|
6557
|
+
state.latched ||= latched;
|
|
6558
|
+
const failure = {
|
|
6559
|
+
failureClass: STALE_CHILD_SPAWN_FAILURE,
|
|
6560
|
+
persistedVersion,
|
|
6561
|
+
supportedVersion,
|
|
6562
|
+
consecutiveFailures: state.consecutiveFailures,
|
|
6563
|
+
totalFailures: state.totalFailures,
|
|
6564
|
+
latched: state.latched
|
|
6565
|
+
};
|
|
6566
|
+
state.failure = failure;
|
|
6567
|
+
const shouldSurface = state.latched && !state.noticeEmitted;
|
|
6568
|
+
if (shouldSurface)
|
|
6569
|
+
state.noticeEmitted = true;
|
|
6570
|
+
return { allowSpawn: false, failure, shouldSurface };
|
|
6571
|
+
}
|
|
6572
|
+
function probeChildSpawnFence(db) {
|
|
6573
|
+
if (!db) {
|
|
6574
|
+
const knownRejection = getSchemaFenceRejection();
|
|
6575
|
+
if (knownRejection) {
|
|
6576
|
+
return recordStaleFence(knownRejection.persistedVersion, knownRejection.supportedVersion);
|
|
6577
|
+
}
|
|
6578
|
+
return { allowSpawn: true };
|
|
6579
|
+
}
|
|
6580
|
+
try {
|
|
6581
|
+
const persistedVersion = getPersistedSchemaVersion(db);
|
|
6582
|
+
if (persistedVersion > LATEST_SUPPORTED_VERSION) {
|
|
6583
|
+
return recordStaleFence(persistedVersion, LATEST_SUPPORTED_VERSION);
|
|
6584
|
+
}
|
|
6585
|
+
} catch {
|
|
6586
|
+
return { allowSpawn: true };
|
|
6587
|
+
}
|
|
6588
|
+
state.consecutiveFailures = 0;
|
|
6589
|
+
state.latched = false;
|
|
6590
|
+
state.noticeEmitted = false;
|
|
6591
|
+
return { allowSpawn: true };
|
|
6592
|
+
}
|
|
6593
|
+
// src/features/magic-context/project-docs-hash.ts
|
|
6851
6594
|
import { createHash as createHash6 } from "node:crypto";
|
|
6595
|
+
import { lstatSync, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
|
|
6596
|
+
import path2 from "node:path";
|
|
6597
|
+
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
6598
|
+
var PROJECT_DOCS_DELIMITER = `
|
|
6599
|
+
|
|
6600
|
+
---
|
|
6601
|
+
|
|
6602
|
+
`;
|
|
6603
|
+
var MAX_PROJECT_DOC_BYTES = 256 * 1024;
|
|
6604
|
+
var docsCache = new Map;
|
|
6605
|
+
function canonicalizeDocContent(raw) {
|
|
6606
|
+
return raw.replace(/^\uFEFF/, "").replace(/\r\n/g, `
|
|
6607
|
+
`).split(`
|
|
6608
|
+
`).map((line) => line.replace(/[ \t]+$/, "")).join(`
|
|
6609
|
+
`).replace(/\n+$/, "");
|
|
6610
|
+
}
|
|
6611
|
+
function fingerprintFile(filePath) {
|
|
6612
|
+
try {
|
|
6613
|
+
const stat = lstatSync(filePath);
|
|
6614
|
+
const isReadableDoc = stat.isFile() && stat.size <= MAX_PROJECT_DOC_BYTES;
|
|
6615
|
+
return {
|
|
6616
|
+
exists: isReadableDoc,
|
|
6617
|
+
mtimeMs: stat.mtimeMs,
|
|
6618
|
+
size: stat.size
|
|
6619
|
+
};
|
|
6620
|
+
} catch {
|
|
6621
|
+
return { exists: false, mtimeMs: 0, size: 0 };
|
|
6622
|
+
}
|
|
6623
|
+
}
|
|
6624
|
+
function readDirectoryMtimeMs(projectDirectory) {
|
|
6625
|
+
try {
|
|
6626
|
+
return statSync2(projectDirectory).mtimeMs;
|
|
6627
|
+
} catch {
|
|
6628
|
+
return 0;
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6631
|
+
function fingerprintsEqual(a, b) {
|
|
6632
|
+
return a?.exists === b.exists && a.mtimeMs === b.mtimeMs && a.size === b.size;
|
|
6633
|
+
}
|
|
6634
|
+
function cacheFilesEqual(cachedFiles, currentFiles) {
|
|
6635
|
+
for (const [filePath, current] of currentFiles) {
|
|
6636
|
+
if (!fingerprintsEqual(cachedFiles.get(filePath), current)) {
|
|
6637
|
+
return false;
|
|
6638
|
+
}
|
|
6639
|
+
}
|
|
6640
|
+
return true;
|
|
6641
|
+
}
|
|
6642
|
+
function readCurrentFingerprints(projectDirectory) {
|
|
6643
|
+
const files = new Map;
|
|
6644
|
+
for (const filename of PROJECT_DOC_FILES) {
|
|
6645
|
+
const filePath = path2.join(projectDirectory, filename);
|
|
6646
|
+
files.set(filePath, fingerprintFile(filePath));
|
|
6647
|
+
}
|
|
6648
|
+
return { directoryMtimeMs: readDirectoryMtimeMs(projectDirectory), files };
|
|
6649
|
+
}
|
|
6650
|
+
function readCanonicalPieces(projectDirectory, files) {
|
|
6651
|
+
const hashPieces = [];
|
|
6652
|
+
const renderedSections = [];
|
|
6653
|
+
for (const filename of PROJECT_DOC_FILES) {
|
|
6654
|
+
const filePath = path2.join(projectDirectory, filename);
|
|
6655
|
+
const fingerprint = files.get(filePath);
|
|
6656
|
+
if (!fingerprint?.exists) {
|
|
6657
|
+
continue;
|
|
6658
|
+
}
|
|
6659
|
+
let safeToRead = false;
|
|
6660
|
+
try {
|
|
6661
|
+
const st = lstatSync(filePath);
|
|
6662
|
+
safeToRead = st.isFile() && st.size <= MAX_PROJECT_DOC_BYTES;
|
|
6663
|
+
} catch {
|
|
6664
|
+
safeToRead = false;
|
|
6665
|
+
}
|
|
6666
|
+
if (!safeToRead) {
|
|
6667
|
+
continue;
|
|
6668
|
+
}
|
|
6669
|
+
const canonicalContent = canonicalizeDocContent(readFileSync2(filePath, "utf8"));
|
|
6670
|
+
hashPieces.push(`file:${filename}
|
|
6671
|
+
${canonicalContent}`);
|
|
6672
|
+
renderedSections.push(`<file name="${escapeXmlAttr(filename)}">
|
|
6673
|
+
${escapeXmlContent(canonicalContent)}
|
|
6674
|
+
</file>`);
|
|
6675
|
+
}
|
|
6676
|
+
return { hashPieces, renderedSections };
|
|
6677
|
+
}
|
|
6678
|
+
function buildRenderedBlock(renderedSections) {
|
|
6679
|
+
if (renderedSections.length === 0) {
|
|
6680
|
+
return "";
|
|
6681
|
+
}
|
|
6682
|
+
return `<project-docs>
|
|
6683
|
+
${renderedSections.join(`
|
|
6684
|
+
|
|
6685
|
+
`)}
|
|
6686
|
+
</project-docs>`;
|
|
6687
|
+
}
|
|
6688
|
+
function hashCanonicalPieces(hashPieces) {
|
|
6689
|
+
if (hashPieces.length === 0) {
|
|
6690
|
+
return "";
|
|
6691
|
+
}
|
|
6692
|
+
return createHash6("sha256").update(hashPieces.join(PROJECT_DOCS_DELIMITER), "utf8").digest("hex");
|
|
6693
|
+
}
|
|
6694
|
+
function readProjectDocsCanonical(projectDirectory) {
|
|
6695
|
+
const canonicalDirectory = path2.resolve(projectDirectory);
|
|
6696
|
+
const current = readCurrentFingerprints(canonicalDirectory);
|
|
6697
|
+
const cached = docsCache.get(canonicalDirectory);
|
|
6698
|
+
if (cached && cacheFilesEqual(cached.files, current.files)) {
|
|
6699
|
+
cached.directoryMtimeMs = current.directoryMtimeMs;
|
|
6700
|
+
return {
|
|
6701
|
+
renderedBlock: cached.cachedRendered,
|
|
6702
|
+
canonicalHash: cached.cachedHash
|
|
6703
|
+
};
|
|
6704
|
+
}
|
|
6705
|
+
const { hashPieces, renderedSections } = readCanonicalPieces(canonicalDirectory, current.files);
|
|
6706
|
+
const canonicalHash = hashCanonicalPieces(hashPieces);
|
|
6707
|
+
const renderedBlock = buildRenderedBlock(renderedSections);
|
|
6708
|
+
docsCache.set(canonicalDirectory, {
|
|
6709
|
+
directoryMtimeMs: current.directoryMtimeMs,
|
|
6710
|
+
files: current.files,
|
|
6711
|
+
cachedHash: canonicalHash,
|
|
6712
|
+
cachedRendered: renderedBlock
|
|
6713
|
+
});
|
|
6714
|
+
return { renderedBlock, canonicalHash };
|
|
6715
|
+
}
|
|
6716
|
+
function computeProjectDocsHash(projectDirectory) {
|
|
6717
|
+
return readProjectDocsCanonical(projectDirectory).canonicalHash;
|
|
6718
|
+
}
|
|
6719
|
+
// src/features/magic-context/storage-embedding-measurements.ts
|
|
6720
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
6852
6721
|
function normalizedQueryHash(query) {
|
|
6853
6722
|
const normalized = query.trim().replace(/\s+/g, " ").toLowerCase();
|
|
6854
|
-
return
|
|
6723
|
+
return createHash7("sha256").update(normalized).digest("hex");
|
|
6855
6724
|
}
|
|
6856
6725
|
var MEASUREMENT_CORPUS_SESSION_ROW_CAP = 2000;
|
|
6857
6726
|
function recordEmbeddingMeasurement(db, input) {
|
|
@@ -7067,7 +6936,7 @@ function getMemoryMutationsForRenderByIdentitySet(db, projectPaths, afterId, ren
|
|
|
7067
6936
|
}
|
|
7068
6937
|
visited.add(terminal);
|
|
7069
6938
|
const next = byTarget.get(terminal);
|
|
7070
|
-
if (
|
|
6939
|
+
if (next?.mutationType !== "superseded")
|
|
7071
6940
|
break;
|
|
7072
6941
|
if (depth >= MAX_MEMORY_REPLACEMENT_DEPTH - 1) {
|
|
7073
6942
|
terminal = null;
|
|
@@ -7101,6 +6970,24 @@ function getMaxMemoryMutationIdForProjects(db, projectPaths) {
|
|
|
7101
6970
|
WHERE project_path IN (${placeholders2(identities)})`).get(...identities);
|
|
7102
6971
|
return row?.max_id ?? null;
|
|
7103
6972
|
}
|
|
6973
|
+
// src/shared/context-limit-provenance.ts
|
|
6974
|
+
function normalizeContextLimitProvenance(value) {
|
|
6975
|
+
if (value === "prompt_only" || value === "combined")
|
|
6976
|
+
return value;
|
|
6977
|
+
return "unknown";
|
|
6978
|
+
}
|
|
6979
|
+
|
|
6980
|
+
// src/shared/escalation-bands.ts
|
|
6981
|
+
var MAX_EXECUTE_THRESHOLD = 90;
|
|
6982
|
+
var ABSOLUTE_EMERGENCY_PERCENTAGE = 95;
|
|
6983
|
+
function escalationBands(effectiveThresholdPercentage) {
|
|
6984
|
+
const threshold = Number.isFinite(effectiveThresholdPercentage) ? Math.min(effectiveThresholdPercentage, MAX_EXECUTE_THRESHOLD) : 65;
|
|
6985
|
+
return {
|
|
6986
|
+
forceMaterializationPercentage: Math.max(85, threshold + 2),
|
|
6987
|
+
emergencyPercentage: ABSOLUTE_EMERGENCY_PERCENTAGE
|
|
6988
|
+
};
|
|
6989
|
+
}
|
|
6990
|
+
|
|
7104
6991
|
// src/features/magic-context/storage-meta-persisted.ts
|
|
7105
6992
|
var emergencyRecoveryArmedSessions = new Set;
|
|
7106
6993
|
var providerOverflowReconfirmedSessions = new Set;
|
|
@@ -7322,11 +7209,11 @@ function readRawWrapupState(db, sessionId) {
|
|
|
7322
7209
|
return parseWrapupState(row?.wrapup_in_progress_state);
|
|
7323
7210
|
}
|
|
7324
7211
|
function getWrapupInProgressState(db, sessionId, now = Date.now()) {
|
|
7325
|
-
const
|
|
7326
|
-
if (!
|
|
7212
|
+
const state2 = readRawWrapupState(db, sessionId);
|
|
7213
|
+
if (!state2)
|
|
7327
7214
|
return null;
|
|
7328
|
-
if (
|
|
7329
|
-
return
|
|
7215
|
+
if (state2.expiresAt > now)
|
|
7216
|
+
return state2;
|
|
7330
7217
|
try {
|
|
7331
7218
|
db.exec("BEGIN IMMEDIATE");
|
|
7332
7219
|
} catch {
|
|
@@ -7352,10 +7239,10 @@ function getWrapupInProgressState(db, sessionId, now = Date.now()) {
|
|
|
7352
7239
|
function isWrapupInProgress(db, sessionId, now = Date.now()) {
|
|
7353
7240
|
return getWrapupInProgressState(db, sessionId, now) !== null;
|
|
7354
7241
|
}
|
|
7355
|
-
function acquireWrapupInProgress(db, sessionId,
|
|
7242
|
+
function acquireWrapupInProgress(db, sessionId, state2, now = Date.now()) {
|
|
7356
7243
|
const acquiredAt = now;
|
|
7357
7244
|
const next = {
|
|
7358
|
-
...
|
|
7245
|
+
...state2,
|
|
7359
7246
|
acquiredAt,
|
|
7360
7247
|
expiresAt: acquiredAt + WRAPUP_IN_PROGRESS_TTL_MS,
|
|
7361
7248
|
updatedAt: acquiredAt
|
|
@@ -7365,7 +7252,7 @@ function acquireWrapupInProgress(db, sessionId, state, now = Date.now()) {
|
|
|
7365
7252
|
try {
|
|
7366
7253
|
ensureSessionMetaRow(db, sessionId);
|
|
7367
7254
|
const current = readRawWrapupState(db, sessionId);
|
|
7368
|
-
if (current && current.expiresAt > now && current.holderId !==
|
|
7255
|
+
if (current && current.expiresAt > now && current.holderId !== state2.holderId) {
|
|
7369
7256
|
db.exec("COMMIT");
|
|
7370
7257
|
finished = true;
|
|
7371
7258
|
return { ok: false, state: current };
|
|
@@ -7429,6 +7316,45 @@ function releaseWrapupInProgress(db, sessionId, holderId) {
|
|
|
7429
7316
|
}
|
|
7430
7317
|
}
|
|
7431
7318
|
}
|
|
7319
|
+
var COMPACTION_MODE_RECORD_VALUES = new Set([
|
|
7320
|
+
"on",
|
|
7321
|
+
"off",
|
|
7322
|
+
"on_notice_pending",
|
|
7323
|
+
"off_notice_pending",
|
|
7324
|
+
"off_cleanup_pending"
|
|
7325
|
+
]);
|
|
7326
|
+
function normalizeCompactionModeRecord(value) {
|
|
7327
|
+
if (value === null || value === undefined)
|
|
7328
|
+
return null;
|
|
7329
|
+
if (typeof value === "string" && COMPACTION_MODE_RECORD_VALUES.has(value)) {
|
|
7330
|
+
return value;
|
|
7331
|
+
}
|
|
7332
|
+
return null;
|
|
7333
|
+
}
|
|
7334
|
+
function resolveCompactionModeRecord(record) {
|
|
7335
|
+
switch (record) {
|
|
7336
|
+
case "on":
|
|
7337
|
+
case "on_notice_pending":
|
|
7338
|
+
return "on";
|
|
7339
|
+
case "off":
|
|
7340
|
+
case "off_notice_pending":
|
|
7341
|
+
case "off_cleanup_pending":
|
|
7342
|
+
return "off";
|
|
7343
|
+
default:
|
|
7344
|
+
return null;
|
|
7345
|
+
}
|
|
7346
|
+
}
|
|
7347
|
+
function getCompactionModeRecord(db, sessionId) {
|
|
7348
|
+
const row = db.prepare("SELECT compaction_mode_record FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
7349
|
+
return normalizeCompactionModeRecord(row?.compaction_mode_record);
|
|
7350
|
+
}
|
|
7351
|
+
function setCompactionModeRecord(db, sessionId, value) {
|
|
7352
|
+
if (value !== null && !COMPACTION_MODE_RECORD_VALUES.has(value)) {
|
|
7353
|
+
throw new Error(`Invalid compaction_mode_record value: ${String(value)} (expected a supported compaction mode record or null)`);
|
|
7354
|
+
}
|
|
7355
|
+
ensureSessionMetaRow(db, sessionId);
|
|
7356
|
+
db.prepare("UPDATE session_meta SET compaction_mode_record = ? WHERE session_id = ?").run(value, sessionId);
|
|
7357
|
+
}
|
|
7432
7358
|
function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
7433
7359
|
if (usagePercentage >= 95)
|
|
7434
7360
|
return Math.min(1e6, Math.max(4 * perRunCap, Math.round(0.5 * usable)));
|
|
@@ -7436,7 +7362,6 @@ function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
|
|
|
7436
7362
|
return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
|
|
7437
7363
|
return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
|
|
7438
7364
|
}
|
|
7439
|
-
var EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95;
|
|
7440
7365
|
var EMERGENCY_DRAIN_EXIT_MARGIN = 10;
|
|
7441
7366
|
var EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55;
|
|
7442
7367
|
var EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000;
|
|
@@ -7471,7 +7396,8 @@ function reserveProtectedTailDrainTokens(args) {
|
|
|
7471
7396
|
}
|
|
7472
7397
|
const exitThreshold = emergencyDrainExitThreshold(args.executeThresholdPercentage);
|
|
7473
7398
|
let latchActiveSince = meta.emergencyDrainActive;
|
|
7474
|
-
|
|
7399
|
+
const { forceMaterializationPercentage } = escalationBands(args.executeThresholdPercentage);
|
|
7400
|
+
if (args.usagePercentage >= forceMaterializationPercentage) {
|
|
7475
7401
|
if (latchActiveSince <= 0)
|
|
7476
7402
|
latchActiveSince = now;
|
|
7477
7403
|
} else if (latchActiveSince > 0) {
|
|
@@ -7623,13 +7549,20 @@ function getChannel2NudgeState(db, sessionId) {
|
|
|
7623
7549
|
function getChannel2NudgeClaim(db, sessionId) {
|
|
7624
7550
|
const result = db.prepare("SELECT channel2_nudge_state, channel2_nudge_claimed_at, channel2_nudge_claim_token FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
7625
7551
|
const rawState = typeof result?.channel2_nudge_state === "string" ? result.channel2_nudge_state : "";
|
|
7626
|
-
const
|
|
7552
|
+
const state2 = rawState === "pending" || rawState === "claimed" || rawState === "delivered" ? rawState : "";
|
|
7627
7553
|
return {
|
|
7628
|
-
state,
|
|
7554
|
+
state: state2,
|
|
7629
7555
|
claimedAt: typeof result?.channel2_nudge_claimed_at === "number" ? result.channel2_nudge_claimed_at : 0,
|
|
7630
7556
|
claimToken: typeof result?.channel2_nudge_claim_token === "string" ? result.channel2_nudge_claim_token : ""
|
|
7631
7557
|
};
|
|
7632
7558
|
}
|
|
7559
|
+
function setChannel2NudgeState(db, sessionId, state2) {
|
|
7560
|
+
db.transaction(() => {
|
|
7561
|
+
ensureSessionMetaRow(db, sessionId);
|
|
7562
|
+
const claimedAt = state2 === "claimed" ? Date.now() : 0;
|
|
7563
|
+
db.prepare("UPDATE session_meta SET channel2_nudge_state = ?, channel2_nudge_claimed_at = ?, channel2_nudge_claim_token = '' WHERE session_id = ?").run(state2, claimedAt, sessionId);
|
|
7564
|
+
})();
|
|
7565
|
+
}
|
|
7633
7566
|
function casChannel2NudgeState(db, sessionId, from, to) {
|
|
7634
7567
|
let changed = false;
|
|
7635
7568
|
db.transaction(() => {
|
|
@@ -7809,6 +7742,18 @@ function removeAutoSearchHintDecisionByMessageId(db, sessionId, messageId) {
|
|
|
7809
7742
|
}, { ensureRow: false });
|
|
7810
7743
|
return ok && removed;
|
|
7811
7744
|
}
|
|
7745
|
+
function getPersistedTodoPermissionDenied(db, sessionId) {
|
|
7746
|
+
const row = db.prepare("SELECT todo_permission_denied FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
7747
|
+
if (row?.todo_permission_denied === 1)
|
|
7748
|
+
return true;
|
|
7749
|
+
if (row?.todo_permission_denied === 0)
|
|
7750
|
+
return false;
|
|
7751
|
+
return null;
|
|
7752
|
+
}
|
|
7753
|
+
function setPersistedTodoPermissionDenied(db, sessionId, denied) {
|
|
7754
|
+
ensureSessionMetaRow(db, sessionId);
|
|
7755
|
+
db.prepare("UPDATE session_meta SET todo_permission_denied = ? WHERE session_id = ?").run(denied ? 1 : 0, sessionId);
|
|
7756
|
+
}
|
|
7812
7757
|
function getPersistedTodoSyntheticAnchor(db, sessionId) {
|
|
7813
7758
|
const result = db.prepare("SELECT todo_synthetic_call_id, todo_synthetic_anchor_message_id, todo_synthetic_state_json FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
7814
7759
|
if (!isPersistedTodoSyntheticAnchorRow(result)) {
|
|
@@ -7885,17 +7830,19 @@ function normalizeEmergencyRecoveryOrigin(value) {
|
|
|
7885
7830
|
return value === "provider_overflow" || value === "proactive_model_shrink" ? value : null;
|
|
7886
7831
|
}
|
|
7887
7832
|
function getOverflowState(db, sessionId, modelKey) {
|
|
7888
|
-
const result = db.prepare("SELECT detected_context_limit, detected_context_limit_model_key, needs_emergency_recovery, emergency_recovery_origin FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
7833
|
+
const result = db.prepare("SELECT detected_context_limit, detected_context_limit_model_key, detected_context_limit_provenance, needs_emergency_recovery, emergency_recovery_origin FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
7889
7834
|
if (!result) {
|
|
7890
7835
|
return {
|
|
7891
7836
|
detectedContextLimit: 0,
|
|
7892
7837
|
detectedContextLimitModelKey: null,
|
|
7838
|
+
detectedContextLimitProvenance: "unknown",
|
|
7893
7839
|
needsEmergencyRecovery: false,
|
|
7894
7840
|
emergencyRecoveryOrigin: null
|
|
7895
7841
|
};
|
|
7896
7842
|
}
|
|
7897
7843
|
const storedModelKey = normalizeDetectedLimitModelKey(result.detected_context_limit_model_key);
|
|
7898
7844
|
const requestedModelKey = normalizeDetectedLimitModelKey(modelKey);
|
|
7845
|
+
const provenance = normalizeContextLimitProvenance(result.detected_context_limit_provenance);
|
|
7899
7846
|
const limit = typeof result.detected_context_limit === "number" && result.detected_context_limit > 0 ? result.detected_context_limit : 0;
|
|
7900
7847
|
const modelMatches = limit > 0 && requestedModelKey && storedModelKey ? requestedModelKey === storedModelKey : true;
|
|
7901
7848
|
const needs = typeof result.needs_emergency_recovery === "number" && result.needs_emergency_recovery > 0;
|
|
@@ -7904,11 +7851,12 @@ function getOverflowState(db, sessionId, modelKey) {
|
|
|
7904
7851
|
return {
|
|
7905
7852
|
detectedContextLimit: modelMatches ? limit : 0,
|
|
7906
7853
|
detectedContextLimitModelKey: storedModelKey,
|
|
7854
|
+
detectedContextLimitProvenance: provenance,
|
|
7907
7855
|
needsEmergencyRecovery: needs,
|
|
7908
7856
|
emergencyRecoveryOrigin: recoveryOrigin
|
|
7909
7857
|
};
|
|
7910
7858
|
}
|
|
7911
|
-
function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin = "provider_overflow") {
|
|
7859
|
+
function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin = "provider_overflow", provenance = "unknown") {
|
|
7912
7860
|
emergencyRecoveryArmedSessions.add(sessionId);
|
|
7913
7861
|
db.transaction(() => {
|
|
7914
7862
|
ensureSessionMetaRow(db, sessionId);
|
|
@@ -7917,18 +7865,18 @@ function recordOverflowDetected(db, sessionId, reportedLimit, modelKey, origin =
|
|
|
7917
7865
|
providerOverflowReconfirmedSessions.add(sessionId);
|
|
7918
7866
|
}
|
|
7919
7867
|
if (typeof reportedLimit === "number" && reportedLimit > 0) {
|
|
7920
|
-
db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), origin, sessionId);
|
|
7868
|
+
db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, detected_context_limit_provenance = ?, needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), normalizeContextLimitProvenance(provenance), origin, sessionId);
|
|
7921
7869
|
} else {
|
|
7922
7870
|
db.prepare("UPDATE session_meta SET needs_emergency_recovery = 1, emergency_recovery_origin = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(origin, sessionId);
|
|
7923
7871
|
}
|
|
7924
7872
|
})();
|
|
7925
7873
|
}
|
|
7926
|
-
function recordDetectedContextLimit(db, sessionId, reportedLimit, modelKey) {
|
|
7874
|
+
function recordDetectedContextLimit(db, sessionId, reportedLimit, modelKey, provenance = "unknown") {
|
|
7927
7875
|
if (!(reportedLimit > 0))
|
|
7928
7876
|
return;
|
|
7929
7877
|
db.transaction(() => {
|
|
7930
7878
|
ensureSessionMetaRow(db, sessionId);
|
|
7931
|
-
db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), sessionId);
|
|
7879
|
+
db.prepare("UPDATE session_meta SET detected_context_limit = ?, detected_context_limit_model_key = ?, detected_context_limit_provenance = ?, observed_safe_input_tokens = 0, cache_alert_sent = 0 WHERE session_id = ?").run(reportedLimit, normalizeDetectedLimitModelKey(modelKey), normalizeContextLimitProvenance(provenance), sessionId);
|
|
7932
7880
|
})();
|
|
7933
7881
|
}
|
|
7934
7882
|
function clearEmergencyRecovery(db, sessionId) {
|
|
@@ -7946,7 +7894,7 @@ function clearEmergencyRecovery(db, sessionId) {
|
|
|
7946
7894
|
function clearDetectedContextLimit(db, sessionId) {
|
|
7947
7895
|
db.transaction(() => {
|
|
7948
7896
|
ensureSessionMetaRow(db, sessionId);
|
|
7949
|
-
db.prepare("UPDATE session_meta SET detected_context_limit = 0, detected_context_limit_model_key = NULL WHERE session_id = ?").run(sessionId);
|
|
7897
|
+
db.prepare("UPDATE session_meta SET detected_context_limit = 0, detected_context_limit_model_key = NULL, detected_context_limit_provenance = 'unknown' WHERE session_id = ?").run(sessionId);
|
|
7950
7898
|
})();
|
|
7951
7899
|
}
|
|
7952
7900
|
function getPersistedCompactionMarkerState(db, sessionId) {
|
|
@@ -7966,10 +7914,10 @@ function getPersistedCompactionMarkerState(db, sessionId) {
|
|
|
7966
7914
|
} catch {}
|
|
7967
7915
|
return null;
|
|
7968
7916
|
}
|
|
7969
|
-
function setPersistedCompactionMarkerState(db, sessionId,
|
|
7917
|
+
function setPersistedCompactionMarkerState(db, sessionId, state2) {
|
|
7970
7918
|
ensureSessionMetaRow(db, sessionId);
|
|
7971
|
-
const json =
|
|
7972
|
-
db.prepare("UPDATE session_meta SET compaction_marker_state = ?, compaction_marker_target_end_message_id = ? WHERE session_id = ?").run(json,
|
|
7919
|
+
const json = state2 ? JSON.stringify(state2) : "";
|
|
7920
|
+
db.prepare("UPDATE session_meta SET compaction_marker_state = ?, compaction_marker_target_end_message_id = ? WHERE session_id = ?").run(json, state2?.targetEndMessageId ?? null, sessionId);
|
|
7973
7921
|
}
|
|
7974
7922
|
function getStrippedPlaceholderIds(db, sessionId) {
|
|
7975
7923
|
const row = db.prepare("SELECT stripped_placeholder_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
@@ -8101,9 +8049,9 @@ function getPendingCompactionMarkerState(db, sessionId) {
|
|
|
8101
8049
|
} catch {}
|
|
8102
8050
|
return null;
|
|
8103
8051
|
}
|
|
8104
|
-
function setPendingCompactionMarkerState(db, sessionId,
|
|
8052
|
+
function setPendingCompactionMarkerState(db, sessionId, state2) {
|
|
8105
8053
|
ensureSessionMetaRow(db, sessionId);
|
|
8106
|
-
const blob =
|
|
8054
|
+
const blob = state2 ? stableStringify(state2) : null;
|
|
8107
8055
|
db.prepare("UPDATE session_meta SET pending_compaction_marker_state = ? WHERE session_id = ?").run(blob, sessionId);
|
|
8108
8056
|
}
|
|
8109
8057
|
function clearPendingCompactionMarkerStateIf(db, sessionId, expected) {
|
|
@@ -8374,6 +8322,14 @@ function getPendingOpsStatement(db) {
|
|
|
8374
8322
|
}
|
|
8375
8323
|
return stmt;
|
|
8376
8324
|
}
|
|
8325
|
+
function getClearPendingOpsStatement(db) {
|
|
8326
|
+
let stmt = clearPendingOpsStatements.get(db);
|
|
8327
|
+
if (!stmt) {
|
|
8328
|
+
stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ?");
|
|
8329
|
+
clearPendingOpsStatements.set(db, stmt);
|
|
8330
|
+
}
|
|
8331
|
+
return stmt;
|
|
8332
|
+
}
|
|
8377
8333
|
function getRemovePendingOpStatement(db) {
|
|
8378
8334
|
let stmt = removePendingOpStatements.get(db);
|
|
8379
8335
|
if (!stmt) {
|
|
@@ -8408,6 +8364,9 @@ function getPendingOps(db, sessionId) {
|
|
|
8408
8364
|
const rows = getPendingOpsStatement(db).all(sessionId).filter(isPendingOpRow);
|
|
8409
8365
|
return rows.map(toPendingOp).filter((op) => op !== null);
|
|
8410
8366
|
}
|
|
8367
|
+
function clearPendingOps(db, sessionId) {
|
|
8368
|
+
getClearPendingOpsStatement(db).run(sessionId);
|
|
8369
|
+
}
|
|
8411
8370
|
function removePendingOp(db, sessionId, tagId) {
|
|
8412
8371
|
getRemovePendingOpStatement(db).run(sessionId, tagId);
|
|
8413
8372
|
}
|
|
@@ -8603,11 +8562,11 @@ function bumpProjectMemoryEpoch(db, projectPath, now = Date.now()) {
|
|
|
8603
8562
|
ON CONFLICT(project_path) DO UPDATE SET
|
|
8604
8563
|
project_memory_epoch = project_memory_epoch + 1,
|
|
8605
8564
|
updated_at = excluded.updated_at`).run(projectPath, now);
|
|
8606
|
-
const
|
|
8607
|
-
if (!
|
|
8565
|
+
const state2 = getProjectState(db, projectPath);
|
|
8566
|
+
if (!state2) {
|
|
8608
8567
|
throw new Error(`Failed to bump project memory epoch for ${projectPath}`);
|
|
8609
8568
|
}
|
|
8610
|
-
return
|
|
8569
|
+
return state2;
|
|
8611
8570
|
}
|
|
8612
8571
|
function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PROJECT_PATH, now = Date.now()) {
|
|
8613
8572
|
db.prepare(`INSERT INTO project_state
|
|
@@ -8616,11 +8575,11 @@ function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PRO
|
|
|
8616
8575
|
ON CONFLICT(project_path) DO UPDATE SET
|
|
8617
8576
|
project_user_profile_version = project_user_profile_version + 1,
|
|
8618
8577
|
updated_at = excluded.updated_at`).run(projectPath, now);
|
|
8619
|
-
const
|
|
8620
|
-
if (!
|
|
8578
|
+
const state2 = getProjectState(db, projectPath);
|
|
8579
|
+
if (!state2) {
|
|
8621
8580
|
throw new Error(`Failed to bump project user profile version for ${projectPath}`);
|
|
8622
8581
|
}
|
|
8623
|
-
return
|
|
8582
|
+
return state2;
|
|
8624
8583
|
}
|
|
8625
8584
|
// src/features/magic-context/storage-source.ts
|
|
8626
8585
|
function isSourceContentRow(row) {
|
|
@@ -9210,6 +9169,518 @@ var ERROR_CLASSES = new Set([
|
|
|
9210
9169
|
"permission_denied",
|
|
9211
9170
|
"unknown"
|
|
9212
9171
|
]);
|
|
9172
|
+
// src/hooks/magic-context/child-session-spawn.ts
|
|
9173
|
+
var STALE_PLUGIN_RESTART_NOTICE = "Magic Context: plugin build is older than its database — restart OpenCode";
|
|
9174
|
+
async function surfaceStalePluginBuild(args) {
|
|
9175
|
+
if (!args.parentSessionId)
|
|
9176
|
+
return;
|
|
9177
|
+
try {
|
|
9178
|
+
if (args.db) {
|
|
9179
|
+
updateSessionMeta(args.db, args.parentSessionId, {
|
|
9180
|
+
lastTransformError: STALE_PLUGIN_RESTART_NOTICE
|
|
9181
|
+
});
|
|
9182
|
+
}
|
|
9183
|
+
pushNotification("toast", {
|
|
9184
|
+
title: "Magic Context",
|
|
9185
|
+
message: STALE_PLUGIN_RESTART_NOTICE,
|
|
9186
|
+
variant: "error",
|
|
9187
|
+
duration: 1e4
|
|
9188
|
+
}, args.parentSessionId);
|
|
9189
|
+
pushNotification("action", { action: "refresh-sidebar" }, args.parentSessionId);
|
|
9190
|
+
await sendIgnoredMessage(args.client, args.parentSessionId, STALE_PLUGIN_RESTART_NOTICE, args.notificationParams ?? {}, true);
|
|
9191
|
+
} catch (error) {
|
|
9192
|
+
sessionLog(args.parentSessionId, `stale plugin-build warning delivery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
9193
|
+
}
|
|
9194
|
+
}
|
|
9195
|
+
async function createChildSessionWithFence(args) {
|
|
9196
|
+
const verdict = probeChildSpawnFence(args.db);
|
|
9197
|
+
if (!verdict.allowSpawn) {
|
|
9198
|
+
if (args.parentSessionId) {
|
|
9199
|
+
sessionLog(args.parentSessionId, `child session skipped (${verdict.failure.failureClass}): database=v${verdict.failure.persistedVersion}, supported_fence=v${verdict.failure.supportedVersion}, consecutive=${verdict.failure.consecutiveFailures}, total=${verdict.failure.totalFailures}`);
|
|
9200
|
+
}
|
|
9201
|
+
if (verdict.shouldSurface) {
|
|
9202
|
+
if (args.onFenceLatched)
|
|
9203
|
+
await args.onFenceLatched(verdict.failure);
|
|
9204
|
+
else
|
|
9205
|
+
await surfaceStalePluginBuild(args);
|
|
9206
|
+
}
|
|
9207
|
+
return null;
|
|
9208
|
+
}
|
|
9209
|
+
return args.client.session.create({
|
|
9210
|
+
body: {
|
|
9211
|
+
...args.parentSessionId ? { parentID: args.parentSessionId } : {},
|
|
9212
|
+
title: args.title
|
|
9213
|
+
},
|
|
9214
|
+
query: { directory: args.directory }
|
|
9215
|
+
});
|
|
9216
|
+
}
|
|
9217
|
+
// src/features/magic-context/overflow-detection.ts
|
|
9218
|
+
var OVERFLOW_PATTERNS = [
|
|
9219
|
+
/prompt is too long/i,
|
|
9220
|
+
/input is too long for requested model/i,
|
|
9221
|
+
/exceeds the context window/i,
|
|
9222
|
+
/input token count.*exceeds the maximum/i,
|
|
9223
|
+
/maximum prompt length is \d+/i,
|
|
9224
|
+
/reduce the length of the messages/i,
|
|
9225
|
+
/maximum context length is \d+ tokens/i,
|
|
9226
|
+
/maximum model length is \d+/i,
|
|
9227
|
+
/exceeds the limit of \d+/i,
|
|
9228
|
+
/exceeds the available context size/i,
|
|
9229
|
+
/greater than the context length/i,
|
|
9230
|
+
/context window exceeds limit/i,
|
|
9231
|
+
/exceeded model token limit/i,
|
|
9232
|
+
/context[_ ]length[_ ]exceeded/i,
|
|
9233
|
+
/request entity too large/i,
|
|
9234
|
+
/context length is only \d+ tokens/i,
|
|
9235
|
+
/input length.*exceeds.*context length/i,
|
|
9236
|
+
/prompt too long; exceeded (?:max )?context length/i,
|
|
9237
|
+
/too large for model with \d+ maximum context length/i,
|
|
9238
|
+
/model_context_window_exceeded/i,
|
|
9239
|
+
/context size has been exceeded/i
|
|
9240
|
+
];
|
|
9241
|
+
var LIMIT_EXTRACTION_PATTERNS = [
|
|
9242
|
+
{ pattern: /maximum prompt length is (\d+)/i, provenance: "prompt_only" },
|
|
9243
|
+
{
|
|
9244
|
+
pattern: /maximum context length is (\d+) tokens?/i,
|
|
9245
|
+
provenance: "combined"
|
|
9246
|
+
},
|
|
9247
|
+
{ pattern: /maximum model length is (\d+)/i, provenance: "combined" },
|
|
9248
|
+
{ pattern: /context length is only (\d+) tokens?/i, provenance: "combined" },
|
|
9249
|
+
{ pattern: /exceeds the limit of (\d+)/i, provenance: "unknown" },
|
|
9250
|
+
{
|
|
9251
|
+
pattern: /too large for model with (\d+) maximum context length/i,
|
|
9252
|
+
provenance: "combined"
|
|
9253
|
+
},
|
|
9254
|
+
{ pattern: /context size.*(\d+) tokens?/i, provenance: "combined" },
|
|
9255
|
+
{ pattern: /exceeds? the context length of (\d+)/i, provenance: "combined" },
|
|
9256
|
+
{
|
|
9257
|
+
pattern: />\s*(\d+)\s*(?:tokens?\s*)?(?:maximum|max|limit)\b/i,
|
|
9258
|
+
provenance: "prompt_only"
|
|
9259
|
+
},
|
|
9260
|
+
{ pattern: /max(?:imum)?.*context.*?(\d+)/i, provenance: "unknown" }
|
|
9261
|
+
];
|
|
9262
|
+
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
9263
|
+
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
9264
|
+
function extractErrorMessage(error) {
|
|
9265
|
+
if (!error)
|
|
9266
|
+
return "";
|
|
9267
|
+
if (typeof error === "string")
|
|
9268
|
+
return error;
|
|
9269
|
+
if (typeof error === "object") {
|
|
9270
|
+
const obj = error;
|
|
9271
|
+
const nested = obj.error;
|
|
9272
|
+
if (nested && typeof nested.message === "string" && nested.message.length > 0) {
|
|
9273
|
+
return nested.message;
|
|
9274
|
+
}
|
|
9275
|
+
}
|
|
9276
|
+
if (error instanceof Error)
|
|
9277
|
+
return error.message;
|
|
9278
|
+
if (typeof error === "object") {
|
|
9279
|
+
const obj = error;
|
|
9280
|
+
if (typeof obj.message === "string")
|
|
9281
|
+
return obj.message;
|
|
9282
|
+
if (typeof obj.responseBody === "string")
|
|
9283
|
+
return obj.responseBody;
|
|
9284
|
+
try {
|
|
9285
|
+
return JSON.stringify(error);
|
|
9286
|
+
} catch {
|
|
9287
|
+
return String(error);
|
|
9288
|
+
}
|
|
9289
|
+
}
|
|
9290
|
+
return String(error);
|
|
9291
|
+
}
|
|
9292
|
+
function detectOverflow(error) {
|
|
9293
|
+
const message = extractErrorMessage(error);
|
|
9294
|
+
if (!message) {
|
|
9295
|
+
return { isOverflow: false };
|
|
9296
|
+
}
|
|
9297
|
+
const hasStatus413 = /\b413\b/.test(message) && /(entity|payload|context|prompt)/i.test(message);
|
|
9298
|
+
let matched;
|
|
9299
|
+
for (const pattern of OVERFLOW_PATTERNS) {
|
|
9300
|
+
if (pattern.test(message)) {
|
|
9301
|
+
matched = pattern;
|
|
9302
|
+
break;
|
|
9303
|
+
}
|
|
9304
|
+
}
|
|
9305
|
+
if (!matched && !hasStatus413) {
|
|
9306
|
+
return { isOverflow: false };
|
|
9307
|
+
}
|
|
9308
|
+
const reportedLimit = parseReportedLimit(message);
|
|
9309
|
+
return {
|
|
9310
|
+
isOverflow: true,
|
|
9311
|
+
reportedLimit: reportedLimit?.value,
|
|
9312
|
+
reportedLimitProvenance: reportedLimit?.provenance,
|
|
9313
|
+
matchedPattern: matched?.source
|
|
9314
|
+
};
|
|
9315
|
+
}
|
|
9316
|
+
function parseReportedLimit(message) {
|
|
9317
|
+
if (!message)
|
|
9318
|
+
return;
|
|
9319
|
+
for (const { pattern, provenance } of LIMIT_EXTRACTION_PATTERNS) {
|
|
9320
|
+
const match = message.match(pattern);
|
|
9321
|
+
if (!match)
|
|
9322
|
+
continue;
|
|
9323
|
+
const raw = match[1];
|
|
9324
|
+
if (!raw)
|
|
9325
|
+
continue;
|
|
9326
|
+
const value = Number.parseInt(raw, 10);
|
|
9327
|
+
if (!Number.isFinite(value))
|
|
9328
|
+
continue;
|
|
9329
|
+
if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
|
|
9330
|
+
continue;
|
|
9331
|
+
return { value, provenance };
|
|
9332
|
+
}
|
|
9333
|
+
return;
|
|
9334
|
+
}
|
|
9335
|
+
|
|
9336
|
+
// src/shared/model-suggestion-retry.ts
|
|
9337
|
+
var ABORT_CALL_TIMEOUT_MS = 3000;
|
|
9338
|
+
function copyPromptArgs(args, body) {
|
|
9339
|
+
return { ...args, body: { ...body } };
|
|
9340
|
+
}
|
|
9341
|
+
function extractMessage(error) {
|
|
9342
|
+
if (typeof error === "string")
|
|
9343
|
+
return error;
|
|
9344
|
+
if (error instanceof Error)
|
|
9345
|
+
return error.message;
|
|
9346
|
+
if (typeof error === "object" && error !== null) {
|
|
9347
|
+
const obj = error;
|
|
9348
|
+
if (typeof obj.message === "string")
|
|
9349
|
+
return obj.message;
|
|
9350
|
+
}
|
|
9351
|
+
try {
|
|
9352
|
+
return JSON.stringify(error);
|
|
9353
|
+
} catch (_error) {
|
|
9354
|
+
return String(error);
|
|
9355
|
+
}
|
|
9356
|
+
}
|
|
9357
|
+
function parseModelSuggestion(error) {
|
|
9358
|
+
if (!error)
|
|
9359
|
+
return null;
|
|
9360
|
+
if (typeof error === "object" && error !== null) {
|
|
9361
|
+
const errObj = error;
|
|
9362
|
+
if (errObj.name === "ProviderModelNotFoundError" && typeof errObj.data === "object" && errObj.data !== null) {
|
|
9363
|
+
const data = errObj.data;
|
|
9364
|
+
const suggestions = data.suggestions;
|
|
9365
|
+
if (Array.isArray(suggestions) && typeof suggestions[0] === "string") {
|
|
9366
|
+
return {
|
|
9367
|
+
providerID: String(data.providerID ?? ""),
|
|
9368
|
+
modelID: String(data.modelID ?? ""),
|
|
9369
|
+
suggestion: suggestions[0]
|
|
9370
|
+
};
|
|
9371
|
+
}
|
|
9372
|
+
}
|
|
9373
|
+
for (const key of ["data", "error", "cause"]) {
|
|
9374
|
+
const nested = errObj[key];
|
|
9375
|
+
if (nested && typeof nested === "object") {
|
|
9376
|
+
const result = parseModelSuggestion(nested);
|
|
9377
|
+
if (result)
|
|
9378
|
+
return result;
|
|
9379
|
+
}
|
|
9380
|
+
}
|
|
9381
|
+
}
|
|
9382
|
+
const message = extractMessage(error);
|
|
9383
|
+
const modelMatch = message.match(/model not found:\s*([^/\s]+)\s*\/\s*([^.,\s]+)/i);
|
|
9384
|
+
const suggestionMatch = message.match(/did you mean:\s*([^,?]+)/i);
|
|
9385
|
+
if (!modelMatch || !suggestionMatch) {
|
|
9386
|
+
return null;
|
|
9387
|
+
}
|
|
9388
|
+
return {
|
|
9389
|
+
providerID: modelMatch[1].trim(),
|
|
9390
|
+
modelID: modelMatch[2].trim(),
|
|
9391
|
+
suggestion: suggestionMatch[1].trim()
|
|
9392
|
+
};
|
|
9393
|
+
}
|
|
9394
|
+
async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
9395
|
+
if (signal?.aborted) {
|
|
9396
|
+
throw new Error("prompt aborted by external signal");
|
|
9397
|
+
}
|
|
9398
|
+
const controller = new AbortController;
|
|
9399
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
9400
|
+
const onExternalAbort = () => controller.abort();
|
|
9401
|
+
signal?.addEventListener("abort", onExternalAbort);
|
|
9402
|
+
try {
|
|
9403
|
+
await client.session.prompt({
|
|
9404
|
+
...args,
|
|
9405
|
+
signal: controller.signal
|
|
9406
|
+
});
|
|
9407
|
+
} catch (error) {
|
|
9408
|
+
if (signal?.aborted) {
|
|
9409
|
+
await abortChildRun(client, args.path.id);
|
|
9410
|
+
throw new Error("prompt aborted by external signal");
|
|
9411
|
+
}
|
|
9412
|
+
if (controller.signal.aborted) {
|
|
9413
|
+
await abortChildRun(client, args.path.id);
|
|
9414
|
+
throw new Error(`prompt timed out after ${timeoutMs}ms`);
|
|
9415
|
+
}
|
|
9416
|
+
throw error;
|
|
9417
|
+
} finally {
|
|
9418
|
+
clearTimeout(timeout);
|
|
9419
|
+
signal?.removeEventListener("abort", onExternalAbort);
|
|
9420
|
+
}
|
|
9421
|
+
}
|
|
9422
|
+
async function abortChildRun(client, sessionId) {
|
|
9423
|
+
try {
|
|
9424
|
+
await Promise.race([
|
|
9425
|
+
client.session.abort({ path: { id: sessionId } }),
|
|
9426
|
+
new Promise((resolve) => setTimeout(resolve, ABORT_CALL_TIMEOUT_MS))
|
|
9427
|
+
]);
|
|
9428
|
+
} catch (error) {
|
|
9429
|
+
log(`[model-retry] child session abort failed for ${sessionId}: ${String(error)}`);
|
|
9430
|
+
}
|
|
9431
|
+
}
|
|
9432
|
+
function isNonRetryable(error, externalSignal) {
|
|
9433
|
+
if (externalSignal?.aborted)
|
|
9434
|
+
return true;
|
|
9435
|
+
if (error instanceof Error) {
|
|
9436
|
+
if (error.name === "AbortError")
|
|
9437
|
+
return true;
|
|
9438
|
+
if (error.message === "prompt aborted by external signal")
|
|
9439
|
+
return true;
|
|
9440
|
+
if (/^prompt timed out after \d+ms$/.test(error.message))
|
|
9441
|
+
return true;
|
|
9442
|
+
}
|
|
9443
|
+
if (detectOverflow(error).isOverflow)
|
|
9444
|
+
return true;
|
|
9445
|
+
return false;
|
|
9446
|
+
}
|
|
9447
|
+
function shortErr(error) {
|
|
9448
|
+
if (error instanceof Error) {
|
|
9449
|
+
return error.name && error.name !== "Error" ? `${error.name}: ${error.message}` : error.message;
|
|
9450
|
+
}
|
|
9451
|
+
return extractMessage(error);
|
|
9452
|
+
}
|
|
9453
|
+
async function attemptOnce(client, args, timeoutMs, signal, callContext, label) {
|
|
9454
|
+
const originalBody = { ...args.body };
|
|
9455
|
+
const attemptArgs = copyPromptArgs(args, originalBody);
|
|
9456
|
+
try {
|
|
9457
|
+
await promptWithTimeout(client, attemptArgs, timeoutMs, signal);
|
|
9458
|
+
return;
|
|
9459
|
+
} catch (error) {
|
|
9460
|
+
if (isNonRetryable(error, signal))
|
|
9461
|
+
throw error;
|
|
9462
|
+
const suggestion = parseModelSuggestion(error);
|
|
9463
|
+
if (!suggestion || !originalBody.model) {
|
|
9464
|
+
throw error;
|
|
9465
|
+
}
|
|
9466
|
+
log(`[${callContext}] ${label}: model not found, retrying with suggestion`, {
|
|
9467
|
+
original: `${suggestion.providerID}/${suggestion.modelID}`,
|
|
9468
|
+
suggested: suggestion.suggestion
|
|
9469
|
+
});
|
|
9470
|
+
await promptWithTimeout(client, copyPromptArgs(args, {
|
|
9471
|
+
...originalBody,
|
|
9472
|
+
model: {
|
|
9473
|
+
providerID: suggestion.providerID,
|
|
9474
|
+
modelID: suggestion.suggestion
|
|
9475
|
+
}
|
|
9476
|
+
}), timeoutMs, signal);
|
|
9477
|
+
}
|
|
9478
|
+
}
|
|
9479
|
+
async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
|
|
9480
|
+
const timeoutMs = options.timeoutMs ?? 300000;
|
|
9481
|
+
const callContext = options.callContext ?? "subagent";
|
|
9482
|
+
const fallbacks = options.fallbackModels ?? [];
|
|
9483
|
+
const baseBody = { ...args.body };
|
|
9484
|
+
const baseArgs = copyPromptArgs(args, baseBody);
|
|
9485
|
+
const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
|
|
9486
|
+
let lastError = null;
|
|
9487
|
+
try {
|
|
9488
|
+
await attemptOnce(client, baseArgs, timeoutMs, options.signal, callContext, explicitPrimaryLabel);
|
|
9489
|
+
return;
|
|
9490
|
+
} catch (error) {
|
|
9491
|
+
lastError = error;
|
|
9492
|
+
if (isNonRetryable(error, options.signal))
|
|
9493
|
+
throw error;
|
|
9494
|
+
if (fallbacks.length === 0) {
|
|
9495
|
+
throw error;
|
|
9496
|
+
}
|
|
9497
|
+
log(`[${callContext}] primary (${explicitPrimaryLabel}) failed: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
|
|
9498
|
+
}
|
|
9499
|
+
for (let i = 0;i < fallbacks.length; i += 1) {
|
|
9500
|
+
const parsed = parseProviderModel(fallbacks[i]);
|
|
9501
|
+
if (!parsed) {
|
|
9502
|
+
log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
|
|
9503
|
+
continue;
|
|
9504
|
+
}
|
|
9505
|
+
const label = `${parsed.providerID}/${parsed.modelID}`;
|
|
9506
|
+
const attemptArgs = copyPromptArgs(baseArgs, {
|
|
9507
|
+
...baseBody,
|
|
9508
|
+
model: parsed
|
|
9509
|
+
});
|
|
9510
|
+
try {
|
|
9511
|
+
await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label);
|
|
9512
|
+
log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
|
|
9513
|
+
return;
|
|
9514
|
+
} catch (error) {
|
|
9515
|
+
lastError = error;
|
|
9516
|
+
if (isNonRetryable(error, options.signal))
|
|
9517
|
+
throw error;
|
|
9518
|
+
const remaining = fallbacks.length - i - 1;
|
|
9519
|
+
if (remaining > 0) {
|
|
9520
|
+
log(`[${callContext}] ${label} failed: ${shortErr(error)}; ${remaining} fallback(s) left`);
|
|
9521
|
+
}
|
|
9522
|
+
}
|
|
9523
|
+
}
|
|
9524
|
+
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; last error: ${shortErr(lastError)}`);
|
|
9525
|
+
throw lastError ?? new Error("All fallback models failed");
|
|
9526
|
+
}
|
|
9527
|
+
async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options) {
|
|
9528
|
+
await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label);
|
|
9529
|
+
const output = await options.fetchOutput(args, attempt);
|
|
9530
|
+
const validated = await options.validateOutput(output, attempt);
|
|
9531
|
+
return { output, validated, attempt };
|
|
9532
|
+
}
|
|
9533
|
+
async function promptSyncWithValidatedOutputRetry(client, args, options) {
|
|
9534
|
+
const timeoutMs = options.timeoutMs ?? 300000;
|
|
9535
|
+
const callContext = options.callContext ?? "subagent";
|
|
9536
|
+
const fallbacks = options.fallbackModels ?? [];
|
|
9537
|
+
const baseBody = { ...args.body };
|
|
9538
|
+
const baseArgs = copyPromptArgs(args, baseBody);
|
|
9539
|
+
const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
|
|
9540
|
+
const totalAttempts = fallbacks.length + 1;
|
|
9541
|
+
let firstError = null;
|
|
9542
|
+
let lastError = null;
|
|
9543
|
+
try {
|
|
9544
|
+
return await attemptAndValidate(client, baseArgs, timeoutMs, options.signal, callContext, {
|
|
9545
|
+
label: explicitPrimaryLabel,
|
|
9546
|
+
attemptIndex: 0,
|
|
9547
|
+
isFallback: false,
|
|
9548
|
+
totalAttempts,
|
|
9549
|
+
model: baseBody.model
|
|
9550
|
+
}, options);
|
|
9551
|
+
} catch (error) {
|
|
9552
|
+
firstError = error;
|
|
9553
|
+
lastError = error;
|
|
9554
|
+
if (isNonRetryable(error, options.signal))
|
|
9555
|
+
throw error;
|
|
9556
|
+
if (fallbacks.length === 0) {
|
|
9557
|
+
throw error;
|
|
9558
|
+
}
|
|
9559
|
+
log(`[${callContext}] primary (${explicitPrimaryLabel}) failed validation/prompt: ${shortErr(error)}; trying ${fallbacks.length} fallback(s)`);
|
|
9560
|
+
}
|
|
9561
|
+
for (let i = 0;i < fallbacks.length; i += 1) {
|
|
9562
|
+
const parsed = parseProviderModel(fallbacks[i]);
|
|
9563
|
+
if (!parsed) {
|
|
9564
|
+
log(`[${callContext}] skipping invalid fallback spec: ${fallbacks[i]}`);
|
|
9565
|
+
continue;
|
|
9566
|
+
}
|
|
9567
|
+
const label = `${parsed.providerID}/${parsed.modelID}`;
|
|
9568
|
+
const attemptArgs = copyPromptArgs(baseArgs, {
|
|
9569
|
+
...baseBody,
|
|
9570
|
+
model: parsed
|
|
9571
|
+
});
|
|
9572
|
+
const attempt = {
|
|
9573
|
+
label,
|
|
9574
|
+
attemptIndex: i + 1,
|
|
9575
|
+
isFallback: true,
|
|
9576
|
+
totalAttempts,
|
|
9577
|
+
model: parsed
|
|
9578
|
+
};
|
|
9579
|
+
try {
|
|
9580
|
+
const result = await attemptAndValidate(client, attemptArgs, timeoutMs, options.signal, callContext, attempt, options);
|
|
9581
|
+
log(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
|
|
9582
|
+
return result;
|
|
9583
|
+
} catch (error) {
|
|
9584
|
+
if (firstError === null)
|
|
9585
|
+
firstError = error;
|
|
9586
|
+
lastError = error;
|
|
9587
|
+
if (isNonRetryable(error, options.signal))
|
|
9588
|
+
throw error;
|
|
9589
|
+
const remaining = fallbacks.length - i - 1;
|
|
9590
|
+
if (remaining > 0) {
|
|
9591
|
+
log(`[${callContext}] ${label} failed validation/prompt: ${shortErr(error)}; ${remaining} fallback(s) left`);
|
|
9592
|
+
}
|
|
9593
|
+
}
|
|
9594
|
+
}
|
|
9595
|
+
log(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks].join(", ")}; original error: ${shortErr(firstError)}; last error: ${shortErr(lastError)}`);
|
|
9596
|
+
throw firstError ?? lastError ?? new Error("All fallback models failed validation");
|
|
9597
|
+
}
|
|
9598
|
+
// src/shared/normalize-sdk-response.ts
|
|
9599
|
+
function normalizeSDKResponse(response, fallback, options) {
|
|
9600
|
+
if (response === null || response === undefined) {
|
|
9601
|
+
return fallback;
|
|
9602
|
+
}
|
|
9603
|
+
if (Array.isArray(response)) {
|
|
9604
|
+
return response;
|
|
9605
|
+
}
|
|
9606
|
+
if (typeof response === "object" && "data" in response) {
|
|
9607
|
+
const data = response.data;
|
|
9608
|
+
if (data !== null && data !== undefined) {
|
|
9609
|
+
return data;
|
|
9610
|
+
}
|
|
9611
|
+
if (options?.preferResponseOnMissingData === true) {
|
|
9612
|
+
return response;
|
|
9613
|
+
}
|
|
9614
|
+
return fallback;
|
|
9615
|
+
}
|
|
9616
|
+
if (options?.preferResponseOnMissingData === true) {
|
|
9617
|
+
return response;
|
|
9618
|
+
}
|
|
9619
|
+
return fallback;
|
|
9620
|
+
}
|
|
9621
|
+
// src/shared/assistant-message-extractor.ts
|
|
9622
|
+
function asSessionMessage(value) {
|
|
9623
|
+
if (!isRecord(value))
|
|
9624
|
+
return null;
|
|
9625
|
+
const info = value.info;
|
|
9626
|
+
const parts = value.parts;
|
|
9627
|
+
return {
|
|
9628
|
+
info: isRecord(info) ? {
|
|
9629
|
+
role: typeof info.role === "string" ? info.role : undefined,
|
|
9630
|
+
time: isRecord(info.time) ? {
|
|
9631
|
+
created: typeof info.time.created === "number" ? info.time.created : undefined
|
|
9632
|
+
} : undefined
|
|
9633
|
+
} : undefined,
|
|
9634
|
+
parts
|
|
9635
|
+
};
|
|
9636
|
+
}
|
|
9637
|
+
function getCreatedTime(message) {
|
|
9638
|
+
return message.info?.time?.created ?? 0;
|
|
9639
|
+
}
|
|
9640
|
+
function getTextParts(message) {
|
|
9641
|
+
if (!Array.isArray(message.parts))
|
|
9642
|
+
return [];
|
|
9643
|
+
return message.parts.filter((part) => isRecord(part)).map((part) => ({
|
|
9644
|
+
type: typeof part.type === "string" ? part.type : undefined,
|
|
9645
|
+
text: typeof part.text === "string" ? part.text : undefined
|
|
9646
|
+
})).filter((part) => part.type === "text" && Boolean(part.text));
|
|
9647
|
+
}
|
|
9648
|
+
function extractLatestAssistantText(messages) {
|
|
9649
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
9650
|
+
return null;
|
|
9651
|
+
const assistantMessages = messages.map(asSessionMessage).filter((message) => message !== null).filter((message) => message.info?.role === "assistant").sort((a, b) => getCreatedTime(b) - getCreatedTime(a));
|
|
9652
|
+
const latest = assistantMessages[0];
|
|
9653
|
+
if (!latest)
|
|
9654
|
+
return null;
|
|
9655
|
+
return getTextParts(latest).map((part) => part.text).join(`
|
|
9656
|
+
`) || null;
|
|
9657
|
+
}
|
|
9658
|
+
function hasLengthCappedOutput(value) {
|
|
9659
|
+
if (Array.isArray(value))
|
|
9660
|
+
return value.some((item) => hasLengthCappedOutput(item));
|
|
9661
|
+
if (!isRecord(value))
|
|
9662
|
+
return false;
|
|
9663
|
+
if (value.length_capped === true || value.lengthCapped === true)
|
|
9664
|
+
return true;
|
|
9665
|
+
const finishReason = value.finish_reason ?? value.finishReason;
|
|
9666
|
+
if (typeof finishReason === "string") {
|
|
9667
|
+
const normalized = finishReason.toLowerCase();
|
|
9668
|
+
if (normalized === "length" || normalized === "max_tokens" || normalized === "max_output_tokens") {
|
|
9669
|
+
return true;
|
|
9670
|
+
}
|
|
9671
|
+
}
|
|
9672
|
+
return Object.values(value).some((item) => hasLengthCappedOutput(item));
|
|
9673
|
+
}
|
|
9674
|
+
|
|
9675
|
+
// src/shared/keep-subagents.ts
|
|
9676
|
+
var keepSubagents = false;
|
|
9677
|
+
function setKeepSubagents(value) {
|
|
9678
|
+
keepSubagents = value === true;
|
|
9679
|
+
}
|
|
9680
|
+
function shouldKeepSubagents() {
|
|
9681
|
+
return keepSubagents;
|
|
9682
|
+
}
|
|
9683
|
+
|
|
9213
9684
|
// src/features/magic-context/user-memory/storage-user-memory.ts
|
|
9214
9685
|
var USER_MEMORY_CANDIDATE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
9215
9686
|
function insertUserMemoryCandidates(db, candidates) {
|
|
@@ -9277,9 +9748,9 @@ function parseUserMemoryRow(row) {
|
|
|
9277
9748
|
}
|
|
9278
9749
|
|
|
9279
9750
|
// src/features/magic-context/mural/storage-mural-cues.ts
|
|
9280
|
-
import { createHash as
|
|
9751
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
9281
9752
|
function computeCueContentHash(content) {
|
|
9282
|
-
return
|
|
9753
|
+
return createHash8("sha256").update(content).digest("hex");
|
|
9283
9754
|
}
|
|
9284
9755
|
var muralCueColumnCache = new WeakMap;
|
|
9285
9756
|
function hasMuralCueColumns(db) {
|
|
@@ -9305,10 +9776,10 @@ function getMuralCueState(db, memoryIds) {
|
|
|
9305
9776
|
}
|
|
9306
9777
|
return out;
|
|
9307
9778
|
}
|
|
9308
|
-
function memoryNeedsCue(
|
|
9309
|
-
if (!
|
|
9779
|
+
function memoryNeedsCue(state2, currentContent) {
|
|
9780
|
+
if (!state2 || state2.cue === null || state2.hash === null)
|
|
9310
9781
|
return true;
|
|
9311
|
-
return
|
|
9782
|
+
return state2.hash !== computeCueContentHash(currentContent);
|
|
9312
9783
|
}
|
|
9313
9784
|
function setMuralCue(db, projectPath, id, cue, contentHash) {
|
|
9314
9785
|
if (!hasMuralCueColumns(db))
|
|
@@ -9330,7 +9801,6 @@ var deleteEmbeddingStatements = new WeakMap;
|
|
|
9330
9801
|
var getStoredModelIdStatements = new WeakMap;
|
|
9331
9802
|
var clearAllEmbeddingsStatements = new WeakMap;
|
|
9332
9803
|
var clearModelEmbeddingsStatements = new WeakMap;
|
|
9333
|
-
var getDistinctStoredModelIdsStatements = new WeakMap;
|
|
9334
9804
|
function isEmbeddingBlob(value) {
|
|
9335
9805
|
return value instanceof Uint8Array || value instanceof ArrayBuffer;
|
|
9336
9806
|
}
|
|
@@ -9447,13 +9917,13 @@ function invalidateMemory(projectPath, memoryId) {
|
|
|
9447
9917
|
}
|
|
9448
9918
|
|
|
9449
9919
|
// src/features/magic-context/memory/normalize-hash.ts
|
|
9450
|
-
import { createHash as
|
|
9920
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
9451
9921
|
function normalizeMemoryContent(content) {
|
|
9452
9922
|
return content.toLowerCase().replace(/\s+/g, " ").trim();
|
|
9453
9923
|
}
|
|
9454
9924
|
function computeNormalizedHash(content) {
|
|
9455
9925
|
const normalized = normalizeMemoryContent(content);
|
|
9456
|
-
return
|
|
9926
|
+
return createHash9("md5").update(normalized).digest("hex");
|
|
9457
9927
|
}
|
|
9458
9928
|
|
|
9459
9929
|
// src/features/magic-context/memory/visibility.ts
|
|
@@ -10317,9 +10787,12 @@ async function runMemoryMigration(deps) {
|
|
|
10317
10787
|
const modelOverride = modelId ? parseProviderModel(modelId) : null;
|
|
10318
10788
|
await cleanupChildSession(agentSessionId);
|
|
10319
10789
|
agentSessionId = null;
|
|
10320
|
-
const createResponse = await
|
|
10321
|
-
|
|
10322
|
-
|
|
10790
|
+
const createResponse = await createChildSessionWithFence({
|
|
10791
|
+
client,
|
|
10792
|
+
db,
|
|
10793
|
+
parentSessionId,
|
|
10794
|
+
title: "magic-context-memory-migration",
|
|
10795
|
+
directory
|
|
10323
10796
|
});
|
|
10324
10797
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
10325
10798
|
preferResponseOnMissingData: true
|
|
@@ -10419,7 +10892,7 @@ async function runMemoryMigration(deps) {
|
|
|
10419
10892
|
}
|
|
10420
10893
|
|
|
10421
10894
|
// src/features/magic-context/compartment-chunk-embedding.ts
|
|
10422
|
-
import { createHash as
|
|
10895
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
10423
10896
|
|
|
10424
10897
|
// src/features/magic-context/recursive-text-splitter.ts
|
|
10425
10898
|
var DEFAULT_SEPARATORS = [`
|
|
@@ -10514,9 +10987,6 @@ var existingHashStatements = new WeakMap;
|
|
|
10514
10987
|
var existingHashByProjectStatements = new WeakMap;
|
|
10515
10988
|
var deleteByCompartmentStatements = new WeakMap;
|
|
10516
10989
|
var insertEmbeddingStatements = new WeakMap;
|
|
10517
|
-
var distinctModelStatements = new WeakMap;
|
|
10518
|
-
var clearProjectStatements = new WeakMap;
|
|
10519
|
-
var clearProjectModelStatements = new WeakMap;
|
|
10520
10990
|
var searchRowsStatements = new WeakMap;
|
|
10521
10991
|
var searchRowsByModelStatements = new WeakMap;
|
|
10522
10992
|
var searchPoolProbeStatements = new WeakMap;
|
|
@@ -10707,7 +11177,7 @@ function parseCanonicalLineRange(line) {
|
|
|
10707
11177
|
return { start, end };
|
|
10708
11178
|
}
|
|
10709
11179
|
function hashChunkText(text) {
|
|
10710
|
-
return
|
|
11180
|
+
return createHash10("sha256").update(text).digest("hex");
|
|
10711
11181
|
}
|
|
10712
11182
|
function vectorBlob2(vector) {
|
|
10713
11183
|
return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
|
|
@@ -11098,7 +11568,7 @@ function countSessionCompartmentEmbedCoverage(db, projectPath, sessionId, modelI
|
|
|
11098
11568
|
}
|
|
11099
11569
|
|
|
11100
11570
|
// src/features/magic-context/project-embedding-registry.ts
|
|
11101
|
-
import { createHash as
|
|
11571
|
+
import { createHash as createHash12, randomUUID as randomUUID2 } from "node:crypto";
|
|
11102
11572
|
|
|
11103
11573
|
// src/config/schema/magic-context.ts
|
|
11104
11574
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -25550,7 +26020,7 @@ var AgentOverrideConfigSchema = exports_external.object({
|
|
|
25550
26020
|
|
|
25551
26021
|
// src/config/schema/magic-context.ts
|
|
25552
26022
|
var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65;
|
|
25553
|
-
var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at
|
|
26023
|
+
var EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 90% for cache safety: output capacity is reserved from the usable context window, and the remaining 10% absorbs mid-turn growth before the absolute 95% emergency wall. Use a value between 20 and 90.";
|
|
25554
26024
|
var DEFAULT_HISTORIAN_TIMEOUT_MS = 300000;
|
|
25555
26025
|
var DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15;
|
|
25556
26026
|
var DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
@@ -25648,7 +26118,22 @@ var BaseEmbeddingConfigSchema = exports_external.object({
|
|
|
25648
26118
|
input_type: exports_external.string().optional().describe("Default input_type for stored/indexed (passage) embeddings in the request body. Required by some openai-compatible providers (e.g. NVIDIA NIM). Omitted from the request when unset."),
|
|
25649
26119
|
query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
|
|
25650
26120
|
truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
|
|
25651
|
-
max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
|
|
26121
|
+
max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted."),
|
|
26122
|
+
local_dtype: exports_external.enum([
|
|
26123
|
+
"auto",
|
|
26124
|
+
"fp32",
|
|
26125
|
+
"fp16",
|
|
26126
|
+
"q8",
|
|
26127
|
+
"int8",
|
|
26128
|
+
"uint8",
|
|
26129
|
+
"q4",
|
|
26130
|
+
"bnb4",
|
|
26131
|
+
"q4f16",
|
|
26132
|
+
"q2",
|
|
26133
|
+
"q2f16",
|
|
26134
|
+
"q1",
|
|
26135
|
+
"q1f16"
|
|
26136
|
+
]).optional().describe("Local provider only: ONNX model dtype passed to the transformers.js feature-extraction pipeline. Accepts the @huggingface/transformers DataType strings (auto, fp32, fp16, q8, int8, uint8, q4, bnb4, q4f16, q2, q2f16, q1, q1f16). Omitted keeps today's behavior (fp32). A non-default value changes the produced vectors and folds into the embedding model identity, so switching dtype re-embeds rather than mixing vector spaces. Useful for selecting a quantized variant (e.g. q8) of a larger multilingual model to cut memory and CPU cost; see issue #259.")
|
|
25652
26137
|
}).superRefine((data, ctx) => {
|
|
25653
26138
|
const validationProvider = data.provider === "synapse" ? data.fallback_provider : data.provider;
|
|
25654
26139
|
if (validationProvider === "openai-compatible" && !data.endpoint?.trim()) {
|
|
@@ -25690,7 +26175,8 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
|
25690
26175
|
return {
|
|
25691
26176
|
provider: "local",
|
|
25692
26177
|
model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
25693
|
-
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
|
|
26178
|
+
...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {},
|
|
26179
|
+
...data.local_dtype ? { local_dtype: data.local_dtype } : {}
|
|
25694
26180
|
};
|
|
25695
26181
|
}
|
|
25696
26182
|
if (data.provider === "openai-compatible") {
|
|
@@ -25713,6 +26199,7 @@ var EmbeddingConfigSchema = BaseEmbeddingConfigSchema.transform((data) => {
|
|
|
25713
26199
|
});
|
|
25714
26200
|
var MagicContextConfigSchema = exports_external.object({
|
|
25715
26201
|
enabled: exports_external.boolean().default(true).describe("Enable magic context (default: true)"),
|
|
26202
|
+
allow_home_project: exports_external.boolean().default(false).describe("Allow Magic Context sessions launched from the exact canonical home directory. The home session uses its deterministic dir: identity so pre-gate memories reconnect. USER-LEVEL ONLY: project config is ignored. The home identity is excluded from registry seed exports, never resolves descendants by containment, and cannot join a workspace."),
|
|
25716
26203
|
experimental: exports_external.object({
|
|
25717
26204
|
mural: exports_external.object({
|
|
25718
26205
|
enabled: exports_external.boolean().default(false),
|
|
@@ -25724,15 +26211,19 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
25724
26211
|
language: exports_external.string().trim().toLowerCase().refine((s) => isValidLanguageCode(s), 'language must be a 2-letter ISO 639-1 code (e.g. "tr", "es", "de")').optional().describe("Output language for Magic Context's generated content and guidance, as a " + '2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' + "historian, dreamer, sidekick, and the agent-guidance block instruct the model to " + "write its PROSE in this language while keeping all structural tokens (XML tags, " + "the five memory category names, code identifiers, file paths) in English. " + "USER-LEVEL ONLY (ignored in project config for security). Unset = today's " + "behavior (model mirrors the conversation; English scaffolding). Changing it " + "triggers one cache re-materialization; existing compartments/memories keep their " + "original language until naturally rewritten."),
|
|
25725
26212
|
historian: HistorianConfigSchema.describe("Historian agent configuration (model, fallback_models, variant, temperature, maxTokens, permission, two_pass, etc.)"),
|
|
25726
26213
|
dreamer: DreamerConfigSchema.optional().describe("Dreamer agent + scheduling configuration (model, fallback_models, disable, schedule, tasks, etc.)"),
|
|
25727
|
-
cache_ttl: exports_external.union([exports_external.string(), exports_external.object({ default: exports_external.string() }).catchall(exports_external.string())]).default("5m").describe('Cache TTL: string (e.g. "5m") or per-model object ({ default: "5m", "model-id": "10m" })'),
|
|
26214
|
+
cache_ttl: exports_external.union([exports_external.string(), exports_external.object({ default: exports_external.string() }).catchall(exports_external.string())]).default("5m").describe('Cache TTL: string (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "model-id": "10m" }). Set to "never" for lanes kept warm by an external keepwarm proxy — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time.'),
|
|
26215
|
+
output_reserve: exports_external.union([
|
|
26216
|
+
exports_external.number().min(0),
|
|
26217
|
+
exports_external.object({ default: exports_external.number().min(0) }).catchall(exports_external.number().min(0))
|
|
26218
|
+
]).optional().describe('User-only output-token reservation override. Number or per-model object ({ default: 16384, "provider/model": 8192 }); 0 disables reservation. When unset, Magic Context reserves the catalog output limit (capped at 25% of context) for shared-window providers and keeps proven separate-quota Google/Gemini windows unchanged.'),
|
|
25728
26219
|
toast_duration_ms: exports_external.number().min(0).max(60000).default(5000).describe("TUI toast lifetime in milliseconds for Magic Context notifications. Set to 0 to disable Magic Context toasts entirely (min: 0, max: 60000, default: 5000)"),
|
|
25729
26220
|
execute_threshold_percentage: exports_external.union([
|
|
25730
|
-
exports_external.number().min(20).max(
|
|
25731
|
-
exports_external.object({ default: exports_external.number().min(20).max(
|
|
25732
|
-
]).default(DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE).describe('Context percentage that forces queued operations to execute. Number or per-model object ({ default: 65, "provider/model": 45 }). Values above
|
|
26221
|
+
exports_external.number().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE),
|
|
26222
|
+
exports_external.object({ default: exports_external.number().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE) }).catchall(exports_external.number().min(20).max(90, EXECUTE_THRESHOLD_CAP_MESSAGE))
|
|
26223
|
+
]).default(DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE).describe('Context percentage that forces queued operations to execute. Number or per-model object ({ default: 65, "provider/model": 45 }). Values above 90 are rejected because the runtime caps at 90% of the output-reserved safe window (MAX_EXECUTE_THRESHOLD). Default: DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE'),
|
|
25733
26224
|
execute_threshold_tokens: exports_external.object({
|
|
25734
26225
|
default: exports_external.number().min(5000).max(2000000).optional()
|
|
25735
|
-
}).catchall(exports_external.number().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above
|
|
26226
|
+
}).catchall(exports_external.number().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000."),
|
|
25736
26227
|
protected_tags: exports_external.number().min(1).max(100).optional().describe("Number of recent tags to protect from dropping (min: 1, max: 100, default: 20)"),
|
|
25737
26228
|
clear_reasoning_age: exports_external.number().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
|
|
25738
26229
|
history_budget_percentage: exports_external.number().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE).describe("Fraction of usable context (context_limit × execute_threshold) reserved for the session history block (default: 0.15)"),
|
|
@@ -25752,6 +26243,9 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
25752
26243
|
cache_size_mb: exports_external.number().min(2).max(2048).default(64).describe("Page-cache size in MiB per connection (PRAGMA cache_size). Larger keeps more hot pages resident, cutting re-reads on repeated full-table scans. (min 2, max 2048, default 64)"),
|
|
25753
26244
|
mmap_size_mb: exports_external.number().min(0).max(8192).default(0).describe("Memory-mapped I/O size in MiB (PRAGMA mmap_size). 0 disables mmap (SQLite default). Raising it can cut read overhead on large DBs at the cost of address space. (min 0, max 8192, default 0)")
|
|
25754
26245
|
}).default({ cache_size_mb: 64, mmap_size_mb: 0 }).describe("SQLite connection tuning for Magic Context's own context.db. These are per-connection PRAGMAs applied at open; they do not change the schema or what is stored."),
|
|
26246
|
+
storage: exports_external.object({
|
|
26247
|
+
enforce_private_permissions: exports_external.boolean().default(true).describe("When true (default), Magic Context creates and re-tightens its storage directories to owner-only 0700 and storage files to owner-only 0600. Set false only for a deliberate trusted-group deployment whose operator manages directory, database, WAL/SHM, cache, and RPC file permissions externally; Magic Context then never chmods or supplies restrictive creation modes. USER-LEVEL ONLY — ignored in project config for security. On Windows, POSIX chmod modes are already meaningless, so this setting is a no-op.")
|
|
26248
|
+
}).default({ enforce_private_permissions: true }).describe("Storage permission policy. The default keeps session content and memories owner-private. Disabling enforcement is for trusted shared-group storage managed externally; every group member able to read the storage can read all stored session content and memories."),
|
|
25755
26249
|
embedding: EmbeddingConfigSchema.default({
|
|
25756
26250
|
provider: "local",
|
|
25757
26251
|
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
@@ -25765,6 +26259,9 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
25765
26259
|
temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add compact date ranges to compartment headings. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
|
|
25766
26260
|
keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
|
|
25767
26261
|
fail_closed_blocking: exports_external.boolean().default(true).describe("When Magic Context cannot operate (schema fence mismatch, storage open/migration failure), block the primary-session prompt with a loud recovery error instead of silently degrading to native compaction. Default true. Set false only to restore the old degrade-silently behavior (not recommended). USER-LEVEL ONLY — ignored in project config for security. Requires a restart."),
|
|
26262
|
+
compaction: exports_external.object({
|
|
26263
|
+
enabled: exports_external.boolean().default(true).describe("When false, Magic Context stops managing the context window and keeps its knowledge layer: memory and docs/user-profile/key-files injection through additive m[0]/m[1], raw-message FTS indexing, dreamer, notes, ctx_search, ctx_expand, ctx_memory, and /ctx-embed remain available. MC's historian/compartment preparation, tagging, markers, pruning, folding, drops, strips, splicing, synthetic context-management todos, temporal markers, nudges, and fail-closed blocking stop; ctx_expand remains a knowledge-surface tool. fail_closed_blocking is inert: a transform failure passes the input messages through without blocking or cancelling. This setting does not enable native compaction: OpenCode's compaction.auto / compaction.prune or Pi's equivalent owns the window, or nothing does. MC's compaction.enabled in magic-context.jsonc is distinct from OpenCode's compaction.auto / compaction.prune in opencode.jsonc; they are different files and different owners. On the first turn after disabling, a long session may trigger one native compaction cycle; MC removes only its own marker boundary, leaves native boundaries and stored compartments intact, and does no pre-trimming mitigation. Marker cleanup is lazy per session, so an unresumed session is cleaned when it is next resumed. If compaction is enabled again, run /ctx-wrapup when the historian is runnable to catch up. OpenCode peer verification against v1.18.4 confirms native compaction covers child sessions: subagents receive additive memory/docs injection and no MC reclaim in this mode, so keep subagent tasks small or leave compaction.enabled on for long subagent runs. If transform_mode is rust, compaction-off resolves to the TypeScript transform and emits one frozen boot warning because there is no Rust reduced-mode contract. This is boot-resolved and requires a process restart; project-tier compaction.enabled is stripped so a cloned repository cannot disable the user's setting. The sidebar reports raw usage as Context: <pct>% · native compaction or Context: <pct>% · no active compaction and does not show an MC execute-threshold fill. /ctx-wrapup, /ctx-recomp, /ctx-flush, and /ctx-session-upgrade refuse without context-management side effects; /ctx-embed remains functional. Raw content hidden by a native boundary before Magic Context's first pass is not retroactively indexed.")
|
|
26264
|
+
}).default({ enabled: true }).describe("Compaction-off mode gate. Default true (MC manages the context window as today). Set compaction.enabled=false to keep the knowledge layer while letting native compaction (or nothing) own the window. Boot-resolved; requires a restart to change."),
|
|
25768
26265
|
todowrite: exports_external.object({
|
|
25769
26266
|
enabled: exports_external.boolean().default(true).describe("Pi only: register Magic Context's todowrite task-list tool. Disable if you use your own todo extension. OpenCode ships its own built-in todowrite; this setting has no effect there."),
|
|
25770
26267
|
overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
|
|
@@ -25811,9 +26308,6 @@ var saveStatements = new WeakMap;
|
|
|
25811
26308
|
var loadProjectStatements = new WeakMap;
|
|
25812
26309
|
var loadUnembeddedStatements = new WeakMap;
|
|
25813
26310
|
var countEmbeddedStatements = new WeakMap;
|
|
25814
|
-
var clearProjectStatements2 = new WeakMap;
|
|
25815
|
-
var clearProjectModelStatements2 = new WeakMap;
|
|
25816
|
-
var distinctModelIdStatements = new WeakMap;
|
|
25817
26311
|
function getSaveStatement(db) {
|
|
25818
26312
|
let stmt = saveStatements.get(db);
|
|
25819
26313
|
if (!stmt) {
|
|
@@ -25884,7 +26378,6 @@ function countEmbeddedCommits(db, projectPath, modelId) {
|
|
|
25884
26378
|
var insertStatements = new WeakMap;
|
|
25885
26379
|
var existingShasStatements = new WeakMap;
|
|
25886
26380
|
var projectCountStatements = new WeakMap;
|
|
25887
|
-
var evictStatements = new WeakMap;
|
|
25888
26381
|
var evictOverflowStatements = new WeakMap;
|
|
25889
26382
|
var latestCommitTimeStatements = new WeakMap;
|
|
25890
26383
|
function getInsertStatement(db) {
|
|
@@ -26126,7 +26619,7 @@ function releaseGitSweepLease(db, projectPath, holderId) {
|
|
|
26126
26619
|
}
|
|
26127
26620
|
|
|
26128
26621
|
// src/features/magic-context/memory/embedding-synapse.ts
|
|
26129
|
-
import { createHash as
|
|
26622
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
26130
26623
|
|
|
26131
26624
|
// ../../node_modules/.bun/@cortexkit+subc-client@0.4.1/node_modules/@cortexkit/subc-client/dist/client.js
|
|
26132
26625
|
import { promises as fs2 } from "node:fs";
|
|
@@ -28339,7 +28832,7 @@ function wait(ms) {
|
|
|
28339
28832
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
28340
28833
|
}
|
|
28341
28834
|
function sha256(value) {
|
|
28342
|
-
return
|
|
28835
|
+
return createHash11("sha256").update(value).digest("hex");
|
|
28343
28836
|
}
|
|
28344
28837
|
function stableJson(value) {
|
|
28345
28838
|
if (Array.isArray(value))
|
|
@@ -28387,7 +28880,7 @@ function extractCatalogEntries(value) {
|
|
|
28387
28880
|
const batchRecord = asRecord(rawBatch);
|
|
28388
28881
|
const recommendedBatch = typeof rawBatch === "number" ? rawBatch : batchRecord ? batchRecord.rows : undefined;
|
|
28389
28882
|
const recommendedTokenBudget = batchRecord ? batchRecord.token_budget : undefined;
|
|
28390
|
-
const
|
|
28883
|
+
const state2 = typeof record2.state === "string" ? record2.state : undefined;
|
|
28391
28884
|
return [
|
|
28392
28885
|
{
|
|
28393
28886
|
model,
|
|
@@ -28398,7 +28891,7 @@ function extractCatalogEntries(value) {
|
|
|
28398
28891
|
...typeof recommendedTokenBudget === "number" && recommendedTokenBudget > 0 ? { recommended_token_budget: Math.floor(recommendedTokenBudget) } : {},
|
|
28399
28892
|
...record2.provenance !== undefined ? { provenance: record2.provenance } : {},
|
|
28400
28893
|
...typeof record2.certified === "boolean" ? { certified: record2.certified } : {},
|
|
28401
|
-
...typeof record2.status === "string" ? { status: record2.status } :
|
|
28894
|
+
...typeof record2.status === "string" ? { status: record2.status } : state2 ? { status: state2 } : {}
|
|
28402
28895
|
}
|
|
28403
28896
|
];
|
|
28404
28897
|
});
|
|
@@ -28784,6 +29277,7 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
28784
29277
|
throw new Error("Unknown embedding provider");
|
|
28785
29278
|
}
|
|
28786
29279
|
const truncate = config2.provider === "openai-compatible" ? config2.truncate?.trim() : undefined;
|
|
29280
|
+
const localDtype = config2.provider === "local" && config2.local_dtype && config2.local_dtype !== "fp32" ? config2.local_dtype : undefined;
|
|
28787
29281
|
const identityInput = config2.provider === "openai-compatible" ? {
|
|
28788
29282
|
provider: "openai-compatible",
|
|
28789
29283
|
model: config2.model.trim(),
|
|
@@ -28795,7 +29289,8 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
28795
29289
|
provider: "local",
|
|
28796
29290
|
model: config2.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
28797
29291
|
endpoint: "",
|
|
28798
|
-
apiKeyPresent: false
|
|
29292
|
+
apiKeyPresent: false,
|
|
29293
|
+
...localDtype ? { localDtype } : {}
|
|
28799
29294
|
};
|
|
28800
29295
|
return `embedding-provider:${computeNormalizedHash(JSON.stringify(identityInput))}`;
|
|
28801
29296
|
}
|
|
@@ -28803,7 +29298,7 @@ function getEmbeddingProviderIdentity(config2) {
|
|
|
28803
29298
|
// src/features/magic-context/memory/embedding-local.ts
|
|
28804
29299
|
import { chmodSync as chmodSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
28805
29300
|
import { open, stat, unlink, writeFile } from "node:fs/promises";
|
|
28806
|
-
import { dirname as dirname2, join as
|
|
29301
|
+
import { dirname as dirname2, join as join4 } from "node:path";
|
|
28807
29302
|
import { pathToFileURL } from "node:url";
|
|
28808
29303
|
var LOCK_POLL_MS = 150;
|
|
28809
29304
|
var STALE_LOCK_MS = 3 * 60000;
|
|
@@ -28883,6 +29378,7 @@ async function injectWasmOrtForElectron() {
|
|
|
28883
29378
|
return false;
|
|
28884
29379
|
}
|
|
28885
29380
|
}
|
|
29381
|
+
var DEFAULT_LOCAL_DTYPE = "fp32";
|
|
28886
29382
|
async function withQuietConsole(fn) {
|
|
28887
29383
|
const origWarn = console.warn;
|
|
28888
29384
|
const origError = console.error;
|
|
@@ -28959,16 +29455,22 @@ class LocalEmbeddingProvider {
|
|
|
28959
29455
|
modelId;
|
|
28960
29456
|
maxInputTokens;
|
|
28961
29457
|
model;
|
|
29458
|
+
dtype;
|
|
28962
29459
|
pipeline = null;
|
|
28963
29460
|
initPromise = null;
|
|
28964
29461
|
inFlight = 0;
|
|
28965
29462
|
disposing = false;
|
|
28966
29463
|
disposePromise = null;
|
|
28967
29464
|
inFlightWaiters = [];
|
|
28968
|
-
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512) {
|
|
29465
|
+
constructor(model = DEFAULT_LOCAL_EMBEDDING_MODEL, maxInputTokens = 512, dtype = DEFAULT_LOCAL_DTYPE) {
|
|
28969
29466
|
this.model = model;
|
|
28970
29467
|
this.maxInputTokens = maxInputTokens;
|
|
28971
|
-
this.
|
|
29468
|
+
this.dtype = dtype || DEFAULT_LOCAL_DTYPE;
|
|
29469
|
+
this.modelId = getEmbeddingProviderIdentity({
|
|
29470
|
+
provider: "local",
|
|
29471
|
+
model,
|
|
29472
|
+
...dtype && dtype !== DEFAULT_LOCAL_DTYPE ? { local_dtype: dtype } : {}
|
|
29473
|
+
});
|
|
28972
29474
|
}
|
|
28973
29475
|
async initialize() {
|
|
28974
29476
|
if (this.disposing) {
|
|
@@ -28997,20 +29499,24 @@ class LocalEmbeddingProvider {
|
|
|
28997
29499
|
if (LogLevel && "ERROR" in LogLevel) {
|
|
28998
29500
|
env.logLevel = LogLevel.ERROR;
|
|
28999
29501
|
}
|
|
29000
|
-
const modelCacheDir =
|
|
29502
|
+
const modelCacheDir = join4(getMagicContextStorageDir(), "models");
|
|
29001
29503
|
try {
|
|
29002
|
-
|
|
29003
|
-
|
|
29004
|
-
|
|
29005
|
-
|
|
29006
|
-
|
|
29504
|
+
if (shouldEnforcePrivateStoragePermissions()) {
|
|
29505
|
+
mkdirSync2(modelCacheDir, { recursive: true, mode: 448 });
|
|
29506
|
+
if (process.platform !== "win32") {
|
|
29507
|
+
try {
|
|
29508
|
+
chmodSync2(modelCacheDir, 448);
|
|
29509
|
+
} catch {}
|
|
29510
|
+
}
|
|
29511
|
+
} else {
|
|
29512
|
+
mkdirSync2(modelCacheDir, { recursive: true });
|
|
29007
29513
|
}
|
|
29008
29514
|
env.cacheDir = modelCacheDir;
|
|
29009
29515
|
} catch {
|
|
29010
29516
|
log("[magic-context] could not create model cache dir, using library default");
|
|
29011
29517
|
}
|
|
29012
29518
|
const createPipeline = transformersModule.pipeline;
|
|
29013
|
-
const lockPath =
|
|
29519
|
+
const lockPath = join4(modelCacheDir, ".load.lock");
|
|
29014
29520
|
const releaseLock = await acquireModelLoadLock(lockPath);
|
|
29015
29521
|
const stopHeartbeat = startLockHeartbeat(lockPath);
|
|
29016
29522
|
try {
|
|
@@ -29019,7 +29525,7 @@ class LocalEmbeddingProvider {
|
|
|
29019
29525
|
for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
|
|
29020
29526
|
try {
|
|
29021
29527
|
const pipeline = await withQuietConsole(() => createPipeline("feature-extraction", this.model, {
|
|
29022
|
-
dtype:
|
|
29528
|
+
dtype: this.dtype,
|
|
29023
29529
|
...injectedWasmOrt ? { device: "auto" } : {}
|
|
29024
29530
|
}));
|
|
29025
29531
|
if (this.disposing) {
|
|
@@ -29670,7 +30176,8 @@ function resolveEmbeddingConfig(config2) {
|
|
|
29670
30176
|
model: config2?.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
|
|
29671
30177
|
...config2?.max_input_tokens ? {
|
|
29672
30178
|
max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
|
|
29673
|
-
} : {}
|
|
30179
|
+
} : {},
|
|
30180
|
+
...config2?.local_dtype ? { local_dtype: config2.local_dtype } : {}
|
|
29674
30181
|
};
|
|
29675
30182
|
}
|
|
29676
30183
|
if (config2.provider === "openai-compatible") {
|
|
@@ -29729,7 +30236,7 @@ function createProvider(config2, context) {
|
|
|
29729
30236
|
});
|
|
29730
30237
|
}
|
|
29731
30238
|
if (config2.provider === "local") {
|
|
29732
|
-
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
30239
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype);
|
|
29733
30240
|
}
|
|
29734
30241
|
if (config2.provider === "synapse") {
|
|
29735
30242
|
const synapse = config2;
|
|
@@ -29758,10 +30265,10 @@ function stableStringify2(value) {
|
|
|
29758
30265
|
return JSON.stringify(value);
|
|
29759
30266
|
}
|
|
29760
30267
|
function sha256Prefix(value, length = 16) {
|
|
29761
|
-
return
|
|
30268
|
+
return createHash12("sha256").update(value).digest("hex").slice(0, length);
|
|
29762
30269
|
}
|
|
29763
30270
|
function contentSha256(value) {
|
|
29764
|
-
return
|
|
30271
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
29765
30272
|
}
|
|
29766
30273
|
function getRuntimeFingerprint(config2) {
|
|
29767
30274
|
if (config2.provider === "off") {
|
|
@@ -31036,12 +31543,12 @@ function parseFields(json2) {
|
|
|
31036
31543
|
}
|
|
31037
31544
|
|
|
31038
31545
|
// src/hooks/magic-context/historian-state-file.ts
|
|
31039
|
-
import { mkdirSync as mkdirSync3, unlinkSync, writeFileSync } from "node:fs";
|
|
31546
|
+
import { mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, writeFileSync } from "node:fs";
|
|
31040
31547
|
function cleanupHistorianStateFile(path3) {
|
|
31041
31548
|
if (!path3)
|
|
31042
31549
|
return;
|
|
31043
31550
|
try {
|
|
31044
|
-
|
|
31551
|
+
unlinkSync2(path3);
|
|
31045
31552
|
} catch {}
|
|
31046
31553
|
}
|
|
31047
31554
|
// src/features/magic-context/memory/cosine-similarity.ts
|
|
@@ -31084,7 +31591,7 @@ function createProvider2(config2) {
|
|
|
31084
31591
|
});
|
|
31085
31592
|
}
|
|
31086
31593
|
if (config2.provider === "local") {
|
|
31087
|
-
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens);
|
|
31594
|
+
return new LocalEmbeddingProvider(config2.model, config2.max_input_tokens, config2.local_dtype);
|
|
31088
31595
|
}
|
|
31089
31596
|
if (config2.provider === "synapse") {
|
|
31090
31597
|
const synapse = config2;
|
|
@@ -31356,8 +31863,8 @@ function getMemoryVerifications(db, memoryIds) {
|
|
|
31356
31863
|
existing.mappedAt = Math.max(existing.mappedAt, row.mapped_at ?? 0);
|
|
31357
31864
|
result.set(row.memory_id, existing);
|
|
31358
31865
|
}
|
|
31359
|
-
for (const
|
|
31360
|
-
|
|
31866
|
+
for (const state2 of result.values()) {
|
|
31867
|
+
state2.files.sort();
|
|
31361
31868
|
}
|
|
31362
31869
|
return result;
|
|
31363
31870
|
}
|
|
@@ -31594,18 +32101,18 @@ function tallyFactsByCategory(facts) {
|
|
|
31594
32101
|
}
|
|
31595
32102
|
|
|
31596
32103
|
// src/hooks/magic-context/compaction-marker-manager.ts
|
|
31597
|
-
import { join as
|
|
32104
|
+
import { join as join6 } from "node:path";
|
|
31598
32105
|
|
|
31599
32106
|
// src/features/magic-context/compaction-marker.ts
|
|
31600
|
-
import { createHash as
|
|
32107
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
31601
32108
|
import { existsSync as existsSync5 } from "node:fs";
|
|
31602
|
-
import { join as
|
|
32109
|
+
import { join as join5 } from "node:path";
|
|
31603
32110
|
var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
31604
32111
|
var ID_PREFIX_HEX_LENGTH = 12;
|
|
31605
32112
|
var ID_SUFFIX_LENGTH = 14;
|
|
31606
32113
|
var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
|
|
31607
32114
|
function deterministicBase62(seed, length) {
|
|
31608
|
-
let value = BigInt(`0x${
|
|
32115
|
+
let value = BigInt(`0x${createHash13("sha256").update(seed).digest("hex")}`);
|
|
31609
32116
|
const chars = Array(length);
|
|
31610
32117
|
for (let index = length - 1;index >= 0; index -= 1) {
|
|
31611
32118
|
chars[index] = BASE62_CHARS[Number(value % 62n)];
|
|
@@ -31625,7 +32132,7 @@ function generatePartId(timestampMs, counter = 0n, identity = "") {
|
|
|
31625
32132
|
return generateId("prt", timestampMs, counter, identity);
|
|
31626
32133
|
}
|
|
31627
32134
|
function getOpenCodeDbPath() {
|
|
31628
|
-
return
|
|
32135
|
+
return join5(getDataDir(), "opencode", "opencode.db");
|
|
31629
32136
|
}
|
|
31630
32137
|
var cachedWriteDb = null;
|
|
31631
32138
|
var REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
|
|
@@ -31885,13 +32392,176 @@ function removeForeignCompactionMarker(sessionId, marker, protectedSummaryMessag
|
|
|
31885
32392
|
return false;
|
|
31886
32393
|
}
|
|
31887
32394
|
}
|
|
31888
|
-
function
|
|
32395
|
+
function dataReferencesTailStart(data) {
|
|
32396
|
+
if (typeof data !== "object" || data === null)
|
|
32397
|
+
return null;
|
|
32398
|
+
const record2 = data;
|
|
32399
|
+
if (typeof record2.tail_start_id === "string" && record2.tail_start_id.length > 0) {
|
|
32400
|
+
return record2.tail_start_id;
|
|
32401
|
+
}
|
|
32402
|
+
const nested = record2.compaction;
|
|
32403
|
+
if (typeof nested === "object" && nested !== null) {
|
|
32404
|
+
const nestedTail = nested.tail_start_id;
|
|
32405
|
+
if (typeof nestedTail === "string" && nestedTail.length > 0)
|
|
32406
|
+
return nestedTail;
|
|
32407
|
+
}
|
|
32408
|
+
return null;
|
|
32409
|
+
}
|
|
32410
|
+
function isMcCanonicalCompactionPartData(data) {
|
|
32411
|
+
if (typeof data !== "object" || data === null || Array.isArray(data))
|
|
32412
|
+
return false;
|
|
32413
|
+
const record2 = data;
|
|
32414
|
+
const keys = Object.keys(record2).sort();
|
|
32415
|
+
return keys.length === 2 && keys[0] === "auto" && keys[1] === "type" && record2.type === "compaction" && record2.auto === true;
|
|
32416
|
+
}
|
|
32417
|
+
function removeMcOwnedCompactionMarkers(sessionId, summaryText) {
|
|
32418
|
+
const db = getWritableOpenCodeDb();
|
|
32419
|
+
if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
|
|
32420
|
+
return {
|
|
32421
|
+
verified: false,
|
|
32422
|
+
removedLineages: 0,
|
|
32423
|
+
removedRows: 0,
|
|
32424
|
+
retainedLineages: 0
|
|
32425
|
+
};
|
|
32426
|
+
}
|
|
32427
|
+
const canonicalSummaries = db.prepare(`SELECT id, COALESCE(json_extract(data, '$.parentID'), '') AS parent_id
|
|
32428
|
+
FROM message
|
|
32429
|
+
WHERE session_id = ?
|
|
32430
|
+
AND COALESCE(json_extract(data, '$.summary'), 0) = 1
|
|
32431
|
+
AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
|
|
32432
|
+
AND COALESCE(json_extract(data, '$.providerID'), '') = 'magic-context'`).all(sessionId);
|
|
32433
|
+
const legacySummaries = db.prepare(`SELECT m.id, COALESCE(json_extract(m.data, '$.parentID'), '') AS parent_id
|
|
32434
|
+
FROM message m
|
|
32435
|
+
WHERE m.session_id = ?
|
|
32436
|
+
AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
|
|
32437
|
+
AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
|
|
32438
|
+
AND COALESCE(json_extract(m.data, '$.providerID'), '') <> 'magic-context'
|
|
32439
|
+
AND EXISTS (
|
|
32440
|
+
SELECT 1
|
|
32441
|
+
FROM part p
|
|
32442
|
+
WHERE p.session_id = m.session_id
|
|
32443
|
+
AND p.message_id = m.id
|
|
32444
|
+
AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
|
|
32445
|
+
AND COALESCE(json_extract(p.data, '$.text'), '') = ?
|
|
32446
|
+
)`).all(sessionId, summaryText);
|
|
32447
|
+
const summariesByBoundary = new Map;
|
|
32448
|
+
const orphanSummaryIds = new Set;
|
|
32449
|
+
for (const row of [...canonicalSummaries, ...legacySummaries]) {
|
|
32450
|
+
if (typeof row.id !== "string")
|
|
32451
|
+
continue;
|
|
32452
|
+
if (typeof row.parent_id === "string" && row.parent_id.length > 0) {
|
|
32453
|
+
const set2 = summariesByBoundary.get(row.parent_id) ?? new Set;
|
|
32454
|
+
set2.add(row.id);
|
|
32455
|
+
summariesByBoundary.set(row.parent_id, set2);
|
|
32456
|
+
} else {
|
|
32457
|
+
orphanSummaryIds.add(row.id);
|
|
32458
|
+
}
|
|
32459
|
+
}
|
|
32460
|
+
const compactionParts = db.prepare(`SELECT id, message_id, data
|
|
32461
|
+
FROM part
|
|
32462
|
+
WHERE session_id = ?
|
|
32463
|
+
AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'`).all(sessionId);
|
|
32464
|
+
const parsedParts = [];
|
|
32465
|
+
for (const part of compactionParts) {
|
|
32466
|
+
if (typeof part.id !== "string" || typeof part.message_id !== "string")
|
|
32467
|
+
continue;
|
|
32468
|
+
let data;
|
|
32469
|
+
try {
|
|
32470
|
+
data = typeof part.data === "string" ? JSON.parse(part.data) : part.data;
|
|
32471
|
+
} catch {
|
|
32472
|
+
data = null;
|
|
32473
|
+
}
|
|
32474
|
+
parsedParts.push({
|
|
32475
|
+
id: part.id,
|
|
32476
|
+
messageId: part.message_id,
|
|
32477
|
+
data,
|
|
32478
|
+
tailStartId: dataReferencesTailStart(data)
|
|
32479
|
+
});
|
|
32480
|
+
}
|
|
32481
|
+
const messageTailRefs = db.prepare(`SELECT id, data
|
|
32482
|
+
FROM message
|
|
32483
|
+
WHERE session_id = ?
|
|
32484
|
+
AND json_extract(data, '$.compaction.tail_start_id') IS NOT NULL`).all(sessionId);
|
|
32485
|
+
const messageTailStartIds = new Set;
|
|
32486
|
+
for (const row of messageTailRefs) {
|
|
32487
|
+
if (typeof row.id !== "string")
|
|
32488
|
+
continue;
|
|
32489
|
+
let data;
|
|
32490
|
+
try {
|
|
32491
|
+
data = typeof row.data === "string" ? JSON.parse(row.data) : row.data;
|
|
32492
|
+
} catch {
|
|
32493
|
+
data = null;
|
|
32494
|
+
}
|
|
32495
|
+
const ref = dataReferencesTailStart(data);
|
|
32496
|
+
if (ref)
|
|
32497
|
+
messageTailStartIds.add(ref);
|
|
32498
|
+
}
|
|
32499
|
+
let removedLineages = 0;
|
|
32500
|
+
let removedRows = 0;
|
|
32501
|
+
let retainedLineages = 0;
|
|
32502
|
+
const deletePartsOfMessage = db.prepare("DELETE FROM part WHERE session_id = ? AND message_id = ?");
|
|
32503
|
+
const deleteMessage = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
|
|
32504
|
+
const deletePart = db.prepare("DELETE FROM part WHERE session_id = ? AND id = ?");
|
|
32505
|
+
const deleteSummaries = (summaryIds) => {
|
|
32506
|
+
let rows = 0;
|
|
32507
|
+
for (const summaryId of summaryIds) {
|
|
32508
|
+
rows += deletePartsOfMessage.run(sessionId, summaryId).changes;
|
|
32509
|
+
rows += deleteMessage.run(sessionId, summaryId).changes;
|
|
32510
|
+
}
|
|
32511
|
+
return rows;
|
|
32512
|
+
};
|
|
32513
|
+
for (const [boundaryMessageId, summaryIds] of summariesByBoundary) {
|
|
32514
|
+
const boundaryParts = parsedParts.filter((part) => part.messageId === boundaryMessageId);
|
|
32515
|
+
const mcPartIds = boundaryParts.filter((part) => isMcCanonicalCompactionPartData(part.data)).map((part) => part.id);
|
|
32516
|
+
const rowsToDelete = new Set([...summaryIds, ...mcPartIds]);
|
|
32517
|
+
const survivingPartsReferenceDeletion = parsedParts.some((part) => !mcPartIds.includes(part.id) && part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
|
|
32518
|
+
const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
|
|
32519
|
+
if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
|
|
32520
|
+
retainedLineages += 1;
|
|
32521
|
+
log(`[magic-context] compaction-marker: flip-off cleanup RETAINED lineage at boundary ${boundaryMessageId} — a surviving tail_start_id references a row the deletion would remove`);
|
|
32522
|
+
continue;
|
|
32523
|
+
}
|
|
32524
|
+
const rows = db.transaction(() => {
|
|
32525
|
+
let changed = deleteSummaries(summaryIds);
|
|
32526
|
+
for (const partId of mcPartIds) {
|
|
32527
|
+
changed += deletePart.run(sessionId, partId).changes;
|
|
32528
|
+
}
|
|
32529
|
+
return changed;
|
|
32530
|
+
})();
|
|
32531
|
+
if (rows > 0 || summaryIds.size > 0 || mcPartIds.length > 0) {
|
|
32532
|
+
removedLineages += 1;
|
|
32533
|
+
removedRows += rows;
|
|
32534
|
+
}
|
|
32535
|
+
}
|
|
32536
|
+
if (orphanSummaryIds.size > 0) {
|
|
32537
|
+
const rowsToDelete = new Set(orphanSummaryIds);
|
|
32538
|
+
const survivingPartsReferenceDeletion = parsedParts.some((part) => part.tailStartId !== null && rowsToDelete.has(part.tailStartId));
|
|
32539
|
+
const messageFieldReferencesDeletion = [...rowsToDelete].some((id) => messageTailStartIds.has(id));
|
|
32540
|
+
if (survivingPartsReferenceDeletion || messageFieldReferencesDeletion) {
|
|
32541
|
+
retainedLineages += 1;
|
|
32542
|
+
} else {
|
|
32543
|
+
const rows = db.transaction(() => deleteSummaries(orphanSummaryIds))();
|
|
32544
|
+
removedLineages += 1;
|
|
32545
|
+
removedRows += rows;
|
|
32546
|
+
}
|
|
32547
|
+
}
|
|
32548
|
+
if (removedLineages > 0 || retainedLineages > 0) {
|
|
32549
|
+
log(`[magic-context] compaction-marker: flip-off cleanup for ${sessionId} removed ${removedLineages} lineage(s) (${removedRows} rows), retained ${retainedLineages}`);
|
|
32550
|
+
}
|
|
32551
|
+
return {
|
|
32552
|
+
verified: retainedLineages === 0,
|
|
32553
|
+
removedLineages,
|
|
32554
|
+
removedRows,
|
|
32555
|
+
retainedLineages
|
|
32556
|
+
};
|
|
32557
|
+
}
|
|
32558
|
+
function removeCompactionMarker(state2) {
|
|
31889
32559
|
try {
|
|
31890
32560
|
const db = getWritableOpenCodeDb();
|
|
31891
32561
|
db.transaction(() => {
|
|
31892
|
-
db.prepare("DELETE FROM part WHERE id = ?").run(
|
|
31893
|
-
db.prepare("DELETE FROM message WHERE id = ?").run(
|
|
31894
|
-
db.prepare("DELETE FROM part WHERE id = ?").run(
|
|
32562
|
+
db.prepare("DELETE FROM part WHERE id = ?").run(state2.summaryPartId);
|
|
32563
|
+
db.prepare("DELETE FROM message WHERE id = ?").run(state2.summaryMessageId);
|
|
32564
|
+
db.prepare("DELETE FROM part WHERE id = ?").run(state2.compactionPartId);
|
|
31895
32565
|
})();
|
|
31896
32566
|
return true;
|
|
31897
32567
|
} catch (error51) {
|
|
@@ -31907,9 +32577,9 @@ function dropMarkerSummaryTag(db, sessionId, summaryMessageId) {
|
|
|
31907
32577
|
if (tagNumber !== null)
|
|
31908
32578
|
updateTagStatus(db, sessionId, tagNumber, "dropped");
|
|
31909
32579
|
}
|
|
31910
|
-
function persistMarkerStateAndDropReplacedTag(db, sessionId,
|
|
32580
|
+
function persistMarkerStateAndDropReplacedTag(db, sessionId, state2, replacedSummaryMessageId) {
|
|
31911
32581
|
db.transaction(() => {
|
|
31912
|
-
setPersistedCompactionMarkerState(db, sessionId,
|
|
32582
|
+
setPersistedCompactionMarkerState(db, sessionId, state2);
|
|
31913
32583
|
if (replacedSummaryMessageId !== null) {
|
|
31914
32584
|
dropMarkerSummaryTag(db, sessionId, replacedSummaryMessageId);
|
|
31915
32585
|
}
|
|
@@ -32130,7 +32800,7 @@ function reconcileForkOrphanedCompactionMarkers(db, sessionId) {
|
|
|
32130
32800
|
}
|
|
32131
32801
|
}
|
|
32132
32802
|
function checkCompactionMarkerConsistency(db) {
|
|
32133
|
-
const opencodeDbPath =
|
|
32803
|
+
const opencodeDbPath = join6(getDataDir(), "opencode", "opencode.db");
|
|
32134
32804
|
let opencodeDb;
|
|
32135
32805
|
try {
|
|
32136
32806
|
opencodeDb = new Database(opencodeDbPath, { readonly: true });
|
|
@@ -32146,19 +32816,19 @@ function checkCompactionMarkerConsistency(db) {
|
|
|
32146
32816
|
const checkPart = opencodeDb.prepare("SELECT 1 FROM part WHERE id = ? LIMIT 1");
|
|
32147
32817
|
let reconciledCount = 0;
|
|
32148
32818
|
for (const row of persistedRows) {
|
|
32149
|
-
const
|
|
32150
|
-
if (!
|
|
32819
|
+
const state2 = getPersistedCompactionMarkerState(db, row.session_id);
|
|
32820
|
+
if (!state2)
|
|
32151
32821
|
continue;
|
|
32152
|
-
const boundaryExists = checkMessage.get(
|
|
32153
|
-
const summaryMessageExists = checkMessage.get(
|
|
32154
|
-
const compactionPartExists = checkPart.get(
|
|
32155
|
-
const summaryPartExists = checkPart.get(
|
|
32822
|
+
const boundaryExists = checkMessage.get(state2.boundaryMessageId) != null;
|
|
32823
|
+
const summaryMessageExists = checkMessage.get(state2.summaryMessageId) != null;
|
|
32824
|
+
const compactionPartExists = checkPart.get(state2.compactionPartId) != null;
|
|
32825
|
+
const summaryPartExists = checkPart.get(state2.summaryPartId) != null;
|
|
32156
32826
|
const allPresent = boundaryExists && summaryMessageExists && compactionPartExists && summaryPartExists;
|
|
32157
32827
|
if (allPresent)
|
|
32158
32828
|
continue;
|
|
32159
32829
|
let removedOk = false;
|
|
32160
32830
|
try {
|
|
32161
|
-
removedOk = removeCompactionMarker(
|
|
32831
|
+
removedOk = removeCompactionMarker(state2);
|
|
32162
32832
|
} catch (error51) {
|
|
32163
32833
|
sessionLog(row.session_id, "compaction-marker consistency: partial cleanup of half-written marker failed:", error51);
|
|
32164
32834
|
}
|
|
@@ -33108,8 +33778,8 @@ function queueDropsForCompartmentalizedMessages(db, sessionId, upToMessageIndex)
|
|
|
33108
33778
|
}
|
|
33109
33779
|
|
|
33110
33780
|
// src/hooks/magic-context/compartment-runner-historian.ts
|
|
33111
|
-
import { mkdirSync as mkdirSync4, unlinkSync as
|
|
33112
|
-
import { join as
|
|
33781
|
+
import { mkdirSync as mkdirSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
33782
|
+
import { join as join7 } from "node:path";
|
|
33113
33783
|
|
|
33114
33784
|
// src/features/magic-context/subagent-token-capture.ts
|
|
33115
33785
|
function asNumber(value) {
|
|
@@ -33405,6 +34075,24 @@ function historianResponseDumpDir(directory) {
|
|
|
33405
34075
|
return getProjectMagicContextHistorianDir(directory);
|
|
33406
34076
|
}
|
|
33407
34077
|
var MAX_HISTORIAN_RETRIES = 2;
|
|
34078
|
+
var HISTORIAN_REASONING_PART_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
|
|
34079
|
+
function extractLatestHistorianReasoning(messages) {
|
|
34080
|
+
if (!Array.isArray(messages))
|
|
34081
|
+
return null;
|
|
34082
|
+
const latest = messages.filter((message) => isRecord(message) && isRecord(message.info) && message.info.role === "assistant").sort((left, right) => historianMessageCreatedAt(right) - historianMessageCreatedAt(left))[0];
|
|
34083
|
+
if (!latest || !Array.isArray(latest.parts))
|
|
34084
|
+
return null;
|
|
34085
|
+
return latest.parts.filter(isHistorianReasoningPart).map((part) => part.text).join(`
|
|
34086
|
+
`) || null;
|
|
34087
|
+
}
|
|
34088
|
+
function isHistorianReasoningPart(part) {
|
|
34089
|
+
return isRecord(part) && typeof part.type === "string" && HISTORIAN_REASONING_PART_TYPES.has(part.type) && typeof part.text === "string" && part.text.length > 0;
|
|
34090
|
+
}
|
|
34091
|
+
function historianMessageCreatedAt(message) {
|
|
34092
|
+
if (!isRecord(message.info) || !isRecord(message.info.time))
|
|
34093
|
+
return 0;
|
|
34094
|
+
return typeof message.info.time.created === "number" ? message.info.time.created : 0;
|
|
34095
|
+
}
|
|
33408
34096
|
async function runValidatedHistorianPass(args) {
|
|
33409
34097
|
const firstRun = await runHistorianPrompt({
|
|
33410
34098
|
...args,
|
|
@@ -33470,6 +34158,7 @@ async function runEditorPassOrFallback(args) {
|
|
|
33470
34158
|
sessionLog(args.parentSessionId, "historian two-pass: running editor on draft");
|
|
33471
34159
|
const editorRun = await runHistorianPrompt({
|
|
33472
34160
|
client: args.client,
|
|
34161
|
+
db: args.db,
|
|
33473
34162
|
parentSessionId: args.parentSessionId,
|
|
33474
34163
|
sessionDirectory: args.sessionDirectory,
|
|
33475
34164
|
prompt: buildHistorianEditorPrompt(args.draftXml),
|
|
@@ -33496,6 +34185,7 @@ async function runEditorPassOrFallback(args) {
|
|
|
33496
34185
|
async function runHistorianPrompt(args) {
|
|
33497
34186
|
const {
|
|
33498
34187
|
client,
|
|
34188
|
+
db,
|
|
33499
34189
|
parentSessionId,
|
|
33500
34190
|
sessionDirectory,
|
|
33501
34191
|
prompt,
|
|
@@ -33529,12 +34219,12 @@ async function runHistorianPrompt(args) {
|
|
|
33529
34219
|
};
|
|
33530
34220
|
try {
|
|
33531
34221
|
sessionLog(parentSessionId, `historian: creating child session (agent=${agentId}, model=${modelOverride ? `${modelOverride.providerID}/${modelOverride.modelID}` : `agent:${agentId}`})`);
|
|
33532
|
-
const createResponse = await
|
|
33533
|
-
|
|
33534
|
-
|
|
33535
|
-
|
|
33536
|
-
|
|
33537
|
-
|
|
34222
|
+
const createResponse = await createChildSessionWithFence({
|
|
34223
|
+
client,
|
|
34224
|
+
db,
|
|
34225
|
+
parentSessionId,
|
|
34226
|
+
title: "magic-context-compartment",
|
|
34227
|
+
directory: sessionDirectory
|
|
33538
34228
|
});
|
|
33539
34229
|
const createdSession = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
33540
34230
|
agentSessionId = typeof createdSession?.id === "string" ? createdSession.id : null;
|
|
@@ -33582,7 +34272,18 @@ async function runHistorianPrompt(args) {
|
|
|
33582
34272
|
preferResponseOnMissingData: true
|
|
33583
34273
|
});
|
|
33584
34274
|
const invocationId = recordInvocation({ status: "completed", messages });
|
|
33585
|
-
const
|
|
34275
|
+
const lengthCapped = hasLengthCappedOutput(messages);
|
|
34276
|
+
const textResult = extractLatestAssistantText(messages);
|
|
34277
|
+
const reasoningResult = textResult ? null : extractLatestHistorianReasoning(messages);
|
|
34278
|
+
if (!textResult && reasoningResult && lengthCapped) {
|
|
34279
|
+
const outputTokens = sumTokensFromChildMessages(messages).output;
|
|
34280
|
+
return {
|
|
34281
|
+
ok: false,
|
|
34282
|
+
error: `historian output length-capped at ${outputTokens} tokens (all reasoning, no text) — set historian.maxTokens or route historian.model to a low-reasoning lane/variant`,
|
|
34283
|
+
invocationId: invocationId ?? undefined
|
|
34284
|
+
};
|
|
34285
|
+
}
|
|
34286
|
+
const result = textResult ?? reasoningResult;
|
|
33586
34287
|
if (!result) {
|
|
33587
34288
|
return {
|
|
33588
34289
|
ok: false,
|
|
@@ -33634,6 +34335,7 @@ async function runFallbackHistorianPass(args) {
|
|
|
33634
34335
|
args.callbacks?.onModelFallback?.(modelId, i + 1, chain.length);
|
|
33635
34336
|
const fallbackRun = await runHistorianPrompt({
|
|
33636
34337
|
client: args.client,
|
|
34338
|
+
db: args.db,
|
|
33637
34339
|
parentSessionId: args.parentSessionId,
|
|
33638
34340
|
sessionDirectory: args.sessionDirectory,
|
|
33639
34341
|
prompt: args.prompt,
|
|
@@ -33695,7 +34397,7 @@ function cleanupHistorianDump(sessionId, dumpPath) {
|
|
|
33695
34397
|
if (!dumpPath)
|
|
33696
34398
|
return;
|
|
33697
34399
|
try {
|
|
33698
|
-
|
|
34400
|
+
unlinkSync3(dumpPath);
|
|
33699
34401
|
} catch (error51) {
|
|
33700
34402
|
sessionLog(sessionId, "compartment agent: failed to remove historian response dump", {
|
|
33701
34403
|
dumpPath,
|
|
@@ -33710,7 +34412,7 @@ function dumpHistorianResponse(sessionId, directory, label, text) {
|
|
|
33710
34412
|
ensureCortexKitArtifactGitignore(directory);
|
|
33711
34413
|
const safeSessionId = sanitizeDumpName(sessionId);
|
|
33712
34414
|
const safeLabel = sanitizeDumpName(label);
|
|
33713
|
-
const dumpPath =
|
|
34415
|
+
const dumpPath = join7(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
|
|
33714
34416
|
writeFileSync2(dumpPath, text, "utf8");
|
|
33715
34417
|
sessionLog(sessionId, "compartment agent: historian response dumped", {
|
|
33716
34418
|
label,
|
|
@@ -33733,26 +34435,7 @@ function sanitizeDumpName(value) {
|
|
|
33733
34435
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
33734
34436
|
|
|
33735
34437
|
// src/features/magic-context/mural/render-trigger.ts
|
|
33736
|
-
import { createHash as
|
|
33737
|
-
|
|
33738
|
-
// src/shared/harness-provider-map.ts
|
|
33739
|
-
var PI_TO_CANONICAL_PROVIDER = {
|
|
33740
|
-
"openai-codex": "openai",
|
|
33741
|
-
"google-antigravity": "google"
|
|
33742
|
-
};
|
|
33743
|
-
function remapProviderPrefix(ref, map2) {
|
|
33744
|
-
if (typeof ref !== "string")
|
|
33745
|
-
return ref;
|
|
33746
|
-
const slash = ref.indexOf("/");
|
|
33747
|
-
if (slash <= 0)
|
|
33748
|
-
return ref;
|
|
33749
|
-
const provider2 = ref.slice(0, slash);
|
|
33750
|
-
const mapped = map2[provider2];
|
|
33751
|
-
return mapped ? `${mapped}${ref.slice(slash)}` : ref;
|
|
33752
|
-
}
|
|
33753
|
-
function piModelRefToCanonical(ref) {
|
|
33754
|
-
return remapProviderPrefix(ref, PI_TO_CANONICAL_PROVIDER);
|
|
33755
|
-
}
|
|
34438
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
33756
34439
|
|
|
33757
34440
|
// src/features/magic-context/mural/mural-selection.ts
|
|
33758
34441
|
var DEFAULT_MURAL_MEMORY_BUDGET = 8000;
|
|
@@ -33955,6 +34638,8 @@ function naturalLineLengths(entries, roomWidth) {
|
|
|
33955
34638
|
let currentCategory = null;
|
|
33956
34639
|
for (let index = 0;index < entries.length; index++) {
|
|
33957
34640
|
const entry = entries[index];
|
|
34641
|
+
if (!entry)
|
|
34642
|
+
continue;
|
|
33958
34643
|
if (entry.category !== currentCategory) {
|
|
33959
34644
|
currentCategory = entry.category;
|
|
33960
34645
|
lengths.push(codepoints(` <${entry.category}> `));
|
|
@@ -33987,6 +34672,8 @@ function planLines(entries, roomWidth) {
|
|
|
33987
34672
|
let currentCategory = null;
|
|
33988
34673
|
for (let index = 0;index < entries.length; index++) {
|
|
33989
34674
|
const entry = entries[index];
|
|
34675
|
+
if (!entry)
|
|
34676
|
+
continue;
|
|
33990
34677
|
if (entry.category !== currentCategory) {
|
|
33991
34678
|
currentCategory = entry.category;
|
|
33992
34679
|
lines.push({
|
|
@@ -34050,8 +34737,11 @@ function renderLayout(entries, plan, roomWidth, columnCount) {
|
|
|
34050
34737
|
const usage = {};
|
|
34051
34738
|
let filledLineCount = 0;
|
|
34052
34739
|
for (const [column, columnPlan] of splitPlan(plan, columnCount).entries()) {
|
|
34740
|
+
const columnGrid = grid[column];
|
|
34741
|
+
if (!columnGrid)
|
|
34742
|
+
continue;
|
|
34053
34743
|
for (const [row, line] of columnPlan.entries()) {
|
|
34054
|
-
|
|
34744
|
+
columnGrid[row] = line.text;
|
|
34055
34745
|
filledLineCount += 1;
|
|
34056
34746
|
usage[line.category] = (usage[line.category] ?? 0) + 1;
|
|
34057
34747
|
const placementLine = row + 1;
|
|
@@ -34162,6 +34852,7 @@ function glyph(character) {
|
|
|
34162
34852
|
}
|
|
34163
34853
|
function drawGlyph(pixels, width, height, x, y, character, color) {
|
|
34164
34854
|
const glyphData = glyph(character);
|
|
34855
|
+
const [red, green, blue] = color;
|
|
34165
34856
|
for (let row = 0;row < MURAL_CELL_HEIGHT; row++) {
|
|
34166
34857
|
const pattern = glyphData.rows[row] ?? 0;
|
|
34167
34858
|
for (let column = 0;column < glyphData.width; column++) {
|
|
@@ -34172,9 +34863,9 @@ function drawGlyph(pixels, width, height, x, y, character, color) {
|
|
|
34172
34863
|
if (px < 0 || py < 0 || px >= width || py >= height)
|
|
34173
34864
|
continue;
|
|
34174
34865
|
const offset = (py * width + px) * 3;
|
|
34175
|
-
pixels[offset] =
|
|
34176
|
-
pixels[offset + 1] =
|
|
34177
|
-
pixels[offset + 2] =
|
|
34866
|
+
pixels[offset] = red;
|
|
34867
|
+
pixels[offset + 1] = green;
|
|
34868
|
+
pixels[offset + 2] = blue;
|
|
34178
34869
|
}
|
|
34179
34870
|
}
|
|
34180
34871
|
}
|
|
@@ -34186,6 +34877,7 @@ function drawText(pixels, width, height, x, y, text, color) {
|
|
|
34186
34877
|
}
|
|
34187
34878
|
}
|
|
34188
34879
|
function fillRect(pixels, canvasWidth, canvasHeight, x, y, width, height, color) {
|
|
34880
|
+
const [red, green, blue] = color;
|
|
34189
34881
|
const left = Math.max(0, x);
|
|
34190
34882
|
const top = Math.max(0, y);
|
|
34191
34883
|
const right = Math.min(canvasWidth, x + width);
|
|
@@ -34193,9 +34885,9 @@ function fillRect(pixels, canvasWidth, canvasHeight, x, y, width, height, color)
|
|
|
34193
34885
|
for (let py = top;py < bottom; py++) {
|
|
34194
34886
|
for (let px = left;px < right; px++) {
|
|
34195
34887
|
const offset = (py * canvasWidth + px) * 3;
|
|
34196
|
-
pixels[offset] =
|
|
34197
|
-
pixels[offset + 1] =
|
|
34198
|
-
pixels[offset + 2] =
|
|
34888
|
+
pixels[offset] = red;
|
|
34889
|
+
pixels[offset + 1] = green;
|
|
34890
|
+
pixels[offset + 2] = blue;
|
|
34199
34891
|
}
|
|
34200
34892
|
}
|
|
34201
34893
|
}
|
|
@@ -34222,6 +34914,9 @@ function renderMural(entries) {
|
|
|
34222
34914
|
});
|
|
34223
34915
|
const fittingCandidates = candidates.filter((candidate) => candidate.layout.droppedIds.length === 0);
|
|
34224
34916
|
const candidatesToCompare = fittingCandidates.length > 0 ? fittingCandidates : candidates;
|
|
34917
|
+
const firstCandidate = candidatesToCompare[0];
|
|
34918
|
+
if (!firstCandidate)
|
|
34919
|
+
throw new Error("mural layout candidate list is empty");
|
|
34225
34920
|
const selected = candidatesToCompare.reduce((best, candidate) => {
|
|
34226
34921
|
if (!best)
|
|
34227
34922
|
return candidate;
|
|
@@ -34232,7 +34927,7 @@ function renderMural(entries) {
|
|
|
34232
34927
|
return candidate.tileArea < best.tileArea ? candidate : best;
|
|
34233
34928
|
}
|
|
34234
34929
|
return candidate.requestedColumnCount < best.requestedColumnCount ? candidate : best;
|
|
34235
|
-
},
|
|
34930
|
+
}, firstCandidate);
|
|
34236
34931
|
const { layout, width, height } = selected;
|
|
34237
34932
|
const pixels = new Uint8Array(width * height * 3).fill(255);
|
|
34238
34933
|
const contentWidth = layout.columnCount === 0 ? 0 : layout.columnCount * roomWidth * MURAL_CELL_WIDTH + MURAL_COLUMN_GAP * (layout.columnCount - 1) * MURAL_CELL_WIDTH;
|
|
@@ -34276,8 +34971,8 @@ function getMuralCoverage(db, projectIdentity) {
|
|
|
34276
34971
|
const cueState = getMuralCueState(db, memories.map((memory) => memory.id));
|
|
34277
34972
|
let cuedMemoryCount = 0;
|
|
34278
34973
|
for (const memory of memories) {
|
|
34279
|
-
const
|
|
34280
|
-
if (
|
|
34974
|
+
const state2 = cueState.get(memory.id);
|
|
34975
|
+
if (state2 && typeof state2.cue === "string" && state2.cue.trim() !== "" && state2.hash !== null && state2.hash === computeCueContentHash(memory.content)) {
|
|
34281
34976
|
cuedMemoryCount += 1;
|
|
34282
34977
|
}
|
|
34283
34978
|
}
|
|
@@ -34291,16 +34986,16 @@ function resolveMural(db, projectIdentity, budgetTokens = DEFAULT_MURAL_MEMORY_B
|
|
|
34291
34986
|
const cueState = getMuralCueState(db, overflow.map((memory) => memory.id));
|
|
34292
34987
|
const entries = [];
|
|
34293
34988
|
for (const memory of overflow) {
|
|
34294
|
-
const
|
|
34295
|
-
if (!
|
|
34989
|
+
const state2 = cueState.get(memory.id);
|
|
34990
|
+
if (!state2 || state2.cue === null || state2.hash === null)
|
|
34296
34991
|
continue;
|
|
34297
|
-
if (
|
|
34992
|
+
if (state2.hash !== computeCueContentHash(memory.content))
|
|
34298
34993
|
continue;
|
|
34299
34994
|
entries.push({
|
|
34300
34995
|
id: memory.id,
|
|
34301
34996
|
category: memory.category,
|
|
34302
34997
|
importance: memory.importance ?? 50,
|
|
34303
|
-
cue:
|
|
34998
|
+
cue: state2.cue
|
|
34304
34999
|
});
|
|
34305
35000
|
}
|
|
34306
35001
|
entries.sort(compareMuralEntries);
|
|
@@ -34366,7 +35061,7 @@ function ensureMuralRendered(db, projectIdentity, budgetTokens = DEFAULT_MURAL_M
|
|
|
34366
35061
|
return { hasMural: false, rerendered: false };
|
|
34367
35062
|
}
|
|
34368
35063
|
const rendered = renderMural(entries);
|
|
34369
|
-
const textHash =
|
|
35064
|
+
const textHash = createHash14("sha256").update(rendered.sha256Input).digest("hex");
|
|
34370
35065
|
const existing = getMural(db, projectIdentity);
|
|
34371
35066
|
if (existing && existing.contentHash === textHash && existing.width === rendered.width && existing.height === rendered.height) {
|
|
34372
35067
|
return {
|
|
@@ -35491,41 +36186,41 @@ function readCurrentM0SnapshotMarkers(args) {
|
|
|
35491
36186
|
});
|
|
35492
36187
|
return fresh.markers;
|
|
35493
36188
|
}
|
|
35494
|
-
function snapshotMarkersFromCachedM0(
|
|
35495
|
-
if (!
|
|
36189
|
+
function snapshotMarkersFromCachedM0(state2) {
|
|
36190
|
+
if (!state2.cachedM0Bytes)
|
|
35496
36191
|
return null;
|
|
35497
|
-
const cachedUpgradeIdentity = decodeCachedM0UpgradeIdentity(
|
|
35498
|
-
if (
|
|
36192
|
+
const cachedUpgradeIdentity = decodeCachedM0UpgradeIdentity(state2.cachedM0UpgradeState);
|
|
36193
|
+
if (state2.cachedM0ProjectMemoryEpoch === null)
|
|
35499
36194
|
return null;
|
|
35500
|
-
if (
|
|
36195
|
+
if (state2.cachedM0ProjectUserProfileVersion === null)
|
|
35501
36196
|
return null;
|
|
35502
|
-
if (
|
|
36197
|
+
if (state2.cachedM0MaxCompartmentSeq === null)
|
|
35503
36198
|
return null;
|
|
35504
|
-
if (
|
|
36199
|
+
if (state2.cachedM0MaxMemoryId === null)
|
|
35505
36200
|
return null;
|
|
35506
|
-
if (
|
|
36201
|
+
if (state2.cachedM0MaxMutationId === null)
|
|
35507
36202
|
return null;
|
|
35508
|
-
if (
|
|
36203
|
+
if (state2.cachedM0MaxMemoryMutationId === null)
|
|
35509
36204
|
return null;
|
|
35510
|
-
if (
|
|
36205
|
+
if (state2.cachedM0SessionFactsVersion === null)
|
|
35511
36206
|
return null;
|
|
35512
36207
|
return {
|
|
35513
|
-
projectMemoryEpoch:
|
|
35514
|
-
workspaceFingerprint:
|
|
35515
|
-
projectUserProfileVersion:
|
|
35516
|
-
maxCompartmentSeq:
|
|
35517
|
-
maxMemoryId:
|
|
35518
|
-
maxMutationId:
|
|
35519
|
-
maxMemoryMutationId:
|
|
35520
|
-
projectDocsHash:
|
|
35521
|
-
materializedAt:
|
|
35522
|
-
sessionFactsVersion:
|
|
36208
|
+
projectMemoryEpoch: state2.cachedM0ProjectMemoryEpoch,
|
|
36209
|
+
workspaceFingerprint: state2.cachedM0WorkspaceFingerprint,
|
|
36210
|
+
projectUserProfileVersion: state2.cachedM0ProjectUserProfileVersion,
|
|
36211
|
+
maxCompartmentSeq: state2.cachedM0MaxCompartmentSeq,
|
|
36212
|
+
maxMemoryId: state2.cachedM0MaxMemoryId,
|
|
36213
|
+
maxMutationId: state2.cachedM0MaxMutationId,
|
|
36214
|
+
maxMemoryMutationId: state2.cachedM0MaxMemoryMutationId,
|
|
36215
|
+
projectDocsHash: state2.cachedM0ProjectDocsHash ?? "",
|
|
36216
|
+
materializedAt: state2.cachedM0MaterializedAt ?? 0,
|
|
36217
|
+
sessionFactsVersion: state2.cachedM0SessionFactsVersion,
|
|
35523
36218
|
upgradeState: cachedUpgradeIdentity.upgradeState,
|
|
35524
36219
|
compartmentRenderEpoch: cachedUpgradeIdentity.compartmentRenderEpoch,
|
|
35525
|
-
systemHash:
|
|
35526
|
-
modelKey:
|
|
35527
|
-
projectIdentity:
|
|
35528
|
-
muralHash:
|
|
36220
|
+
systemHash: state2.cachedM0SystemHash ?? "",
|
|
36221
|
+
modelKey: state2.cachedM0ModelKey ?? "",
|
|
36222
|
+
projectIdentity: state2.cachedM0ProjectIdentity ?? null,
|
|
36223
|
+
muralHash: state2.cachedM0MuralHash ?? null
|
|
35529
36224
|
};
|
|
35530
36225
|
}
|
|
35531
36226
|
function mustMaterialize(args) {
|
|
@@ -35841,26 +36536,26 @@ ${sessionHistory}
|
|
|
35841
36536
|
|
|
35842
36537
|
`).trim();
|
|
35843
36538
|
}
|
|
35844
|
-
function applyMarkersToState(
|
|
35845
|
-
|
|
36539
|
+
function applyMarkersToState(state2, m0Bytes, markers, m1Bytes) {
|
|
36540
|
+
state2.cachedM0Bytes = m0Bytes;
|
|
35846
36541
|
if (m1Bytes)
|
|
35847
|
-
|
|
35848
|
-
|
|
35849
|
-
|
|
35850
|
-
|
|
35851
|
-
|
|
35852
|
-
|
|
35853
|
-
|
|
35854
|
-
|
|
35855
|
-
|
|
35856
|
-
|
|
35857
|
-
|
|
35858
|
-
|
|
35859
|
-
|
|
35860
|
-
|
|
35861
|
-
|
|
35862
|
-
|
|
35863
|
-
|
|
36542
|
+
state2.cachedM1Bytes = m1Bytes;
|
|
36543
|
+
state2.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
|
|
36544
|
+
state2.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
|
|
36545
|
+
state2.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
|
|
36546
|
+
state2.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
|
|
36547
|
+
state2.cachedM0MaxMemoryId = markers.maxMemoryId;
|
|
36548
|
+
state2.cachedM0MaxMutationId = markers.maxMutationId;
|
|
36549
|
+
state2.cachedM0MaxMemoryMutationId = markers.maxMemoryMutationId;
|
|
36550
|
+
state2.cachedM0ProjectDocsHash = markers.projectDocsHash;
|
|
36551
|
+
state2.cachedM0MaterializedAt = markers.materializedAt;
|
|
36552
|
+
state2.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
|
|
36553
|
+
state2.cachedM0UpgradeState = encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch);
|
|
36554
|
+
state2.cachedM0SystemHash = markers.systemHash;
|
|
36555
|
+
state2.cachedM0ModelKey = markers.modelKey;
|
|
36556
|
+
state2.cachedM0ProjectIdentity = markers.projectIdentity;
|
|
36557
|
+
state2.cachedM0MuralHash = markers.muralHash ?? null;
|
|
36558
|
+
state2.snapshotMarkers = markers;
|
|
35864
36559
|
}
|
|
35865
36560
|
function historySliceTokens(m0Text) {
|
|
35866
36561
|
const slice = extractM0Block(m0Text, "session-history");
|
|
@@ -35910,7 +36605,7 @@ function materializeM0(options) {
|
|
|
35910
36605
|
});
|
|
35911
36606
|
docs = readProjectDocsForM0(projectDirectory, options.injectDocs);
|
|
35912
36607
|
snapshotMarkers.projectDocsHash = docs.canonicalHash;
|
|
35913
|
-
compartments = readM0Compartments(options.db, options.sessionId);
|
|
36608
|
+
compartments = options.compactionOff ? [] : readM0Compartments(options.db, options.sessionId);
|
|
35914
36609
|
facts = [];
|
|
35915
36610
|
memories = projectPath ? workspace.isWorkspaced ? getMemoriesByProjects(options.db, workspace.expandedIdentities, ["active", "permanent"], foldMaterializedAt, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(options.db, projectPath, ["active", "permanent"], foldMaterializedAt) : [];
|
|
35916
36611
|
userMemories = safeGetActiveUserMemories(options.db);
|
|
@@ -36275,39 +36970,39 @@ function markersFromCachedRow(row) {
|
|
|
36275
36970
|
muralHash: row.cached_m0_mural_hash ?? null
|
|
36276
36971
|
};
|
|
36277
36972
|
}
|
|
36278
|
-
function cachedRowMatchesState(row,
|
|
36279
|
-
return bufferEqualsNullable(row.cached_m0_bytes,
|
|
36973
|
+
function cachedRowMatchesState(row, state2) {
|
|
36974
|
+
return bufferEqualsNullable(row.cached_m0_bytes, state2.cachedM0Bytes) && (row.cached_m0_mural_data_url ?? null) === (state2.cachedM0MuralDataUrl ?? null) && (row.cached_m0_mural_hash ?? null) === (state2.cachedM0MuralHash ?? null) && row.cached_m0_project_memory_epoch === state2.cachedM0ProjectMemoryEpoch && (row.cached_m0_workspace_fingerprint ?? null) === (state2.cachedM0WorkspaceFingerprint ?? null) && row.cached_m0_project_user_profile_version === state2.cachedM0ProjectUserProfileVersion && row.cached_m0_max_compartment_seq === state2.cachedM0MaxCompartmentSeq && row.cached_m0_max_memory_id === state2.cachedM0MaxMemoryId && row.cached_m0_max_mutation_id === state2.cachedM0MaxMutationId && row.cached_m0_max_memory_mutation_id === state2.cachedM0MaxMemoryMutationId && row.cached_m0_materialized_at === state2.cachedM0MaterializedAt && row.cached_m0_session_facts_version === state2.cachedM0SessionFactsVersion && (row.cached_m0_upgrade_state ?? null) === (state2.cachedM0UpgradeState ?? null) && (row.cached_m0_system_hash ?? "") === (state2.cachedM0SystemHash ?? "") && (row.cached_m0_model_key ?? "") === (state2.cachedM0ModelKey ?? "") && (row.cached_m0_project_identity ?? null) === (state2.cachedM0ProjectIdentity ?? null);
|
|
36280
36975
|
}
|
|
36281
|
-
function applyCachedRowToState(
|
|
36976
|
+
function applyCachedRowToState(state2, row) {
|
|
36282
36977
|
const markers = markersFromCachedRow(row);
|
|
36283
36978
|
if (!row.cached_m0_bytes || !row.cached_m1_bytes || !markers) {
|
|
36284
|
-
throw new RenderM1InvalidMarkersError(
|
|
36285
|
-
}
|
|
36286
|
-
|
|
36287
|
-
|
|
36288
|
-
|
|
36289
|
-
|
|
36290
|
-
|
|
36291
|
-
|
|
36292
|
-
|
|
36293
|
-
|
|
36294
|
-
|
|
36295
|
-
|
|
36296
|
-
|
|
36297
|
-
|
|
36298
|
-
|
|
36299
|
-
|
|
36300
|
-
|
|
36301
|
-
|
|
36302
|
-
|
|
36303
|
-
|
|
36304
|
-
|
|
36305
|
-
}
|
|
36306
|
-
function replayCachedM1(
|
|
36307
|
-
if (!
|
|
36308
|
-
throw new RenderM1InvalidMarkersError(
|
|
36309
|
-
}
|
|
36310
|
-
return decodeM0Bytes(
|
|
36979
|
+
throw new RenderM1InvalidMarkersError(state2.sessionId);
|
|
36980
|
+
}
|
|
36981
|
+
state2.cachedM0Bytes = toBuffer(row.cached_m0_bytes);
|
|
36982
|
+
state2.cachedM0MuralDataUrl = row.cached_m0_mural_data_url ?? null;
|
|
36983
|
+
state2.cachedM0MuralHash = row.cached_m0_mural_hash ?? null;
|
|
36984
|
+
state2.cachedM1Bytes = toBuffer(row.cached_m1_bytes);
|
|
36985
|
+
state2.cachedM0ProjectMemoryEpoch = markers.projectMemoryEpoch;
|
|
36986
|
+
state2.cachedM0WorkspaceFingerprint = markers.workspaceFingerprint;
|
|
36987
|
+
state2.cachedM0ProjectUserProfileVersion = markers.projectUserProfileVersion;
|
|
36988
|
+
state2.cachedM0MaxCompartmentSeq = markers.maxCompartmentSeq;
|
|
36989
|
+
state2.cachedM0MaxMemoryId = markers.maxMemoryId;
|
|
36990
|
+
state2.cachedM0MaxMutationId = markers.maxMutationId;
|
|
36991
|
+
state2.cachedM0MaxMemoryMutationId = markers.maxMemoryMutationId;
|
|
36992
|
+
state2.cachedM0ProjectDocsHash = markers.projectDocsHash;
|
|
36993
|
+
state2.cachedM0MaterializedAt = markers.materializedAt;
|
|
36994
|
+
state2.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
|
|
36995
|
+
state2.cachedM0UpgradeState = encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch);
|
|
36996
|
+
state2.cachedM0SystemHash = markers.systemHash;
|
|
36997
|
+
state2.cachedM0ModelKey = markers.modelKey;
|
|
36998
|
+
state2.cachedM0ProjectIdentity = markers.projectIdentity;
|
|
36999
|
+
state2.snapshotMarkers = markers;
|
|
37000
|
+
}
|
|
37001
|
+
function replayCachedM1(state2) {
|
|
37002
|
+
if (!state2.cachedM1Bytes) {
|
|
37003
|
+
throw new RenderM1InvalidMarkersError(state2.sessionId);
|
|
37004
|
+
}
|
|
37005
|
+
return decodeM0Bytes(state2.cachedM1Bytes) ?? M1_EMPTY_PLACEHOLDER;
|
|
36311
37006
|
}
|
|
36312
37007
|
function softRefreshCachedM1(options) {
|
|
36313
37008
|
options.db.exec("BEGIN IMMEDIATE");
|
|
@@ -36391,7 +37086,7 @@ function renderFreshM0NonPersisted(options) {
|
|
|
36391
37086
|
const docs = readProjectDocsForM0(projectDirectory ?? "", options.injectDocs);
|
|
36392
37087
|
snapshotMarkers.projectDocsHash = docs.canonicalHash;
|
|
36393
37088
|
snapshotMarkers.materializedAt = options.state.cachedM0MaterializedAt ?? 0;
|
|
36394
|
-
const compartments = withCompartmentDates(options.sessionId, readM0Compartments(options.db, options.sessionId), options.temporalAwareness);
|
|
37089
|
+
const compartments = options.compactionOff ? [] : withCompartmentDates(options.sessionId, readM0Compartments(options.db, options.sessionId), options.temporalAwareness);
|
|
36395
37090
|
const memories = projectPath ? workspace.isWorkspaced ? getMemoriesByProjects(options.db, workspace.expandedIdentities, ["active", "permanent"], snapshotMarkers.materializedAt, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(options.db, projectPath, ["active", "permanent"], snapshotMarkers.materializedAt) : [];
|
|
36396
37091
|
const userMemories = safeGetActiveUserMemories(options.db);
|
|
36397
37092
|
const memoryBudget = options.memoryInjectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
@@ -36469,7 +37164,7 @@ function injectM0M1(options) {
|
|
|
36469
37164
|
m0Bytes: options.state.cachedM0Bytes,
|
|
36470
37165
|
m1Text: null
|
|
36471
37166
|
};
|
|
36472
|
-
if (options.state.isSubagent)
|
|
37167
|
+
if (options.state.isSubagent && !options.compactionOff)
|
|
36473
37168
|
return skipped;
|
|
36474
37169
|
const decision = mustMaterialize({
|
|
36475
37170
|
db: options.db,
|
|
@@ -36598,14 +37293,14 @@ function onNoteTrigger(db, sessionId, trigger) {
|
|
|
36598
37293
|
sessionLog(sessionId, `note-nudge: trigger fired (${trigger}), triggerPending=true`);
|
|
36599
37294
|
}
|
|
36600
37295
|
function peekNoteNudgeText(db, sessionId, currentUserMessageId, projectIdentity, noteReadStillVisible) {
|
|
36601
|
-
const
|
|
36602
|
-
if (!
|
|
37296
|
+
const state2 = getPersistedNoteNudge(db, sessionId);
|
|
37297
|
+
if (!state2.triggerPending)
|
|
36603
37298
|
return null;
|
|
36604
|
-
if (!
|
|
37299
|
+
if (!state2.triggerMessageId && currentUserMessageId) {
|
|
36605
37300
|
setPersistedNoteNudgeTriggerMessageId(db, sessionId, currentUserMessageId);
|
|
36606
|
-
|
|
37301
|
+
state2.triggerMessageId = currentUserMessageId;
|
|
36607
37302
|
}
|
|
36608
|
-
if (
|
|
37303
|
+
if (state2.triggerMessageId && currentUserMessageId && state2.triggerMessageId === currentUserMessageId) {
|
|
36609
37304
|
sessionLog(sessionId, `note-nudge: deferring — current user message ${currentUserMessageId} is same as trigger-time message`);
|
|
36610
37305
|
return null;
|
|
36611
37306
|
}
|
|
@@ -36807,29 +37502,29 @@ function callIdFromPart(part) {
|
|
|
36807
37502
|
const direct = firstStringField(part, ["callID", "callId", "toolCallId", "tool_call_id", "id"]);
|
|
36808
37503
|
if (direct)
|
|
36809
37504
|
return direct;
|
|
36810
|
-
const
|
|
36811
|
-
return
|
|
37505
|
+
const state2 = isRecord(part.state) ? part.state : null;
|
|
37506
|
+
return state2 ? firstStringField(state2, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
|
|
36812
37507
|
}
|
|
36813
37508
|
function toolSignalFromPart(part) {
|
|
36814
37509
|
if (!isRecord(part))
|
|
36815
37510
|
return null;
|
|
36816
37511
|
const type = partType(part);
|
|
36817
|
-
const
|
|
37512
|
+
const state2 = isRecord(part.state) ? part.state : null;
|
|
36818
37513
|
const callId = callIdFromPart(part);
|
|
36819
37514
|
if (!callId && type !== "tool")
|
|
36820
37515
|
return null;
|
|
36821
37516
|
if (type === "tool") {
|
|
36822
|
-
const hasInput =
|
|
36823
|
-
const outputKey =
|
|
37517
|
+
const hasInput = state2 !== null && hasOwn(state2, "input");
|
|
37518
|
+
const outputKey = state2 ? hasOwn(state2, "output") ? "output" : hasOwn(state2, "error") ? "error" : hasOwn(state2, "result") ? "result" : null : null;
|
|
36824
37519
|
const hasOutput = outputKey !== null;
|
|
36825
|
-
const outputValue = outputKey &&
|
|
37520
|
+
const outputValue = outputKey && state2 ? state2[outputKey] : undefined;
|
|
36826
37521
|
const providerExecuted = part.providerExecuted === true;
|
|
36827
37522
|
const openInvocation = !providerExecuted && !hasOutput;
|
|
36828
37523
|
return {
|
|
36829
37524
|
callId,
|
|
36830
37525
|
hasInput: hasInput || openInvocation,
|
|
36831
37526
|
hasOutput,
|
|
36832
|
-
inputText: hasInput &&
|
|
37527
|
+
inputText: hasInput && state2 ? stringValue(state2.input) : "",
|
|
36833
37528
|
outputText: hasOutput ? stringValue(outputValue) : ""
|
|
36834
37529
|
};
|
|
36835
37530
|
}
|
|
@@ -37057,24 +37752,27 @@ function tokenForMessage(message, options) {
|
|
|
37057
37752
|
function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
37058
37753
|
const ordered = [...messages].sort((a, b) => a.ordinal - b.ordinal);
|
|
37059
37754
|
const sliceCount = ordered.length;
|
|
37060
|
-
const
|
|
37061
|
-
const
|
|
37755
|
+
const firstOrdinal = ordered.length > 0 ? ordered[0].ordinal : 1;
|
|
37756
|
+
const terminalOrdinal = ordered.length > 0 ? ordered[ordered.length - 1].ordinal : 0;
|
|
37757
|
+
const rawMessageCount = Math.max(sliceCount, terminalOrdinal, options.absoluteMessageCount ?? sliceCount);
|
|
37758
|
+
const ordinalSpan = terminalOrdinal >= firstOrdinal ? terminalOrdinal - firstOrdinal + 1 : 0;
|
|
37062
37759
|
const tokensByOrdinal = new Map;
|
|
37063
37760
|
const idsByOrdinal = new Map;
|
|
37064
|
-
const prefix = new Array(
|
|
37761
|
+
const prefix = new Array(ordinalSpan + 1).fill(0);
|
|
37065
37762
|
for (const message of ordered) {
|
|
37066
37763
|
const stored = options.storedTotalForMessage?.(message);
|
|
37067
37764
|
const total = stored !== undefined && stored !== null ? stored : tokenForMessage(message, options).total;
|
|
37068
37765
|
tokensByOrdinal.set(message.ordinal, total);
|
|
37069
37766
|
idsByOrdinal.set(message.ordinal, message.id);
|
|
37070
|
-
|
|
37071
|
-
|
|
37767
|
+
const relative = message.ordinal - firstOrdinal + 1;
|
|
37768
|
+
if (relative >= 1 && relative <= ordinalSpan) {
|
|
37769
|
+
prefix[relative] = total;
|
|
37072
37770
|
}
|
|
37073
37771
|
}
|
|
37074
|
-
for (let k = 1;k <=
|
|
37772
|
+
for (let k = 1;k <= ordinalSpan; k += 1) {
|
|
37075
37773
|
prefix[k] += prefix[k - 1];
|
|
37076
37774
|
}
|
|
37077
|
-
const ordinalToIndex = (ordinal) => Math.max(0, Math.min(
|
|
37775
|
+
const ordinalToIndex = (ordinal) => Math.max(0, Math.min(ordinalSpan, ordinal - firstOrdinal));
|
|
37078
37776
|
return {
|
|
37079
37777
|
sessionId,
|
|
37080
37778
|
providerShapeVersion: options.providerShapeVersion,
|
|
@@ -37086,27 +37784,27 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
|
37086
37784
|
return idsByOrdinal.get(ordinal) ?? null;
|
|
37087
37785
|
},
|
|
37088
37786
|
suffixTokensFromOrdinal(ordinal) {
|
|
37089
|
-
if (ordinal <=
|
|
37090
|
-
return prefix[
|
|
37091
|
-
if (ordinal >
|
|
37787
|
+
if (ordinal <= firstOrdinal)
|
|
37788
|
+
return prefix[ordinalSpan];
|
|
37789
|
+
if (ordinal > terminalOrdinal)
|
|
37092
37790
|
return 0;
|
|
37093
|
-
return prefix[
|
|
37791
|
+
return prefix[ordinalSpan] - prefix[ordinalToIndex(ordinal)];
|
|
37094
37792
|
},
|
|
37095
37793
|
rangeTokens(startInclusive, endExclusive) {
|
|
37096
|
-
const start = Math.max(
|
|
37097
|
-
const end = Math.max(start, Math.min(
|
|
37098
|
-
return prefix[end -
|
|
37794
|
+
const start = Math.max(firstOrdinal, startInclusive);
|
|
37795
|
+
const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
|
|
37796
|
+
return prefix[end - firstOrdinal] - prefix[start - firstOrdinal];
|
|
37099
37797
|
},
|
|
37100
37798
|
findSuffixStartForTokens(tokens) {
|
|
37101
37799
|
if (!Number.isFinite(tokens) || tokens <= 0)
|
|
37102
|
-
return
|
|
37800
|
+
return terminalOrdinal + 1;
|
|
37103
37801
|
const target = Math.max(0, Math.floor(tokens));
|
|
37104
|
-
const total = prefix[
|
|
37802
|
+
const total = prefix[ordinalSpan];
|
|
37105
37803
|
if (total < target)
|
|
37106
|
-
return
|
|
37804
|
+
return firstOrdinal;
|
|
37107
37805
|
const cut = total - target;
|
|
37108
37806
|
let lo = 0;
|
|
37109
|
-
let hi =
|
|
37807
|
+
let hi = ordinalSpan;
|
|
37110
37808
|
let best = 0;
|
|
37111
37809
|
while (lo <= hi) {
|
|
37112
37810
|
const mid = lo + hi >> 1;
|
|
@@ -37117,29 +37815,31 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
|
37117
37815
|
hi = mid - 1;
|
|
37118
37816
|
}
|
|
37119
37817
|
}
|
|
37120
|
-
return
|
|
37818
|
+
return firstOrdinal + best;
|
|
37121
37819
|
},
|
|
37122
37820
|
findHeadEndForCap(startInclusive, endExclusive, capTokens) {
|
|
37123
|
-
const start = Math.max(
|
|
37124
|
-
const end = Math.max(start, Math.min(
|
|
37821
|
+
const start = Math.max(firstOrdinal, Math.min(terminalOrdinal + 1, startInclusive));
|
|
37822
|
+
const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
|
|
37125
37823
|
if (!Number.isFinite(capTokens) || capTokens <= 0)
|
|
37126
37824
|
return start;
|
|
37127
|
-
const
|
|
37128
|
-
const
|
|
37129
|
-
|
|
37130
|
-
let
|
|
37131
|
-
let
|
|
37825
|
+
const startIndex = start - firstOrdinal;
|
|
37826
|
+
const endIndex = end - firstOrdinal;
|
|
37827
|
+
const cut = prefix[startIndex] + Math.floor(capTokens);
|
|
37828
|
+
let lo = startIndex + 1;
|
|
37829
|
+
let hi = endIndex;
|
|
37830
|
+
let bestEndIndex = startIndex;
|
|
37132
37831
|
while (lo <= hi) {
|
|
37133
37832
|
const mid = lo + hi >> 1;
|
|
37134
37833
|
if (prefix[mid] <= cut) {
|
|
37135
|
-
|
|
37834
|
+
bestEndIndex = mid;
|
|
37136
37835
|
lo = mid + 1;
|
|
37137
37836
|
} else {
|
|
37138
37837
|
hi = mid - 1;
|
|
37139
37838
|
}
|
|
37140
37839
|
}
|
|
37840
|
+
let bestEnd = firstOrdinal + bestEndIndex;
|
|
37141
37841
|
if (bestEnd === start && start < end)
|
|
37142
|
-
|
|
37842
|
+
bestEnd = start + 1;
|
|
37143
37843
|
return Math.min(bestEnd, end);
|
|
37144
37844
|
}
|
|
37145
37845
|
};
|
|
@@ -37456,7 +38156,8 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
37456
38156
|
if (ctx.migrationFloorActive)
|
|
37457
38157
|
runtimeFloor = Math.max(runtimeFloor, ctx.priorBoundaryOrdinal);
|
|
37458
38158
|
let protectedTailStart = Math.max(boundary, runtimeFloor);
|
|
37459
|
-
|
|
38159
|
+
const forceMaterializationPercentage = escalationBands(ctx.executeThresholdPercentage).forceMaterializationPercentage;
|
|
38160
|
+
if (!ctx.emergencyTailScale && usagePercentage < forceMaterializationPercentage) {
|
|
37460
38161
|
let lastMeaningfulUserOrdinal = 0;
|
|
37461
38162
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
37462
38163
|
const message = messages[i];
|
|
@@ -37697,7 +38398,8 @@ function getRawHistoryEligibility(db, sessionId) {
|
|
|
37697
38398
|
function hasRunnableCompartmentWindow(snapshot) {
|
|
37698
38399
|
if (snapshot.offset >= snapshot.protectedTailStart)
|
|
37699
38400
|
return false;
|
|
37700
|
-
|
|
38401
|
+
const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
|
|
38402
|
+
if (snapshot.usagePercentage >= forceMaterializationPercentage || snapshot.emergencyTailScale) {
|
|
37701
38403
|
return snapshot.trueRawEligibleTokens >= deriveMinForceEligibleTokens(snapshot.N) || snapshot.eligibleEndOrdinal > snapshot.offset;
|
|
37702
38404
|
}
|
|
37703
38405
|
return snapshot.eligibleEndOrdinal > snapshot.offset;
|
|
@@ -37760,8 +38462,10 @@ function validateBoundarySnapshot(args) {
|
|
|
37760
38462
|
return { ok: true };
|
|
37761
38463
|
}
|
|
37762
38464
|
function recordHighPressureNoEligibleHead(db, snapshot) {
|
|
37763
|
-
|
|
38465
|
+
const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
|
|
38466
|
+
if (snapshot.usagePercentage < forceMaterializationPercentage && !snapshot.emergencyTailScale) {
|
|
37764
38467
|
return 0;
|
|
38468
|
+
}
|
|
37765
38469
|
return recordProtectedTailNoEligibleHead(db, snapshot.sessionId);
|
|
37766
38470
|
}
|
|
37767
38471
|
|
|
@@ -39792,6 +40496,7 @@ ${chunkText}`,
|
|
|
39792
40496
|
retainDrainReservationForRetryThrottle = true;
|
|
39793
40497
|
const validatedPass = await runValidatedHistorianPass({
|
|
39794
40498
|
client,
|
|
40499
|
+
db,
|
|
39795
40500
|
parentSessionId: sessionId,
|
|
39796
40501
|
sessionDirectory,
|
|
39797
40502
|
prompt,
|
|
@@ -40252,6 +40957,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
40252
40957
|
emitProgress(`Running historian (pass ${passCount + 1})…`);
|
|
40253
40958
|
const validatedPass = await runValidatedHistorianPass({
|
|
40254
40959
|
client,
|
|
40960
|
+
db,
|
|
40255
40961
|
parentSessionId: sessionId,
|
|
40256
40962
|
sessionDirectory,
|
|
40257
40963
|
prompt,
|
|
@@ -40671,6 +41377,7 @@ ${chunk.text}`,
|
|
|
40671
41377
|
Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${chunk.startIndex}-${chunk.endIndex}.`, notifParams());
|
|
40672
41378
|
const validatedPass = await runValidatedHistorianPass({
|
|
40673
41379
|
client,
|
|
41380
|
+
db,
|
|
40674
41381
|
parentSessionId: sessionId,
|
|
40675
41382
|
sessionDirectory,
|
|
40676
41383
|
prompt,
|
|
@@ -40922,7 +41629,7 @@ async function executeContextRecomp(deps, options = {}) {
|
|
|
40922
41629
|
}
|
|
40923
41630
|
|
|
40924
41631
|
// src/hooks/magic-context/lkg-slot.ts
|
|
40925
|
-
import { createHash as
|
|
41632
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
40926
41633
|
var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
|
|
40927
41634
|
var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
|
|
40928
41635
|
var LKG_METADATA_BYTES = 256;
|
|
@@ -40933,7 +41640,7 @@ function slotBytes(slot) {
|
|
|
40933
41640
|
return 2 * slot.jsonPrefix.length + digestBytes + LKG_METADATA_BYTES;
|
|
40934
41641
|
}
|
|
40935
41642
|
function lkgContentDigest(message) {
|
|
40936
|
-
const hash2 =
|
|
41643
|
+
const hash2 = createHash15("sha256");
|
|
40937
41644
|
const seen = new WeakSet;
|
|
40938
41645
|
const visit = (value) => {
|
|
40939
41646
|
if (value === null) {
|
|
@@ -41299,4 +42006,4 @@ async function runUpgradeMemoryMigration(ctx, sessionId, migrationDirectory) {
|
|
|
41299
42006
|
}
|
|
41300
42007
|
}
|
|
41301
42008
|
|
|
41302
|
-
export { withContentLanguageDirective, buildPrimaryLanguageDirective, exports_external, DEFAULT_PROTECTED_TAGS, parseCron, nextOccurrence, nextDueAtMs, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, DEFAULT_LOCAL_EMBEDDING_MODEL, MagicContextConfigSchema, getOpenCodeDbPath, ProjectIdentityError, resolveProjectIdentityStrict, takeDubiousOwnershipProjectIdentityWarning, resolveProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, recordSessionProjectIdentity,
|
|
42009
|
+
export { withContentLanguageDirective, buildPrimaryLanguageDirective, exports_external, DEFAULT_PROTECTED_TAGS, parseCron, nextOccurrence, nextDueAtMs, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, DEFAULT_HISTORIAN_TIMEOUT_MS, DEFAULT_LOCAL_EMBEDDING_MODEL, MagicContextConfigSchema, getOpenCodeDbPath, removeMcOwnedCompactionMarkers, ProjectIdentityError, resolveProjectIdentityStrict, takeDubiousOwnershipProjectIdentityWarning, resolveProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, recordSessionProjectIdentity, beginBootQuietPeriod, bootQuietRemainingMs, scheduleAfterBootQuiet, rpcPortDir, rpcPortFilePath, isPidAlive, parseRpcPortFile, registerModuleNoteEvaluationBridge, getModuleNoteEvaluationBridge, getContextStoreUuid, ensureContextStoreUuid, getAuthorityManagedMarker, reconcileAuthorityProject, checksumAuthoritySeedRows, prepareAuthority, drainAuthority, getMirrorCursor, applyMirrorPage, pullMemoryMirrorOnce, V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, resolveStoredPathWorkspaceIdentity, storedPathBelongsToWorkspace, sourceNameForMemory, computeWorkspaceEpochFingerprint, recordToolDefinition, getMeasuredToolDefinitionTokens, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getDatabasePath, getPersistedSchemaVersion, setSqlitePragmaConfig, runSqliteOptimize, openDatabase, openDatabaseAsync, isDatabasePersisted, getDatabasePersistenceError, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, clearRecompStaging, recordEmbeddingMeasurement, getMaxM0MutationId, queueMemoryMutation, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationIdForProjects, MAX_EXECUTE_THRESHOLD, escalationBands, isEmergencyRecoveryArmed, isProviderOverflowReconfirmed, loadPersistedUsage, loadProtectedTailMeta, resetProtectedTailNoEligibleHead, getWrapupInProgressState, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, getPersistedReasoningWatermark, setPersistedReasoningWatermark, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getLastNudgeLevel, setLastNudgeLevel, resetLastNudgeCycle, resetLastNudgeCycleIfTailShrank, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, getNoteNudgeAnchors, getAutoSearchHintDecisions, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, removeNoteNudgeAnchorByMessageId, removeAutoSearchHintDecisionByMessageId, getPersistedTodoPermissionDenied, setPersistedTodoPermissionDenied, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, setNoteLastReadAt, getHistorianFailureState, clearHistorianFailureState, getOverflowState, recordOverflowDetected, recordDetectedContextLimit, clearEmergencyRecovery, clearDetectedContextLimit, getPersistedCompactionMarkerState, setPersistedCompactionMarkerState, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, removeStrippedPlaceholderId, getStaleReduceStrippedIds, addStaleReduceStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, clearPendingCompactionMarkerStateIf, peekDeferredExecutePending, setDeferredExecutePendingIfAbsent, clearDeferredExecutePendingIfMatches, getSessionsWithPendingMarker, setSessionWorkMetrics, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNote, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, clearPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectMemoryEpoch, bumpProjectUserProfileVersion, saveSourceContent, replaceSourceContent, getSourceContents, getActiveTagTokenAggregate, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, updateTagDropMode, updateCavemanDepth, updateTagMessageId, deleteTagsByMessageId, getMaxTagNumberBySession, getTagNumberByMessageId, deriveTagLoadFloor, getTagsBySession, getActiveTagsBySession, getDroppedTagsBySession, getTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, createChildSessionWithFence, detectOverflow, promptSyncWithValidatedOutputRetry, normalizeSDKResponse, extractLatestAssistantText, hasLengthCappedOutput, setKeepSubagents, shouldKeepSubagents, recordChildInvocation, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_EDITOR_SYSTEM_PROMPT, COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, Priority, AdmissionClass, StaleRouteHandleError, SocketClosedError, SocketTimeoutError, SubcClient, isConsumerReconnectTransient, getCompartmentEvents, loadCompartmentChunkEmbeddingsForSearch, cosineSimilarity, SYNAPSE_DEFAULT_MODEL, SynapseEmbeddingProvider, computeNormalizedHash, saveCommitEmbedding, loadProjectCommitEmbeddings, loadUnembeddedCommits, countEmbeddedCommits, upsertCommits, getLatestIndexedCommitTimeMs, enforceProjectCap, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, saveEmbeddingIfHashMatches, getProjectEmbeddings, peekProjectEmbeddings, invalidateProject, invalidateMemory, markProjectLoadUntrusted, contentSha256, sweepStaleEmbeddingIdentitiesForProject, registerProjectEmbedding, registerProjectShadowEmbedding, getShadowEmbeddingMeasurementCohort, getPrimaryEmbeddingMeasurementCohort, embedShadowTextForProject, enqueueShadowEmbeddingItems, registerProjectInObservationMode, getProjectEmbeddingSnapshot, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, isEmbeddingEnabled, embedText, ensureMemoryEmbeddings, computeCueContentHash, getMuralCueState, memoryNeedsCue, setMuralCue, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, ModuleMemoryAuthorityError, insertMemory, insertMemoryIdempotent, getMemoryByHash, getMemoriesByProject, buildWorkspaceMemorySqlFilter, getMemoriesByProjects, getMaxMemoryIdForProjects, readNewMemoriesForM1Union, getMemoryById, getMemoriesByIds, updateMemorySeenCount, updateMemoryRetrievalCount, setMemoryClassification, supersededMemory, mergeMemoryStats, archiveMemory, getMemoryCountsByStatus, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, MARKER_SUMMARY_TEXT, applyDeferredCompactionMarker, removeCompactionMarkerForSession, checkCompactionMarkerConsistency, getMural, BoundedSessionMap, extractM0Block, formatDate, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, prepareCompartmentInjection, renderCompartmentInjection, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, injectM0M1, onNoteTrigger, peekNoteNudgeText, markNoteNudgeDelivered, clearNoteNudgeTriggerAndCooldown, resetNoteNudgeCooldownOnly, clearNoteNudgeTriggerOnly, estimateTrueRawMessageTokens, invalidateTrueRawTokenCache, RECOVERY_NO_HEAD_LIMIT, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, snapRangeToCompartments, lkgContentDigest, captureSlot, getSlot, dropSlot, noteEntry, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, isRecompFailure, isRecompSkip, isRecompComplete, extractRecompReason, contextualizeUpgradeReason, setRecompStarting, setRecompNote, setRecompTerminal, runManagedRecomp, runManagedUpgrade };
|