@cortexkit/opencode-magic-context 0.41.4 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -3
- package/dist/agents/hidden-agent-registrations.d.ts +1 -3
- package/dist/agents/hidden-agent-registrations.d.ts.map +1 -1
- package/dist/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/agents/permissions.d.ts +1 -22
- package/dist/agents/permissions.d.ts.map +1 -1
- package/dist/config/agent-disable.d.ts +0 -5
- package/dist/config/agent-disable.d.ts.map +1 -1
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/migrate-config-location.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +17 -0
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/removed-agent-config.d.ts +8 -0
- package/dist/config/removed-agent-config.d.ts.map +1 -0
- package/dist/config/schema/magic-context.d.ts +23 -201
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-ejkc9sjn.js → conflict-warning-hook-6p3xqeac.js} +3 -3
- package/dist/{derive-budgets-bc366cz8.js → derive-budgets-s2pgnnm4.js} +1 -1
- package/dist/features/builtin-commands/commands.d.ts +0 -4
- package/dist/features/builtin-commands/commands.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +7 -0
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-storage.d.ts.map +1 -1
- package/dist/features/magic-context/context-authority.d.ts +31 -4
- package/dist/features/magic-context/context-authority.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/open-opencode-db.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts +19 -9
- package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts +4 -0
- package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/sweep-coordinator.d.ts.map +1 -1
- package/dist/features/magic-context/index.d.ts +0 -1
- package/dist/features/magic-context/index.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-local.d.ts +13 -0
- package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding-synapse.d.ts +43 -10
- package/dist/features/magic-context/memory/embedding-synapse.d.ts.map +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts +1 -1
- package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
- package/dist/features/magic-context/memory/memory-migration.d.ts.map +1 -1
- package/dist/features/magic-context/memory/project-identity.d.ts +1 -0
- package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
- package/dist/features/magic-context/memory/promotion.d.ts +7 -1
- package/dist/features/magic-context/memory/promotion.d.ts.map +1 -1
- package/dist/features/magic-context/merged-reasoning-decisions.d.ts +6 -0
- package/dist/features/magic-context/merged-reasoning-decisions.d.ts.map +1 -0
- package/dist/features/magic-context/message-fts-rowid-map.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +12 -0
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-trigger.d.ts +6 -0
- package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
- package/dist/features/magic-context/no-content-compartment.d.ts +12 -0
- package/dist/features/magic-context/no-content-compartment.d.ts.map +1 -0
- package/dist/features/magic-context/pi-content-decisions.d.ts +9 -0
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -0
- package/dist/features/magic-context/project-docs-hash.d.ts +4 -0
- package/dist/features/magic-context/project-docs-hash.d.ts.map +1 -1
- package/dist/features/magic-context/project-embedding-registry.d.ts +13 -4
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/protection-window.d.ts +79 -0
- package/dist/features/magic-context/protection-window.d.ts.map +1 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-project-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/shadow-backfill-state.d.ts +26 -0
- package/dist/features/magic-context/shadow-backfill-state.d.ts.map +1 -0
- package/dist/features/magic-context/smart-notes/compiler.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts +4 -0
- package/dist/features/magic-context/smart-notes/sandbox-runner.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-embedding-measurements.d.ts +2 -2
- package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts +4 -0
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts +1 -0
- package/dist/features/magic-context/storage-memory-mutation-log.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +79 -13
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-native-replay.d.ts +29 -0
- package/dist/features/magic-context/storage-native-replay.d.ts.map +1 -0
- package/dist/features/magic-context/storage-notes.d.ts +6 -0
- package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
- package/dist/features/magic-context/storage-replay-document.d.ts +33 -0
- package/dist/features/magic-context/storage-replay-document.d.ts.map +1 -0
- package/dist/features/magic-context/storage-subagent-invocations.d.ts +1 -1
- package/dist/features/magic-context/storage-subagent-invocations.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +19 -11
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +3 -3
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +13 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/tool-owner-backfill.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
- package/dist/features/magic-context/user-memory/storage-user-memory.d.ts.map +1 -1
- package/dist/features/magic-context/workspaces.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +11 -5
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts +9 -1
- package/dist/hooks/magic-context/cache-busting-signals.d.ts.map +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts +1 -1
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
- package/dist/hooks/magic-context/child-session-spawn.d.ts +3 -3
- package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +1 -10
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts +10 -21
- package/dist/hooks/magic-context/compartment-runner-drop-queue.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +26 -2
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
- package/dist/hooks/magic-context/decay-render.d.ts.map +1 -1
- package/dist/hooks/magic-context/dropped-input-guard.d.ts +9 -0
- package/dist/hooks/magic-context/dropped-input-guard.d.ts.map +1 -0
- package/dist/hooks/magic-context/emergency-drop.d.ts +6 -1
- package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +0 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-payloads.d.ts +7 -6
- package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/format-embed-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts +7 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts +3 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +13 -4
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts +14 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/live-session-state.d.ts +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +34 -0
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-state-sync-timing.d.ts +21 -0
- package/dist/hooks/magic-context/module-state-sync-timing.d.ts.map +1 -0
- package/dist/hooks/magic-context/module-state-sync.d.ts +21 -7
- package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-transport.d.ts +12 -0
- package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
- package/dist/hooks/magic-context/module-wire.d.ts +8 -0
- package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
- package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
- package/dist/hooks/magic-context/persist-filtered-noise.d.ts +5 -0
- package/dist/hooks/magic-context/persist-filtered-noise.d.ts.map +1 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts +6 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +18 -18
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +22 -12
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +8 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +10 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/reference-retrieval.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +74 -9
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/send-session-notification.d.ts +11 -10
- package/dist/hooks/magic-context/send-session-notification.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +7 -0
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/supersession-reclaim.d.ts +13 -0
- package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +2 -3
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +8 -3
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-context-state.d.ts +7 -1
- package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +11 -4
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +7 -2
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/upgrade-reminder.d.ts +7 -9
- package/dist/hooks/magic-context/upgrade-reminder.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/index-1974jvn3.js +783 -0
- package/dist/{index-4avmwfp5.js → index-36wd1d6k.js} +6 -29
- package/dist/{index-0y2mcg5y.js → index-c9hamh36.js} +18332 -16226
- package/dist/{index-fz104x1j.js → index-jmtjh2d3.js} +3 -3
- package/dist/{index-q264erdp.js → index-nqgjwfzn.js} +70 -38
- package/dist/{index-mjv9je4e.js → index-xdtge3y2.js} +45 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6199 -5088
- package/dist/plugin/conflict-warning-hook.d.ts +5 -6
- package/dist/plugin/conflict-warning-hook.d.ts.map +1 -1
- package/dist/plugin/dream-timer.d.ts +1 -0
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/embedding-routing.d.ts +4 -1
- package/dist/plugin/embedding-routing.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +16 -2
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts +31 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/rust-tool-backends.d.ts +1 -0
- package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/{recomp-orchestrator-q98r6rga.js → recomp-orchestrator-3atsasjy.js} +5 -5
- package/dist/{send-session-notification-hdh02wy9.js → send-session-notification-1qeqkswb.js} +6 -4
- package/dist/shared/child-session-teardown.d.ts +34 -0
- package/dist/shared/child-session-teardown.d.ts.map +1 -0
- package/dist/shared/keep-subagents.d.ts +1 -1
- package/dist/shared/keep-subagents.d.ts.map +1 -1
- package/dist/shared/model-suggestion-retry.d.ts +1 -1
- package/dist/shared/opencode-db-path.d.ts +24 -0
- package/dist/shared/opencode-db-path.d.ts.map +1 -0
- package/dist/shared/prompt-surface-runtime.d.ts +10 -5
- package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
- package/dist/shared/resolve-fallbacks.d.ts +1 -1
- package/dist/shared/rpc-types.d.ts +111 -0
- package/dist/shared/rpc-types.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +42 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/status-detail-text.d.ts.map +1 -1
- package/dist/shared/subagent-runner.d.ts +17 -10
- package/dist/shared/subagent-runner.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/shared/transcript.d.ts +6 -0
- package/dist/shared/transcript.d.ts.map +1 -1
- package/dist/shared/window-geometry.d.ts +23 -0
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/dist/shared/write-transaction-timing.d.ts +1 -1
- package/dist/shared/write-transaction-timing.d.ts.map +1 -1
- package/dist/{storage-meta-session-dvwfw778.js → storage-meta-session-e6g0mmec.js} +2 -2
- package/dist/tools/ctx-memory/tools.d.ts.map +1 -1
- package/dist/tools/ctx-memory/verification-recording.d.ts.map +1 -1
- package/dist/tools/ctx-note/constants.d.ts +1 -1
- package/dist/tools/ctx-note/constants.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/types.d.ts +1 -0
- package/dist/tools/ctx-note/types.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +10 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/constants.d.ts +1 -1
- package/dist/tools/ctx-search/constants.d.ts.map +1 -1
- package/dist/tools/light-descriptions.d.ts +2 -2
- package/dist/tools/light-descriptions.d.ts.map +1 -1
- package/package.json +2 -3
- package/src/agents/hidden-agent-registrations.ts +3 -15
- package/src/agents/magic-context-prompt.test.ts +7 -5
- package/src/agents/magic-context-prompt.ts +22 -30
- package/src/agents/permissions.test.ts +1 -42
- package/src/agents/permissions.ts +1 -24
- package/src/config/agent-disable.ts +5 -22
- package/src/config/index.test.ts +126 -15
- package/src/config/index.ts +41 -6
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/migrate-config-location.test.ts +39 -6
- package/src/config/migrate-config-location.ts +18 -31
- package/src/config/profiles.ts +1 -1
- package/src/config/project-security.hostile-matrix.test.ts +0 -8
- package/src/config/project-security.test.ts +11 -22
- package/src/config/project-security.ts +103 -9
- package/src/config/protected-tokens.test.ts +235 -0
- package/src/config/removed-agent-config.ts +45 -0
- package/src/config/removed-agent-source-fence.test.ts +56 -0
- package/src/config/schema/magic-context.test.ts +21 -42
- package/src/config/schema/magic-context.ts +46 -37
- package/src/shared/child-session-teardown.test.ts +218 -0
- package/src/shared/child-session-teardown.ts +66 -0
- package/src/shared/keep-subagents.ts +9 -14
- package/src/shared/model-suggestion-retry.ts +1 -1
- package/src/shared/opencode-db-path.test.ts +196 -0
- package/src/shared/opencode-db-path.ts +215 -0
- package/src/shared/prompt-surface-a1-golden.md +50 -35
- package/src/shared/prompt-surface-runtime.test.ts +28 -0
- package/src/shared/prompt-surface-runtime.ts +22 -5
- package/src/shared/resolve-fallbacks.ts +1 -1
- package/src/shared/rpc-types.ts +118 -0
- package/src/shared/session-messages-bounded.test.ts +1 -1
- package/src/shared/sqlite-import-fence.test.ts +19 -0
- package/src/shared/sqlite.test.ts +27 -1
- package/src/shared/sqlite.ts +204 -1
- package/src/shared/status-detail-text.test.ts +6 -3
- package/src/shared/status-detail-text.ts +15 -0
- package/src/shared/subagent-runner.ts +17 -10
- package/src/shared/tag-transcript.ts +33 -21
- package/src/shared/transcript.ts +7 -0
- package/src/shared/window-geometry.test.ts +44 -0
- package/src/shared/window-geometry.ts +89 -11
- package/src/shared/write-transaction-attribution.test.ts +241 -0
- package/src/shared/write-transaction-timing.ts +2 -1
- package/src/tui/index.tsx +3 -3
- package/src/tui/slots/sidebar-content.tsx +12 -7
- package/src/tui-compiled/index.tsx +3 -3
- package/src/tui-compiled/slots/sidebar-content.tsx +301 -305
- package/dist/agents/sidekick.d.ts +0 -2
- package/dist/agents/sidekick.d.ts.map +0 -1
- package/dist/features/magic-context/defaults.d.ts +0 -2
- package/dist/features/magic-context/defaults.d.ts.map +0 -1
- package/dist/features/magic-context/sidekick/agent.d.ts +0 -14
- package/dist/features/magic-context/sidekick/agent.d.ts.map +0 -1
- package/dist/features/magic-context/sidekick/core.d.ts +0 -38
- package/dist/features/magic-context/sidekick/core.d.ts.map +0 -1
- package/dist/features/magic-context/sidekick/index.d.ts +0 -3
- package/dist/features/magic-context/sidekick/index.d.ts.map +0 -1
- package/dist/hooks/magic-context/boundary-execution.d.ts +0 -27
- package/dist/hooks/magic-context/boundary-execution.d.ts.map +0 -1
- package/dist/index-raatkvw5.js +0 -360
- package/src/agents/sidekick.ts +0 -1
- package/src/features/magic-context/defaults.ts +0 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { shouldKeepSubagents } from "./keep-subagents";
|
|
2
|
+
|
|
3
|
+
interface ChildSessionRequest {
|
|
4
|
+
path: { id: string };
|
|
5
|
+
query?: { directory: string };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface ArchiveChildSessionRequest extends ChildSessionRequest {
|
|
9
|
+
body: { time: { archived: number } };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ChildSessionTeardownClient {
|
|
13
|
+
session: {
|
|
14
|
+
delete(request: ChildSessionRequest): Promise<unknown>;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TeardownChildSessionArgs {
|
|
19
|
+
client: ChildSessionTeardownClient;
|
|
20
|
+
sessionId: string | null;
|
|
21
|
+
sessionDirectory?: string;
|
|
22
|
+
promptSettled: boolean;
|
|
23
|
+
privacySensitive: boolean;
|
|
24
|
+
context: string;
|
|
25
|
+
log: (message: string) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Retire a child only after its prompt helper resolves. An unresolved client call
|
|
30
|
+
* can leave OpenCode's server loop writing, so that row is archived for immediate
|
|
31
|
+
* UI hiding and retained until the age-gated sweep can delete it safely.
|
|
32
|
+
*
|
|
33
|
+
* OpenCode's generated v2 SDK models archival as `session.update` with
|
|
34
|
+
* `time.archived`; the plugin's legacy path/body client reaches the same PATCH
|
|
35
|
+
* endpoint, although its generated TypeScript body type does not yet expose time.
|
|
36
|
+
*/
|
|
37
|
+
export async function teardownChildSession(args: TeardownChildSessionArgs): Promise<void> {
|
|
38
|
+
const { client, sessionId, sessionDirectory, promptSettled, privacySensitive, context, log } =
|
|
39
|
+
args;
|
|
40
|
+
if (!sessionId) return;
|
|
41
|
+
|
|
42
|
+
const request: ChildSessionRequest = {
|
|
43
|
+
path: { id: sessionId },
|
|
44
|
+
...(sessionDirectory ? { query: { directory: sessionDirectory } } : {}),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (promptSettled && (privacySensitive || !shouldKeepSubagents())) {
|
|
48
|
+
await client.session.delete(request).catch((error: unknown) => {
|
|
49
|
+
log(`${context}: session cleanup failed: ${String(error)}`);
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!promptSettled) {
|
|
55
|
+
const archiveSession = client.session as unknown as {
|
|
56
|
+
update?: (request: ArchiveChildSessionRequest) => Promise<unknown>;
|
|
57
|
+
};
|
|
58
|
+
await archiveSession
|
|
59
|
+
.update?.({
|
|
60
|
+
...request,
|
|
61
|
+
body: { time: { archived: Date.now() } },
|
|
62
|
+
})
|
|
63
|
+
.catch(() => {});
|
|
64
|
+
log(`${context}: prompt unsettled — session ${sessionId} left to the age-gated sweep`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Debug / data-collection switch
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Debug / data-collection switch for settled ordinary child sessions
|
|
3
|
+
* (historian and memory migration). Privacy-sensitive Dreamer and
|
|
4
|
+
* smart-note children are still deleted after their prompts settle.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* inspectable in OpenCode's session store / the dashboard. Intended for
|
|
10
|
-
* short-term data collection (e.g. profiling what the dreamer actually does)
|
|
11
|
-
* before the dreamer v2 overhaul, NOT for steady-state use — kept sessions
|
|
12
|
-
* accumulate in the host's session DB until manually cleared.
|
|
6
|
+
* Unsettled children are never deleted inline because OpenCode's server loop may
|
|
7
|
+
* still be writing after a client timeout or abort. They remain for the
|
|
8
|
+
* age-gated sweep; privacy-sensitive rows are swept even when this switch is on.
|
|
13
9
|
*
|
|
14
|
-
* Process-global, set once at boot from config (mirrors `harness.ts`). A
|
|
15
|
-
*
|
|
16
|
-
* per-call args — it's a coarse, boot-time debug toggle.
|
|
10
|
+
* Process-global, set once at boot from config (mirrors `harness.ts`). A config
|
|
11
|
+
* change requires a restart to take effect.
|
|
17
12
|
*/
|
|
18
13
|
let keepSubagents = false;
|
|
19
14
|
|
|
@@ -22,7 +17,7 @@ export function setKeepSubagents(value: boolean): void {
|
|
|
22
17
|
keepSubagents = value === true;
|
|
23
18
|
}
|
|
24
19
|
|
|
25
|
-
/** True when
|
|
20
|
+
/** True when settled ordinary child sessions should be retained. */
|
|
26
21
|
export function shouldKeepSubagents(): boolean {
|
|
27
22
|
return keepSubagents;
|
|
28
23
|
}
|
|
@@ -71,7 +71,7 @@ export interface PromptRetryOptions {
|
|
|
71
71
|
fallbackModels?: readonly ModelInput[];
|
|
72
72
|
/**
|
|
73
73
|
* Identifier for structured logging (e.g. "dreamer:consolidate",
|
|
74
|
-
* "historian", "compressor", "
|
|
74
|
+
* "historian", "compressor", "dreamer"). Helps correlate fallback
|
|
75
75
|
* attempts to a specific call site in `magic-context.log`. Defaults to
|
|
76
76
|
* "subagent" if not provided.
|
|
77
77
|
*/
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
2
|
+
|
|
3
|
+
import { afterEach, describe, expect, it } from "bun:test";
|
|
4
|
+
import { mkdirSync, mkdtempSync, rmSync, unlinkSync, utimesSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import {
|
|
8
|
+
formatOpenCodeDbDoctorLine,
|
|
9
|
+
formatOpenCodeDbMissingBanner,
|
|
10
|
+
formatOpenCodeDbMissingStatusLine,
|
|
11
|
+
openCodeDbPathExists,
|
|
12
|
+
resetOpenCodeDbPathStateForTesting,
|
|
13
|
+
resolveOpenCodeDbPath,
|
|
14
|
+
} from "./opencode-db-path";
|
|
15
|
+
|
|
16
|
+
const ORIGINAL_ENV = {
|
|
17
|
+
XDG_DATA_HOME: process.env.XDG_DATA_HOME,
|
|
18
|
+
OPENCODE_DB: process.env.OPENCODE_DB,
|
|
19
|
+
OPENCODE_DISABLE_CHANNEL_DB: process.env.OPENCODE_DISABLE_CHANNEL_DB,
|
|
20
|
+
OPENCODE_CHANNEL: process.env.OPENCODE_CHANNEL,
|
|
21
|
+
};
|
|
22
|
+
const tempDirs: string[] = [];
|
|
23
|
+
|
|
24
|
+
function restore(name: keyof typeof ORIGINAL_ENV): void {
|
|
25
|
+
const value = ORIGINAL_ENV[name];
|
|
26
|
+
if (value === undefined) delete process.env[name];
|
|
27
|
+
else process.env[name] = value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
restore("XDG_DATA_HOME");
|
|
32
|
+
restore("OPENCODE_DB");
|
|
33
|
+
restore("OPENCODE_DISABLE_CHANNEL_DB");
|
|
34
|
+
restore("OPENCODE_CHANNEL");
|
|
35
|
+
resetOpenCodeDbPathStateForTesting();
|
|
36
|
+
for (const directory of tempDirs.splice(0)) rmSync(directory, { recursive: true, force: true });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
function useDataHome(): { dataHome: string; openCodeDir: string } {
|
|
40
|
+
const dataHome = mkdtempSync(join(tmpdir(), "opencode-db-path-"));
|
|
41
|
+
const openCodeDir = join(dataHome, "opencode");
|
|
42
|
+
mkdirSync(openCodeDir, { recursive: true });
|
|
43
|
+
tempDirs.push(dataHome);
|
|
44
|
+
process.env.XDG_DATA_HOME = dataHome;
|
|
45
|
+
delete process.env.OPENCODE_DB;
|
|
46
|
+
delete process.env.OPENCODE_DISABLE_CHANNEL_DB;
|
|
47
|
+
delete process.env.OPENCODE_CHANNEL;
|
|
48
|
+
resetOpenCodeDbPathStateForTesting();
|
|
49
|
+
return { dataHome, openCodeDir };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function createCandidate(openCodeDir: string, name: string, mtimeMs: number): string {
|
|
53
|
+
const path = join(openCodeDir, name);
|
|
54
|
+
writeFileSync(path, "sqlite fixture");
|
|
55
|
+
const time = new Date(mtimeMs);
|
|
56
|
+
utimesSync(path, time, time);
|
|
57
|
+
return path;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe("resolveOpenCodeDbPath", () => {
|
|
61
|
+
it("honors absolute and relative OPENCODE_DB overrides before every other source", () => {
|
|
62
|
+
const { openCodeDir } = useDataHome();
|
|
63
|
+
const absolute = join(openCodeDir, "elsewhere.db");
|
|
64
|
+
process.env.OPENCODE_DB = absolute;
|
|
65
|
+
process.env.OPENCODE_DISABLE_CHANNEL_DB = "true";
|
|
66
|
+
process.env.OPENCODE_CHANNEL = "dev";
|
|
67
|
+
expect(resolveOpenCodeDbPath()).toEqual({
|
|
68
|
+
path: absolute,
|
|
69
|
+
source: "OPENCODE_DB",
|
|
70
|
+
channel: null,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
process.env.OPENCODE_DB = "relative.db";
|
|
74
|
+
expect(resolveOpenCodeDbPath()).toEqual({
|
|
75
|
+
path: join(openCodeDir, "relative.db"),
|
|
76
|
+
source: "OPENCODE_DB",
|
|
77
|
+
channel: null,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("treats OPENCODE_DB=:memory: as an explicit but absent store", () => {
|
|
82
|
+
useDataHome();
|
|
83
|
+
process.env.OPENCODE_DB = ":memory:";
|
|
84
|
+
const resolution = resolveOpenCodeDbPath();
|
|
85
|
+
expect(resolution).toEqual({ path: ":memory:", source: "OPENCODE_DB", channel: null });
|
|
86
|
+
expect(openCodeDbPathExists(resolution)).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("uses the default DB when channel databases are disabled", () => {
|
|
90
|
+
const { openCodeDir } = useDataHome();
|
|
91
|
+
process.env.OPENCODE_DISABLE_CHANNEL_DB = "1";
|
|
92
|
+
process.env.OPENCODE_CHANNEL = "dev";
|
|
93
|
+
expect(resolveOpenCodeDbPath()).toEqual({
|
|
94
|
+
path: join(openCodeDir, "opencode.db"),
|
|
95
|
+
source: "default",
|
|
96
|
+
channel: null,
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("honors an OPENCODE_CHANNEL visible to the plugin", () => {
|
|
101
|
+
const { openCodeDir } = useDataHome();
|
|
102
|
+
process.env.OPENCODE_CHANNEL = "dev";
|
|
103
|
+
expect(resolveOpenCodeDbPath()).toEqual({
|
|
104
|
+
path: join(openCodeDir, "opencode-dev.db"),
|
|
105
|
+
source: "channel",
|
|
106
|
+
channel: "dev",
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
for (const selectedName of [
|
|
111
|
+
"opencode.db",
|
|
112
|
+
"opencode-local.db",
|
|
113
|
+
"opencode-dev.db",
|
|
114
|
+
"opencode-nightly.db",
|
|
115
|
+
]) {
|
|
116
|
+
it(`discovers ${selectedName} when it is the newest existing candidate`, () => {
|
|
117
|
+
const { openCodeDir } = useDataHome();
|
|
118
|
+
const names = [
|
|
119
|
+
"opencode.db",
|
|
120
|
+
"opencode-local.db",
|
|
121
|
+
"opencode-dev.db",
|
|
122
|
+
"opencode-nightly.db",
|
|
123
|
+
];
|
|
124
|
+
for (const [index, name] of names.entries()) {
|
|
125
|
+
createCandidate(openCodeDir, name, name === selectedName ? 10_000 : 1_000 + index);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
expect(resolveOpenCodeDbPath()).toEqual({
|
|
129
|
+
path: join(openCodeDir, selectedName),
|
|
130
|
+
source: "discovered",
|
|
131
|
+
channel:
|
|
132
|
+
selectedName === "opencode.db"
|
|
133
|
+
? null
|
|
134
|
+
: selectedName.slice("opencode-".length, -".db".length),
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
it("uses candidate order as the deterministic tie-breaker for equal mtimes", () => {
|
|
140
|
+
const { openCodeDir } = useDataHome();
|
|
141
|
+
for (const name of ["opencode-local.db", "opencode-dev.db", "opencode.db"]) {
|
|
142
|
+
createCandidate(openCodeDir, name, 5_000);
|
|
143
|
+
}
|
|
144
|
+
expect(resolveOpenCodeDbPath()).toEqual({
|
|
145
|
+
path: join(openCodeDir, "opencode.db"),
|
|
146
|
+
source: "discovered",
|
|
147
|
+
channel: null,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("returns the default path by value when no candidate exists", () => {
|
|
152
|
+
const { openCodeDir } = useDataHome();
|
|
153
|
+
const resolution = resolveOpenCodeDbPath();
|
|
154
|
+
expect(resolution).toEqual({
|
|
155
|
+
path: join(openCodeDir, "opencode.db"),
|
|
156
|
+
source: "default",
|
|
157
|
+
channel: null,
|
|
158
|
+
});
|
|
159
|
+
expect(openCodeDbPathExists(resolution)).toBe(false);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("re-probes discovery when the memoized chosen file disappears", () => {
|
|
163
|
+
const { openCodeDir } = useDataHome();
|
|
164
|
+
const primary = createCandidate(openCodeDir, "opencode-local.db", 2_000);
|
|
165
|
+
const fallback = createCandidate(openCodeDir, "opencode.db", 1_000);
|
|
166
|
+
expect(resolveOpenCodeDbPath().path).toBe(primary);
|
|
167
|
+
|
|
168
|
+
unlinkSync(primary);
|
|
169
|
+
expect(resolveOpenCodeDbPath()).toEqual({
|
|
170
|
+
path: fallback,
|
|
171
|
+
source: "discovered",
|
|
172
|
+
channel: null,
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("formats the missing banner, status, and doctor lines by value", () => {
|
|
177
|
+
const { openCodeDir } = useDataHome();
|
|
178
|
+
const lookedFor = [
|
|
179
|
+
join(openCodeDir, "opencode.db"),
|
|
180
|
+
join(openCodeDir, "opencode-local.db"),
|
|
181
|
+
join(openCodeDir, "opencode-dev.db"),
|
|
182
|
+
join(openCodeDir, "opencode-<channel>.db"),
|
|
183
|
+
].join(", ");
|
|
184
|
+
const resolution = resolveOpenCodeDbPath();
|
|
185
|
+
|
|
186
|
+
expect(formatOpenCodeDbMissingBanner(resolution)).toBe(
|
|
187
|
+
`Magic Context cannot find OpenCode's session database (looked for ${lookedFor}). History compaction (historian) and the mid-turn valve are disabled until it is found; set OPENCODE_DB if OpenCode stores it elsewhere.`,
|
|
188
|
+
);
|
|
189
|
+
expect(formatOpenCodeDbMissingStatusLine(resolution)).toBe(
|
|
190
|
+
`OpenCode DB: MISSING (looked for ${lookedFor}). History compaction (historian) and the mid-turn valve are disabled; set OPENCODE_DB if OpenCode stores it elsewhere.`,
|
|
191
|
+
);
|
|
192
|
+
expect(formatOpenCodeDbDoctorLine(resolution)).toBe(
|
|
193
|
+
`FAIL OpenCode session database: not found (looked for ${lookedFor}); set OPENCODE_DB if OpenCode stores it elsewhere.`,
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { isAbsolute, join } from "node:path";
|
|
4
|
+
|
|
5
|
+
export type OpenCodeDbPathSource = "OPENCODE_DB" | "channel" | "default" | "discovered";
|
|
6
|
+
|
|
7
|
+
export interface OpenCodeDbPathResolution {
|
|
8
|
+
path: string;
|
|
9
|
+
source: OpenCodeDbPathSource;
|
|
10
|
+
channel: string | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface OpenCodeDbReadFailure extends OpenCodeDbPathResolution {
|
|
14
|
+
message: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface CachedResolution {
|
|
18
|
+
key: string;
|
|
19
|
+
resolution: OpenCodeDbPathResolution;
|
|
20
|
+
existed: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let cachedResolution: CachedResolution | null = null;
|
|
24
|
+
let lastReadFailure: OpenCodeDbReadFailure | null = null;
|
|
25
|
+
const claimedDiagnostics = new Set<string>();
|
|
26
|
+
|
|
27
|
+
function openCodeDataDir(): string {
|
|
28
|
+
return join(process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "opencode");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function environmentKey(dataDir: string): string {
|
|
32
|
+
return [
|
|
33
|
+
dataDir,
|
|
34
|
+
process.env.OPENCODE_DB ?? "",
|
|
35
|
+
process.env.OPENCODE_DISABLE_CHANNEL_DB ?? "",
|
|
36
|
+
process.env.OPENCODE_CHANNEL ?? "",
|
|
37
|
+
].join("\0");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function channelPath(dataDir: string, channel: string): string {
|
|
41
|
+
return ["latest", "beta", "prod"].includes(channel)
|
|
42
|
+
? join(dataDir, "opencode.db")
|
|
43
|
+
: join(dataDir, `opencode-${channel}.db`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function discoveredCandidateNames(dataDir: string): string[] {
|
|
47
|
+
const names = ["opencode.db", "opencode-local.db", "opencode-dev.db"];
|
|
48
|
+
try {
|
|
49
|
+
const discovered = readdirSync(dataDir, { withFileTypes: true })
|
|
50
|
+
.filter((entry) => /^opencode-.+\.db$/.test(entry.name) && !names.includes(entry.name))
|
|
51
|
+
.map((entry) => entry.name)
|
|
52
|
+
.sort();
|
|
53
|
+
names.push(...discovered);
|
|
54
|
+
} catch {
|
|
55
|
+
// A missing or unreadable data directory has no discovered candidates.
|
|
56
|
+
}
|
|
57
|
+
return names;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function discoverOpenCodeDb(dataDir: string): OpenCodeDbPathResolution {
|
|
61
|
+
const candidates = discoveredCandidateNames(dataDir).map((name, order) => {
|
|
62
|
+
const path = join(dataDir, name);
|
|
63
|
+
try {
|
|
64
|
+
const metadata = statSync(path);
|
|
65
|
+
return metadata.isFile() ? { path, order, mtimeMs: metadata.mtimeMs } : null;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
const existing = candidates
|
|
71
|
+
.filter((candidate): candidate is NonNullable<typeof candidate> => candidate !== null)
|
|
72
|
+
.sort((left, right) => right.mtimeMs - left.mtimeMs || left.order - right.order)[0];
|
|
73
|
+
|
|
74
|
+
if (!existing) {
|
|
75
|
+
return { path: join(dataDir, "opencode.db"), source: "default", channel: null };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const name = existing.path.slice(dataDir.length + 1);
|
|
79
|
+
const channel =
|
|
80
|
+
name === "opencode.db" ? null : name.slice("opencode-".length, -".db".length) || null;
|
|
81
|
+
return { path: existing.path, source: "discovered", channel };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function resolveFresh(dataDir: string): OpenCodeDbPathResolution {
|
|
85
|
+
const explicit = process.env.OPENCODE_DB;
|
|
86
|
+
if (explicit !== undefined && explicit.length > 0) {
|
|
87
|
+
if (explicit === ":memory:") {
|
|
88
|
+
return { path: explicit, source: "OPENCODE_DB", channel: null };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
path: isAbsolute(explicit) ? explicit : join(dataDir, explicit),
|
|
92
|
+
source: "OPENCODE_DB",
|
|
93
|
+
channel: null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const disableChannelDb = process.env.OPENCODE_DISABLE_CHANNEL_DB;
|
|
98
|
+
if (disableChannelDb === "1" || disableChannelDb === "true") {
|
|
99
|
+
return { path: join(dataDir, "opencode.db"), source: "default", channel: null };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const channel = process.env.OPENCODE_CHANNEL;
|
|
103
|
+
if (channel !== undefined && channel.length > 0) {
|
|
104
|
+
return { path: channelPath(dataDir, channel), source: "channel", channel };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return discoverOpenCodeDb(dataDir);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Resolve an explicit DB override first, then channel paths; discover candidates when the compiled channel is unknown. */
|
|
111
|
+
export function resolveOpenCodeDbPath(): OpenCodeDbPathResolution {
|
|
112
|
+
const dataDir = openCodeDataDir();
|
|
113
|
+
const key = environmentKey(dataDir);
|
|
114
|
+
if (
|
|
115
|
+
cachedResolution?.key === key &&
|
|
116
|
+
(!cachedResolution.existed || existsSync(cachedResolution.resolution.path))
|
|
117
|
+
) {
|
|
118
|
+
if (cachedResolution.existed) return cachedResolution.resolution;
|
|
119
|
+
// An absent result is re-probed so a DB created after plugin boot is detected.
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const resolution = resolveFresh(dataDir);
|
|
123
|
+
cachedResolution = {
|
|
124
|
+
key,
|
|
125
|
+
resolution,
|
|
126
|
+
existed: resolution.path !== ":memory:" && existsSync(resolution.path),
|
|
127
|
+
};
|
|
128
|
+
return resolution;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function openCodeDbPathExists(
|
|
132
|
+
resolution: OpenCodeDbPathResolution = resolveOpenCodeDbPath(),
|
|
133
|
+
): boolean {
|
|
134
|
+
return resolution.path !== ":memory:" && existsSync(resolution.path);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function getOpenCodeDbProbeDescriptions(
|
|
138
|
+
resolution: OpenCodeDbPathResolution = resolveOpenCodeDbPath(),
|
|
139
|
+
): string[] {
|
|
140
|
+
if (resolution.source === "OPENCODE_DB") return [resolution.path];
|
|
141
|
+
if (
|
|
142
|
+
resolution.source === "channel" ||
|
|
143
|
+
process.env.OPENCODE_DISABLE_CHANNEL_DB === "1" ||
|
|
144
|
+
process.env.OPENCODE_DISABLE_CHANNEL_DB === "true"
|
|
145
|
+
) {
|
|
146
|
+
return [resolution.path];
|
|
147
|
+
}
|
|
148
|
+
const dataDir = openCodeDataDir();
|
|
149
|
+
return [
|
|
150
|
+
join(dataDir, "opencode.db"),
|
|
151
|
+
join(dataDir, "opencode-local.db"),
|
|
152
|
+
join(dataDir, "opencode-dev.db"),
|
|
153
|
+
join(dataDir, "opencode-<channel>.db"),
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function lookedForText(resolution: OpenCodeDbPathResolution): string {
|
|
158
|
+
return getOpenCodeDbProbeDescriptions(resolution).join(", ");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function formatOpenCodeDbMissingBanner(
|
|
162
|
+
resolution: OpenCodeDbPathResolution = resolveOpenCodeDbPath(),
|
|
163
|
+
): string {
|
|
164
|
+
return `Magic Context cannot find OpenCode's session database (looked for ${lookedForText(resolution)}). History compaction (historian) and the mid-turn valve are disabled until it is found; set OPENCODE_DB if OpenCode stores it elsewhere.`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function formatOpenCodeDbMissingStatusLine(
|
|
168
|
+
resolution: OpenCodeDbPathResolution = resolveOpenCodeDbPath(),
|
|
169
|
+
): string {
|
|
170
|
+
return `OpenCode DB: MISSING (looked for ${lookedForText(resolution)}). History compaction (historian) and the mid-turn valve are disabled; set OPENCODE_DB if OpenCode stores it elsewhere.`;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function formatOpenCodeDbDoctorLine(
|
|
174
|
+
resolution: OpenCodeDbPathResolution = resolveOpenCodeDbPath(),
|
|
175
|
+
): string {
|
|
176
|
+
return `FAIL OpenCode session database: not found (looked for ${lookedForText(resolution)}); set OPENCODE_DB if OpenCode stores it elsewhere.`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function formatOpenCodeDbReadFailureStatusLine(failure: OpenCodeDbReadFailure): string {
|
|
180
|
+
return `OpenCode DB: READ FAILED (path=${failure.path}, source=${failure.source}) — ${failure.message}`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function recordOpenCodeDbReadFailure(
|
|
184
|
+
resolution: OpenCodeDbPathResolution,
|
|
185
|
+
error: unknown,
|
|
186
|
+
): OpenCodeDbReadFailure {
|
|
187
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
188
|
+
lastReadFailure = { ...resolution, message };
|
|
189
|
+
return lastReadFailure;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function clearOpenCodeDbReadFailure(path?: string): void {
|
|
193
|
+
if (path === undefined || lastReadFailure?.path === path) lastReadFailure = null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function getOpenCodeDbReadFailure(): OpenCodeDbReadFailure | null {
|
|
197
|
+
return lastReadFailure;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function claimOpenCodeDbDiagnosticOnce(
|
|
201
|
+
surface: string,
|
|
202
|
+
resolution: OpenCodeDbPathResolution,
|
|
203
|
+
): boolean {
|
|
204
|
+
const key = `${surface}\0${resolution.path}\0${resolution.source}`;
|
|
205
|
+
if (claimedDiagnostics.has(key)) return false;
|
|
206
|
+
claimedDiagnostics.add(key);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Test-only reset for process memoization and once-only diagnostics. */
|
|
211
|
+
export function resetOpenCodeDbPathStateForTesting(): void {
|
|
212
|
+
cachedResolution = null;
|
|
213
|
+
lastReadFailure = null;
|
|
214
|
+
claimedDiagnostics.clear();
|
|
215
|
+
}
|