@cortexkit/opencode-magic-context 0.42.3 → 0.42.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/{announcement-3c1vertn.js → announcement-8mgn61fw.js} +1 -1
- package/dist/{conflict-warning-hook-aedp084d.js → conflict-warning-hook-jyj54gbe.js} +4 -4
- package/dist/{derive-budgets-s2pgnnm4.js → derive-budgets-v1fkhjjr.js} +2 -2
- package/dist/features/magic-context/context-authority.d.ts +13 -0
- package/dist/features/magic-context/context-authority.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts +3 -1
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/curate-category-rotation.d.ts +26 -0
- package/dist/features/magic-context/dreamer/curate-category-rotation.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts +7 -5
- package/dist/features/magic-context/dreamer/storage-task-schedule.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +6 -2
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-gates.d.ts +1 -0
- package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-prompts.d.ts +3 -0
- package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +9 -0
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts +5 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +11 -0
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts +3 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +4 -0
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +4 -1
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts +4 -0
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts +5 -2
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts +2 -2
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +61 -2
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts +2 -2
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/dropped-token-estimate.d.ts +20 -0
- package/dist/hooks/magic-context/dropped-token-estimate.d.ts.map +1 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +2 -2
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-transport.d.ts +4 -1
- package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +2 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/tail-hygiene-walk.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 +8 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +21 -0
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-sf6x1ga9.js → index-1ar7b3e9.js} +3 -3
- package/dist/{index-wde5446v.js → index-3wbd8sdq.js} +225 -67
- package/dist/{index-3fe78beq.js → index-4ftb5hcq.js} +9 -1
- package/dist/{index-may8skc8.js → index-4wwr6cz0.js} +18 -1
- package/dist/{index-ecz14qke.js → index-d8mgqezq.js} +2 -2
- package/dist/{index-xdtge3y2.js → index-f9gem5cr.js} +2 -2
- package/dist/{index-z8552w7e.js → index-jkrqhc7y.js} +1 -1
- package/dist/{index-3wzdwt6p.js → index-ntbmt6rq.js} +1 -1
- package/dist/{index-gynz8qdc.js → index-p474rw9p.js} +3 -3
- package/dist/{index-dkv2dn46.js → index-qp20p2py.js} +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1625 -148
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +18 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/rust-tool-backends.d.ts +3 -1
- package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-447vycpt.js → recomp-orchestrator-k20sfpm2.js} +6 -6
- package/dist/{safe-notification-target-q9z81zt3.js → safe-notification-target-fepvcbsj.js} +1 -1
- package/dist/{send-session-notification-2mzgd3zf.js → send-session-notification-xnypkxpx.js} +3 -3
- package/dist/shared/harness.d.ts +2 -1
- package/dist/shared/harness.d.ts.map +1 -1
- package/dist/shared/model-suggestion-retry.d.ts +5 -1
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
- package/dist/shared/rpc-types.d.ts +13 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/status-detail-text.d.ts.map +1 -1
- package/dist/shared/status-summary.d.ts.map +1 -1
- package/dist/shared/user-facing-codes.d.ts +10 -0
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/{storage-meta-session-fkmfhswa.js → storage-meta-session-x3j0q9qy.js} +3 -3
- package/dist/{task-config-hnv93r7p.js → task-config-cv8k9y8r.js} +1 -1
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/v2/fold/markers.d.ts +7 -0
- package/dist/v2/fold/markers.d.ts.map +1 -0
- package/dist/v2/fold/owner.d.ts +40 -0
- package/dist/v2/fold/owner.d.ts.map +1 -0
- package/dist/v2/fold/restore.d.ts +11 -0
- package/dist/v2/fold/restore.d.ts.map +1 -0
- package/dist/v2/hidden-completion.d.ts +20 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -0
- package/dist/v2/hooks/channel2.d.ts +8 -0
- package/dist/v2/hooks/channel2.d.ts.map +1 -0
- package/dist/v2/hooks/context.d.ts +7 -0
- package/dist/v2/hooks/context.d.ts.map +1 -0
- package/dist/v2/hooks/dream-trigger.d.ts +19 -0
- package/dist/v2/hooks/dream-trigger.d.ts.map +1 -0
- package/dist/v2/hooks/payload.d.ts +12 -0
- package/dist/v2/hooks/payload.d.ts.map +1 -0
- package/dist/v2/hooks/refusal.d.ts +7 -0
- package/dist/v2/hooks/refusal.d.ts.map +1 -0
- package/dist/v2/hooks/store.d.ts +6 -0
- package/dist/v2/hooks/store.d.ts.map +1 -0
- package/dist/v2/hooks/types.d.ts +90 -0
- package/dist/v2/hooks/types.d.ts.map +1 -0
- package/dist/v2/hooks/update-check.d.ts +10 -0
- package/dist/v2/hooks/update-check.d.ts.map +1 -0
- package/dist/v2/server.d.ts +3 -1
- package/dist/v2/server.d.ts.map +1 -1
- package/dist/v2/server.js +116641 -4
- package/dist/v2/store-reader.d.ts +2 -0
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/index.js +1 -0
- package/package.json +5 -4
- package/src/features/magic-context/dreamer/task-registry.ts +29 -0
- package/src/shared/harness.ts +2 -1
- package/src/shared/model-suggestion-retry.ts +66 -14
- package/src/shared/prompt-surface-runtime.ts +5 -1
- package/src/shared/rpc-types.ts +13 -0
- package/src/shared/status-detail-text.test.ts +26 -0
- package/src/shared/status-detail-text.ts +11 -0
- package/src/shared/status-summary.ts +2 -0
- package/src/shared/user-facing-codes.test.ts +1 -1
- package/src/shared/user-facing-codes.ts +10 -0
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
sessionLog,
|
|
6
6
|
getLoggerDiagnostics,
|
|
7
7
|
flushLogger
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-qp20p2py.js";
|
|
9
9
|
import {
|
|
10
10
|
withContentLanguageDirective,
|
|
11
11
|
buildPrimaryLanguageDirective,
|
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
checksumAuthoritySeedRows,
|
|
72
72
|
prepareAuthority,
|
|
73
73
|
drainAuthority,
|
|
74
|
+
getMemoryMirrorStatus,
|
|
74
75
|
applyMirroredNoteCompileFields,
|
|
75
76
|
drainMirrorPages,
|
|
76
77
|
pullMemoryMirrorOnce,
|
|
@@ -191,6 +192,7 @@ import {
|
|
|
191
192
|
isToolPartWithOutput,
|
|
192
193
|
isFilePart,
|
|
193
194
|
buildFileSourceContent,
|
|
195
|
+
assertExecutableToolInput,
|
|
194
196
|
createDroppedInputToolExecuteBeforeHook,
|
|
195
197
|
isEditTool,
|
|
196
198
|
partHasCompletedResult,
|
|
@@ -359,6 +361,7 @@ import {
|
|
|
359
361
|
replaceSourceContent,
|
|
360
362
|
getSourceContents,
|
|
361
363
|
createChildSessionWithFence,
|
|
364
|
+
HiddenCompletionRefusal,
|
|
362
365
|
detectThinkingBindingMismatch,
|
|
363
366
|
isFable51ThinkingBindingModel,
|
|
364
367
|
detectOverflow,
|
|
@@ -472,6 +475,7 @@ import {
|
|
|
472
475
|
verificationFileExists,
|
|
473
476
|
normalizeVerificationFiles,
|
|
474
477
|
recordChildInvocation,
|
|
478
|
+
createV1HiddenCompletionExecutor,
|
|
475
479
|
USER_MEMORY_CANDIDATE_TTL_MS,
|
|
476
480
|
insertUserMemoryCandidates,
|
|
477
481
|
getUserMemoryCandidates,
|
|
@@ -522,6 +526,7 @@ import {
|
|
|
522
526
|
mustMaterialize,
|
|
523
527
|
trimMemoriesToBudgetV2,
|
|
524
528
|
renderMemoryBlockV2,
|
|
529
|
+
materializeM0,
|
|
525
530
|
prepareCachedM0M1Replay,
|
|
526
531
|
hasCompleteCachedM0M1,
|
|
527
532
|
injectM0M1,
|
|
@@ -542,7 +547,7 @@ import {
|
|
|
542
547
|
setRecompTerminal2,
|
|
543
548
|
runManagedRecomp2,
|
|
544
549
|
runManagedUpgrade2
|
|
545
|
-
} from "./index-
|
|
550
|
+
} from "./index-3wbd8sdq.js";
|
|
546
551
|
import {
|
|
547
552
|
stripJsonComments,
|
|
548
553
|
isPrototypePollutionKey,
|
|
@@ -568,7 +573,7 @@ import {
|
|
|
568
573
|
deriveHistorianChunkTokens2,
|
|
569
574
|
resolveKnownHistorianContextLimit2,
|
|
570
575
|
resolveHistorianContextLimit2
|
|
571
|
-
} from "./index-
|
|
576
|
+
} from "./index-f9gem5cr.js";
|
|
572
577
|
import {
|
|
573
578
|
resolveOpenCodeDbPath,
|
|
574
579
|
openCodeDbPathExists,
|
|
@@ -589,7 +594,7 @@ import {
|
|
|
589
594
|
assistantAwaitingTools,
|
|
590
595
|
getMessageTimesFromOpenCodeDb,
|
|
591
596
|
findLastAssistantModelFromOpenCodeDb
|
|
592
|
-
} from "./index-
|
|
597
|
+
} from "./index-jkrqhc7y.js";
|
|
593
598
|
import {
|
|
594
599
|
getErrorMessage,
|
|
595
600
|
describeError,
|
|
@@ -598,13 +603,13 @@ import {
|
|
|
598
603
|
clearIgnoredMessages2,
|
|
599
604
|
observeIgnoredNotificationEvent2,
|
|
600
605
|
sendStatusNotification2
|
|
601
|
-
} from "./index-
|
|
606
|
+
} from "./index-p474rw9p.js";
|
|
602
607
|
import {
|
|
603
608
|
detectConflicts,
|
|
604
609
|
resolveCompactionForBoot,
|
|
605
610
|
sendConflictWarning2,
|
|
606
611
|
cleanupConflictWarnings2
|
|
607
|
-
} from "./index-
|
|
612
|
+
} from "./index-d8mgqezq.js";
|
|
608
613
|
import {
|
|
609
614
|
resolveHistorianModel2,
|
|
610
615
|
resolveOpenCodeAgentOverrides2,
|
|
@@ -612,6 +617,7 @@ import {
|
|
|
612
617
|
} from "./index-7k55qm8a.js";
|
|
613
618
|
import {
|
|
614
619
|
CANONICAL_DREAM_TASKS,
|
|
620
|
+
DREAM_TASK_CAPABILITIES,
|
|
615
621
|
formatDreamTaskBacklogs,
|
|
616
622
|
processedDreamTaskItems,
|
|
617
623
|
leaseKindFor,
|
|
@@ -620,7 +626,7 @@ import {
|
|
|
620
626
|
compareTaskOrder,
|
|
621
627
|
buildDreamTaskRuntimeConfigs2,
|
|
622
628
|
userMemoryCollectionEnabled2
|
|
623
|
-
} from "./index-
|
|
629
|
+
} from "./index-4wwr6cz0.js";
|
|
624
630
|
import {
|
|
625
631
|
logSlowWriteTransaction,
|
|
626
632
|
getOrCreateSessionMeta2,
|
|
@@ -630,7 +636,7 @@ import {
|
|
|
630
636
|
retryPendingSessionCleanups2,
|
|
631
637
|
retryPendingRustSessionCleanupsForProject2,
|
|
632
638
|
clearSession2
|
|
633
|
-
} from "./index-
|
|
639
|
+
} from "./index-1ar7b3e9.js";
|
|
634
640
|
import {
|
|
635
641
|
registerNotificationSink2,
|
|
636
642
|
pushNotification2,
|
|
@@ -646,7 +652,7 @@ import {
|
|
|
646
652
|
ANNOUNCEMENT_FOOTER2,
|
|
647
653
|
markAnnouncementSeen2,
|
|
648
654
|
shouldShowAnnouncement2
|
|
649
|
-
} from "./index-
|
|
655
|
+
} from "./index-ntbmt6rq.js";
|
|
650
656
|
import {
|
|
651
657
|
resolvePromptContext2
|
|
652
658
|
} from "./index-fmsr7v69.js";
|
|
@@ -656,12 +662,13 @@ import {
|
|
|
656
662
|
modelRefLookupOrder
|
|
657
663
|
} from "./index-avwt563y.js";
|
|
658
664
|
import {
|
|
665
|
+
setHarness,
|
|
659
666
|
getHarness,
|
|
660
667
|
getDataDir,
|
|
661
668
|
getOpenCodeStorageDir,
|
|
662
669
|
getMagicContextStorageResolution,
|
|
663
670
|
getMagicContextStorageDir
|
|
664
|
-
} from "./index-
|
|
671
|
+
} from "./index-4ftb5hcq.js";
|
|
665
672
|
import {
|
|
666
673
|
__toESM,
|
|
667
674
|
__commonJS
|
|
@@ -10774,9 +10781,11 @@ function buildCuratePrompt(args) {
|
|
|
10774
10781
|
|
|
10775
10782
|
**Project:** ${args.projectPath}
|
|
10776
10783
|
|
|
10784
|
+
This run covers the whole of the \`${args.category}\` category (the other categories run in later windows).
|
|
10785
|
+
|
|
10777
10786
|
The memories below are assumed ACCURATE (a separate verify task keeps them true). Your job is pool QUALITY: remove duplicates, tighten wording, and consolidate redundant entries that waste the ~6000-token injection budget. Explain each action in one line first. Do NOT mint new facts (that is the historian's job).
|
|
10778
10787
|
|
|
10779
|
-
Work ALL THREE phases below in order (A → B → C) over
|
|
10788
|
+
Work ALL THREE phases below in order (A → B → C) over this category. Do NOT stop after consolidating — a run that only merges and never improves or archives is incomplete.
|
|
10780
10789
|
|
|
10781
10790
|
### Phase A — Consolidate duplicates
|
|
10782
10791
|
Group by category, then merge near-identical / superset-subset / same-fact-different-angle clusters into one canonical memory with \`ctx_memory(action="merge", ids=[...], content="...", category="...")\`. Preserve every unique detail; terse present tense; paths/keys verbatim. Every id in a merge MUST share the same category — the system rejects cross-category merges. If two similar memories sit in different categories they are NOT duplicates; do not archive either as a consolidation. One fact per memory.
|
|
@@ -10996,6 +11005,7 @@ function buildDreamTaskPrompt(task, args) {
|
|
|
10996
11005
|
case "curate":
|
|
10997
11006
|
return buildCuratePrompt({
|
|
10998
11007
|
projectPath: args.projectPath,
|
|
11008
|
+
category: args.curate?.category ?? "PROJECT_RULES",
|
|
10999
11009
|
memories: args.curate?.memories ?? []
|
|
11000
11010
|
});
|
|
11001
11011
|
case "maintain-docs":
|
|
@@ -12174,7 +12184,7 @@ var SERIAL_LANE_MAX_WAITERS = 16;
|
|
|
12174
12184
|
var SERIAL_LANE_MAX_WAITERS_PER_SESSION = 8;
|
|
12175
12185
|
var SERIAL_LANE_MIN_REMAINING_MS = 25;
|
|
12176
12186
|
var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
|
|
12177
|
-
function
|
|
12187
|
+
function getDefaultSubcConnectionFile() {
|
|
12178
12188
|
return join5(getDataDir(), "cortexkit", "run", "subc-connection.json");
|
|
12179
12189
|
}
|
|
12180
12190
|
function errorChainSome(error, predicate) {
|
|
@@ -12289,7 +12299,7 @@ class SubcModuleTransport {
|
|
|
12289
12299
|
return capabilities;
|
|
12290
12300
|
}
|
|
12291
12301
|
constructor(connectionFile, moduleId = DEFAULT_MODULE_ID, requestTimeoutMs = MODULE_SEND_TIMEOUT_MS, routeSessionPrefix = "") {
|
|
12292
|
-
this.connectionFile = connectionFile
|
|
12302
|
+
this.connectionFile = connectionFile;
|
|
12293
12303
|
this.moduleId = moduleId;
|
|
12294
12304
|
this.requestTimeoutMs = requestTimeoutMs;
|
|
12295
12305
|
this.routeSessionPrefix = routeSessionPrefix;
|
|
@@ -12567,8 +12577,8 @@ class SubcModuleTransport {
|
|
|
12567
12577
|
}
|
|
12568
12578
|
async authorityStatus(args) {
|
|
12569
12579
|
this.authorityProjectRoot = args.project;
|
|
12570
|
-
const { projectRoot, ...body } = args;
|
|
12571
|
-
const response = await this.authorityRequest(args.project, projectRoot ?? this.bindRootForAuthority(), "authority.status", body);
|
|
12580
|
+
const { projectRoot, sessionId, ...body } = args;
|
|
12581
|
+
const response = await this.authorityRequest(sessionId ?? args.project, projectRoot ?? this.bindRootForAuthority(), "authority.status", body);
|
|
12572
12582
|
return { authority: response.authority ?? null };
|
|
12573
12583
|
}
|
|
12574
12584
|
async authorityPrepare(args) {
|
|
@@ -13560,6 +13570,7 @@ function toRow(r) {
|
|
|
13560
13570
|
lastStatus: r.last_status ?? null,
|
|
13561
13571
|
lastError: r.last_error,
|
|
13562
13572
|
retryCount: r.retry_count ?? 0,
|
|
13573
|
+
taskStateJson: r.last_checked_commit ?? null,
|
|
13563
13574
|
lastCheckedCommit: r.last_checked_commit ?? null,
|
|
13564
13575
|
lastBroadRunAt: r.last_broad_run_at ?? null,
|
|
13565
13576
|
retrospectiveWatermarkMs: r.retrospective_watermark_ms ?? null
|
|
@@ -13603,7 +13614,12 @@ function writeTaskScheduleState(db, row) {
|
|
|
13603
13614
|
retry_count = excluded.retry_count,
|
|
13604
13615
|
last_checked_commit = COALESCE(excluded.last_checked_commit, task_schedule_state.last_checked_commit),
|
|
13605
13616
|
${broadCycleUpdate},
|
|
13606
|
-
retrospective_watermark_ms = COALESCE(excluded.retrospective_watermark_ms, task_schedule_state.retrospective_watermark_ms)`).run(row.projectPath, row.task, row.lastRunAt, row.nextDueAt, row.schedule, row.lastStatus, row.lastError, row.retryCount, row.lastCheckedCommit ?? null, row.lastBroadRunAt ?? null, row.retrospectiveWatermarkMs ?? null);
|
|
13617
|
+
retrospective_watermark_ms = COALESCE(excluded.retrospective_watermark_ms, task_schedule_state.retrospective_watermark_ms)`).run(row.projectPath, row.task, row.lastRunAt, row.nextDueAt, row.schedule, row.lastStatus, row.lastError, row.retryCount, row.taskStateJson ?? row.lastCheckedCommit ?? null, row.lastBroadRunAt ?? null, row.retrospectiveWatermarkMs ?? null);
|
|
13618
|
+
}
|
|
13619
|
+
function writeTaskStateJson(db, projectPath, task, taskStateJson) {
|
|
13620
|
+
db.prepare(`INSERT INTO task_schedule_state (project_path, task, last_checked_commit)
|
|
13621
|
+
VALUES (?, ?, ?)
|
|
13622
|
+
ON CONFLICT(project_path, task) DO UPDATE SET last_checked_commit = excluded.last_checked_commit`).run(projectPath, task, taskStateJson);
|
|
13607
13623
|
}
|
|
13608
13624
|
function isRetrospectiveWindowProcessed(db, projectPath, windowKey) {
|
|
13609
13625
|
const row = db.prepare("SELECT 1 AS one FROM retrospective_processed_windows WHERE project_path = ? AND window_key = ?").get(projectPath, windowKey);
|
|
@@ -14041,6 +14057,8 @@ function isTimeoutClassError(error) {
|
|
|
14041
14057
|
}
|
|
14042
14058
|
async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
14043
14059
|
let agentSessionId = null;
|
|
14060
|
+
let handle = null;
|
|
14061
|
+
const executor = args.hiddenCompletionExecutor ?? createV1HiddenCompletionExecutor(args.client, args.db, args.sessionDirectory);
|
|
14044
14062
|
let promptSettled = false;
|
|
14045
14063
|
const startedAt = Date.now();
|
|
14046
14064
|
try {
|
|
@@ -14048,19 +14066,22 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
14048
14066
|
projectPath: args.projectIdentity,
|
|
14049
14067
|
memories: chunk.map(toPromptMemory)
|
|
14050
14068
|
});
|
|
14051
|
-
|
|
14052
|
-
client: args.client,
|
|
14053
|
-
db: args.db,
|
|
14069
|
+
handle = await executor.open({
|
|
14054
14070
|
parentSessionId: args.parentSessionId,
|
|
14071
|
+
agent: DREAMER_CLASSIFIER_AGENT,
|
|
14072
|
+
kind: "dreamer-task",
|
|
14073
|
+
system: COMPRESS_CUES_SYSTEM_PROMPT,
|
|
14074
|
+
model: args.model,
|
|
14075
|
+
configuredModels: [...args.model ? [args.model] : [], ...args.fallbackModels ?? []],
|
|
14076
|
+
timeoutMs: sliceMs,
|
|
14055
14077
|
title: "magic-context-dream-compress-cues",
|
|
14056
|
-
directory: args.sessionDirectory
|
|
14078
|
+
directory: args.sessionDirectory,
|
|
14079
|
+
metadata: { task: "compress-cues" }
|
|
14057
14080
|
});
|
|
14058
|
-
|
|
14059
|
-
preferResponseOnMissingData: true
|
|
14060
|
-
});
|
|
14061
|
-
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
14081
|
+
agentSessionId = handle.id || null;
|
|
14062
14082
|
if (!agentSessionId)
|
|
14063
14083
|
throw new Error("Could not create compress-cues session.");
|
|
14084
|
+
const opened = handle;
|
|
14064
14085
|
const run = await promptSyncWithValidatedOutputRetry(args.client, {
|
|
14065
14086
|
path: { id: agentSessionId },
|
|
14066
14087
|
query: { directory: args.sessionDirectory },
|
|
@@ -14071,24 +14092,18 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
14071
14092
|
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
14072
14093
|
}
|
|
14073
14094
|
}, {
|
|
14095
|
+
transport: Object.assign((request) => executor.attempt(opened, request), { childSessionId: opened.childSessionId }),
|
|
14074
14096
|
timeoutMs: sliceMs,
|
|
14075
14097
|
signal,
|
|
14076
14098
|
fallbackModels: args.fallbackModels,
|
|
14077
14099
|
callContext: "dreamer:compress-cues",
|
|
14078
|
-
fetchOutput:
|
|
14079
|
-
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
});
|
|
14083
|
-
return normalizeSDKResponse(messagesResponse, [], {
|
|
14084
|
-
preferResponseOnMissingData: true
|
|
14085
|
-
});
|
|
14086
|
-
},
|
|
14087
|
-
validateOutput: (messages) => {
|
|
14088
|
-
if (hasLengthCappedOutput(messages)) {
|
|
14100
|
+
fetchOutput: () => executor.collect(opened, 50),
|
|
14101
|
+
validateOutput: (completion) => {
|
|
14102
|
+
const messages = completion.messages ?? [];
|
|
14103
|
+
if (completion.lengthCapped) {
|
|
14089
14104
|
throw new Error("compress-cues returned length-capped output");
|
|
14090
14105
|
}
|
|
14091
|
-
const text =
|
|
14106
|
+
const text = completion.text;
|
|
14092
14107
|
if (!text)
|
|
14093
14108
|
throw new Error("compress-cues returned no output");
|
|
14094
14109
|
try {
|
|
@@ -14103,11 +14118,25 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
14103
14118
|
}
|
|
14104
14119
|
});
|
|
14105
14120
|
promptSettled = true;
|
|
14121
|
+
if (args.hiddenCompletionExecutor && args.parentSessionId) {
|
|
14122
|
+
recordChildInvocation({
|
|
14123
|
+
db: args.db,
|
|
14124
|
+
parentSessionId: args.parentSessionId,
|
|
14125
|
+
harness: executor.capabilities.harness,
|
|
14126
|
+
subagent: "dreamer",
|
|
14127
|
+
task: "compress-cues",
|
|
14128
|
+
startedAt,
|
|
14129
|
+
status: "completed",
|
|
14130
|
+
tokens: run.output.usage,
|
|
14131
|
+
providerId: run.output.providerId,
|
|
14132
|
+
modelId: run.output.modelId
|
|
14133
|
+
});
|
|
14134
|
+
}
|
|
14106
14135
|
return args.moduleRoute ? await applyCuesThroughModule(args, chunk, run.validated, signal) : applyCues(args, chunk, run.validated);
|
|
14107
14136
|
} catch (error) {
|
|
14108
14137
|
const desc = describeError(error);
|
|
14109
14138
|
log(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
14110
|
-
if (signal.aborted || error instanceof DreamerProviderOutputFailureError)
|
|
14139
|
+
if (signal.aborted || error instanceof HiddenCompletionRefusal || error instanceof DreamerProviderOutputFailureError)
|
|
14111
14140
|
throw error;
|
|
14112
14141
|
return {
|
|
14113
14142
|
compressed: 0,
|
|
@@ -14119,10 +14148,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
14119
14148
|
}
|
|
14120
14149
|
};
|
|
14121
14150
|
} finally {
|
|
14122
|
-
await
|
|
14123
|
-
client: args.client,
|
|
14124
|
-
sessionId: agentSessionId,
|
|
14125
|
-
sessionDirectory: args.sessionDirectory,
|
|
14151
|
+
await executor.close(handle, {
|
|
14126
14152
|
promptSettled,
|
|
14127
14153
|
privacySensitive: true,
|
|
14128
14154
|
context: "[dreamer] compress-cues",
|
|
@@ -14777,6 +14803,8 @@ async function runClassify(args) {
|
|
|
14777
14803
|
}
|
|
14778
14804
|
async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
14779
14805
|
let agentSessionId = null;
|
|
14806
|
+
let handle = null;
|
|
14807
|
+
const executor = args.hiddenCompletionExecutor ?? createV1HiddenCompletionExecutor(args.client, args.db, args.sessionDirectory);
|
|
14780
14808
|
let promptSettled = false;
|
|
14781
14809
|
const startedAt = Date.now();
|
|
14782
14810
|
const moduleRoute = isModuleRoute(args);
|
|
@@ -14791,19 +14819,22 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
14791
14819
|
recordInvocation(args, startedAt, { status: "completed" });
|
|
14792
14820
|
return run;
|
|
14793
14821
|
}
|
|
14794
|
-
|
|
14795
|
-
client: args.client,
|
|
14796
|
-
db: args.db,
|
|
14822
|
+
handle = await executor.open({
|
|
14797
14823
|
parentSessionId: args.parentSessionId,
|
|
14824
|
+
agent: DREAMER_CLASSIFIER_AGENT,
|
|
14825
|
+
kind: "dreamer-task",
|
|
14826
|
+
system: withContentLanguageDirective(CLASSIFY_SYSTEM_PROMPT, args.language),
|
|
14827
|
+
model: args.model,
|
|
14828
|
+
configuredModels: [...args.model ? [args.model] : [], ...args.fallbackModels ?? []],
|
|
14829
|
+
timeoutMs: sliceMs,
|
|
14798
14830
|
title: "magic-context-dream-classify",
|
|
14799
|
-
directory: args.sessionDirectory
|
|
14831
|
+
directory: args.sessionDirectory,
|
|
14832
|
+
metadata: { task: "classify-memories" }
|
|
14800
14833
|
});
|
|
14801
|
-
|
|
14802
|
-
preferResponseOnMissingData: true
|
|
14803
|
-
});
|
|
14804
|
-
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
14834
|
+
agentSessionId = handle.id || null;
|
|
14805
14835
|
if (!agentSessionId)
|
|
14806
14836
|
throw new Error("Could not create classify session.");
|
|
14837
|
+
const opened = handle;
|
|
14807
14838
|
const run = await promptSyncWithValidatedOutputRetry(args.client, {
|
|
14808
14839
|
path: { id: agentSessionId },
|
|
14809
14840
|
query: { directory: args.sessionDirectory },
|
|
@@ -14814,24 +14845,18 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
14814
14845
|
parts: [{ type: "text", text: prompt, synthetic: true }]
|
|
14815
14846
|
}
|
|
14816
14847
|
}, {
|
|
14848
|
+
transport: Object.assign((request) => executor.attempt(opened, request), { childSessionId: opened.childSessionId }),
|
|
14817
14849
|
timeoutMs: sliceMs,
|
|
14818
14850
|
signal,
|
|
14819
14851
|
fallbackModels: args.fallbackModels,
|
|
14820
14852
|
callContext: "dreamer:classify-memories",
|
|
14821
|
-
fetchOutput:
|
|
14822
|
-
|
|
14823
|
-
|
|
14824
|
-
|
|
14825
|
-
});
|
|
14826
|
-
return normalizeSDKResponse(messagesResponse, [], {
|
|
14827
|
-
preferResponseOnMissingData: true
|
|
14828
|
-
});
|
|
14829
|
-
},
|
|
14830
|
-
validateOutput: (messages) => {
|
|
14831
|
-
if (hasLengthCappedOutput(messages)) {
|
|
14853
|
+
fetchOutput: () => executor.collect(opened, 50),
|
|
14854
|
+
validateOutput: (completion) => {
|
|
14855
|
+
const messages = completion.messages ?? [];
|
|
14856
|
+
if (completion.lengthCapped) {
|
|
14832
14857
|
throw new Error("classify returned length-capped output");
|
|
14833
14858
|
}
|
|
14834
|
-
const text =
|
|
14859
|
+
const text = completion.text;
|
|
14835
14860
|
if (!text)
|
|
14836
14861
|
throw new Error("classify returned no output");
|
|
14837
14862
|
try {
|
|
@@ -14846,21 +14871,22 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
14846
14871
|
}
|
|
14847
14872
|
});
|
|
14848
14873
|
promptSettled = true;
|
|
14849
|
-
recordInvocation(args, startedAt, {
|
|
14874
|
+
recordInvocation(args, startedAt, {
|
|
14875
|
+
status: "completed",
|
|
14876
|
+
messages: run.output.messages,
|
|
14877
|
+
completion: run.output
|
|
14878
|
+
});
|
|
14850
14879
|
return applyClassifications(args, chunk.map((candidate) => candidate.contextMemory), run.validated);
|
|
14851
14880
|
} catch (error) {
|
|
14852
14881
|
const failure = moduleRoute ? new ClassifyModuleFailureError("module", error) : error;
|
|
14853
14882
|
const desc = describeError(failure);
|
|
14854
14883
|
log(`[dreamer] classify chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
14855
14884
|
recordInvocation(args, startedAt, { status: "failed", error: failure });
|
|
14856
|
-
if (moduleRoute || signal.aborted || failure instanceof DreamerProviderOutputFailureError || getPromptFailureDetail(failure)?.failureClass !== "parse_failed" && getPromptFailureDetail(failure) !== null)
|
|
14885
|
+
if (moduleRoute || failure instanceof HiddenCompletionRefusal || signal.aborted || failure instanceof DreamerProviderOutputFailureError || getPromptFailureDetail(failure)?.failureClass !== "parse_failed" && getPromptFailureDetail(failure) !== null)
|
|
14857
14886
|
throw failure;
|
|
14858
14887
|
return { classified: 0, changed: 0 };
|
|
14859
14888
|
} finally {
|
|
14860
|
-
await
|
|
14861
|
-
client: args.client,
|
|
14862
|
-
sessionId: agentSessionId,
|
|
14863
|
-
sessionDirectory: args.sessionDirectory,
|
|
14889
|
+
await executor.close(handle, {
|
|
14864
14890
|
promptSettled,
|
|
14865
14891
|
privacySensitive: true,
|
|
14866
14892
|
context: "[dreamer] classify",
|
|
@@ -15014,16 +15040,119 @@ function recordInvocation(args, startedAt, params) {
|
|
|
15014
15040
|
recordChildInvocation({
|
|
15015
15041
|
db: args.db,
|
|
15016
15042
|
parentSessionId: args.parentSessionId,
|
|
15017
|
-
harness: "opencode",
|
|
15043
|
+
harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
|
|
15018
15044
|
subagent: "dreamer",
|
|
15019
15045
|
task: "classify-memories",
|
|
15020
15046
|
startedAt,
|
|
15021
15047
|
status: params.status,
|
|
15022
15048
|
messages: params.messages,
|
|
15049
|
+
...params.completion && !params.completion.messages ? {
|
|
15050
|
+
tokens: params.completion.usage,
|
|
15051
|
+
providerId: params.completion.providerId,
|
|
15052
|
+
modelId: params.completion.modelId
|
|
15053
|
+
} : {},
|
|
15023
15054
|
error: params.error
|
|
15024
15055
|
});
|
|
15025
15056
|
}
|
|
15026
15057
|
|
|
15058
|
+
// src/features/magic-context/dreamer/curate-category-rotation.ts
|
|
15059
|
+
var CURATE_MEMORY_CATEGORIES = [
|
|
15060
|
+
"PROJECT_RULES",
|
|
15061
|
+
"ARCHITECTURE",
|
|
15062
|
+
"CONSTRAINTS",
|
|
15063
|
+
"CONFIG_VALUES",
|
|
15064
|
+
"NAMING"
|
|
15065
|
+
];
|
|
15066
|
+
var LEGACY_CURATE_CATEGORY_BUCKETS = {
|
|
15067
|
+
ARCHITECTURE_DECISIONS: "ARCHITECTURE",
|
|
15068
|
+
CONFIG_DEFAULTS: "CONFIG_VALUES",
|
|
15069
|
+
ENVIRONMENT: "CONFIG_VALUES",
|
|
15070
|
+
KNOWN_ISSUES: "CONSTRAINTS",
|
|
15071
|
+
USER_DIRECTIVES: "PROJECT_RULES",
|
|
15072
|
+
USER_PREFERENCES: "PROJECT_RULES",
|
|
15073
|
+
WORKFLOW_RULES: "PROJECT_RULES"
|
|
15074
|
+
};
|
|
15075
|
+
function curateCategoryForMemoryCategory(category) {
|
|
15076
|
+
return isCurateMemoryCategory(category) ? category : LEGACY_CURATE_CATEGORY_BUCKETS[category] ?? null;
|
|
15077
|
+
}
|
|
15078
|
+
function isCurateMemoryCategory(value) {
|
|
15079
|
+
return CURATE_MEMORY_CATEGORIES.includes(value);
|
|
15080
|
+
}
|
|
15081
|
+
function parseTaskState(raw) {
|
|
15082
|
+
if (!raw)
|
|
15083
|
+
return {};
|
|
15084
|
+
try {
|
|
15085
|
+
const parsed = JSON.parse(raw);
|
|
15086
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
15087
|
+
} catch {
|
|
15088
|
+
return {};
|
|
15089
|
+
}
|
|
15090
|
+
}
|
|
15091
|
+
function normalizedCursor(value) {
|
|
15092
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value % CURATE_MEMORY_CATEGORIES.length : 0;
|
|
15093
|
+
}
|
|
15094
|
+
function readState(db, projectIdentity) {
|
|
15095
|
+
return parseTaskState(getTaskScheduleState(db, projectIdentity, "curate")?.taskStateJson);
|
|
15096
|
+
}
|
|
15097
|
+
function categoryStartIndex(state, populated) {
|
|
15098
|
+
const active = state.curate?.activeCategory;
|
|
15099
|
+
if (isCurateMemoryCategory(active)) {
|
|
15100
|
+
const activeIndex = CURATE_MEMORY_CATEGORIES.indexOf(active);
|
|
15101
|
+
return populated.has(active) ? activeIndex : (activeIndex + 1) % CURATE_MEMORY_CATEGORIES.length;
|
|
15102
|
+
}
|
|
15103
|
+
return normalizedCursor(state.curate?.cursor);
|
|
15104
|
+
}
|
|
15105
|
+
function peekCurateCategoryScope(db, projectIdentity, memories) {
|
|
15106
|
+
const populated = new Set(memories.map((memory) => curateCategoryForMemoryCategory(memory.category)).filter((category) => category !== null));
|
|
15107
|
+
const start = categoryStartIndex(readState(db, projectIdentity), populated);
|
|
15108
|
+
for (let offset = 0;offset < CURATE_MEMORY_CATEGORIES.length; offset += 1) {
|
|
15109
|
+
const category = CURATE_MEMORY_CATEGORIES[(start + offset) % CURATE_MEMORY_CATEGORIES.length];
|
|
15110
|
+
const scoped = memories.filter((memory) => curateCategoryForMemoryCategory(memory.category) === category);
|
|
15111
|
+
if (scoped.length > 0)
|
|
15112
|
+
return { category, memories: scoped };
|
|
15113
|
+
}
|
|
15114
|
+
return null;
|
|
15115
|
+
}
|
|
15116
|
+
function beginCurateCategoryRun(db, projectIdentity, memories) {
|
|
15117
|
+
const scope = peekCurateCategoryScope(db, projectIdentity, memories);
|
|
15118
|
+
if (!scope)
|
|
15119
|
+
return null;
|
|
15120
|
+
const state = readState(db, projectIdentity);
|
|
15121
|
+
writeTaskStateJson(db, projectIdentity, "curate", JSON.stringify({
|
|
15122
|
+
...state,
|
|
15123
|
+
curate: {
|
|
15124
|
+
cursor: normalizedCursor(state.curate?.cursor),
|
|
15125
|
+
activeCategory: scope.category
|
|
15126
|
+
}
|
|
15127
|
+
}));
|
|
15128
|
+
return scope;
|
|
15129
|
+
}
|
|
15130
|
+
function curateTaskStateAfterSuccess(db, projectIdentity, category) {
|
|
15131
|
+
const state = readState(db, projectIdentity);
|
|
15132
|
+
return JSON.stringify({
|
|
15133
|
+
...state,
|
|
15134
|
+
curate: {
|
|
15135
|
+
cursor: (CURATE_MEMORY_CATEGORIES.indexOf(category) + 1) % CURATE_MEMORY_CATEGORIES.length
|
|
15136
|
+
}
|
|
15137
|
+
});
|
|
15138
|
+
}
|
|
15139
|
+
function getActiveCurateCategory(db, projectIdentity) {
|
|
15140
|
+
const active = readState(db, projectIdentity).curate?.activeCategory;
|
|
15141
|
+
return isCurateMemoryCategory(active) ? active : null;
|
|
15142
|
+
}
|
|
15143
|
+
function getCurateCategoryScopeRefusal(args) {
|
|
15144
|
+
if (args.requestedCategory && args.requestedCategory !== args.scope) {
|
|
15145
|
+
return `Error: Curate scope is ${args.scope}; ${args.action} cannot target category ${args.requestedCategory}.`;
|
|
15146
|
+
}
|
|
15147
|
+
for (const id of args.ids ?? []) {
|
|
15148
|
+
const category = args.categoryForId(id);
|
|
15149
|
+
if (category && category !== args.scope) {
|
|
15150
|
+
return `Error: Curate scope is ${args.scope}; memory ID ${id} is outside the scoped category.`;
|
|
15151
|
+
}
|
|
15152
|
+
}
|
|
15153
|
+
return null;
|
|
15154
|
+
}
|
|
15155
|
+
|
|
15027
15156
|
// src/features/magic-context/dreamer/memory-claim-safety.ts
|
|
15028
15157
|
var POLICY_SENTENCE_START = /(?:^|[.!?]\s+|\n\s*)(?:[-*]\s+|\d+[.)]\s+)?(?:you\s+|we\s+)?(?:must(?:\s+not)?|never|always|do\s+not|don't|shall\s+not)\b/i;
|
|
15029
15158
|
var ACTOR_POLICY = /\b(?:you|we|agents?|masons?|workers?|operators?|users?|maintainers?)\s+(?:must(?:\s+not)?|should(?:\s+not)?|need\s+to|shall(?:\s+not)?|cannot|can't|may\s+not)\b/i;
|
|
@@ -18316,12 +18445,13 @@ function countActiveMemories(db, projectPath) {
|
|
|
18316
18445
|
}
|
|
18317
18446
|
function countLiveMemories(db, projectPath, options = {}) {
|
|
18318
18447
|
const unclassified = options.unclassifiedOnly && hasMemoryClassifiedAtColumn(db);
|
|
18319
|
-
const
|
|
18320
|
-
|
|
18321
|
-
|
|
18322
|
-
|
|
18323
|
-
|
|
18324
|
-
|
|
18448
|
+
const sql = `SELECT COUNT(*) AS cnt
|
|
18449
|
+
FROM memories
|
|
18450
|
+
WHERE project_path = ?
|
|
18451
|
+
AND status IN ('active','permanent')
|
|
18452
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
18453
|
+
${unclassified ? "AND classified_at IS NULL" : ""}`;
|
|
18454
|
+
const row = options.category ? db.prepare(`${sql} AND category = ?`).get(projectPath, Date.now(), options.category) : db.prepare(sql).get(projectPath, Date.now());
|
|
18325
18455
|
return row?.cnt ?? 0;
|
|
18326
18456
|
}
|
|
18327
18457
|
function countUnmappedActiveMemories(db, projectPath) {
|
|
@@ -18432,8 +18562,13 @@ function getDreamTaskBacklog(db, projectPath, task, options = {}) {
|
|
|
18432
18562
|
return { pending, total };
|
|
18433
18563
|
}
|
|
18434
18564
|
case "curate": {
|
|
18435
|
-
const
|
|
18436
|
-
|
|
18565
|
+
const categories = db.prepare(`SELECT category FROM memories
|
|
18566
|
+
WHERE project_path = ?
|
|
18567
|
+
AND status IN ('active','permanent')
|
|
18568
|
+
AND (expires_at IS NULL OR expires_at > ?)`).all(projectPath, Date.now());
|
|
18569
|
+
const scope = peekCurateCategoryScope(db, projectPath, categories);
|
|
18570
|
+
const total = scope?.memories.length ?? 0;
|
|
18571
|
+
return scope ? { pending: total, total, category: scope.category } : { pending: 0, total: 0 };
|
|
18437
18572
|
}
|
|
18438
18573
|
case "compress-cues": {
|
|
18439
18574
|
const total = countLiveMemories(db, projectPath);
|
|
@@ -19156,7 +19291,7 @@ function dreamRunFailureDetail(error) {
|
|
|
19156
19291
|
}
|
|
19157
19292
|
const described = describeError(error);
|
|
19158
19293
|
const message = described.brief;
|
|
19159
|
-
const providerFailure = error instanceof Error && error.name === "DreamerProviderOutputFailureError";
|
|
19294
|
+
const providerFailure = error instanceof HiddenCompletionRefusal || error instanceof Error && error.name === "DreamerProviderOutputFailureError";
|
|
19160
19295
|
return {
|
|
19161
19296
|
failure_class: providerFailure ? "provider_error" : /no models?|model chain is empty/i.test(message) ? "no_models" : "unknown",
|
|
19162
19297
|
model_attempted: null,
|
|
@@ -19246,13 +19381,20 @@ function formatCurateMemoryOperations(actions) {
|
|
|
19246
19381
|
const noun = actions.length === 1 ? "operation" : "operations";
|
|
19247
19382
|
return `curate: ${actions.length} memory ${noun} applied${actionDetail ? ` (${actionDetail})` : ""}`;
|
|
19248
19383
|
}
|
|
19384
|
+
function requireDreamClient(client) {
|
|
19385
|
+
if (!client)
|
|
19386
|
+
throw new HiddenCompletionRefusal("hidden_tools_unsupported", "This dream task requires the child-session tool transport", true);
|
|
19387
|
+
return client;
|
|
19388
|
+
}
|
|
19249
19389
|
function createDreamTaskExecutor(deps) {
|
|
19250
19390
|
let parentSessionIdPromise;
|
|
19251
19391
|
const resolveParentSessionId = () => {
|
|
19392
|
+
if (deps.hiddenCompletionExecutor)
|
|
19393
|
+
return Promise.resolve(deps.parentSessionId);
|
|
19252
19394
|
if (!parentSessionIdPromise) {
|
|
19253
19395
|
parentSessionIdPromise = (async () => {
|
|
19254
19396
|
try {
|
|
19255
|
-
const listResponse = await deps.client.session.list({
|
|
19397
|
+
const listResponse = await requireDreamClient(deps.client).session.list({
|
|
19256
19398
|
query: { directory: deps.sessionDirectory }
|
|
19257
19399
|
});
|
|
19258
19400
|
const sessions = normalizeSDKResponse(listResponse, [], { preferResponseOnMissingData: true });
|
|
@@ -19278,6 +19420,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19278
19420
|
processed: Math.max(0, processed),
|
|
19279
19421
|
total: backlogAtStart.pending,
|
|
19280
19422
|
startedAt,
|
|
19423
|
+
...backlogAtStart.category ? { category: backlogAtStart.category } : {},
|
|
19281
19424
|
...refused === undefined ? {} : { refused: Math.max(0, refused) }
|
|
19282
19425
|
});
|
|
19283
19426
|
};
|
|
@@ -19330,7 +19473,8 @@ function createDreamTaskExecutor(deps) {
|
|
|
19330
19473
|
totalAtStart: backlogAtStart.total,
|
|
19331
19474
|
pendingAtEnd: end.pending,
|
|
19332
19475
|
totalAtEnd: end.total,
|
|
19333
|
-
processed
|
|
19476
|
+
processed,
|
|
19477
|
+
...backlogAtStart.category ? { category: backlogAtStart.category } : {}
|
|
19334
19478
|
};
|
|
19335
19479
|
return value;
|
|
19336
19480
|
})()
|
|
@@ -19366,6 +19510,9 @@ function createDreamTaskExecutor(deps) {
|
|
|
19366
19510
|
return writtenIds.length || deletedIds.length || archivedIds.length || mergedIds.length ? changes : null;
|
|
19367
19511
|
}
|
|
19368
19512
|
try {
|
|
19513
|
+
if (deps.hiddenCompletionExecutor?.capabilities.tools === false && DREAM_TASK_CAPABILITIES[config.task].requiresTools) {
|
|
19514
|
+
throw new HiddenCompletionRefusal("hidden_tools_unsupported", `${config.task} requires tools; opencode2 hidden completions have no tool loop`, true);
|
|
19515
|
+
}
|
|
19369
19516
|
if (config.task === "compress-cues") {
|
|
19370
19517
|
if (deps.mural?.enabled !== true) {
|
|
19371
19518
|
log("[dreamer] compress-cues: skipped (mural is not enabled)");
|
|
@@ -19375,6 +19522,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19375
19522
|
const result = await runCompressCues({
|
|
19376
19523
|
db,
|
|
19377
19524
|
client: deps.client,
|
|
19525
|
+
hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
|
|
19378
19526
|
projectIdentity,
|
|
19379
19527
|
parentSessionId: parent,
|
|
19380
19528
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -19399,7 +19547,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19399
19547
|
if (config.task === "review-user-memories") {
|
|
19400
19548
|
const result = await reviewUserMemories({
|
|
19401
19549
|
db,
|
|
19402
|
-
client: deps.client,
|
|
19550
|
+
client: requireDreamClient(deps.client),
|
|
19403
19551
|
parentSessionId: parent,
|
|
19404
19552
|
sessionDirectory: deps.sessionDirectory,
|
|
19405
19553
|
holderId,
|
|
@@ -19418,7 +19566,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19418
19566
|
if (config.task === "map-memories") {
|
|
19419
19567
|
const result = await mapMemories({
|
|
19420
19568
|
db,
|
|
19421
|
-
client: deps.client,
|
|
19569
|
+
client: requireDreamClient(deps.client),
|
|
19422
19570
|
projectIdentity,
|
|
19423
19571
|
parentSessionId: parent,
|
|
19424
19572
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -19455,7 +19603,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19455
19603
|
const memoryBefore = getMemoryCountsByStatus(db, projectIdentity);
|
|
19456
19604
|
const result = await runVerify({
|
|
19457
19605
|
db,
|
|
19458
|
-
client: deps.client,
|
|
19606
|
+
client: requireDreamClient(deps.client),
|
|
19459
19607
|
projectIdentity,
|
|
19460
19608
|
parentSessionId: parent,
|
|
19461
19609
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -19513,6 +19661,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19513
19661
|
const result = await runClassify({
|
|
19514
19662
|
db,
|
|
19515
19663
|
client: deps.client,
|
|
19664
|
+
hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
|
|
19516
19665
|
projectIdentity,
|
|
19517
19666
|
parentSessionId: parent,
|
|
19518
19667
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -19538,7 +19687,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19538
19687
|
if (config.task === "promote-primers") {
|
|
19539
19688
|
const result = await promotePrimers({
|
|
19540
19689
|
db,
|
|
19541
|
-
client: deps.client,
|
|
19690
|
+
client: requireDreamClient(deps.client),
|
|
19542
19691
|
projectIdentity,
|
|
19543
19692
|
sessionDirectory: deps.sessionDirectory,
|
|
19544
19693
|
holderId,
|
|
@@ -19555,7 +19704,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19555
19704
|
if (config.task === "refresh-primers") {
|
|
19556
19705
|
const result = await refreshPrimers({
|
|
19557
19706
|
db,
|
|
19558
|
-
client: deps.client,
|
|
19707
|
+
client: requireDreamClient(deps.client),
|
|
19559
19708
|
projectIdentity,
|
|
19560
19709
|
parentSessionId: parent,
|
|
19561
19710
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -19576,7 +19725,7 @@ function createDreamTaskExecutor(deps) {
|
|
|
19576
19725
|
if (config.task === "evaluate-smart-notes") {
|
|
19577
19726
|
const result = await evaluateSmartNotes({
|
|
19578
19727
|
db,
|
|
19579
|
-
client: deps.client,
|
|
19728
|
+
client: requireDreamClient(deps.client),
|
|
19580
19729
|
projectIdentity,
|
|
19581
19730
|
parentSessionId: parent,
|
|
19582
19731
|
sessionDirectory: deps.sessionDirectory,
|
|
@@ -19743,7 +19892,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
19743
19892
|
let promptSettled = false;
|
|
19744
19893
|
try {
|
|
19745
19894
|
const createResponse = await createChildSessionWithFence({
|
|
19746
|
-
client: deps.client,
|
|
19895
|
+
client: requireDreamClient(deps.client),
|
|
19747
19896
|
db,
|
|
19748
19897
|
parentSessionId: parent ?? undefined,
|
|
19749
19898
|
title: "magic-context-dream-retrospective",
|
|
@@ -19757,7 +19906,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
19757
19906
|
const runChildTurn = async (system, userText) => {
|
|
19758
19907
|
const remainingMs = Math.max(0, deadline - Date.now());
|
|
19759
19908
|
promptSettled = false;
|
|
19760
|
-
const run = await promptSyncWithValidatedOutputRetry(deps.client, {
|
|
19909
|
+
const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
|
|
19761
19910
|
path: { id: sessionId },
|
|
19762
19911
|
query: { directory: deps.sessionDirectory },
|
|
19763
19912
|
body: {
|
|
@@ -19772,7 +19921,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
19772
19921
|
fallbackModels: config.fallbackModels,
|
|
19773
19922
|
callContext: "dreamer:retrospective",
|
|
19774
19923
|
fetchOutput: async () => {
|
|
19775
|
-
const messagesResponse = await deps.client.session.messages({
|
|
19924
|
+
const messagesResponse = await requireDreamClient(deps.client).session.messages({
|
|
19776
19925
|
path: { id: sessionId },
|
|
19777
19926
|
query: { directory: deps.sessionDirectory, limit: 50 }
|
|
19778
19927
|
});
|
|
@@ -19897,7 +20046,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
19897
20046
|
} finally {
|
|
19898
20047
|
heartbeat.stop();
|
|
19899
20048
|
await teardownChildSession({
|
|
19900
|
-
client: deps.client,
|
|
20049
|
+
client: requireDreamClient(deps.client),
|
|
19901
20050
|
sessionId: childSessionId,
|
|
19902
20051
|
sessionDirectory: deps.sessionDirectory,
|
|
19903
20052
|
promptSettled,
|
|
@@ -19931,6 +20080,7 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
19931
20080
|
let expiredArchived = 0;
|
|
19932
20081
|
try {
|
|
19933
20082
|
let curateMemories;
|
|
20083
|
+
let curateCategory;
|
|
19934
20084
|
if (task === "curate") {
|
|
19935
20085
|
expiredArchived = await archiveExpiredMemories({
|
|
19936
20086
|
db,
|
|
@@ -19942,10 +20092,12 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
19942
20092
|
});
|
|
19943
20093
|
if (leaseLost)
|
|
19944
20094
|
throw new Error("Dream lease lost during expired-memory archive");
|
|
19945
|
-
|
|
19946
|
-
|
|
19947
|
-
|
|
19948
|
-
|
|
20095
|
+
const scope = beginCurateCategoryRun(db, projectIdentity, loadActiveMemoryPromptMemories(db, projectIdentity));
|
|
20096
|
+
curateMemories = scope?.memories ?? [];
|
|
20097
|
+
curateCategory = scope?.category;
|
|
20098
|
+
log(`[dreamer] curate pool: category=${curateCategory ?? "none"} in_scope=${curateMemories.length} expired_archived=${expiredArchived}`);
|
|
20099
|
+
if (curateMemories.length === 0) {
|
|
20100
|
+
const progress = expiredArchived > 0 ? formatExpiredArchiveProgress(expiredArchived) : "curate: no populated project-memory category";
|
|
19949
20101
|
helpers.recordRun("completed", null, {
|
|
19950
20102
|
memoryChanges: helpers.computeMemoryDelta(memoryBefore),
|
|
19951
20103
|
progress
|
|
@@ -19957,10 +20109,10 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
19957
20109
|
projectPath: projectIdentity,
|
|
19958
20110
|
lastDreamAt: lastRunAt ? String(lastRunAt) : null,
|
|
19959
20111
|
existingDocs,
|
|
19960
|
-
curate: curateMemories ? { memories: curateMemories } : undefined
|
|
20112
|
+
curate: curateMemories && curateCategory ? { category: curateCategory, memories: curateMemories } : undefined
|
|
19961
20113
|
});
|
|
19962
20114
|
const createResponse = await createChildSessionWithFence({
|
|
19963
|
-
client: deps.client,
|
|
20115
|
+
client: requireDreamClient(deps.client),
|
|
19964
20116
|
db,
|
|
19965
20117
|
parentSessionId: parent ?? undefined,
|
|
19966
20118
|
title: `magic-context-dream-${task}`,
|
|
@@ -19974,7 +20126,7 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
19974
20126
|
throw new Error("Dreamer could not create its child session.");
|
|
19975
20127
|
const sessionId = childSessionId;
|
|
19976
20128
|
const remainingMs = Math.max(0, deadline - Date.now());
|
|
19977
|
-
const run = await promptSyncWithValidatedOutputRetry(deps.client, {
|
|
20129
|
+
const run = await promptSyncWithValidatedOutputRetry(requireDreamClient(deps.client), {
|
|
19978
20130
|
path: { id: sessionId },
|
|
19979
20131
|
query: { directory: docsDir },
|
|
19980
20132
|
body: {
|
|
@@ -19989,7 +20141,7 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
19989
20141
|
fallbackModels: config.fallbackModels,
|
|
19990
20142
|
callContext: `dreamer:${task}`,
|
|
19991
20143
|
fetchOutput: async () => {
|
|
19992
|
-
const messagesResponse = await deps.client.session.messages({
|
|
20144
|
+
const messagesResponse = await requireDreamClient(deps.client).session.messages({
|
|
19993
20145
|
path: { id: sessionId },
|
|
19994
20146
|
query: {
|
|
19995
20147
|
directory: docsDir,
|
|
@@ -20049,22 +20201,40 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
20049
20201
|
}
|
|
20050
20202
|
}
|
|
20051
20203
|
const curateOutput = task === "curate" ? run.validated : undefined;
|
|
20204
|
+
const curateScopeProgress = task === "curate" && curateCategory && curateMemories ? `curate: ${curateCategory} (${curateMemories.length})` : null;
|
|
20052
20205
|
const progress = [
|
|
20206
|
+
curateScopeProgress,
|
|
20053
20207
|
expiredArchived > 0 ? formatExpiredArchiveProgress(expiredArchived) : null,
|
|
20054
20208
|
curateOutput && curateOutput.memoryOperations.completedActions.length > 0 ? formatCurateMemoryOperations(curateOutput.memoryOperations.completedActions) : null,
|
|
20055
20209
|
curateRefused > 0 ? `curate: refused ${curateRefused} unsafe mutation(s)` : null
|
|
20056
20210
|
].filter((value) => Boolean(value)).join("; ");
|
|
20211
|
+
const curateCount = task === "curate" && curateCategory ? loadActiveMemoryPromptMemories(db, projectIdentity).filter((memory) => curateCategoryForMemoryCategory(memory.category) === curateCategory).length : undefined;
|
|
20212
|
+
const curateBacklog = curateCount !== undefined && curateCategory ? {
|
|
20213
|
+
pending: curateCount,
|
|
20214
|
+
total: curateCount,
|
|
20215
|
+
category: curateCategory
|
|
20216
|
+
} : undefined;
|
|
20057
20217
|
helpers.recordRun("completed", null, {
|
|
20058
20218
|
memoryChanges: helpers.computeMemoryDelta(memoryBefore),
|
|
20059
|
-
progress: progress || null
|
|
20219
|
+
progress: progress || null,
|
|
20220
|
+
backlogAfter: curateBacklog
|
|
20060
20221
|
});
|
|
20061
|
-
return {
|
|
20222
|
+
return {
|
|
20223
|
+
status: "completed",
|
|
20224
|
+
...progress ? { detail: progress } : {},
|
|
20225
|
+
...curateBacklog ? { backlog: curateBacklog } : {},
|
|
20226
|
+
...curateCategory ? {
|
|
20227
|
+
schedulePatch: {
|
|
20228
|
+
taskStateJson: curateTaskStateAfterSuccess(db, projectIdentity, curateCategory)
|
|
20229
|
+
}
|
|
20230
|
+
} : {}
|
|
20231
|
+
};
|
|
20062
20232
|
} finally {
|
|
20063
20233
|
heartbeat.stop();
|
|
20064
20234
|
if (childSessionId)
|
|
20065
20235
|
takeCurateSafetyRefusalCount(childSessionId);
|
|
20066
20236
|
await teardownChildSession({
|
|
20067
|
-
client: deps.client,
|
|
20237
|
+
client: requireDreamClient(deps.client),
|
|
20068
20238
|
sessionId: childSessionId,
|
|
20069
20239
|
sessionDirectory: docsDir,
|
|
20070
20240
|
promptSettled,
|
|
@@ -20133,6 +20303,7 @@ function advanceAfterRun(db, projectIdentity, due, finishedAt, status, error, sc
|
|
|
20133
20303
|
lastStatus: status,
|
|
20134
20304
|
lastError: error,
|
|
20135
20305
|
retryCount: 0,
|
|
20306
|
+
taskStateJson: schedulePatch?.taskStateJson,
|
|
20136
20307
|
retrospectiveWatermarkMs: schedulePatch?.retrospectiveWatermarkMs
|
|
20137
20308
|
});
|
|
20138
20309
|
}
|
|
@@ -20225,7 +20396,7 @@ async function runDomainGroup(deps, group, cb) {
|
|
|
20225
20396
|
const finishedAt = Date.now();
|
|
20226
20397
|
if (outcome.status === "completed") {
|
|
20227
20398
|
advanceAfterRun(db, projectIdentity, due, finishedAt, "completed", null, outcome.schedulePatch);
|
|
20228
|
-
cb?.onRan?.(due.config.task, outcome.detail);
|
|
20399
|
+
cb?.onRan?.(due.config.task, outcome.detail, outcome.backlog);
|
|
20229
20400
|
} else if (outcome.transient) {
|
|
20230
20401
|
recordTransientFailure(db, projectIdentity, due, finishedAt, outcome.error ?? null);
|
|
20231
20402
|
cb?.onFailed?.(due.config.task, outcome.failureDetail ?? outcome.error);
|
|
@@ -20292,6 +20463,7 @@ async function runManualDream(deps) {
|
|
|
20292
20463
|
return result;
|
|
20293
20464
|
}
|
|
20294
20465
|
const groups = new Map;
|
|
20466
|
+
const runLocalBacklogs = {};
|
|
20295
20467
|
for (const d of gated) {
|
|
20296
20468
|
const kind = leaseKindFor(d.config.task);
|
|
20297
20469
|
const arr = groups.get(kind) ?? [];
|
|
@@ -20301,10 +20473,12 @@ async function runManualDream(deps) {
|
|
|
20301
20473
|
await Promise.all([...groups.values()].map((group) => runDomainGroup({ ...deps, executor: deps.executor }, group, {
|
|
20302
20474
|
forceGate,
|
|
20303
20475
|
leaseWaitMs: MANUAL_RUN_LEASE_WAIT_MS,
|
|
20304
|
-
onRan: (t, detail) => {
|
|
20476
|
+
onRan: (t, detail, backlog) => {
|
|
20305
20477
|
result.ran.push(t);
|
|
20306
20478
|
if (detail)
|
|
20307
20479
|
result.details?.push(detail);
|
|
20480
|
+
if (backlog)
|
|
20481
|
+
runLocalBacklogs[t] = backlog;
|
|
20308
20482
|
},
|
|
20309
20483
|
onFailed: (task, error) => {
|
|
20310
20484
|
result.failed.push(task);
|
|
@@ -20313,7 +20487,10 @@ async function runManualDream(deps) {
|
|
|
20313
20487
|
},
|
|
20314
20488
|
onBusy: (t) => result.deferredBusy.push(t)
|
|
20315
20489
|
})));
|
|
20316
|
-
result.backlogAfter =
|
|
20490
|
+
result.backlogAfter = {
|
|
20491
|
+
...getDreamTaskBacklogs(deps.db, deps.projectIdentity, selectedTaskNames),
|
|
20492
|
+
...runLocalBacklogs
|
|
20493
|
+
};
|
|
20317
20494
|
return result;
|
|
20318
20495
|
}
|
|
20319
20496
|
async function runDueTasksForProject(deps) {
|
|
@@ -24972,6 +25149,10 @@ function statusSummaryFromDetail(detail) {
|
|
|
24972
25149
|
if ((detail.loggerDiagnostics?.swallowedWriteCount ?? 0) > 0) {
|
|
24973
25150
|
warnings.push("status_log_unavailable");
|
|
24974
25151
|
}
|
|
25152
|
+
if (detail.memoryMirror?.stalled)
|
|
25153
|
+
warnings.push("memory_mirror_stalled");
|
|
25154
|
+
if (detail.memoryAuthorityMismatch)
|
|
25155
|
+
warnings.push("memory_authority_mismatch");
|
|
24975
25156
|
return {
|
|
24976
25157
|
inputTokens: detail.inputTokens,
|
|
24977
25158
|
usableContextTokens: detail.contextLimit,
|
|
@@ -25108,6 +25289,9 @@ function formatStatusDiagnosticsMarkdown(detail) {
|
|
|
25108
25289
|
`- **${formatCacheTtlDisplay({ value: detail.cacheTtl, source: detail.cacheTtlSource ?? "session", modelKey: detail.cacheTtlModelKey })}**; ${formatCacheLane(detail)}`,
|
|
25109
25290
|
`- **Historian:** ${[historianState, ...historianDetails].join("; ")}`,
|
|
25110
25291
|
...detail.hostBackendsModuleSide ? [`- ${RUST_MODE_HOST_PATHS_LINE}`] : [],
|
|
25292
|
+
...detail.memoryMirror ? [
|
|
25293
|
+
`- **Memory mirror:** cursor ${formatCount2(detail.memoryMirror.cursor)} / ${detail.memoryMirror.feedHead === null ? "unknown" : formatCount2(detail.memoryMirror.feedHead)}; ${formatCount2(detail.memoryMirror.liveRows)} live rows; ${detail.memoryMirror.stalled ? `stalled (${detail.memoryMirror.code})` : "advancing or caught up"}`
|
|
25294
|
+
] : [],
|
|
25111
25295
|
`- **Memory:** ${formatCount2(detail.memoryCount)} active; ${formatCount2(detail.memoryBlockCount)} injected`,
|
|
25112
25296
|
`- **Tags:** ${formatCount2(detail.activeTags)} active, ${formatCount2(detail.droppedTags)} dropped; ${formatCount2(detail.pendingOpsCount)} pending drops`,
|
|
25113
25297
|
`- **Execute threshold:** ${detail.executeThreshold.toFixed(1)}%${detail.executeThresholdClamped ? " (clamped)" : ""}`
|
|
@@ -25118,6 +25302,12 @@ function formatStatusDiagnosticsMarkdown(detail) {
|
|
|
25118
25302
|
if (detail.lastTransformError) {
|
|
25119
25303
|
lines.push(`- **Warning:** ${renderUserFacingFailure("transform_update_failed")}`);
|
|
25120
25304
|
}
|
|
25305
|
+
if (detail.memoryMirror?.stalled) {
|
|
25306
|
+
lines.push(`- **Warning:** ${renderUserFacingFailure("memory_mirror_stalled")}`);
|
|
25307
|
+
}
|
|
25308
|
+
if (detail.memoryAuthorityMismatch) {
|
|
25309
|
+
lines.push(`- **Warning:** ${renderUserFacingFailure("memory_authority_mismatch")}`);
|
|
25310
|
+
}
|
|
25121
25311
|
return lines.join(`
|
|
25122
25312
|
`);
|
|
25123
25313
|
}
|
|
@@ -29005,9 +29195,16 @@ function buildSidebarSnapshotRpcResponse(db, sessionId, directory, liveSessionSt
|
|
|
29005
29195
|
}
|
|
29006
29196
|
function buildStatusDetail(db, sessionId, directory, modelKey, config, liveSessionState, injectionBudgetTokens, moduleStatus, compactionEnabled = true) {
|
|
29007
29197
|
const base = buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config, moduleStatus, compactionEnabled);
|
|
29198
|
+
const rustMode = config?.transform_mode === "rust";
|
|
29199
|
+
const projectIdentity = rustMode ? resolveProjectIdentity(directory) : null;
|
|
29200
|
+
const moduleMemoryAuthority = moduleStatus?.authority?.memories;
|
|
29201
|
+
const moduleMemoryState = moduleMemoryAuthority?.state;
|
|
29202
|
+
const moduleFeedHead = moduleStatus?.memory_mirror?.feed_head;
|
|
29008
29203
|
const detail = {
|
|
29009
29204
|
...base,
|
|
29010
|
-
hostBackendsModuleSide:
|
|
29205
|
+
hostBackendsModuleSide: rustMode,
|
|
29206
|
+
memoryMirror: rustMode ? getMemoryMirrorStatus(db, moduleFeedHead) : undefined,
|
|
29207
|
+
memoryAuthorityMismatch: rustMode && moduleStatus?.authority !== undefined && projectIdentity !== null && getAuthorityManagedMarker(db, projectIdentity) !== null && (moduleMemoryState === "TS" || moduleMemoryAuthority === null),
|
|
29011
29208
|
activeProfile: typeof config?.profile === "string" ? config.profile : null,
|
|
29012
29209
|
tagCounter: 0,
|
|
29013
29210
|
activeTags: 0,
|
|
@@ -29461,9 +29658,9 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
29461
29658
|
return { count: buildCompartmentCount(db, sessionId, moduleStatus) };
|
|
29462
29659
|
});
|
|
29463
29660
|
const buildManagedCtx = async (db) => {
|
|
29464
|
-
const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-
|
|
29661
|
+
const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-v1fkhjjr.js");
|
|
29465
29662
|
const { resolveHistorianModel } = await import("./model-resolution-dxatzjde.js");
|
|
29466
|
-
const { userMemoryCollectionEnabled } = await import("./task-config-
|
|
29663
|
+
const { userMemoryCollectionEnabled } = await import("./task-config-cv8k9y8r.js");
|
|
29467
29664
|
const DEFAULT_HISTORIAN_TIMEOUT_MS = 600000;
|
|
29468
29665
|
const historianModel = resolveHistorianModel(config, "opencode");
|
|
29469
29666
|
return {
|
|
@@ -29494,8 +29691,8 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
29494
29691
|
const db = getDb();
|
|
29495
29692
|
if (!db)
|
|
29496
29693
|
return { ok: false, error: "db unavailable" };
|
|
29497
|
-
const { runManagedRecomp } = await import("./recomp-orchestrator-
|
|
29498
|
-
const { sendIgnoredMessage } = await import("./send-session-notification-
|
|
29694
|
+
const { runManagedRecomp } = await import("./recomp-orchestrator-k20sfpm2.js");
|
|
29695
|
+
const { sendIgnoredMessage } = await import("./send-session-notification-xnypkxpx.js");
|
|
29499
29696
|
log(`[rpc] recomp requested for session ${sessionId}`);
|
|
29500
29697
|
const ctx = await buildManagedCtx(db);
|
|
29501
29698
|
runManagedRecomp(ctx, sessionId).then((message) => {
|
|
@@ -29513,8 +29710,8 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
29513
29710
|
const db = getDb();
|
|
29514
29711
|
if (!db)
|
|
29515
29712
|
return { ok: false, error: "db unavailable" };
|
|
29516
|
-
const { runManagedUpgrade } = await import("./recomp-orchestrator-
|
|
29517
|
-
const { sendIgnoredMessage } = await import("./send-session-notification-
|
|
29713
|
+
const { runManagedUpgrade } = await import("./recomp-orchestrator-k20sfpm2.js");
|
|
29714
|
+
const { sendIgnoredMessage } = await import("./send-session-notification-xnypkxpx.js");
|
|
29518
29715
|
log(`[rpc] session-upgrade requested for session ${sessionId}`);
|
|
29519
29716
|
const ctx = await buildManagedCtx(db);
|
|
29520
29717
|
runManagedUpgrade(ctx, sessionId).then((message) => {
|
|
@@ -29530,7 +29727,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
29530
29727
|
if (!db)
|
|
29531
29728
|
return { ok: false, error: "db unavailable" };
|
|
29532
29729
|
try {
|
|
29533
|
-
const { updateSessionMeta } = await import("./storage-meta-session-
|
|
29730
|
+
const { updateSessionMeta } = await import("./storage-meta-session-x3j0q9qy.js");
|
|
29534
29731
|
updateSessionMeta(db, sessionId, { upgradeRemindedAt: Date.now() });
|
|
29535
29732
|
return { ok: true };
|
|
29536
29733
|
} catch (error) {
|
|
@@ -30179,7 +30376,8 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
|
|
|
30179
30376
|
compressedToLite: 0,
|
|
30180
30377
|
compressedToFull: 0,
|
|
30181
30378
|
compressedToUltra: 0,
|
|
30182
|
-
mutatedTextTags: 0
|
|
30379
|
+
mutatedTextTags: 0,
|
|
30380
|
+
textReductions: []
|
|
30183
30381
|
};
|
|
30184
30382
|
if (!config.enabled)
|
|
30185
30383
|
return result;
|
|
@@ -30219,9 +30417,15 @@ function applyCavemanCleanup(sessionId, db, targets, tags, config) {
|
|
|
30219
30417
|
const target = targets.get(tag.tagNumber);
|
|
30220
30418
|
if (!target)
|
|
30221
30419
|
continue;
|
|
30420
|
+
const priorContent = target.getContent?.();
|
|
30222
30421
|
const didMutate = target.setContent(compressed);
|
|
30223
|
-
if (didMutate)
|
|
30422
|
+
if (didMutate) {
|
|
30224
30423
|
result.mutatedTextTags += 1;
|
|
30424
|
+
result.textReductions.push({
|
|
30425
|
+
tagNumber: tag.tagNumber,
|
|
30426
|
+
removedCharacters: Math.max(0, (priorContent?.length ?? originalText.length) - compressed.length)
|
|
30427
|
+
});
|
|
30428
|
+
}
|
|
30225
30429
|
updateCavemanDepth(db, sessionId, tag.tagNumber, targetDepth);
|
|
30226
30430
|
if (targetDepth === DEPTH_LITE)
|
|
30227
30431
|
result.compressedToLite += 1;
|
|
@@ -32018,6 +32222,73 @@ function dropStaleReduceCalls(messages, frozenIds, options = {}) {
|
|
|
32018
32222
|
return { didDrop, newlyStrippedIds };
|
|
32019
32223
|
}
|
|
32020
32224
|
|
|
32225
|
+
// src/hooks/magic-context/dropped-token-estimate.ts
|
|
32226
|
+
var TAG_QUERY_CHUNK_SIZE = 900;
|
|
32227
|
+
var ESTIMATED_CHARACTERS_PER_TOKEN = 3.5;
|
|
32228
|
+
function estimateCharacters(characters) {
|
|
32229
|
+
return Math.ceil(Math.max(0, characters) / ESTIMATED_CHARACTERS_PER_TOKEN);
|
|
32230
|
+
}
|
|
32231
|
+
function persistedCountOrByteEstimate(count, bytes) {
|
|
32232
|
+
return typeof count === "number" && Number.isFinite(count) ? Math.max(0, count) : estimateCharacters(bytes);
|
|
32233
|
+
}
|
|
32234
|
+
function loadPersistedTagTokenCounts(db, sessionId, tagNumbers) {
|
|
32235
|
+
const countsByTag = new Map;
|
|
32236
|
+
for (let offset = 0;offset < tagNumbers.length; offset += TAG_QUERY_CHUNK_SIZE) {
|
|
32237
|
+
const chunk = tagNumbers.slice(offset, offset + TAG_QUERY_CHUNK_SIZE);
|
|
32238
|
+
const placeholders = chunk.map(() => "?").join(",");
|
|
32239
|
+
const rows = db.prepare(`SELECT tag_number AS tagNumber,
|
|
32240
|
+
type,
|
|
32241
|
+
byte_size AS byteSize,
|
|
32242
|
+
input_byte_size AS inputByteSize,
|
|
32243
|
+
reasoning_byte_size AS reasoningByteSize,
|
|
32244
|
+
token_count AS tokenCount,
|
|
32245
|
+
input_token_count AS inputTokenCount,
|
|
32246
|
+
reasoning_token_count AS reasoningTokenCount
|
|
32247
|
+
FROM tags
|
|
32248
|
+
WHERE session_id = ? AND tag_number IN (${placeholders})`).all(sessionId, ...chunk);
|
|
32249
|
+
for (const row of rows)
|
|
32250
|
+
countsByTag.set(row.tagNumber, row);
|
|
32251
|
+
}
|
|
32252
|
+
return countsByTag;
|
|
32253
|
+
}
|
|
32254
|
+
function estimateDroppedTokensFromTagReductions(db, sessionId, reductions) {
|
|
32255
|
+
if (reductions.length === 0)
|
|
32256
|
+
return 0;
|
|
32257
|
+
const structuralByTag = new Map;
|
|
32258
|
+
const partialCharactersByTag = new Map;
|
|
32259
|
+
for (const reduction of reductions) {
|
|
32260
|
+
if (reduction.mode === "partial") {
|
|
32261
|
+
partialCharactersByTag.set(reduction.tagNumber, (partialCharactersByTag.get(reduction.tagNumber) ?? 0) + Math.max(0, reduction.removedCharacters));
|
|
32262
|
+
continue;
|
|
32263
|
+
}
|
|
32264
|
+
const prior = structuralByTag.get(reduction.tagNumber);
|
|
32265
|
+
if (!prior || reduction.mode === "full") {
|
|
32266
|
+
structuralByTag.set(reduction.tagNumber, reduction);
|
|
32267
|
+
}
|
|
32268
|
+
}
|
|
32269
|
+
const tagNumbers = [...new Set([...structuralByTag.keys(), ...partialCharactersByTag.keys()])];
|
|
32270
|
+
const countsByTag = loadPersistedTagTokenCounts(db, sessionId, tagNumbers);
|
|
32271
|
+
let total = 0;
|
|
32272
|
+
for (const [tagNumber, reduction] of structuralByTag) {
|
|
32273
|
+
const row = countsByTag.get(tagNumber);
|
|
32274
|
+
if (!row)
|
|
32275
|
+
continue;
|
|
32276
|
+
total += persistedCountOrByteEstimate(row.tokenCount, row.byteSize);
|
|
32277
|
+
if (reduction.mode === "full") {
|
|
32278
|
+
total += persistedCountOrByteEstimate(row.reasoningTokenCount, row.reasoningByteSize);
|
|
32279
|
+
if (row.type === "tool") {
|
|
32280
|
+
total += persistedCountOrByteEstimate(row.inputTokenCount, row.inputByteSize);
|
|
32281
|
+
}
|
|
32282
|
+
}
|
|
32283
|
+
}
|
|
32284
|
+
for (const [tagNumber, removedCharacters] of partialCharactersByTag) {
|
|
32285
|
+
if (structuralByTag.has(tagNumber) || !countsByTag.has(tagNumber))
|
|
32286
|
+
continue;
|
|
32287
|
+
total += estimateCharacters(removedCharacters);
|
|
32288
|
+
}
|
|
32289
|
+
return Math.max(0, Math.round(total));
|
|
32290
|
+
}
|
|
32291
|
+
|
|
32021
32292
|
// src/hooks/magic-context/fold-execution-gate.ts
|
|
32022
32293
|
function foldExecutesThisPass(foldDue, materialized) {
|
|
32023
32294
|
return foldDue && materialized;
|
|
@@ -32088,6 +32359,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
32088
32359
|
let emergencyReclaimedTokens = 0;
|
|
32089
32360
|
let deduplicatedTools = 0;
|
|
32090
32361
|
let droppedInjections = 0;
|
|
32362
|
+
const droppedTokenReductions = [];
|
|
32091
32363
|
if (config.emergency) {
|
|
32092
32364
|
const emergency = config.emergency;
|
|
32093
32365
|
const priorInputSample = getEmergencyInputSample(db, sessionId);
|
|
@@ -32123,6 +32395,10 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
32123
32395
|
updateTagDropMode(db, sessionId, tag.tagNumber, skeleton ? "truncated" : "full");
|
|
32124
32396
|
droppedTools++;
|
|
32125
32397
|
emergencyDroppedTools++;
|
|
32398
|
+
droppedTokenReductions.push({
|
|
32399
|
+
tagNumber: tag.tagNumber,
|
|
32400
|
+
mode: result === "removed" ? "full" : "truncated"
|
|
32401
|
+
});
|
|
32126
32402
|
emergencyReclaimedTokens += estimateEmergencyDropReclaimTokens(tag);
|
|
32127
32403
|
}
|
|
32128
32404
|
}
|
|
@@ -32157,12 +32433,18 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
32157
32433
|
const strippedSource = stripTagPrefix(stripped);
|
|
32158
32434
|
if (strippedSource.trim().length === 0) {
|
|
32159
32435
|
const dropResult = target.drop?.() ?? "absent";
|
|
32160
|
-
const
|
|
32436
|
+
const replacement = `[dropped §${tag.tagNumber}§]`;
|
|
32437
|
+
const didReplace = dropResult === "absent" ? target.setContent(replacement) : false;
|
|
32161
32438
|
if (dropResult === "removed" || dropResult === "absent") {
|
|
32162
32439
|
replaceSourceContent(db, sessionId, tag.tagNumber, "");
|
|
32163
32440
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
32164
32441
|
if (dropResult === "removed" || didReplace) {
|
|
32165
32442
|
droppedInjections++;
|
|
32443
|
+
droppedTokenReductions.push(dropResult === "removed" ? { tagNumber: tag.tagNumber, mode: "full" } : {
|
|
32444
|
+
tagNumber: tag.tagNumber,
|
|
32445
|
+
mode: "partial",
|
|
32446
|
+
removedCharacters: Math.max(0, content.length - replacement.length)
|
|
32447
|
+
});
|
|
32166
32448
|
}
|
|
32167
32449
|
}
|
|
32168
32450
|
} else {
|
|
@@ -32170,6 +32452,11 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
32170
32452
|
if (didSet) {
|
|
32171
32453
|
replaceSourceContent(db, sessionId, tag.tagNumber, strippedSource);
|
|
32172
32454
|
droppedInjections++;
|
|
32455
|
+
droppedTokenReductions.push({
|
|
32456
|
+
tagNumber: tag.tagNumber,
|
|
32457
|
+
mode: "partial",
|
|
32458
|
+
removedCharacters: Math.max(0, content.length - stripped.length)
|
|
32459
|
+
});
|
|
32173
32460
|
}
|
|
32174
32461
|
}
|
|
32175
32462
|
}
|
|
@@ -32209,6 +32496,10 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
32209
32496
|
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
32210
32497
|
if (result === "removed" || result === "truncated") {
|
|
32211
32498
|
deduplicatedTools++;
|
|
32499
|
+
droppedTokenReductions.push({
|
|
32500
|
+
tagNumber: tag.tagNumber,
|
|
32501
|
+
mode: result === "removed" ? "full" : "truncated"
|
|
32502
|
+
});
|
|
32212
32503
|
}
|
|
32213
32504
|
}
|
|
32214
32505
|
}
|
|
@@ -32227,6 +32518,10 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
32227
32518
|
});
|
|
32228
32519
|
compressedTextTags = cavemanResult.compressedToLite + cavemanResult.compressedToFull + cavemanResult.compressedToUltra;
|
|
32229
32520
|
mutatedTextTags = cavemanResult.mutatedTextTags;
|
|
32521
|
+
droppedTokenReductions.push(...cavemanResult.textReductions.map((reduction) => ({
|
|
32522
|
+
...reduction,
|
|
32523
|
+
mode: "partial"
|
|
32524
|
+
})));
|
|
32230
32525
|
}
|
|
32231
32526
|
return {
|
|
32232
32527
|
droppedTools,
|
|
@@ -32235,7 +32530,8 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
32235
32530
|
emergencyDroppedTools,
|
|
32236
32531
|
emergencyReclaimedTokens,
|
|
32237
32532
|
compressedTextTags,
|
|
32238
|
-
mutatedTextTags
|
|
32533
|
+
mutatedTextTags,
|
|
32534
|
+
droppedTokenReductions
|
|
32239
32535
|
};
|
|
32240
32536
|
}
|
|
32241
32537
|
function extractToolInfo(part) {
|
|
@@ -32475,7 +32771,7 @@ var RECENT_TOOL_SKELETON_WINDOW = 20;
|
|
|
32475
32771
|
function buildReplacementContent(tagId) {
|
|
32476
32772
|
return `[dropped §${tagId}§]`;
|
|
32477
32773
|
}
|
|
32478
|
-
function applyPendingOperations(sessionId, db, targets, protectedTagIds, preloadedTags, preloadedPendingOps, syntheticPendingOps = [], editMarkerTagIds = new Set) {
|
|
32774
|
+
function applyPendingOperations(sessionId, db, targets, protectedTagIds, preloadedTags, preloadedPendingOps, syntheticPendingOps = [], editMarkerTagIds = new Set, onTagReduced) {
|
|
32479
32775
|
let didMutateMessage = false;
|
|
32480
32776
|
let admitted = false;
|
|
32481
32777
|
let startedAt = 0;
|
|
@@ -32484,6 +32780,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
32484
32780
|
admitted = true;
|
|
32485
32781
|
startedAt = performance.now();
|
|
32486
32782
|
const tags = preloadedTags ?? getTagsBySession(db, sessionId);
|
|
32783
|
+
const tagById = new Map(tags.map((tag) => [tag.tagNumber, tag]));
|
|
32487
32784
|
const tagStatusById = new Map(tags.map((tag) => [tag.tagNumber, tag.status]));
|
|
32488
32785
|
const tagTypeById = new Map(tags.map((tag) => [tag.tagNumber, tag.type]));
|
|
32489
32786
|
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
@@ -32516,6 +32813,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
32516
32813
|
continue;
|
|
32517
32814
|
}
|
|
32518
32815
|
didMutateMessage = true;
|
|
32816
|
+
onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "edit_marker" });
|
|
32519
32817
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "edit_marker");
|
|
32520
32818
|
shouldPersistDrop = true;
|
|
32521
32819
|
} else if (skeletonWindow.has(pendingOp.tagId)) {
|
|
@@ -32525,6 +32823,7 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
32525
32823
|
}
|
|
32526
32824
|
if (truncResult === "truncated") {
|
|
32527
32825
|
didMutateMessage = true;
|
|
32826
|
+
onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "truncated" });
|
|
32528
32827
|
}
|
|
32529
32828
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "truncated");
|
|
32530
32829
|
shouldPersistDrop = true;
|
|
@@ -32535,14 +32834,24 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
32535
32834
|
}
|
|
32536
32835
|
if (dropResult === "removed") {
|
|
32537
32836
|
didMutateMessage = true;
|
|
32837
|
+
onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "full" });
|
|
32538
32838
|
}
|
|
32539
32839
|
updateTagDropMode(db, sessionId, pendingOp.tagId, "full");
|
|
32540
32840
|
shouldPersistDrop = true;
|
|
32541
32841
|
}
|
|
32542
32842
|
} else if (target) {
|
|
32543
|
-
const
|
|
32544
|
-
|
|
32843
|
+
const replacement = buildReplacementContent(pendingOp.tagId);
|
|
32844
|
+
const priorContent = target.getContent?.();
|
|
32845
|
+
const changed = target.setContent(replacement);
|
|
32846
|
+
if (changed) {
|
|
32545
32847
|
didMutateMessage = true;
|
|
32848
|
+
const originalCharacters = typeof priorContent === "string" ? priorContent.length : tagById.get(pendingOp.tagId)?.byteSize ?? replacement.length;
|
|
32849
|
+
onTagReduced?.({
|
|
32850
|
+
tagNumber: pendingOp.tagId,
|
|
32851
|
+
mode: "partial",
|
|
32852
|
+
removedCharacters: Math.max(0, originalCharacters - replacement.length)
|
|
32853
|
+
});
|
|
32854
|
+
}
|
|
32546
32855
|
shouldPersistDrop = true;
|
|
32547
32856
|
} else if (!synthetic) {
|
|
32548
32857
|
shouldPersistDrop = true;
|
|
@@ -33530,6 +33839,10 @@ function clearPendingCompactionMarkerAfterSuccessfulDrain(args) {
|
|
|
33530
33839
|
sessionLog(args.sessionId, "compaction-marker drain: CAS-clear failed but no pending blob remains; another drain already cleared it");
|
|
33531
33840
|
return "cas-lost-already-cleared";
|
|
33532
33841
|
}
|
|
33842
|
+
var defaultCompactionMarkerStrategy = {
|
|
33843
|
+
applyDeferred: applyDeferredCompactionMarker,
|
|
33844
|
+
reconcile: reconcileMarkerRepresentation
|
|
33845
|
+
};
|
|
33533
33846
|
async function abortSessionFailClosed(client, sessionId) {
|
|
33534
33847
|
if (typeof client.session?.abort !== "function") {
|
|
33535
33848
|
throw new Error("OpenCode session.abort is unavailable");
|
|
@@ -33753,7 +34066,7 @@ async function runPostTransformPhase(args) {
|
|
|
33753
34066
|
let heuristicOrReasoningDidMutate = false;
|
|
33754
34067
|
let droppedCount = 0;
|
|
33755
34068
|
let droppedTokens = 0;
|
|
33756
|
-
const
|
|
34069
|
+
const droppedTokenReductions = [];
|
|
33757
34070
|
let emergencyReclaimedTokens = 0;
|
|
33758
34071
|
let emergency = false;
|
|
33759
34072
|
let m0M1InjectedThisPass = false;
|
|
@@ -33775,7 +34088,7 @@ async function runPostTransformPhase(args) {
|
|
|
33775
34088
|
const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : foldExecutedThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (scheduler=${args.schedulerDecision})`;
|
|
33776
34089
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${formatPendingOpsDepth()}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
33777
34090
|
const tApply = performance.now();
|
|
33778
|
-
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.contextUsage.percentage >= 95 ? newestCtxReduceTagNumbers(getTagsBySession(args.db, args.sessionId)) : args.protectedTagIds, undefined, pendingOps);
|
|
34091
|
+
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.contextUsage.percentage >= 95 ? newestCtxReduceTagNumbers(getTagsBySession(args.db, args.sessionId)) : args.protectedTagIds, undefined, pendingOps, [], new Set, (reduction) => droppedTokenReductions.push(reduction));
|
|
33779
34092
|
if (pendingOpsDidMutate) {
|
|
33780
34093
|
rideSignals.agentDrop = true;
|
|
33781
34094
|
isCacheBustingPass = hasReclaimRide(rideSignals);
|
|
@@ -33828,7 +34141,11 @@ async function runPostTransformPhase(args) {
|
|
|
33828
34141
|
emergencyDroppedTools: cleanup.emergencyDroppedTools,
|
|
33829
34142
|
emergencyReclaimedTokens: cleanup.emergencyReclaimedTokens,
|
|
33830
34143
|
compressedTextTags: cleanup.compressedTextTags + ridingCleanup.compressedTextTags,
|
|
33831
|
-
mutatedTextTags: cleanup.mutatedTextTags + ridingCleanup.mutatedTextTags
|
|
34144
|
+
mutatedTextTags: cleanup.mutatedTextTags + ridingCleanup.mutatedTextTags,
|
|
34145
|
+
droppedTokenReductions: [
|
|
34146
|
+
...cleanup.droppedTokenReductions,
|
|
34147
|
+
...ridingCleanup.droppedTokenReductions
|
|
34148
|
+
]
|
|
33832
34149
|
};
|
|
33833
34150
|
routineCleanupApplied = true;
|
|
33834
34151
|
}
|
|
@@ -33840,6 +34157,7 @@ async function runPostTransformPhase(args) {
|
|
|
33840
34157
|
droppedCount += cleanup.droppedTools + cleanup.deduplicatedTools + cleanup.droppedInjections + cleanup.mutatedTextTags;
|
|
33841
34158
|
emergency ||= cleanup.emergencyDroppedTools > 0;
|
|
33842
34159
|
emergencyReclaimedTokens += cleanup.emergencyReclaimedTokens;
|
|
34160
|
+
droppedTokenReductions.push(...cleanup.droppedTokenReductions);
|
|
33843
34161
|
const t7 = performance.now();
|
|
33844
34162
|
const clearedReasoning = routineCleanupApplied && canUseEmptySentinels ? clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge) : 0;
|
|
33845
34163
|
if (routineCleanupApplied && canUseEmptySentinels) {
|
|
@@ -33927,7 +34245,7 @@ async function runPostTransformPhase(args) {
|
|
|
33927
34245
|
}
|
|
33928
34246
|
autoReclaimTargetCount = syntheticPendingOps.length;
|
|
33929
34247
|
if (syntheticPendingOps.length > 0) {
|
|
33930
|
-
autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTagIds, undefined, [], syntheticPendingOps, editMarkerTagIds);
|
|
34248
|
+
autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTagIds, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction));
|
|
33931
34249
|
if (autoReclaimDidMutate) {
|
|
33932
34250
|
droppedCount += syntheticPendingOps.length;
|
|
33933
34251
|
autoReclaimDidMutateThisPass = true;
|
|
@@ -33965,7 +34283,7 @@ async function runPostTransformPhase(args) {
|
|
|
33965
34283
|
updateSessionMeta2(args.db, args.sessionId, { lastTransformError: getErrorMessage(error) });
|
|
33966
34284
|
}
|
|
33967
34285
|
if (isCacheBustingPass) {
|
|
33968
|
-
droppedTokens =
|
|
34286
|
+
droppedTokens = estimateDroppedTokensFromTagReductions(args.db, args.sessionId, droppedTokenReductions);
|
|
33969
34287
|
}
|
|
33970
34288
|
const replaySnapshot = !compactionOff ? loadPostprocessReplaySnapshot(args.db, args.sessionId) : undefined;
|
|
33971
34289
|
if (canUseEmptySentinels && !compactionOff && replaySnapshot) {
|
|
@@ -34131,7 +34449,7 @@ async function runPostTransformPhase(args) {
|
|
|
34131
34449
|
suppressV12HistoryDrain = true;
|
|
34132
34450
|
sessionLog(args.sessionId, `compaction-marker drain: pending ordinal ${pending.ordinal} is newer than consumed boundary ${args.pendingCompartmentInjection?.compartmentEndMessage ?? "<none>"}; preserving deferred history refresh signal`);
|
|
34133
34451
|
} else {
|
|
34134
|
-
const outcome =
|
|
34452
|
+
const outcome = (args.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy).applyDeferred(args.db, args.sessionId, pending, args.sessionDirectory);
|
|
34135
34453
|
switch (outcome.kind) {
|
|
34136
34454
|
case "applied":
|
|
34137
34455
|
case "already-current":
|
|
@@ -34156,7 +34474,7 @@ async function runPostTransformPhase(args) {
|
|
|
34156
34474
|
}
|
|
34157
34475
|
}
|
|
34158
34476
|
if (!compactionOff) {
|
|
34159
|
-
|
|
34477
|
+
(args.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy).reconcile(args.messages, persistedCompactionMarkerState, {
|
|
34160
34478
|
db: args.db,
|
|
34161
34479
|
sessionId: args.sessionId,
|
|
34162
34480
|
tagger: args.tagger,
|
|
@@ -34848,6 +35166,10 @@ function responseValue(response) {
|
|
|
34848
35166
|
throw new Error("module transform returned a non-object response");
|
|
34849
35167
|
}
|
|
34850
35168
|
function mirrorProjectionKey(response) {
|
|
35169
|
+
const memoryMirrorHead = response.memory_mirror_head;
|
|
35170
|
+
if (typeof memoryMirrorHead === "number" && Number.isSafeInteger(memoryMirrorHead) && memoryMirrorHead >= 0) {
|
|
35171
|
+
return JSON.stringify(["memory-feed", memoryMirrorHead]);
|
|
35172
|
+
}
|
|
34851
35173
|
const rowVersion = response.row_version;
|
|
34852
35174
|
if (typeof rowVersion !== "number" || !Number.isSafeInteger(rowVersion) || rowVersion < 0) {
|
|
34853
35175
|
return null;
|
|
@@ -36940,7 +37262,7 @@ async function runCompartmentPhaseImpl(args) {
|
|
|
36940
37262
|
sessionLog(args.sessionId, `transform: skipping compartment start, no eligible history before protected tail (beyond ${lastObservedCompartmentEnd})`);
|
|
36941
37263
|
updateSessionMeta2(args.db, args.sessionId, { compartmentInProgress: false });
|
|
36942
37264
|
compartmentInProgress = false;
|
|
36943
|
-
} else if (!args.client) {
|
|
37265
|
+
} else if (!args.client && !args.hiddenCompletionExecutor) {
|
|
36944
37266
|
sessionLog(args.sessionId, "transform: cannot start compartment agent without client");
|
|
36945
37267
|
updateSessionMeta2(args.db, args.sessionId, { compartmentInProgress: false });
|
|
36946
37268
|
compartmentInProgress = false;
|
|
@@ -36948,6 +37270,8 @@ async function runCompartmentPhaseImpl(args) {
|
|
|
36948
37270
|
sessionLog(args.sessionId, "transform: compartmentInProgress flag set, starting agent");
|
|
36949
37271
|
startCompartmentAgent({
|
|
36950
37272
|
client: args.client,
|
|
37273
|
+
hiddenCompletionExecutor: args.hiddenCompletionExecutor,
|
|
37274
|
+
compactionMarkerStrategy: args.compactionMarkerStrategy,
|
|
36951
37275
|
db: args.db,
|
|
36952
37276
|
sessionId: args.sessionId,
|
|
36953
37277
|
historianChunkTokens: args.historianChunkTokens,
|
|
@@ -36976,10 +37300,12 @@ async function runCompartmentPhaseImpl(args) {
|
|
|
36976
37300
|
let awaitedCompartmentRun = false;
|
|
36977
37301
|
if (historianRunnable && args.canRunCompartments && !args.skipAwaitForThisPass && args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE) {
|
|
36978
37302
|
let activeRun = getActiveCompartmentRun(args.sessionId);
|
|
36979
|
-
if (!activeRun && hasEligibleHistoryForCompartment() && args.client) {
|
|
37303
|
+
if (!activeRun && hasEligibleHistoryForCompartment() && (args.client || args.hiddenCompletionExecutor)) {
|
|
36980
37304
|
sessionLog(args.sessionId, `transform: 95% reached (${args.contextUsage.percentage.toFixed(1)}%), force-starting compartment agent and blocking`);
|
|
36981
37305
|
startCompartmentAgent({
|
|
36982
37306
|
client: args.client,
|
|
37307
|
+
hiddenCompletionExecutor: args.hiddenCompletionExecutor,
|
|
37308
|
+
compactionMarkerStrategy: args.compactionMarkerStrategy,
|
|
36983
37309
|
db: args.db,
|
|
36984
37310
|
sessionId: args.sessionId,
|
|
36985
37311
|
historianChunkTokens: args.historianChunkTokens,
|
|
@@ -37214,7 +37540,16 @@ function scheduleTsAuthorityRecovery(args) {
|
|
|
37214
37540
|
}
|
|
37215
37541
|
});
|
|
37216
37542
|
}
|
|
37543
|
+
function resolveTransformHostSeams(deps) {
|
|
37544
|
+
return {
|
|
37545
|
+
hostRawMessages: deps.hostRawMessages ?? readRawSessionMessages,
|
|
37546
|
+
hostProtectedTailBoundary: deps.hostProtectedTailBoundary ?? resolveOpenCodeProtectedTailBoundary,
|
|
37547
|
+
hostModelFallback: deps.hostModelFallback ?? findLastAssistantModelFromOpenCodeDb,
|
|
37548
|
+
hostRefuse: deps.hostRefuse ?? abortSessionFailClosed
|
|
37549
|
+
};
|
|
37550
|
+
}
|
|
37217
37551
|
function createTransform(deps) {
|
|
37552
|
+
const host = resolveTransformHostSeams(deps);
|
|
37218
37553
|
const loadedSessions = new Set;
|
|
37219
37554
|
const rustModeTransform = deps.transformMode === "rust" && deps.rustModeModuleClient ? createRustModeTransform(deps, {
|
|
37220
37555
|
moduleClient: deps.rustModeModuleClient,
|
|
@@ -37250,7 +37585,7 @@ function createTransform(deps) {
|
|
|
37250
37585
|
logTransformTiming(sessionId, "findSessionId", startTime, `messages=${messages.length}`);
|
|
37251
37586
|
const db = deps.db;
|
|
37252
37587
|
if (deps.client !== undefined) {
|
|
37253
|
-
scheduleReconciliation(db, sessionId,
|
|
37588
|
+
scheduleReconciliation(db, sessionId, host.hostRawMessages);
|
|
37254
37589
|
}
|
|
37255
37590
|
const tUserMsg = performance.now();
|
|
37256
37591
|
const currentTurnId = findLastUserMessageId(messages);
|
|
@@ -37353,7 +37688,7 @@ function createTransform(deps) {
|
|
|
37353
37688
|
}
|
|
37354
37689
|
const compartmentDirectory = sessionDirectory;
|
|
37355
37690
|
const historianRunnable = deps.historianRunnable !== false;
|
|
37356
|
-
const canRunCompartments = fullFeatureMode && !compactionOff && historianRunnable && deps.client !== undefined && compartmentDirectory.length > 0;
|
|
37691
|
+
const canRunCompartments = fullFeatureMode && !compactionOff && historianRunnable && (deps.client !== undefined || deps.hiddenCompletionExecutor !== undefined) && compartmentDirectory.length > 0;
|
|
37357
37692
|
const fallbackModelId = deps.getFallbackModelId?.(sessionId);
|
|
37358
37693
|
const tModelDetect = performance.now();
|
|
37359
37694
|
const persistedUsageBeforeResets = contextUsagePassSnapshot(sessionMeta).persistedUsage;
|
|
@@ -37458,7 +37793,7 @@ function createTransform(deps) {
|
|
|
37458
37793
|
}
|
|
37459
37794
|
let modelForBudget = deps.liveModelBySession?.get(sessionId);
|
|
37460
37795
|
if (!modelForBudget) {
|
|
37461
|
-
const recovered =
|
|
37796
|
+
const recovered = host.hostModelFallback(sessionId);
|
|
37462
37797
|
if (recovered) {
|
|
37463
37798
|
modelForBudget = recovered;
|
|
37464
37799
|
deps.liveModelBySession?.set(sessionId, recovered);
|
|
@@ -37514,7 +37849,7 @@ function createTransform(deps) {
|
|
|
37514
37849
|
if (!canRunCompartments)
|
|
37515
37850
|
return null;
|
|
37516
37851
|
if (_boundarySnapshotCache === undefined || emergencyTailScale) {
|
|
37517
|
-
const snapshot =
|
|
37852
|
+
const snapshot = host.hostProtectedTailBoundary({
|
|
37518
37853
|
db,
|
|
37519
37854
|
sessionId: resolvedSessionId,
|
|
37520
37855
|
mode: "transform-force",
|
|
@@ -37546,7 +37881,7 @@ function createTransform(deps) {
|
|
|
37546
37881
|
boundarySnapshot = getRunnableBoundaryForCompartment(scale);
|
|
37547
37882
|
}
|
|
37548
37883
|
if (false) {}
|
|
37549
|
-
if (!canRunCompartments || !deps.client || !boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot)) {
|
|
37884
|
+
if (!canRunCompartments || !deps.client && !deps.hiddenCompletionExecutor || !boundarySnapshot || !hasRunnableCompartmentWindow(boundarySnapshot)) {
|
|
37550
37885
|
return false;
|
|
37551
37886
|
}
|
|
37552
37887
|
if (getActiveCompartmentRun(sessionId)) {
|
|
@@ -37555,6 +37890,8 @@ function createTransform(deps) {
|
|
|
37555
37890
|
updateSessionMeta2(db, sessionId, { compartmentInProgress: true });
|
|
37556
37891
|
startCompartmentAgent({
|
|
37557
37892
|
client: deps.client,
|
|
37893
|
+
hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
|
|
37894
|
+
compactionMarkerStrategy: deps.compactionMarkerStrategy,
|
|
37558
37895
|
db,
|
|
37559
37896
|
sessionId,
|
|
37560
37897
|
historianChunkTokens: deps.getHistorianChunkTokens?.() ?? 20000,
|
|
@@ -37761,6 +38098,8 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
37761
38098
|
const rawGetNotifParams = deps.getNotificationParams;
|
|
37762
38099
|
const tCompartmentPhase = performance.now();
|
|
37763
38100
|
const compartmentPhase = await runCompartmentPhase({
|
|
38101
|
+
hiddenCompletionExecutor: deps.hiddenCompletionExecutor,
|
|
38102
|
+
compactionMarkerStrategy: deps.compactionMarkerStrategy,
|
|
37764
38103
|
canRunCompartments,
|
|
37765
38104
|
fullFeatureMode,
|
|
37766
38105
|
compactionOff,
|
|
@@ -37871,6 +38210,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
37871
38210
|
const protectedCutoff = protectionWindow.cutoff;
|
|
37872
38211
|
const tPostProcess = performance.now();
|
|
37873
38212
|
const postTransformResult = await runPostTransformPhase({
|
|
38213
|
+
compactionMarkerStrategy: deps.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy,
|
|
37874
38214
|
sessionId,
|
|
37875
38215
|
db,
|
|
37876
38216
|
messages,
|
|
@@ -37988,7 +38328,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
37988
38328
|
throw new EmergencyFailClosedError(`Emergency recovery notification was ${notification}`);
|
|
37989
38329
|
}
|
|
37990
38330
|
try {
|
|
37991
|
-
await
|
|
38331
|
+
await host.hostRefuse(deps.client, sessionId);
|
|
37992
38332
|
} catch (error) {
|
|
37993
38333
|
sessionLog(sessionId, "transform: emergency fail-closed abort failed; refusing to return a sendable prompt:", getErrorMessage(error));
|
|
37994
38334
|
throw new EmergencyFailClosedError("Emergency recovery abort failed", {
|
|
@@ -39785,7 +40125,7 @@ function createMagicContextHook(deps) {
|
|
|
39785
40125
|
};
|
|
39786
40126
|
const rustMemorySyncRequestedSessions = new Set;
|
|
39787
40127
|
const authorityRecoveryModuleClient = deps.rustModeModuleClient ?? (() => {
|
|
39788
|
-
const transport = new SubcModuleTransport(deps.config.subc?.connection_file);
|
|
40128
|
+
const transport = new SubcModuleTransport(deps.config.subc?.connection_file ?? getDefaultSubcConnectionFile());
|
|
39789
40129
|
const client = {
|
|
39790
40130
|
call: (args) => transport.call(args),
|
|
39791
40131
|
stateSyncCapabilities: (args) => transport.stateSyncCapabilities(args),
|
|
@@ -39839,13 +40179,14 @@ function createMagicContextHook(deps) {
|
|
|
39839
40179
|
const syncModuleNotes = () => syncModuleDomain("notes");
|
|
39840
40180
|
const syncModuleMemories = () => syncModuleDomain("memories");
|
|
39841
40181
|
const rustToolBackends = deps.config.transform_mode === "rust" && rustModeModuleClient ? {
|
|
39842
|
-
authorityState: async ({ projectPath, projectRoot, domain }) => {
|
|
40182
|
+
authorityState: async ({ projectPath, projectRoot, sessionId, domain }) => {
|
|
39843
40183
|
if (!rustModeModuleClient.authorityStatus)
|
|
39844
40184
|
return null;
|
|
39845
40185
|
const result = await rustModeModuleClient.authorityStatus({
|
|
39846
40186
|
context_store_uuid: ensureContextStoreUuid(db),
|
|
39847
40187
|
project: projectPath,
|
|
39848
40188
|
projectRoot,
|
|
40189
|
+
sessionId,
|
|
39849
40190
|
domain
|
|
39850
40191
|
});
|
|
39851
40192
|
return result.authority?.state ?? null;
|
|
@@ -39930,7 +40271,8 @@ function createMagicContextHook(deps) {
|
|
|
39930
40271
|
content,
|
|
39931
40272
|
category,
|
|
39932
40273
|
ids,
|
|
39933
|
-
reason
|
|
40274
|
+
reason,
|
|
40275
|
+
limit
|
|
39934
40276
|
}) => {
|
|
39935
40277
|
const response = await rustModeModuleClient.call({
|
|
39936
40278
|
sessionId,
|
|
@@ -39945,6 +40287,7 @@ function createMagicContextHook(deps) {
|
|
|
39945
40287
|
category,
|
|
39946
40288
|
ids,
|
|
39947
40289
|
reason,
|
|
40290
|
+
limit,
|
|
39948
40291
|
memory_project: memoryProject
|
|
39949
40292
|
}
|
|
39950
40293
|
}
|
|
@@ -41070,6 +41413,9 @@ function memoryAuthorityRefusal(args) {
|
|
|
41070
41413
|
const isMutation = args.action !== undefined && ["write", "update", "archive", "merge"].includes(args.action);
|
|
41071
41414
|
return renderCapabilityRefusal(isMutation ? "memory_write" : "memory_access");
|
|
41072
41415
|
}
|
|
41416
|
+
function memoryAuthorityMismatchRefusal() {
|
|
41417
|
+
return renderUserFacingFailure("memory_authority_mismatch");
|
|
41418
|
+
}
|
|
41073
41419
|
function moduleMemoryText(response, args) {
|
|
41074
41420
|
let value = response;
|
|
41075
41421
|
if (value !== null && typeof value === "object" && "result" in value) {
|
|
@@ -41332,6 +41678,24 @@ function createCtxMemoryTool(deps) {
|
|
|
41332
41678
|
return "Error: Could not resolve project identity for memory action.";
|
|
41333
41679
|
}
|
|
41334
41680
|
await deps.ensureProjectRegistered?.(toolContext.directory, deps.db);
|
|
41681
|
+
const activeCurateCategory = toolContext.agent === DREAMER_AGENT ? getActiveCurateCategory(deps.db, projectPath) : null;
|
|
41682
|
+
if (activeCurateCategory) {
|
|
41683
|
+
const scopeRefusal = getCurateCategoryScopeRefusal({
|
|
41684
|
+
scope: activeCurateCategory,
|
|
41685
|
+
action: args.action,
|
|
41686
|
+
requestedCategory: args.category,
|
|
41687
|
+
ids: [
|
|
41688
|
+
...args.ids ?? [],
|
|
41689
|
+
...Number.isInteger(args.superseded_by) ? [args.superseded_by] : []
|
|
41690
|
+
],
|
|
41691
|
+
categoryForId: (id) => {
|
|
41692
|
+
const category = getMemoryById(deps.db, id)?.category;
|
|
41693
|
+
return category ? curateCategoryForMemoryCategory(category) : null;
|
|
41694
|
+
}
|
|
41695
|
+
});
|
|
41696
|
+
if (scopeRefusal)
|
|
41697
|
+
return scopeRefusal;
|
|
41698
|
+
}
|
|
41335
41699
|
const curatePreflight = toolContext.agent === DREAMER_AGENT ? preflightCurateMutation({
|
|
41336
41700
|
db: deps.db,
|
|
41337
41701
|
params: args,
|
|
@@ -41339,13 +41703,14 @@ function createCtxMemoryTool(deps) {
|
|
|
41339
41703
|
}) : { skip: null, successor: null };
|
|
41340
41704
|
if (curatePreflight.skip)
|
|
41341
41705
|
return curatePreflight.skip;
|
|
41342
|
-
|
|
41706
|
+
{
|
|
41343
41707
|
const marker = getAuthorityManagedMarker(deps.db, projectPath);
|
|
41344
41708
|
let authorityState = null;
|
|
41345
41709
|
try {
|
|
41346
41710
|
authorityState = await deps.rustToolBackends?.authorityState?.({
|
|
41347
41711
|
projectPath,
|
|
41348
41712
|
projectRoot: toolContext.directory,
|
|
41713
|
+
sessionId: toolContext.sessionID,
|
|
41349
41714
|
domain: "memories"
|
|
41350
41715
|
}) ?? null;
|
|
41351
41716
|
} catch (error) {
|
|
@@ -41382,7 +41747,8 @@ function createCtxMemoryTool(deps) {
|
|
|
41382
41747
|
content: moduleArgs.content,
|
|
41383
41748
|
category: moduleArgs.category,
|
|
41384
41749
|
ids: moduleArgs.ids,
|
|
41385
|
-
reason: moduleArgs.reason
|
|
41750
|
+
reason: moduleArgs.reason,
|
|
41751
|
+
limit: moduleArgs.action === "list" ? normalizeLimit2(moduleArgs.limit) : undefined
|
|
41386
41752
|
}), moduleArgs);
|
|
41387
41753
|
return text ?? memoryAuthorityRefusal(args);
|
|
41388
41754
|
} catch (error) {
|
|
@@ -41393,6 +41759,9 @@ function createCtxMemoryTool(deps) {
|
|
|
41393
41759
|
return memoryAuthorityRefusal(args);
|
|
41394
41760
|
}
|
|
41395
41761
|
}
|
|
41762
|
+
if (marker && (authorityState === null || authorityState === "TS")) {
|
|
41763
|
+
return memoryAuthorityMismatchRefusal();
|
|
41764
|
+
}
|
|
41396
41765
|
if (marker || authorityState === "PREPARING" || authorityState === "DRAINING") {
|
|
41397
41766
|
return memoryAuthorityRefusal(args);
|
|
41398
41767
|
}
|
|
@@ -41461,7 +41830,8 @@ function createCtxMemoryTool(deps) {
|
|
|
41461
41830
|
if (args.action === "list") {
|
|
41462
41831
|
const limit = normalizeLimit2(args.limit);
|
|
41463
41832
|
const category = normalizeCategory(args.category);
|
|
41464
|
-
const
|
|
41833
|
+
const allMemories = getMemoriesByProject(deps.db, projectPath);
|
|
41834
|
+
const memories = (activeCurateCategory ? allMemories.filter((memory) => curateCategoryForMemoryCategory(memory.category) === activeCurateCategory) : filterByCategory(allMemories, category)).slice(0, limit);
|
|
41465
41835
|
return formatMemoryList(memories);
|
|
41466
41836
|
}
|
|
41467
41837
|
if (args.action === "get") {
|
|
@@ -42417,6 +42787,7 @@ function createCtxNoteTool(deps) {
|
|
|
42417
42787
|
notesAuthority = await deps.rustToolBackends.authorityState({
|
|
42418
42788
|
projectPath: projectIdentity,
|
|
42419
42789
|
projectRoot: toolContext.directory,
|
|
42790
|
+
sessionId,
|
|
42420
42791
|
domain: "notes"
|
|
42421
42792
|
});
|
|
42422
42793
|
} catch (error) {
|
|
@@ -43383,6 +43754,1111 @@ function json(body, status = 200) {
|
|
|
43383
43754
|
});
|
|
43384
43755
|
}
|
|
43385
43756
|
|
|
43757
|
+
// src/v2/fold/markers.ts
|
|
43758
|
+
var v2CompactionMarkerStrategy = {
|
|
43759
|
+
setPending: () => {},
|
|
43760
|
+
publish: () => false,
|
|
43761
|
+
applyDeferred: () => ({ kind: "already-current" }),
|
|
43762
|
+
reconcile: () => false
|
|
43763
|
+
};
|
|
43764
|
+
|
|
43765
|
+
// src/v2/fold/owner.ts
|
|
43766
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
43767
|
+
var foldDigest = (value) => createHash15("sha256").update(value).digest("hex");
|
|
43768
|
+
|
|
43769
|
+
class FoldOwner {
|
|
43770
|
+
storage;
|
|
43771
|
+
pending = new Map;
|
|
43772
|
+
constructor(storage) {
|
|
43773
|
+
this.storage = storage;
|
|
43774
|
+
}
|
|
43775
|
+
async serial(sessionID, operation) {
|
|
43776
|
+
const previous = this.pending.get(sessionID) ?? Promise.resolve();
|
|
43777
|
+
const next = previous.catch(() => {}).then(operation);
|
|
43778
|
+
this.pending.set(sessionID, next);
|
|
43779
|
+
try {
|
|
43780
|
+
return await next;
|
|
43781
|
+
} finally {
|
|
43782
|
+
if (this.pending.get(sessionID) === next)
|
|
43783
|
+
this.pending.delete(sessionID);
|
|
43784
|
+
}
|
|
43785
|
+
}
|
|
43786
|
+
key(sessionID) {
|
|
43787
|
+
return `fold/v1/${sessionID}`;
|
|
43788
|
+
}
|
|
43789
|
+
async read(sessionID) {
|
|
43790
|
+
return await this.storage.get(this.key(sessionID));
|
|
43791
|
+
}
|
|
43792
|
+
async supply(args) {
|
|
43793
|
+
return this.serial(args.sessionID, async () => {
|
|
43794
|
+
const previous = await this.read(args.sessionID);
|
|
43795
|
+
const same = previous && (args.runningCut !== undefined ? previous.cutSeq === args.runningCut : previous.cutSeq === undefined && previous.watermark === args.watermark);
|
|
43796
|
+
if (same)
|
|
43797
|
+
return previous;
|
|
43798
|
+
const submitted = args.materialize();
|
|
43799
|
+
const next = {
|
|
43800
|
+
watermark: args.watermark,
|
|
43801
|
+
cutSeq: args.runningCut,
|
|
43802
|
+
submitted,
|
|
43803
|
+
submittedSha: foldDigest(submitted)
|
|
43804
|
+
};
|
|
43805
|
+
await this.storage.set(this.key(args.sessionID), next);
|
|
43806
|
+
return next;
|
|
43807
|
+
});
|
|
43808
|
+
}
|
|
43809
|
+
async observe(args) {
|
|
43810
|
+
return this.serial(args.sessionID, async () => {
|
|
43811
|
+
let state = await this.read(args.sessionID);
|
|
43812
|
+
const renderedSha = foldDigest(JSON.stringify(args.rendered));
|
|
43813
|
+
if (!state) {
|
|
43814
|
+
args.onHard("boot_recovery");
|
|
43815
|
+
state = {
|
|
43816
|
+
watermark: args.cutSeq,
|
|
43817
|
+
submitted: args.summary,
|
|
43818
|
+
submittedSha: foldDigest(args.summary),
|
|
43819
|
+
reason: "boot_recovery"
|
|
43820
|
+
};
|
|
43821
|
+
}
|
|
43822
|
+
const reason = args.cutSeq < state.watermark ? "host_cut_before_watermark" : state.submittedSha !== foldDigest(args.summary) || state.renderedSha && state.renderedSha !== renderedSha ? "host_rerender" : undefined;
|
|
43823
|
+
if (reason && state.rejectedSha !== renderedSha) {
|
|
43824
|
+
args.onHard(reason);
|
|
43825
|
+
state.reason = reason;
|
|
43826
|
+
state.rejectedSha = renderedSha;
|
|
43827
|
+
}
|
|
43828
|
+
if (state.cutSeq === undefined && args.cutSeq >= state.watermark)
|
|
43829
|
+
state.cutSeq = args.cutSeq;
|
|
43830
|
+
if (!state.rendered && reason !== "host_cut_before_watermark") {
|
|
43831
|
+
state.rendered = structuredClone(args.rendered);
|
|
43832
|
+
state.renderedSha = renderedSha;
|
|
43833
|
+
state.renderedSummary = args.summary;
|
|
43834
|
+
}
|
|
43835
|
+
await this.storage.set(this.key(args.sessionID), state);
|
|
43836
|
+
return state;
|
|
43837
|
+
});
|
|
43838
|
+
}
|
|
43839
|
+
}
|
|
43840
|
+
|
|
43841
|
+
// src/v2/fold/restore.ts
|
|
43842
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
43843
|
+
var imageMimes = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
|
|
43844
|
+
function attachmentParts(files) {
|
|
43845
|
+
const seen = new Map;
|
|
43846
|
+
return files.flatMap((file) => {
|
|
43847
|
+
if (imageMimes.has(file.mime) && file.source.type === "inline" && file.mention?.text) {
|
|
43848
|
+
const key = JSON.stringify([
|
|
43849
|
+
file.mime,
|
|
43850
|
+
file.name ?? null,
|
|
43851
|
+
file.description ?? null,
|
|
43852
|
+
file.mention.text
|
|
43853
|
+
]);
|
|
43854
|
+
const payloads = seen.get(key) ?? new Set;
|
|
43855
|
+
if (payloads.has(file.data))
|
|
43856
|
+
return [];
|
|
43857
|
+
payloads.add(file.data);
|
|
43858
|
+
seen.set(key, payloads);
|
|
43859
|
+
}
|
|
43860
|
+
const uri = file.source.type === "uri" ? file.source.uri : undefined;
|
|
43861
|
+
const location = uri?.startsWith("file:") ? fileURLToPath2(uri) : undefined;
|
|
43862
|
+
if (file.mime === "text/plain" || file.mime === "application/x-directory") {
|
|
43863
|
+
const directory = file.mime === "application/x-directory";
|
|
43864
|
+
return [
|
|
43865
|
+
{
|
|
43866
|
+
type: "text",
|
|
43867
|
+
text: `
|
|
43868
|
+
|
|
43869
|
+
${[
|
|
43870
|
+
directory ? `Attached directory: ${location ?? file.name ?? uri ?? "directory"}` : `Attached file: ${file.name ?? uri ?? "inline attachment"}`,
|
|
43871
|
+
file.description === undefined ? undefined : `Description: ${file.description}`,
|
|
43872
|
+
directory && !file.data.length ? undefined : "",
|
|
43873
|
+
directory && !file.data.length ? undefined : Buffer.from(file.data, "base64").toString("utf8")
|
|
43874
|
+
].filter((line) => line !== undefined).join(`
|
|
43875
|
+
`)}`,
|
|
43876
|
+
metadata: {
|
|
43877
|
+
attachment: {
|
|
43878
|
+
source: file.source,
|
|
43879
|
+
name: file.name,
|
|
43880
|
+
description: file.description
|
|
43881
|
+
}
|
|
43882
|
+
}
|
|
43883
|
+
}
|
|
43884
|
+
];
|
|
43885
|
+
}
|
|
43886
|
+
if (!imageMimes.has(file.mime) && file.mime !== "application/pdf")
|
|
43887
|
+
return [];
|
|
43888
|
+
return [
|
|
43889
|
+
...location ? [{ type: "text", text: `Attached file: ${location}` }] : [],
|
|
43890
|
+
{
|
|
43891
|
+
type: "media",
|
|
43892
|
+
mediaType: file.mime,
|
|
43893
|
+
data: file.data,
|
|
43894
|
+
filename: file.name,
|
|
43895
|
+
metadata: file.description === undefined ? undefined : { description: file.description }
|
|
43896
|
+
}
|
|
43897
|
+
];
|
|
43898
|
+
});
|
|
43899
|
+
}
|
|
43900
|
+
function restoreRow(row, model) {
|
|
43901
|
+
const data = row.data;
|
|
43902
|
+
const make = (role, content, metadata = data.metadata) => ({
|
|
43903
|
+
id: row.id,
|
|
43904
|
+
role,
|
|
43905
|
+
content,
|
|
43906
|
+
...metadata === undefined ? {} : { metadata }
|
|
43907
|
+
});
|
|
43908
|
+
if (row.type === "user") {
|
|
43909
|
+
const skills = data.skills ?? [];
|
|
43910
|
+
const content = [
|
|
43911
|
+
...skills.flatMap((skill) => skill.text === undefined ? [] : [{ type: "text", text: skill.text }]),
|
|
43912
|
+
...data.text ? [{ type: "text", text: data.text }] : [],
|
|
43913
|
+
...attachmentParts(data.files ?? [])
|
|
43914
|
+
];
|
|
43915
|
+
return content.length ? [
|
|
43916
|
+
make("user", content, {
|
|
43917
|
+
...data.metadata ?? {},
|
|
43918
|
+
...data.agents?.length ? { agents: data.agents } : {}
|
|
43919
|
+
})
|
|
43920
|
+
] : [];
|
|
43921
|
+
}
|
|
43922
|
+
if (["synthetic", "skill", "system"].includes(row.type))
|
|
43923
|
+
return [
|
|
43924
|
+
make(row.type === "system" ? "system" : "user", [
|
|
43925
|
+
{ type: "text", text: data.text ?? "" }
|
|
43926
|
+
])
|
|
43927
|
+
];
|
|
43928
|
+
if (row.type === "location-switched")
|
|
43929
|
+
return [
|
|
43930
|
+
make("user", [
|
|
43931
|
+
{
|
|
43932
|
+
type: "text",
|
|
43933
|
+
text: `The working directory has been changed to ${data.location.directory}.`
|
|
43934
|
+
}
|
|
43935
|
+
])
|
|
43936
|
+
];
|
|
43937
|
+
if (row.type === "shell")
|
|
43938
|
+
return data.metadata?.background === true ? [] : [
|
|
43939
|
+
make("user", [
|
|
43940
|
+
{
|
|
43941
|
+
type: "text",
|
|
43942
|
+
text: `The following shell command was executed by the user:
|
|
43943
|
+
|
|
43944
|
+
Command:
|
|
43945
|
+
${data.command}
|
|
43946
|
+
|
|
43947
|
+
Output:
|
|
43948
|
+
${data.output?.output ?? ""}`
|
|
43949
|
+
}
|
|
43950
|
+
])
|
|
43951
|
+
];
|
|
43952
|
+
if (row.type !== "assistant")
|
|
43953
|
+
return [];
|
|
43954
|
+
const previousModel = data.model;
|
|
43955
|
+
const sameProvider = previousModel?.providerID === model.providerID;
|
|
43956
|
+
const sameModel = sameProvider && previousModel?.id === model.id;
|
|
43957
|
+
const reuse = sameModel && data.error === undefined;
|
|
43958
|
+
const metadata = (state) => state === undefined ? undefined : { [model.providerID]: state };
|
|
43959
|
+
const content = [];
|
|
43960
|
+
const results = [];
|
|
43961
|
+
for (const part of data.content ?? []) {
|
|
43962
|
+
if (part.type === "text") {
|
|
43963
|
+
if (part.text !== "")
|
|
43964
|
+
content.push({
|
|
43965
|
+
type: "text",
|
|
43966
|
+
text: part.text,
|
|
43967
|
+
providerMetadata: reuse ? metadata(part.state) : undefined
|
|
43968
|
+
});
|
|
43969
|
+
continue;
|
|
43970
|
+
}
|
|
43971
|
+
if (part.type === "reasoning") {
|
|
43972
|
+
if (part.text !== "" || reuse && part.state !== undefined)
|
|
43973
|
+
content.push({
|
|
43974
|
+
type: reuse || data.error === undefined ? "reasoning" : "text",
|
|
43975
|
+
text: part.text,
|
|
43976
|
+
providerMetadata: reuse ? metadata(part.state) : undefined
|
|
43977
|
+
});
|
|
43978
|
+
continue;
|
|
43979
|
+
}
|
|
43980
|
+
const state = part.state;
|
|
43981
|
+
const completed = state.status === "completed" || state.status === "error";
|
|
43982
|
+
const toolReuse = reuse || sameModel && part.executed === true && completed;
|
|
43983
|
+
let input = state.input;
|
|
43984
|
+
if (state.status === "streaming" && typeof input === "string") {
|
|
43985
|
+
try {
|
|
43986
|
+
input = JSON.parse(input);
|
|
43987
|
+
} catch {}
|
|
43988
|
+
}
|
|
43989
|
+
content.push({
|
|
43990
|
+
type: "tool-call",
|
|
43991
|
+
id: part.id,
|
|
43992
|
+
name: part.name,
|
|
43993
|
+
input,
|
|
43994
|
+
providerExecuted: part.executed,
|
|
43995
|
+
providerMetadata: toolReuse ? metadata(part.providerState) : undefined
|
|
43996
|
+
});
|
|
43997
|
+
if (!completed)
|
|
43998
|
+
continue;
|
|
43999
|
+
const toolContent = state.content ?? [];
|
|
44000
|
+
const single = toolContent.length === 1 ? toolContent[0] : undefined;
|
|
44001
|
+
const result = {
|
|
44002
|
+
type: "tool-result",
|
|
44003
|
+
id: part.id,
|
|
44004
|
+
name: part.name,
|
|
44005
|
+
providerExecuted: part.executed,
|
|
44006
|
+
providerMetadata: toolReuse ? metadata(part.providerResultState ?? part.providerState) : sameProvider ? metadata(part.providerResultState) : undefined,
|
|
44007
|
+
result: state.status === "error" ? { error: state.error, content: toolContent } : single?.type === "text" ? { type: "text", value: single.text } : { type: "content", value: toolContent },
|
|
44008
|
+
...state.status === "error" ? { resultType: "error" } : {}
|
|
44009
|
+
};
|
|
44010
|
+
if (part.executed === true)
|
|
44011
|
+
content.push(result);
|
|
44012
|
+
else
|
|
44013
|
+
results.push({ role: "tool", content: [result] });
|
|
44014
|
+
}
|
|
44015
|
+
return [...content.length ? [make("assistant", content)] : [], ...results];
|
|
44016
|
+
}
|
|
44017
|
+
|
|
44018
|
+
// src/v2/hidden-completion.ts
|
|
44019
|
+
function meter(system, prompt, text) {
|
|
44020
|
+
return {
|
|
44021
|
+
input: estimateTokens(system) + estimateTokens(prompt),
|
|
44022
|
+
output: estimateTokens(text),
|
|
44023
|
+
cacheRead: 0,
|
|
44024
|
+
cacheWrite: 0
|
|
44025
|
+
};
|
|
44026
|
+
}
|
|
44027
|
+
async function createV2HiddenCompletionExecutor(host, currentModel) {
|
|
44028
|
+
const runs = new WeakMap;
|
|
44029
|
+
const pending = new Map;
|
|
44030
|
+
const modelKey = (model) => `${model.providerID}/${model.modelID}`;
|
|
44031
|
+
const requireModel = async (sessionID) => {
|
|
44032
|
+
const model = sessionID ? await currentModel(sessionID) : null;
|
|
44033
|
+
if (!model)
|
|
44034
|
+
throw new HiddenCompletionRefusal("hidden_model_unsupported", "Hidden completion requires an existing session with a resolved current model", true);
|
|
44035
|
+
return model;
|
|
44036
|
+
};
|
|
44037
|
+
const refuseModel = (requested, actual, terminal = false) => {
|
|
44038
|
+
throw new HiddenCompletionRefusal("hidden_model_unsupported", `Hidden completion model ${requested} is unavailable on opencode2; use the session model ${actual} in historian.model or dreaming task model configuration, or unset the configured model`, terminal);
|
|
44039
|
+
};
|
|
44040
|
+
await host.hook("generate", async (draft) => {
|
|
44041
|
+
const last = draft.messages.at(-1);
|
|
44042
|
+
if (last?.role !== "user" || last.content.length !== 1)
|
|
44043
|
+
return;
|
|
44044
|
+
const part = last.content[0];
|
|
44045
|
+
if (part?.type !== "text" || typeof part.text !== "string")
|
|
44046
|
+
return;
|
|
44047
|
+
const attempt = pending.get(part.text);
|
|
44048
|
+
if (!attempt || draft.sessionID !== attempt.run.identity.parentSessionId)
|
|
44049
|
+
return;
|
|
44050
|
+
const actual = `${draft.model.providerID}/${draft.model.id}`;
|
|
44051
|
+
if (modelKey(attempt.model) !== actual)
|
|
44052
|
+
refuseModel(modelKey(attempt.model), actual);
|
|
44053
|
+
if (attempt.request.signal?.aborted)
|
|
44054
|
+
throw new Error("Hidden completion prompt aborted");
|
|
44055
|
+
const body = attempt.request.body;
|
|
44056
|
+
if (typeof body.variant === "string" && body.variant !== draft.model.variant) {
|
|
44057
|
+
refuseModel(`${actual} (${body.variant})`, `${actual} (${draft.model.variant ?? "default variant"})`);
|
|
44058
|
+
}
|
|
44059
|
+
const parts = body.parts;
|
|
44060
|
+
if (!Array.isArray(parts) || parts.some((item) => item.type !== "text" || typeof item.text !== "string")) {
|
|
44061
|
+
throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Hidden completion accepts text-only calibrated prompts", true);
|
|
44062
|
+
}
|
|
44063
|
+
draft.system = [
|
|
44064
|
+
{
|
|
44065
|
+
type: "text",
|
|
44066
|
+
text: typeof body.system === "string" ? body.system : attempt.run.identity.system
|
|
44067
|
+
}
|
|
44068
|
+
];
|
|
44069
|
+
draft.messages = [
|
|
44070
|
+
{ role: "user", content: parts.map((item) => ({ type: "text", text: item.text })) }
|
|
44071
|
+
];
|
|
44072
|
+
draft.tools = {};
|
|
44073
|
+
if (attempt.run.identity.maxOutputTokens !== undefined)
|
|
44074
|
+
draft.options.maxOutputTokens = attempt.run.identity.maxOutputTokens;
|
|
44075
|
+
attempt.shaped = true;
|
|
44076
|
+
});
|
|
44077
|
+
return {
|
|
44078
|
+
capabilities: { tools: false, harness: "opencode2" },
|
|
44079
|
+
async open(identity) {
|
|
44080
|
+
const model = await requireModel(identity.parentSessionId);
|
|
44081
|
+
const configured = (identity.configuredModels ?? (identity.model ? [identity.model] : [])).map(toModelEntry).filter((entry) => entry !== undefined);
|
|
44082
|
+
if (configured.length && !configured.some((entry) => entry.model === modelKey(model))) {
|
|
44083
|
+
refuseModel(configured.map((entry) => entry.model).join(", "), modelKey(model), true);
|
|
44084
|
+
}
|
|
44085
|
+
const handle = { id: `mc:hidden:${crypto.randomUUID()}` };
|
|
44086
|
+
runs.set(handle, { identity });
|
|
44087
|
+
return handle;
|
|
44088
|
+
},
|
|
44089
|
+
async attempt(handle, request) {
|
|
44090
|
+
const run = runs.get(handle);
|
|
44091
|
+
if (!run)
|
|
44092
|
+
throw new Error("Unknown hidden completion run");
|
|
44093
|
+
const sessionID = run.identity.parentSessionId;
|
|
44094
|
+
const actual = await requireModel(sessionID);
|
|
44095
|
+
if (sessionID === undefined)
|
|
44096
|
+
throw new Error("Hidden completion session id missing");
|
|
44097
|
+
const requested = request.body.model ?? actual;
|
|
44098
|
+
if (modelKey(requested) !== modelKey(actual))
|
|
44099
|
+
refuseModel(modelKey(requested), modelKey(actual));
|
|
44100
|
+
if (request.signal?.aborted)
|
|
44101
|
+
throw new Error("Hidden completion prompt aborted");
|
|
44102
|
+
const marker = `${handle.id}:${crypto.randomUUID()}`;
|
|
44103
|
+
const state = { run, request, model: actual, shaped: false };
|
|
44104
|
+
pending.set(marker, state);
|
|
44105
|
+
try {
|
|
44106
|
+
const generation = host.generate({ sessionID, prompt: marker }, { signal: request.signal });
|
|
44107
|
+
const result = await new Promise((resolve, reject) => {
|
|
44108
|
+
const abort = () => reject(new Error("Hidden completion prompt aborted"));
|
|
44109
|
+
request.signal?.addEventListener("abort", abort, { once: true });
|
|
44110
|
+
generation.then(resolve, reject).finally(() => {
|
|
44111
|
+
request.signal?.removeEventListener("abort", abort);
|
|
44112
|
+
pending.delete(marker);
|
|
44113
|
+
});
|
|
44114
|
+
if (request.signal?.aborted)
|
|
44115
|
+
abort();
|
|
44116
|
+
});
|
|
44117
|
+
if (!state.shaped)
|
|
44118
|
+
throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", "Host did not dispatch the hidden generate hook", true);
|
|
44119
|
+
const prompt = request.body.parts.map((part) => part.text).join(`
|
|
44120
|
+
`);
|
|
44121
|
+
const system = typeof request.body.system === "string" ? request.body.system : run.identity.system;
|
|
44122
|
+
const usage = meter(system, prompt, result.text);
|
|
44123
|
+
usage.input += run.usage?.input ?? 0;
|
|
44124
|
+
usage.output += run.usage?.output ?? 0;
|
|
44125
|
+
run.usage = usage;
|
|
44126
|
+
run.completion = {
|
|
44127
|
+
text: result.text,
|
|
44128
|
+
usage,
|
|
44129
|
+
lengthCapped: false,
|
|
44130
|
+
providerId: actual.providerID,
|
|
44131
|
+
modelId: actual.modelID
|
|
44132
|
+
};
|
|
44133
|
+
} finally {
|
|
44134
|
+
if (!request.signal?.aborted)
|
|
44135
|
+
pending.delete(marker);
|
|
44136
|
+
}
|
|
44137
|
+
},
|
|
44138
|
+
async collect(handle) {
|
|
44139
|
+
const completion = runs.get(handle)?.completion;
|
|
44140
|
+
if (!completion)
|
|
44141
|
+
throw new Error("Hidden completion has no settled output");
|
|
44142
|
+
return completion;
|
|
44143
|
+
},
|
|
44144
|
+
async close() {}
|
|
44145
|
+
};
|
|
44146
|
+
}
|
|
44147
|
+
|
|
44148
|
+
// src/v2/store-reader.ts
|
|
44149
|
+
import { join as join11 } from "node:path";
|
|
44150
|
+
function sourceDatabaseFilename(channel, env = process.env) {
|
|
44151
|
+
return env.OPENCODE_DB ?? (["latest", "dev", "beta", "next", "prod"].includes(channel) || env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true" ? "opencode.db" : `opencode-${channel.replace(/[^a-zA-Z0-9._-]/g, "")}.db`);
|
|
44152
|
+
}
|
|
44153
|
+
function gaDatabasePath(dataHome, channel = "latest", env = process.env) {
|
|
44154
|
+
const filename = sourceDatabaseFilename(channel, env);
|
|
44155
|
+
return filename === ":memory:" ? filename : join11(dataHome, "opencode", filename);
|
|
44156
|
+
}
|
|
44157
|
+
function decode(row) {
|
|
44158
|
+
const data = JSON.parse(row.data);
|
|
44159
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
44160
|
+
throw new Error(`Invalid session_message data at seq ${row.seq}`);
|
|
44161
|
+
}
|
|
44162
|
+
if (row.type === "idle" && !["succeeded", "failed", "interrupted"].includes(String(data.outcome))) {
|
|
44163
|
+
throw new Error(`Invalid idle outcome at seq ${row.seq}`);
|
|
44164
|
+
}
|
|
44165
|
+
return { ...row, data };
|
|
44166
|
+
}
|
|
44167
|
+
|
|
44168
|
+
class V2StoreReader {
|
|
44169
|
+
db;
|
|
44170
|
+
constructor(path) {
|
|
44171
|
+
this.db = new Database(path, { readonly: true, fileMustExist: true });
|
|
44172
|
+
}
|
|
44173
|
+
close() {
|
|
44174
|
+
this.db.close();
|
|
44175
|
+
}
|
|
44176
|
+
page(sessionID, options = {}) {
|
|
44177
|
+
const limit = options.limit ?? 100;
|
|
44178
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
|
|
44179
|
+
throw new Error("Invalid page limit");
|
|
44180
|
+
const after = options.after ?? -1;
|
|
44181
|
+
if (!Number.isSafeInteger(after))
|
|
44182
|
+
throw new Error("Invalid seq cursor");
|
|
44183
|
+
const rows = this.db.prepare(`SELECT id, session_id, type, seq, data FROM session_message
|
|
44184
|
+
WHERE session_id = ? AND seq > ? ${options.type ? "AND type = ?" : ""}
|
|
44185
|
+
ORDER BY seq ASC LIMIT ?`).all(...options.type ? [sessionID, after, options.type, limit] : [sessionID, after, limit]).map(decode);
|
|
44186
|
+
return { rows, cursor: rows.at(-1)?.seq };
|
|
44187
|
+
}
|
|
44188
|
+
latestCompaction(sessionID) {
|
|
44189
|
+
const row = this.db.prepare(`SELECT id, session_id, type, seq, data FROM session_message
|
|
44190
|
+
WHERE session_id = ? AND type = 'compaction' AND json_extract(data, '$.status') = 'completed'
|
|
44191
|
+
ORDER BY seq DESC LIMIT 1`).get(sessionID);
|
|
44192
|
+
return row ? decode(row) : undefined;
|
|
44193
|
+
}
|
|
44194
|
+
idleRows(sessionID, after = -1) {
|
|
44195
|
+
return this.all(sessionID, after, "idle");
|
|
44196
|
+
}
|
|
44197
|
+
window(sessionID) {
|
|
44198
|
+
return this.db.transaction(() => {
|
|
44199
|
+
const cut = this.latestCompaction(sessionID);
|
|
44200
|
+
return this.all(sessionID, cut ? cut.seq - 1 : -1);
|
|
44201
|
+
})();
|
|
44202
|
+
}
|
|
44203
|
+
history(sessionID) {
|
|
44204
|
+
return this.all(sessionID, -1);
|
|
44205
|
+
}
|
|
44206
|
+
all(sessionID, after, type) {
|
|
44207
|
+
const rows = [];
|
|
44208
|
+
for (;; ) {
|
|
44209
|
+
const page = this.page(sessionID, { after, type });
|
|
44210
|
+
rows.push(...page.rows);
|
|
44211
|
+
if (page.rows.length < 100 || page.cursor === undefined)
|
|
44212
|
+
return rows;
|
|
44213
|
+
after = page.cursor;
|
|
44214
|
+
}
|
|
44215
|
+
}
|
|
44216
|
+
}
|
|
44217
|
+
|
|
44218
|
+
// src/v2/hooks/channel2.ts
|
|
44219
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
44220
|
+
async function deliverSynthetic(context, sessionID, text) {
|
|
44221
|
+
const id = `msg_${randomBytes2(12).toString("hex")}`;
|
|
44222
|
+
await context.storage.set(`synthetic/${sessionID}/${id}`, { id });
|
|
44223
|
+
await context.session.synthetic({ sessionID, id, text, delivery: "steer" });
|
|
44224
|
+
return id;
|
|
44225
|
+
}
|
|
44226
|
+
async function isAdmittedSynthetic(context, sessionID, id) {
|
|
44227
|
+
const record = await context.storage.get(`synthetic/${sessionID}/${id}`);
|
|
44228
|
+
return record !== null && typeof record === "object" && "id" in record && record.id === id;
|
|
44229
|
+
}
|
|
44230
|
+
async function deliverPendingChannel2(context, db, sessionID, baseline) {
|
|
44231
|
+
if (getChannel2NudgeState(db, sessionID) !== "pending")
|
|
44232
|
+
return;
|
|
44233
|
+
const evaluation = evaluateChannel2(baseline);
|
|
44234
|
+
if (!evaluation.evaluable || !evaluation.shouldTrigger)
|
|
44235
|
+
return;
|
|
44236
|
+
const token = randomBytes2(16).toString("hex");
|
|
44237
|
+
if (!claimChannel2NudgeState(db, sessionID, token))
|
|
44238
|
+
return;
|
|
44239
|
+
try {
|
|
44240
|
+
await deliverSynthetic(context, sessionID, buildChannel2Reminder(evaluation.reclaimableTokens, reclaimableToolOutputCount(baseline?.baselineParts ?? [])));
|
|
44241
|
+
} catch (error) {
|
|
44242
|
+
casChannel2NudgeClaim(db, sessionID, "pending", token);
|
|
44243
|
+
throw error;
|
|
44244
|
+
}
|
|
44245
|
+
casChannel2NudgeClaim(db, sessionID, "delivered", token);
|
|
44246
|
+
}
|
|
44247
|
+
|
|
44248
|
+
// src/v2/hooks/dream-trigger.ts
|
|
44249
|
+
function startDreamTrigger(context, args) {
|
|
44250
|
+
const controller = new AbortController;
|
|
44251
|
+
const done = (async () => {
|
|
44252
|
+
try {
|
|
44253
|
+
for await (const value of context.event.subscribe({ signal: controller.signal })) {
|
|
44254
|
+
if (controller.signal.aborted)
|
|
44255
|
+
break;
|
|
44256
|
+
const event = value;
|
|
44257
|
+
if (event.type !== "session.execution.succeeded" || !event.data?.sessionID)
|
|
44258
|
+
continue;
|
|
44259
|
+
const db = openDatabase();
|
|
44260
|
+
if (!db)
|
|
44261
|
+
continue;
|
|
44262
|
+
try {
|
|
44263
|
+
await runDueTasksForProject({
|
|
44264
|
+
db,
|
|
44265
|
+
projectIdentity: args.projectIdentity(),
|
|
44266
|
+
tasks: buildDreamTaskRuntimeConfigs2(args.config, "opencode", args.language, args.mural?.model),
|
|
44267
|
+
executor: createDreamTaskExecutor({
|
|
44268
|
+
hiddenCompletionExecutor: args.executor,
|
|
44269
|
+
parentSessionId: event.data.sessionID,
|
|
44270
|
+
sessionDirectory: context.location.directory,
|
|
44271
|
+
openOpenCodeDb: () => null,
|
|
44272
|
+
language: args.language,
|
|
44273
|
+
mural: args.mural
|
|
44274
|
+
})
|
|
44275
|
+
});
|
|
44276
|
+
} catch (error) {
|
|
44277
|
+
console.warn("[magic-context] v2 dream scheduling failed", error);
|
|
44278
|
+
}
|
|
44279
|
+
}
|
|
44280
|
+
} catch (error) {
|
|
44281
|
+
if (!controller.signal.aborted)
|
|
44282
|
+
console.warn("[magic-context] v2 dream event subscription failed", error);
|
|
44283
|
+
}
|
|
44284
|
+
})();
|
|
44285
|
+
return {
|
|
44286
|
+
async dispose() {
|
|
44287
|
+
controller.abort();
|
|
44288
|
+
await done;
|
|
44289
|
+
}
|
|
44290
|
+
};
|
|
44291
|
+
}
|
|
44292
|
+
|
|
44293
|
+
// src/v2/hooks/payload.ts
|
|
44294
|
+
var HEAD_IDS = ["__magic_context_v2_m0__", "__magic_context_v2_m1__"];
|
|
44295
|
+
function adaptPayload(draft, admittedIDs = new Set) {
|
|
44296
|
+
const existingHeads = new Map(draft.messages.filter((m) => HEAD_IDS.some((id) => m.id === id)).map((m) => [m.id, m]));
|
|
44297
|
+
const source = draft.messages.filter((m) => !existingHeads.has(m.id));
|
|
44298
|
+
const results = new Map;
|
|
44299
|
+
for (const message of source) {
|
|
44300
|
+
for (const part of message.content) {
|
|
44301
|
+
if (part.type === "tool-result" && typeof part.id === "string") {
|
|
44302
|
+
const queue = results.get(part.id) ?? [];
|
|
44303
|
+
queue.push({ part, message });
|
|
44304
|
+
results.set(part.id, queue);
|
|
44305
|
+
}
|
|
44306
|
+
}
|
|
44307
|
+
}
|
|
44308
|
+
const paired = new Set;
|
|
44309
|
+
const bridges = new Map;
|
|
44310
|
+
const originals = new Map;
|
|
44311
|
+
const nativeTool = (call, result) => {
|
|
44312
|
+
const value = result?.part.result?.value;
|
|
44313
|
+
const output = typeof value === "string" ? value : value === undefined ? "" : JSON.stringify(value);
|
|
44314
|
+
const part = {
|
|
44315
|
+
type: "tool",
|
|
44316
|
+
callID: call?.id ?? result?.part.id,
|
|
44317
|
+
tool: call?.name ?? result?.part.name,
|
|
44318
|
+
state: {
|
|
44319
|
+
input: structuredClone(call?.input ?? {}),
|
|
44320
|
+
status: result ? "completed" : "running",
|
|
44321
|
+
...result ? { output } : {}
|
|
44322
|
+
}
|
|
44323
|
+
};
|
|
44324
|
+
bridges.set(part, { call, result: result?.part, resultMessage: result?.message, output });
|
|
44325
|
+
if (result)
|
|
44326
|
+
paired.add(result.part);
|
|
44327
|
+
return part;
|
|
44328
|
+
};
|
|
44329
|
+
const callParts = new Map;
|
|
44330
|
+
for (const message of source) {
|
|
44331
|
+
for (const part of message.content) {
|
|
44332
|
+
if (part.type === "tool-call")
|
|
44333
|
+
callParts.set(part, nativeTool(part, results.get(String(part.id))?.shift()));
|
|
44334
|
+
}
|
|
44335
|
+
}
|
|
44336
|
+
const messages = [];
|
|
44337
|
+
for (const message of source) {
|
|
44338
|
+
const parts = [];
|
|
44339
|
+
for (const content of message.content) {
|
|
44340
|
+
if (paired.has(content))
|
|
44341
|
+
continue;
|
|
44342
|
+
const part = callParts.get(content) ?? (content.type === "tool-result" ? nativeTool(undefined, { part: content, message }) : structuredClone(content));
|
|
44343
|
+
if (message.id && admittedIDs.has(message.id))
|
|
44344
|
+
part.synthetic = true;
|
|
44345
|
+
parts.push(part);
|
|
44346
|
+
}
|
|
44347
|
+
if (!parts.length && message.content.length)
|
|
44348
|
+
continue;
|
|
44349
|
+
const mapped = {
|
|
44350
|
+
info: {
|
|
44351
|
+
id: message.id,
|
|
44352
|
+
sessionID: draft.sessionID,
|
|
44353
|
+
role: message.role,
|
|
44354
|
+
...{
|
|
44355
|
+
providerID: draft.model.providerID,
|
|
44356
|
+
modelID: draft.model.id,
|
|
44357
|
+
agent: draft.agent,
|
|
44358
|
+
tools: draft.tools
|
|
44359
|
+
}
|
|
44360
|
+
},
|
|
44361
|
+
parts
|
|
44362
|
+
};
|
|
44363
|
+
originals.set(mapped, message);
|
|
44364
|
+
messages.push(mapped);
|
|
44365
|
+
}
|
|
44366
|
+
return {
|
|
44367
|
+
messages,
|
|
44368
|
+
commit() {
|
|
44369
|
+
let head = 0;
|
|
44370
|
+
const rendered = [];
|
|
44371
|
+
for (const message of messages) {
|
|
44372
|
+
const original = originals.get(message);
|
|
44373
|
+
const id = message.info.syntheticHead ? HEAD_IDS[head++] : original?.id;
|
|
44374
|
+
const content = [];
|
|
44375
|
+
const following = [];
|
|
44376
|
+
for (const candidate of message.parts) {
|
|
44377
|
+
const part = candidate;
|
|
44378
|
+
const bridge = bridges.get(part);
|
|
44379
|
+
if (!bridge) {
|
|
44380
|
+
const { synthetic: _synthetic, ...clean } = part;
|
|
44381
|
+
content.push(clean);
|
|
44382
|
+
continue;
|
|
44383
|
+
}
|
|
44384
|
+
const state = part.state;
|
|
44385
|
+
if (bridge.call)
|
|
44386
|
+
content.push({ ...bridge.call, input: state.input });
|
|
44387
|
+
if (bridge.result && bridge.resultMessage) {
|
|
44388
|
+
const result = {
|
|
44389
|
+
...bridge.result,
|
|
44390
|
+
result: state.output === bridge.output ? bridge.result.result : { type: "text", value: state.output }
|
|
44391
|
+
};
|
|
44392
|
+
if (bridge.resultMessage === original)
|
|
44393
|
+
content.push(result);
|
|
44394
|
+
else
|
|
44395
|
+
following.push({ ...bridge.resultMessage, content: [result] });
|
|
44396
|
+
}
|
|
44397
|
+
}
|
|
44398
|
+
if (content.length || !original?.content.length) {
|
|
44399
|
+
const value = {
|
|
44400
|
+
...original,
|
|
44401
|
+
id,
|
|
44402
|
+
role: message.info.role ?? "user",
|
|
44403
|
+
content
|
|
44404
|
+
};
|
|
44405
|
+
const existing = id ? existingHeads.get(id) : undefined;
|
|
44406
|
+
rendered.push(existing ? Object.assign(existing, { content }) : value);
|
|
44407
|
+
}
|
|
44408
|
+
rendered.push(...following);
|
|
44409
|
+
}
|
|
44410
|
+
draft.messages.splice(0, draft.messages.length, ...rendered);
|
|
44411
|
+
}
|
|
44412
|
+
};
|
|
44413
|
+
}
|
|
44414
|
+
|
|
44415
|
+
// src/v2/hooks/refusal.ts
|
|
44416
|
+
class V2ContextRefusal extends Error {
|
|
44417
|
+
constructor(message = "Context full — /ctx-flush or /clear to continue.", options) {
|
|
44418
|
+
super(message, options);
|
|
44419
|
+
this.name = "V2ContextRefusal";
|
|
44420
|
+
}
|
|
44421
|
+
}
|
|
44422
|
+
async function interruptBeforeProvider(session, sessionID) {
|
|
44423
|
+
let timer;
|
|
44424
|
+
try {
|
|
44425
|
+
const result = await Promise.race([
|
|
44426
|
+
session.interrupt({ sessionID }),
|
|
44427
|
+
new Promise((_, reject) => {
|
|
44428
|
+
timer = setTimeout(() => reject(new Error("interrupt exceeded 2000 ms")), 2000);
|
|
44429
|
+
})
|
|
44430
|
+
]);
|
|
44431
|
+
if (result.interrupted !== true)
|
|
44432
|
+
throw new Error("interrupt arrived after the turn became idle");
|
|
44433
|
+
} catch (cause) {
|
|
44434
|
+
throw new V2ContextRefusal(undefined, { cause });
|
|
44435
|
+
} finally {
|
|
44436
|
+
clearTimeout(timer);
|
|
44437
|
+
}
|
|
44438
|
+
}
|
|
44439
|
+
|
|
44440
|
+
// src/v2/hooks/store.ts
|
|
44441
|
+
var isRawRow = (row) => ["user", "synthetic", "assistant", "skill", "shell", "system"].includes(row.type);
|
|
44442
|
+
function rawMessages(rows, history = rows) {
|
|
44443
|
+
const ordinals = new Map(history.filter(isRawRow).map((row, index) => [row.id, index + 1]));
|
|
44444
|
+
return rows.filter(isRawRow).map((row) => ({
|
|
44445
|
+
id: row.id,
|
|
44446
|
+
ordinal: ordinals.get(row.id),
|
|
44447
|
+
role: row.type === "assistant" ? "assistant" : "user",
|
|
44448
|
+
createdAt: row.data.time?.created,
|
|
44449
|
+
parts: row.type === "assistant" ? (row.data.content ?? []).map((part) => {
|
|
44450
|
+
if (part.type !== "tool")
|
|
44451
|
+
return { ...part };
|
|
44452
|
+
const state = part.state;
|
|
44453
|
+
const content = state.content;
|
|
44454
|
+
return {
|
|
44455
|
+
type: "tool",
|
|
44456
|
+
tool: part.name,
|
|
44457
|
+
callID: part.id,
|
|
44458
|
+
state: {
|
|
44459
|
+
...state,
|
|
44460
|
+
output: content?.filter((p) => p.type === "text").map((p) => p.text).join(`
|
|
44461
|
+
`) ?? ""
|
|
44462
|
+
}
|
|
44463
|
+
};
|
|
44464
|
+
}) : [{ type: "text", text: row.data.text ?? "" }]
|
|
44465
|
+
}));
|
|
44466
|
+
}
|
|
44467
|
+
|
|
44468
|
+
// src/v2/hooks/context.ts
|
|
44469
|
+
function createHostSeams(context, read, liveModels) {
|
|
44470
|
+
return {
|
|
44471
|
+
hostRawMessages: read,
|
|
44472
|
+
hostProtectedTailBoundary: (args) => resolveOpenCodeProtectedTailBoundary({
|
|
44473
|
+
...args,
|
|
44474
|
+
cacheNamespace: `opencode2:${args.sessionId}`
|
|
44475
|
+
}),
|
|
44476
|
+
hostModelFallback: (sessionID) => liveModels.get(sessionID) ?? null,
|
|
44477
|
+
hostRefuse: (_client, sessionID) => interruptBeforeProvider(context.session, sessionID)
|
|
44478
|
+
};
|
|
44479
|
+
}
|
|
44480
|
+
async function registerContext(context) {
|
|
44481
|
+
const directory = context.location.directory;
|
|
44482
|
+
const config = loadPluginConfigDetailed(directory).config;
|
|
44483
|
+
if (!config.enabled || !isCompactionEnabled(config))
|
|
44484
|
+
return;
|
|
44485
|
+
const folds = new FoldOwner(context.storage);
|
|
44486
|
+
const limits = new Map;
|
|
44487
|
+
const queriedModels = new Set;
|
|
44488
|
+
const liveModels = new Map;
|
|
44489
|
+
const hostGenerate = context.session.generate?.bind(context.session);
|
|
44490
|
+
const hiddenCompletionExecutor = hostGenerate ? await createV2HiddenCompletionExecutor({
|
|
44491
|
+
hook: (name, callback) => context.session.hook(name, callback),
|
|
44492
|
+
generate: (input, options) => hostGenerate(input, options)
|
|
44493
|
+
}, (sessionID) => liveModels.get(sessionID) ?? null) : undefined;
|
|
44494
|
+
const dreamTrigger = hiddenCompletionExecutor && config.dreamer && !config.dreamer.disable ? startDreamTrigger(context, {
|
|
44495
|
+
config: config.dreamer,
|
|
44496
|
+
executor: hiddenCompletionExecutor,
|
|
44497
|
+
projectIdentity: () => resolveProjectIdentity(directory) ?? directory,
|
|
44498
|
+
language: config.language,
|
|
44499
|
+
mural: config.mural
|
|
44500
|
+
}) : undefined;
|
|
44501
|
+
const historianModels = resolveHistorianModel2(config, "opencode");
|
|
44502
|
+
const usage = new Map;
|
|
44503
|
+
const channel1 = new Map;
|
|
44504
|
+
const variants = new Map;
|
|
44505
|
+
const agents = new Map;
|
|
44506
|
+
const historyRefreshSessions = new Set;
|
|
44507
|
+
const pendingMaterializationSessions = new Set;
|
|
44508
|
+
const lastHeuristicsTurnId = new Map;
|
|
44509
|
+
const rawProviders = new Map;
|
|
44510
|
+
let passDuties;
|
|
44511
|
+
let toolDuties;
|
|
44512
|
+
await context.tool.hook("execute.before", (draft) => assertExecutableToolInput(draft.input));
|
|
44513
|
+
await context.tool.hook("execute.after", async (draft) => {
|
|
44514
|
+
if (!db || draft.status !== "completed")
|
|
44515
|
+
return;
|
|
44516
|
+
try {
|
|
44517
|
+
toolDuties ??= createToolExecuteAfterHook({ db, channel1StateBySession: channel1 });
|
|
44518
|
+
const content = draft.result?.content;
|
|
44519
|
+
const text = typeof content === "string" ? content : Array.isArray(content) ? content.filter((part) => part.type === "text").map((part) => part.text).join(`
|
|
44520
|
+
`) : "";
|
|
44521
|
+
const output = { output: text };
|
|
44522
|
+
await toolDuties({ ...draft, args: draft.input }, output);
|
|
44523
|
+
if (draft.result && output.output !== text) {
|
|
44524
|
+
if (typeof content === "string")
|
|
44525
|
+
draft.result.content = output.output;
|
|
44526
|
+
else if (Array.isArray(content) && output.output.startsWith(text))
|
|
44527
|
+
content.push({ type: "text", text: output.output.slice(text.length) });
|
|
44528
|
+
}
|
|
44529
|
+
const baseline = channel1.get(draft.sessionID);
|
|
44530
|
+
await deliverPendingChannel2(context, db, draft.sessionID, baseline);
|
|
44531
|
+
} catch (error) {
|
|
44532
|
+
console.warn("[magic-context] v2 Channel 2 delivery deferred", error);
|
|
44533
|
+
}
|
|
44534
|
+
});
|
|
44535
|
+
const read = (sessionID) => {
|
|
44536
|
+
const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
|
|
44537
|
+
try {
|
|
44538
|
+
return rawMessages(reader.history(sessionID));
|
|
44539
|
+
} finally {
|
|
44540
|
+
reader.close();
|
|
44541
|
+
}
|
|
44542
|
+
};
|
|
44543
|
+
const pagedRead = Object.assign(read, {
|
|
44544
|
+
readPage: (sessionID, after, limit, watermark) => read(sessionID).filter((m) => m.ordinal > after && m.ordinal <= watermark).slice(0, limit),
|
|
44545
|
+
getCount: (sessionID) => read(sessionID).length
|
|
44546
|
+
});
|
|
44547
|
+
let transform;
|
|
44548
|
+
let db;
|
|
44549
|
+
const refuseIfUnsafe = async (draft) => {
|
|
44550
|
+
let unsafe = false;
|
|
44551
|
+
try {
|
|
44552
|
+
db ??= openDatabase();
|
|
44553
|
+
if (!db || !isDatabasePersisted(db))
|
|
44554
|
+
throw new Error("context storage is not durable");
|
|
44555
|
+
getOrCreateSessionMeta2(db, draft.sessionID);
|
|
44556
|
+
const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
|
|
44557
|
+
try {
|
|
44558
|
+
const latest = reader.history(draft.sessionID).filter((row) => row.type === "assistant").at(-1);
|
|
44559
|
+
const tokens = latest?.data.tokens;
|
|
44560
|
+
const modelKey = `${draft.model.providerID}/${draft.model.id}`;
|
|
44561
|
+
if (!queriedModels.has(modelKey)) {
|
|
44562
|
+
const catalog = await context.catalog.model.list({
|
|
44563
|
+
location: context.location
|
|
44564
|
+
});
|
|
44565
|
+
for (const model of catalog.data)
|
|
44566
|
+
limits.set(`${model.providerID}/${model.id}`, model.limit.context);
|
|
44567
|
+
queriedModels.add(modelKey);
|
|
44568
|
+
}
|
|
44569
|
+
const limit = limits.get(modelKey);
|
|
44570
|
+
if (tokens && limit && Number.isFinite(limit) && limit > 0) {
|
|
44571
|
+
const inputTokens = tokens.input + tokens.cache.read + tokens.cache.write;
|
|
44572
|
+
unsafe = inputTokens / limit >= 0.95;
|
|
44573
|
+
const completed = latest?.data.time?.completed;
|
|
44574
|
+
if (typeof completed === "number")
|
|
44575
|
+
updateSessionMeta2(db, draft.sessionID, { lastResponseTime: completed });
|
|
44576
|
+
usage.set(draft.sessionID, {
|
|
44577
|
+
usage: { inputTokens, percentage: inputTokens / limit * 100 },
|
|
44578
|
+
hasUsageTokens: true,
|
|
44579
|
+
updatedAt: Date.now()
|
|
44580
|
+
});
|
|
44581
|
+
}
|
|
44582
|
+
} finally {
|
|
44583
|
+
reader.close();
|
|
44584
|
+
}
|
|
44585
|
+
} catch {
|
|
44586
|
+
unsafe = true;
|
|
44587
|
+
}
|
|
44588
|
+
if (unsafe)
|
|
44589
|
+
await interruptBeforeProvider(context.session, draft.sessionID);
|
|
44590
|
+
return unsafe;
|
|
44591
|
+
};
|
|
44592
|
+
const materialize = (draft) => {
|
|
44593
|
+
db ??= openDatabase();
|
|
44594
|
+
if (!db || !isDatabasePersisted(db))
|
|
44595
|
+
throw new Error("context storage is not durable");
|
|
44596
|
+
const state = getOrCreateSessionMeta2(db, draft.sessionID);
|
|
44597
|
+
return materializeM0({
|
|
44598
|
+
db,
|
|
44599
|
+
sessionId: draft.sessionID,
|
|
44600
|
+
state,
|
|
44601
|
+
projectPath: resolveProjectIdentity(directory) ?? directory,
|
|
44602
|
+
projectDirectory: directory,
|
|
44603
|
+
memoryEnabled: config.memory.enabled,
|
|
44604
|
+
memoryInjectionBudgetTokens: config.memory.injection_budget_tokens,
|
|
44605
|
+
hardSignals: {
|
|
44606
|
+
systemHash: foldDigest(JSON.stringify(draft.system)),
|
|
44607
|
+
toolSetHash: "",
|
|
44608
|
+
modelKey: `${draft.model.providerID}/${draft.model.id}`,
|
|
44609
|
+
cacheExpired: false,
|
|
44610
|
+
lastResponseTime: state.lastResponseTime
|
|
44611
|
+
}
|
|
44612
|
+
}).m0Text;
|
|
44613
|
+
};
|
|
44614
|
+
await context.session.hook("compaction", async (draft) => {
|
|
44615
|
+
const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
|
|
44616
|
+
try {
|
|
44617
|
+
const rows = reader.history(draft.sessionID);
|
|
44618
|
+
const ids = new Set(draft.messages.map((message) => message.id));
|
|
44619
|
+
const watermark = Math.max(-1, ...rows.filter((row) => ids.has(row.id)).map((row) => row.seq));
|
|
44620
|
+
const running = rows.filter((row) => row.type === "compaction" && row.data.status === "running").at(-1);
|
|
44621
|
+
const fold = await folds.supply({
|
|
44622
|
+
sessionID: draft.sessionID,
|
|
44623
|
+
watermark,
|
|
44624
|
+
runningCut: running?.seq,
|
|
44625
|
+
materialize: () => materialize(draft)
|
|
44626
|
+
});
|
|
44627
|
+
draft.result = { summary: fold.submitted };
|
|
44628
|
+
} catch (cause) {
|
|
44629
|
+
await interruptBeforeProvider(context.session, draft.sessionID);
|
|
44630
|
+
throw new V2ContextRefusal("Magic Context could not preserve the host checkpoint.", {
|
|
44631
|
+
cause
|
|
44632
|
+
});
|
|
44633
|
+
} finally {
|
|
44634
|
+
reader.close();
|
|
44635
|
+
}
|
|
44636
|
+
});
|
|
44637
|
+
await context.session.hook("context", async (draft) => {
|
|
44638
|
+
let postFold = false;
|
|
44639
|
+
try {
|
|
44640
|
+
if (await refuseIfUnsafe(draft))
|
|
44641
|
+
return;
|
|
44642
|
+
if (!db)
|
|
44643
|
+
return;
|
|
44644
|
+
const storage = db;
|
|
44645
|
+
updateSessionMeta2(db, draft.sessionID, {
|
|
44646
|
+
systemPromptHash: foldDigest(JSON.stringify(draft.system))
|
|
44647
|
+
});
|
|
44648
|
+
await preloadTokenizer();
|
|
44649
|
+
passDuties ??= createChatMessageHook({
|
|
44650
|
+
db,
|
|
44651
|
+
liveModelBySession: liveModels,
|
|
44652
|
+
variantBySession: variants,
|
|
44653
|
+
agentBySession: agents,
|
|
44654
|
+
historyRefreshSessions,
|
|
44655
|
+
pendingMaterializationSessions,
|
|
44656
|
+
lastHeuristicsTurnId,
|
|
44657
|
+
systemPromptRefreshSessions: new Set,
|
|
44658
|
+
cacheTtlConfig: config.cache_ttl,
|
|
44659
|
+
upgradeReminder: (sessionID) => maybeSendUpgradeReminder({
|
|
44660
|
+
db: storage,
|
|
44661
|
+
client: undefined,
|
|
44662
|
+
getNotificationParams: () => ({}),
|
|
44663
|
+
sendStatusNotification: async (_client, id, text) => {
|
|
44664
|
+
pushNotification2("toast", { message: text, variant: "info" }, id);
|
|
44665
|
+
return "queued";
|
|
44666
|
+
}
|
|
44667
|
+
}, sessionID)
|
|
44668
|
+
});
|
|
44669
|
+
await passDuties({
|
|
44670
|
+
sessionID: draft.sessionID,
|
|
44671
|
+
agent: draft.agent,
|
|
44672
|
+
variant: draft.model.variant,
|
|
44673
|
+
model: { providerID: draft.model.providerID, modelID: draft.model.id }
|
|
44674
|
+
});
|
|
44675
|
+
if (!rawProviders.has(draft.sessionID))
|
|
44676
|
+
rawProviders.set(draft.sessionID, setRawMessageProvider(draft.sessionID, {
|
|
44677
|
+
readMessages: () => read(draft.sessionID)
|
|
44678
|
+
}));
|
|
44679
|
+
transform ??= createTransform({
|
|
44680
|
+
db,
|
|
44681
|
+
tagger: createTagger(),
|
|
44682
|
+
scheduler: createScheduler({
|
|
44683
|
+
executeThresholdPercentage: config.execute_threshold_percentage
|
|
44684
|
+
}),
|
|
44685
|
+
contextUsageMap: usage,
|
|
44686
|
+
protectedTokens: config.protected_tokens,
|
|
44687
|
+
protectedTokenTierOverrides: getProtectedTokensTierOverrides(config),
|
|
44688
|
+
executeThresholdPercentage: config.execute_threshold_percentage,
|
|
44689
|
+
liveModelBySession: liveModels,
|
|
44690
|
+
channel1StateBySession: channel1,
|
|
44691
|
+
historyRefreshSessions,
|
|
44692
|
+
pendingMaterializationSessions,
|
|
44693
|
+
lastHeuristicsTurnId,
|
|
44694
|
+
variantBySession: variants,
|
|
44695
|
+
clearReasoningAge: config.clear_reasoning_age,
|
|
44696
|
+
directory,
|
|
44697
|
+
projectPath: directory,
|
|
44698
|
+
hiddenCompletionExecutor,
|
|
44699
|
+
historianRunnable: hiddenCompletionExecutor !== undefined && config.historian?.disable !== true,
|
|
44700
|
+
historianModel: historianModels.primary,
|
|
44701
|
+
fallbackModels: historianModels.fallbacks,
|
|
44702
|
+
historianTimeoutMs: config.historian_timeout_ms,
|
|
44703
|
+
historianMaxOutputTokens: config.historian?.maxTokens,
|
|
44704
|
+
historianTwoPass: config.historian?.two_pass,
|
|
44705
|
+
compactionMarkerStrategy: v2CompactionMarkerStrategy,
|
|
44706
|
+
memoryConfig: {
|
|
44707
|
+
enabled: config.memory.enabled,
|
|
44708
|
+
injectionBudgetTokens: config.memory.injection_budget_tokens,
|
|
44709
|
+
autoPromote: config.memory.auto_promote
|
|
44710
|
+
},
|
|
44711
|
+
...createHostSeams(context, pagedRead, liveModels)
|
|
44712
|
+
});
|
|
44713
|
+
const admitted = new Set;
|
|
44714
|
+
for (const message of draft.messages) {
|
|
44715
|
+
if (message.id && await isAdmittedSynthetic(context, draft.sessionID, message.id))
|
|
44716
|
+
admitted.add(message.id);
|
|
44717
|
+
}
|
|
44718
|
+
const reader = new V2StoreReader(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
|
|
44719
|
+
let checkpoint;
|
|
44720
|
+
let submitted;
|
|
44721
|
+
try {
|
|
44722
|
+
const cut = reader.latestCompaction(draft.sessionID);
|
|
44723
|
+
const incoming = cut && draft.messages.find((message) => message.id === cut.id);
|
|
44724
|
+
postFold = cut !== undefined;
|
|
44725
|
+
if (cut && !incoming)
|
|
44726
|
+
throw new Error("The host checkpoint disappeared from the context draft");
|
|
44727
|
+
if (cut && incoming) {
|
|
44728
|
+
const identity = await folds.observe({
|
|
44729
|
+
sessionID: draft.sessionID,
|
|
44730
|
+
cutSeq: cut.seq,
|
|
44731
|
+
summary: cut.data.summary ?? "",
|
|
44732
|
+
rendered: incoming,
|
|
44733
|
+
onHard: (reason) => {
|
|
44734
|
+
console.warn(`[magic-context] HARD reason=${reason} session=${draft.sessionID}`);
|
|
44735
|
+
materialize(draft);
|
|
44736
|
+
pendingMaterializationSessions.add(draft.sessionID);
|
|
44737
|
+
}
|
|
44738
|
+
});
|
|
44739
|
+
checkpoint = structuredClone(identity.rendered ?? incoming);
|
|
44740
|
+
submitted = identity.rendered ? identity.renderedSummary ?? identity.submitted : cut.data.summary ?? "";
|
|
44741
|
+
const all = reader.history(draft.sessionID);
|
|
44742
|
+
const boundaryID = db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id = ?").get(draft.sessionID)?.id;
|
|
44743
|
+
const boundary = all.find((row) => row.id === boundaryID)?.seq ?? -1;
|
|
44744
|
+
const present = new Set(draft.messages.map((message) => message.id));
|
|
44745
|
+
const restored = all.filter((row) => row.seq > boundary && row.seq <= cut.seq && !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model));
|
|
44746
|
+
draft.messages.splice(0, draft.messages.length, ...restored, ...draft.messages.filter((message) => message !== incoming));
|
|
44747
|
+
}
|
|
44748
|
+
} finally {
|
|
44749
|
+
reader.close();
|
|
44750
|
+
}
|
|
44751
|
+
const mapped = adaptPayload(draft, admitted);
|
|
44752
|
+
await transform({}, mapped);
|
|
44753
|
+
mapped.commit();
|
|
44754
|
+
if (checkpoint && submitted !== undefined) {
|
|
44755
|
+
const head = draft.messages.find((message) => message.id === HEAD_IDS[0]);
|
|
44756
|
+
const baseline = head?.content.find((part) => part.type === "text")?.text;
|
|
44757
|
+
if (typeof baseline === "string") {
|
|
44758
|
+
for (const part of checkpoint.content)
|
|
44759
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
44760
|
+
part.text = part.text.replace(`<summary>
|
|
44761
|
+
${submitted}
|
|
44762
|
+
</summary>`, `<summary>
|
|
44763
|
+
${baseline}
|
|
44764
|
+
</summary>`);
|
|
44765
|
+
}
|
|
44766
|
+
const volatile = draft.messages.find((message) => message.id === HEAD_IDS[1]);
|
|
44767
|
+
if (volatile && head)
|
|
44768
|
+
volatile.content.push(...head.content.filter((part) => part.type !== "text"));
|
|
44769
|
+
draft.messages.splice(0, draft.messages.length, checkpoint, ...draft.messages.filter((message) => message !== head));
|
|
44770
|
+
}
|
|
44771
|
+
}
|
|
44772
|
+
} catch (error) {
|
|
44773
|
+
if (error instanceof V2ContextRefusal)
|
|
44774
|
+
throw error;
|
|
44775
|
+
if (postFold) {
|
|
44776
|
+
await interruptBeforeProvider(context.session, draft.sessionID);
|
|
44777
|
+
throw new V2ContextRefusal("Magic Context could not restore the unarchived host history.", { cause: error });
|
|
44778
|
+
}
|
|
44779
|
+
console.warn("[magic-context] v2 context unavailable", error);
|
|
44780
|
+
}
|
|
44781
|
+
});
|
|
44782
|
+
return {
|
|
44783
|
+
async dispose() {
|
|
44784
|
+
await dreamTrigger?.dispose();
|
|
44785
|
+
for (const release of rawProviders.values())
|
|
44786
|
+
release();
|
|
44787
|
+
rawProviders.clear();
|
|
44788
|
+
}
|
|
44789
|
+
};
|
|
44790
|
+
}
|
|
44791
|
+
|
|
44792
|
+
// src/v2/hooks/update-check.ts
|
|
44793
|
+
import { existsSync as existsSync13, readFileSync as readFileSync7 } from "node:fs";
|
|
44794
|
+
import { dirname as dirname8, join as join12 } from "node:path";
|
|
44795
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
44796
|
+
function packageInfo() {
|
|
44797
|
+
let directory = dirname8(fileURLToPath3(import.meta.url));
|
|
44798
|
+
for (;; ) {
|
|
44799
|
+
try {
|
|
44800
|
+
const pkg = JSON.parse(readFileSync7(join12(directory, "package.json"), "utf8"));
|
|
44801
|
+
if (pkg.name === "@cortexkit/opencode-magic-context" && typeof pkg.version === "string") {
|
|
44802
|
+
return {
|
|
44803
|
+
version: pkg.version,
|
|
44804
|
+
development: existsSync13(join12(directory, "src/v2/server.ts"))
|
|
44805
|
+
};
|
|
44806
|
+
}
|
|
44807
|
+
} catch {}
|
|
44808
|
+
const parent = dirname8(directory);
|
|
44809
|
+
if (parent === directory)
|
|
44810
|
+
throw new Error("Magic Context package manifest is unavailable");
|
|
44811
|
+
directory = parent;
|
|
44812
|
+
}
|
|
44813
|
+
}
|
|
44814
|
+
function startUpdateChecks(context, check = (signal) => {
|
|
44815
|
+
return packageInfo().development ? Promise.resolve(null) : getLatestVersion("latest", { signal });
|
|
44816
|
+
}) {
|
|
44817
|
+
const controller = new AbortController;
|
|
44818
|
+
const done = (async () => {
|
|
44819
|
+
try {
|
|
44820
|
+
for await (const _event of context.event.subscribe({ signal: controller.signal })) {
|
|
44821
|
+
if (controller.signal.aborted)
|
|
44822
|
+
break;
|
|
44823
|
+
const last = await context.storage.get("version-check-at");
|
|
44824
|
+
if (typeof last === "number" && Date.now() - last < 60 * 60 * 1000)
|
|
44825
|
+
continue;
|
|
44826
|
+
await context.storage.set("version-check-at", Date.now());
|
|
44827
|
+
const latest = await check(controller.signal);
|
|
44828
|
+
const comparison = latest ? compareSemverCore(latest, packageInfo().version) : null;
|
|
44829
|
+
if (!controller.signal.aborted && comparison !== null && comparison > 0) {
|
|
44830
|
+
pushNotification2("toast", {
|
|
44831
|
+
message: `Magic Context ${latest} is available. Update the plugin to install it.`,
|
|
44832
|
+
variant: "info"
|
|
44833
|
+
});
|
|
44834
|
+
}
|
|
44835
|
+
}
|
|
44836
|
+
} catch (error) {
|
|
44837
|
+
if (!controller.signal.aborted)
|
|
44838
|
+
console.warn("[magic-context] v2 update check unavailable", error);
|
|
44839
|
+
}
|
|
44840
|
+
})();
|
|
44841
|
+
return {
|
|
44842
|
+
done,
|
|
44843
|
+
async dispose() {
|
|
44844
|
+
controller.abort();
|
|
44845
|
+
await done;
|
|
44846
|
+
}
|
|
44847
|
+
};
|
|
44848
|
+
}
|
|
44849
|
+
|
|
44850
|
+
// src/v2/server.ts
|
|
44851
|
+
async function setup(context) {
|
|
44852
|
+
setHarness("opencode2");
|
|
44853
|
+
const duties = await registerContext(context);
|
|
44854
|
+
const checks = loadPluginConfigDetailed(context.location.directory).config.auto_update === false ? undefined : startUpdateChecks(context);
|
|
44855
|
+
console.info("[magic-context] @cortexkit/opencode-magic-context v2 setup");
|
|
44856
|
+
return async () => {
|
|
44857
|
+
await checks?.dispose();
|
|
44858
|
+
await duties?.dispose();
|
|
44859
|
+
};
|
|
44860
|
+
}
|
|
44861
|
+
|
|
43386
44862
|
// src/index.ts
|
|
43387
44863
|
var BOOT_SERVER_DEADLINE_MS = 15000;
|
|
43388
44864
|
var RESOLVED_CONFIG_TIMEOUT_MS = 2000;
|
|
@@ -43435,7 +44911,7 @@ var server = async (ctx) => {
|
|
|
43435
44911
|
if (hasBannerEntries)
|
|
43436
44912
|
setTimeout(async () => {
|
|
43437
44913
|
try {
|
|
43438
|
-
const { sendStatusNotification } = await import("./send-session-notification-
|
|
44914
|
+
const { sendStatusNotification } = await import("./send-session-notification-xnypkxpx.js");
|
|
43439
44915
|
const clientWithSessions = ctx.client;
|
|
43440
44916
|
const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
|
|
43441
44917
|
const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
|
|
@@ -43452,7 +44928,7 @@ var server = async (ctx) => {
|
|
|
43452
44928
|
log(`[magic-context] opencode_db_missing path=${openCodeDbResolution.path} source=${openCodeDbResolution.source}`);
|
|
43453
44929
|
setTimeout(async () => {
|
|
43454
44930
|
try {
|
|
43455
|
-
const { sendStatusNotification } = await import("./send-session-notification-
|
|
44931
|
+
const { sendStatusNotification } = await import("./send-session-notification-xnypkxpx.js");
|
|
43456
44932
|
const clientWithSessions = ctx.client;
|
|
43457
44933
|
const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
|
|
43458
44934
|
const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
|
|
@@ -43484,9 +44960,9 @@ var server = async (ctx) => {
|
|
|
43484
44960
|
}
|
|
43485
44961
|
conflictMs = performance.now() - conflictStartedAt;
|
|
43486
44962
|
const liveSessionState = createLiveSessionState();
|
|
43487
|
-
const rustModeModuleTransport = pluginConfig.transform_mode === "rust" ? new SubcModuleTransport(pluginConfig.subc?.connection_file) : undefined;
|
|
44963
|
+
const rustModeModuleTransport = pluginConfig.transform_mode === "rust" ? new SubcModuleTransport(pluginConfig.subc?.connection_file ?? getDefaultSubcConnectionFile()) : undefined;
|
|
43488
44964
|
const rustModeModuleClient = rustModeModuleTransport;
|
|
43489
|
-
const sessionCleanupModuleClient = pluginConfig.enabled ? rustModeModuleTransport ?? new SubcModuleTransport(pluginConfig.subc?.connection_file) : undefined;
|
|
44965
|
+
const sessionCleanupModuleClient = pluginConfig.enabled ? rustModeModuleTransport ?? new SubcModuleTransport(pluginConfig.subc?.connection_file ?? getDefaultSubcConnectionFile()) : undefined;
|
|
43490
44966
|
const hooksPhase = await runBootPhaseWithinBudget(bootBudget, "hooks", () => createSessionHooksAsync({
|
|
43491
44967
|
ctx,
|
|
43492
44968
|
pluginConfig,
|
|
@@ -43698,12 +45174,12 @@ var server = async (ctx) => {
|
|
|
43698
45174
|
{
|
|
43699
45175
|
const fence = getSchemaFenceRejection();
|
|
43700
45176
|
if (fence) {
|
|
43701
|
-
import("./conflict-warning-hook-
|
|
45177
|
+
import("./conflict-warning-hook-jyj54gbe.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
|
|
43702
45178
|
}
|
|
43703
45179
|
}
|
|
43704
45180
|
const serverUrl = ctx.serverUrl;
|
|
43705
45181
|
const serverUrlStr = serverUrl instanceof URL ? serverUrl.toString().replace(/\/$/, "") : typeof serverUrl === "string" ? serverUrl.replace(/\/$/, "") : undefined;
|
|
43706
|
-
import("./send-session-notification-
|
|
45182
|
+
import("./send-session-notification-xnypkxpx.js").then(({ setNotificationServerUrl }) => {
|
|
43707
45183
|
setNotificationServerUrl(serverUrlStr);
|
|
43708
45184
|
});
|
|
43709
45185
|
if (conflictResult?.hasConflict) {
|
|
@@ -43717,7 +45193,7 @@ var server = async (ctx) => {
|
|
|
43717
45193
|
}
|
|
43718
45194
|
if (pluginConfig.enabled && !conflictResult?.hasConflict) {
|
|
43719
45195
|
setTimeout(() => {
|
|
43720
|
-
import("./announcement-
|
|
45196
|
+
import("./announcement-8mgn61fw.js").then(({
|
|
43721
45197
|
shouldShowAnnouncement,
|
|
43722
45198
|
ANNOUNCEMENT_VERSION,
|
|
43723
45199
|
ANNOUNCEMENT_FEATURES,
|
|
@@ -43726,7 +45202,7 @@ var server = async (ctx) => {
|
|
|
43726
45202
|
}) => {
|
|
43727
45203
|
if (!shouldShowAnnouncement())
|
|
43728
45204
|
return;
|
|
43729
|
-
return import("./conflict-warning-hook-
|
|
45205
|
+
return import("./conflict-warning-hook-jyj54gbe.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, markAnnouncementSeen));
|
|
43730
45206
|
}).catch(() => {});
|
|
43731
45207
|
}, 8000);
|
|
43732
45208
|
}
|
|
@@ -43882,7 +45358,8 @@ var server = async (ctx) => {
|
|
|
43882
45358
|
};
|
|
43883
45359
|
var plugin = {
|
|
43884
45360
|
id: "opencode-magic-context",
|
|
43885
|
-
server
|
|
45361
|
+
server,
|
|
45362
|
+
setup
|
|
43886
45363
|
};
|
|
43887
45364
|
var src_default = plugin;
|
|
43888
45365
|
export {
|