@cortexkit/opencode-magic-context 0.47.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
- package/dist/auto-search-worker.js +27 -30
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/mural-model-deprecation.d.ts +15 -0
- package/dist/config/mural-model-deprecation.d.ts.map +1 -0
- package/dist/config/project-security.d.ts +0 -3
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +10 -6
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-z44ynfz7.js → conflict-warning-hook-kzx4dmk1.js} +12 -10
- package/dist/{context-wq4ffwyb.js → context-nj5f293n.js} +2765 -1925
- package/dist/{derive-budgets-ke12jnnh.js → derive-budgets-qz5rrr08.js} +4 -3
- package/dist/embedding-activity-g1dhes6g.js +10 -0
- package/dist/embedding-backfill-aetxv1vt.js +21 -0
- package/dist/embedding-cache-mgyr73ef.js +16 -0
- package/dist/embedding-worker.js +11 -9
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
- package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +16 -3
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
- package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
- package/dist/features/magic-context/message-index.d.ts +7 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
- package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
- package/dist/features/magic-context/search-rerank.d.ts +35 -0
- package/dist/features/magic-context/search-rerank.d.ts.map +1 -0
- package/dist/features/magic-context/search.d.ts +40 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-activity.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +13 -2
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
- package/dist/features/magic-context/storage-meta-session.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-session-tables.d.ts +2 -0
- package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +153 -4
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +2 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +4 -1
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/harness-e4avh192.js +10 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts +24 -0
- package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts +34 -3
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +3 -0
- package/dist/hooks/magic-context/command-handler.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/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-fail-closed.d.ts +28 -0
- package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/historian-host-runner.d.ts +8 -0
- package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -2
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +7 -0
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
- package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +19 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +118 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +36 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +41 -1
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +8 -1
- package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -1
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +14 -2
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +13 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +9 -2
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
- package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
- package/dist/{index-5gq3b2ya.js → index-1bt88epp.js} +227 -205
- package/dist/{index-cwf6s3ay.js → index-1g30axtz.js} +3279 -2907
- package/dist/{index-5a2r0p9f.js → index-1r0k9js3.js} +20 -13
- package/dist/index-2bvekkfy.js +11 -0
- package/dist/{index-6d9e1m08.js → index-2jcbj7r1.js} +13301 -13225
- package/dist/index-2jgwttpt.js +3269 -0
- package/dist/index-4dhv7mqz.js +131 -0
- package/dist/{index-sj29b3z2.js → index-4mjhqadz.js} +3 -3
- package/dist/{index-0c82743p.js → index-57mrqed8.js} +17 -15
- package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
- package/dist/index-7jzrrxap.js +931 -0
- package/dist/index-8ajstryz.js +18 -0
- package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
- package/dist/{index-6wkcswft.js → index-9qjqq45k.js} +29 -19
- package/dist/{index-adwfkpex.js → index-9rt53q79.js} +23 -23
- package/dist/index-b7mv1jx3.js +1060 -0
- package/dist/index-d9vfe7xq.js +16 -0
- package/dist/{index-gg8j07zz.js → index-ezmszwbd.js} +8 -6
- package/dist/index-fb3zxn06.js +13 -0
- package/dist/index-fr0wbhdn.js +43 -0
- package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
- package/dist/index-gzcmtmar.js +171 -0
- package/dist/{index-w2t4ah5j.js → index-h2py7207.js} +6762 -7400
- package/dist/index-h2wc01qk.js +120 -0
- package/dist/index-h5zfkjyk.js +1277 -0
- package/dist/{index-92bp57hg.js → index-ha87j7a8.js} +1343 -149
- package/dist/index-hj2q50k0.js +856 -0
- package/dist/{index-wx8a6bw3.js → index-kb9nn0a0.js} +270 -53
- package/dist/index-kmpvemph.js +1314 -0
- package/dist/index-kp5qe690.js +3030 -0
- package/dist/{index-m5fe6jch.js → index-kq57tdf0.js} +152 -2453
- package/dist/{v2/server-fq7kq32k.js → index-mfkzp7qj.js} +1 -16
- package/dist/{v2/server-njt3np1k.js → index-nm6a8xpd.js} +220 -961
- package/dist/{index-hybnrwq0.js → index-nsjyysj0.js} +137 -130
- package/dist/index-nydv6g8r.js +3569 -0
- package/dist/index-pavzsdc6.js +17 -0
- package/dist/index-peshmj6h.js +152 -0
- package/dist/index-pxwp2hjk.js +571 -0
- package/dist/{v2/server-yr3zj7e7.js → index-qt1qqasc.js} +6 -7
- package/dist/{v2/server-51dv1pr5.js → index-qx53vezw.js} +301 -27
- package/dist/{index-rrrsepyw.js → index-s4j7t92z.js} +90 -85
- package/dist/{index-9pk9exrb.js → index-stbr4ce6.js} +18 -18
- package/dist/{index-fzbvakh0.js → index-tqf7yg27.js} +3 -3
- package/dist/index-vkbqdnkj.js +2307 -0
- package/dist/{index-8da2zjhz.js → index-z1tjp257.js} +9 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +608 -349
- package/dist/logger-ewak5q1s.js +20 -0
- package/dist/message-index-bounded-h0mrd4pr.js +124 -0
- package/dist/{v2/message-time-backfill-1f9tzvcs.js → message-time-backfill-8x06r9kx.js} +8 -6
- package/dist/migration-worker.js +25 -18
- package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/plugin/dream-timer.d.ts +1 -1
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler-report.d.ts +1 -66
- package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler.d.ts +2 -95
- package/dist/plugin/host-stall-profiler.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +0 -13
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/project-embedding-registry-rtt0djyb.js +88 -0
- package/dist/raw-ordinal-warmup-worker.js +60 -0
- package/dist/{read-session-chunk-4jey7hpt.js → read-session-chunk-ty89v75e.js} +17 -9
- package/dist/read-session-raw-8sjbc9h0.js +60 -0
- package/dist/recomp-orchestrator-4f1yyd1q.js +57 -0
- package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-q0cyrx3x.js} +4 -2
- package/dist/search-pz4f4wge.js +45 -0
- package/dist/{v2/send-session-notification-c0wtscea.js → send-session-notification-38cd5dqt.js} +10 -7
- package/dist/shared/auto-search-lifecycle.d.ts +14 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
- package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-common.d.ts +58 -0
- package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-node.d.ts +36 -0
- package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-report.d.ts +68 -0
- package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler.d.ts +5 -0
- package/dist/shared/host-stall-profiler.d.ts.map +1 -0
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/model-resolution.d.ts +2 -3
- package/dist/shared/model-resolution.d.ts.map +1 -1
- package/dist/shared/models-dev-temperature.d.ts +18 -0
- package/dist/shared/models-dev-temperature.d.ts.map +1 -0
- package/dist/shared/project-directory-key.d.ts +16 -0
- package/dist/shared/project-directory-key.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +30 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/subagent-temperature.d.ts +46 -0
- package/dist/shared/subagent-temperature.d.ts.map +1 -0
- package/dist/shared/user-facing-codes.d.ts +0 -5
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/sqlite-mhjkerzq.js +46 -0
- package/dist/storage-memory-07fx57k6.js +71 -0
- package/dist/storage-tags-k0pda32s.js +133 -0
- package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/constants.d.ts +4 -0
- package/dist/tools/ctx-note/constants.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts +1 -0
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/types.d.ts +1 -0
- package/dist/tools/ctx-search/types.d.ts.map +1 -1
- package/dist/tools/parameter-descriptions.d.ts +2 -2
- package/dist/tools/parameter-descriptions.d.ts.map +1 -1
- package/dist/{transform-postprocess-phase-z5hzpsxv.js → transform-postprocess-phase-tck4g20s.js} +35 -20
- package/dist/transformers-node-wasm.js +18415 -18415
- package/dist/v2/auto-search-worker.js +27 -30
- package/dist/v2/{context-14v1hr8b.js → context-crbt6p1y.js} +4708 -4218
- package/dist/v2/{derive-budgets-nc9avxz8.js → derive-budgets-fgej9j46.js} +4 -3
- package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
- package/dist/v2/embedding-backfill-ph1qfyn3.js +21 -0
- package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
- package/dist/v2/embedding-worker.js +12 -9
- package/dist/v2/fold/host-media.d.ts +4 -0
- package/dist/v2/fold/host-media.d.ts.map +1 -1
- package/dist/v2/fold/memory-cache.d.ts +70 -0
- package/dist/v2/fold/memory-cache.d.ts.map +1 -0
- package/dist/v2/fold/native-codec.d.ts +10 -0
- package/dist/v2/fold/native-codec.d.ts.map +1 -0
- package/dist/v2/fold/native-replay.d.ts +58 -0
- package/dist/v2/fold/native-replay.d.ts.map +1 -0
- package/dist/v2/fold/policy.d.ts +24 -0
- package/dist/v2/fold/policy.d.ts.map +1 -0
- package/dist/v2/harness-e4avh192.js +10 -0
- package/dist/v2/hidden-child-native.d.ts.map +1 -1
- package/dist/v2/hidden-completion.d.ts +7 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts +2 -2
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/dream-manual.d.ts +1 -1
- package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
- package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
- package/dist/v2/hooks/dream-trigger.d.ts +5 -3
- package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
- package/dist/v2/hooks/generate.d.ts +9 -2
- package/dist/v2/hooks/generate.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/tools.d.ts.map +1 -1
- package/dist/v2/hooks/types.d.ts +6 -0
- package/dist/v2/hooks/types.d.ts.map +1 -1
- package/dist/v2/logger-pj02s7sr.js +19 -0
- package/dist/v2/message-index-bounded-xwqdywxg.js +123 -0
- package/dist/{message-time-backfill-r5epkzj3.js → v2/message-time-backfill-cje68egj.js} +7 -7
- package/dist/v2/migration-worker.js +24 -17
- package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/v2/project-embedding-registry-d6m7tyxr.js +86 -0
- package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
- package/dist/v2/{read-session-chunk-gyyv7w2r.js → read-session-chunk-8p5mdryx.js} +16 -8
- package/dist/v2/read-session-raw-j8dvp7f4.js +59 -0
- package/dist/v2/recomp-orchestrator-ckfgt6wq.js +57 -0
- package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-y3p1hce9.js} +3 -3
- package/dist/v2/search-ym8rehhz.js +45 -0
- package/dist/{send-session-notification-0m68ms3n.js → v2/send-session-notification-5m0yapqx.js} +9 -8
- package/dist/v2/{server-rz514f14.js → server-19zjmn02.js} +2044 -2060
- package/dist/v2/server-1tk82krw.js +796 -0
- package/dist/v2/server-2bvekkfy.js +11 -0
- package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
- package/dist/v2/server-2s6ayq3t.js +1048 -0
- package/dist/v2/{server-fcdehk1s.js → server-2s9qz6n7.js} +4 -4
- package/dist/v2/server-3j4d00kf.js +171 -0
- package/dist/v2/{server-14vq4kpm.js → server-3t0q2cqx.js} +3 -3
- package/dist/v2/server-4dhv7mqz.js +131 -0
- package/dist/v2/server-4ez8mntn.js +3213 -0
- package/dist/v2/{server-6r257mf5.js → server-676xw7at.js} +3 -3
- package/dist/v2/{server-vs5gpnd4.js → server-6byqfbqf.js} +165 -145
- package/dist/v2/server-7ekna9zs.js +120 -0
- package/dist/v2/server-7h861yms.js +1272 -0
- package/dist/v2/server-7jzrrxap.js +931 -0
- package/dist/v2/server-8ajstryz.js +18 -0
- package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
- package/dist/v2/{server-cpepxy2q.js → server-8k2agx29.js} +14 -12
- package/dist/v2/server-c5rrgrcd.js +3545 -0
- package/dist/v2/server-d9vfe7xq.js +16 -0
- package/dist/v2/server-fb3zxn06.js +13 -0
- package/dist/v2/server-fr0wbhdn.js +43 -0
- package/dist/v2/{server-y10vbq6y.js → server-hb6xhh9q.js} +11 -1053
- package/dist/v2/server-jvxzm1jy.js +3023 -0
- package/dist/v2/{server-wx8a6bw3.js → server-kb9nn0a0.js} +270 -53
- package/dist/{index-5eqk6z3s.js → v2/server-kzns2hbz.js} +301 -27
- package/dist/{index-rrbbspwh.js → v2/server-mfkzp7qj.js} +1 -16
- package/dist/v2/server-pavzsdc6.js +17 -0
- package/dist/v2/{server-vd4e7174.js → server-pj4pjv02.js} +21 -17
- package/dist/v2/{server-e0c1b7a7.js → server-q4ph9bwn.js} +1340 -148
- package/dist/{index-yr3zj7e7.js → v2/server-qt1qqasc.js} +6 -7
- package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
- package/dist/v2/{server-d0sraw7m.js → server-sa8jvrfc.js} +291 -286
- package/dist/v2/server-ss95ky04.js +1048 -0
- package/dist/v2/{server-1qbnzc80.js → server-t4k4qexw.js} +142 -150
- package/dist/{index-x3kwrmqk.js → v2/server-v4mewb78.js} +35 -792
- package/dist/v2/server-w32kmdez.js +154 -0
- package/dist/v2/{server-nf82q6pt.js → server-x4hscabv.js} +5547 -5449
- package/dist/v2/server-xwz4dqh9.js +569 -0
- package/dist/v2/{server-efhwzx05.js → server-ycw9qqcy.js} +23 -23
- package/dist/v2/{server-50hvkg3v.js → server-zm570tr2.js} +160 -158
- package/dist/v2/server-zp53y8js.js +1311 -0
- package/dist/v2/server.js +16 -14
- package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/v2/sqlite-mhjkerzq.js +46 -0
- package/dist/v2/storage-memory-07fx57k6.js +71 -0
- package/dist/v2/storage-tags-8vw924zn.js +132 -0
- package/dist/v2/store-reader.d.ts +24 -2
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
- package/dist/v2/transformers-node-wasm.js +18415 -18415
- package/dist/v2/tui/index.d.ts.map +1 -1
- package/dist/v2/tui/types.d.ts +1 -10
- package/dist/v2/tui/types.d.ts.map +1 -1
- package/dist/v2/{wrapup-orchestrator-nbz854vc.js → wrapup-orchestrator-a7efxaax.js} +51 -30
- package/dist/wrapup-orchestrator-barbc6h9.js +44 -0
- package/package.json +4 -3
- package/src/agents/magic-context-prompt.ts +27 -2
- package/src/agents/smart-notes-enabled.test.ts +294 -0
- package/src/agents/smart-notes-on.golden.json +70 -0
- package/src/config/index.test.ts +67 -1
- package/src/config/index.ts +2 -0
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/mural-model-deprecation.ts +24 -0
- package/src/config/project-security.hostile-matrix.test.ts +4 -44
- package/src/config/project-security.test.ts +9 -14
- package/src/config/project-security.ts +13 -55
- package/src/config/schema/magic-context.test.ts +2 -2
- package/src/config/schema/magic-context.ts +16 -10
- package/src/features/magic-context/dreamer/task-registry.ts +6 -0
- package/src/shared/auto-search-lifecycle.ts +43 -0
- package/src/shared/conflict-detector.test.ts +56 -0
- package/src/shared/conflict-detector.ts +16 -5
- package/src/shared/host-stall-profiler-bun.ts +358 -0
- package/src/shared/host-stall-profiler-common.ts +159 -0
- package/src/shared/host-stall-profiler-node.test.ts +234 -0
- package/src/shared/host-stall-profiler-node.ts +274 -0
- package/src/shared/host-stall-profiler-report.ts +248 -0
- package/src/shared/host-stall-profiler.ts +57 -0
- package/src/shared/logger.test.ts +38 -0
- package/src/shared/logger.ts +10 -2
- package/src/shared/model-resolution.test.ts +54 -17
- package/src/shared/model-resolution.ts +6 -17
- package/src/shared/models-dev-temperature.ts +107 -0
- package/src/shared/project-directory-key.test.ts +59 -0
- package/src/shared/project-directory-key.ts +20 -0
- package/src/shared/sqlite.test.ts +52 -0
- package/src/shared/sqlite.ts +339 -23
- package/src/shared/stable-json-linear.test.ts +109 -0
- package/src/shared/stable-json.ts +37 -7
- package/src/shared/subagent-temperature.test.ts +270 -0
- package/src/shared/subagent-temperature.ts +110 -0
- package/src/shared/user-facing-codes.ts +2 -6
- package/src/shared/write-transaction-attribution.test.ts +2 -2
- package/src/v2/tui/host-contract.test.ts +41 -67
- package/src/v2/tui/index.ts +6 -214
- package/src/v2/tui/types.ts +5 -17
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
- package/dist/features/magic-context/checkout-claim.d.ts +0 -155
- package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
- package/dist/index-bb36vgr3.js +0 -6608
- package/dist/index-fnn5pjtt.js +0 -6554
- package/dist/recomp-orchestrator-rervg6q4.js +0 -42
- package/dist/v2/recomp-orchestrator-42vjba7p.js +0 -42
- package/dist/v2/server-3trjk1hx.js +0 -6360
- package/dist/v2/server-nm9n3aqq.js +0 -6461
- package/dist/wrapup-orchestrator-b2dztrar.js +0 -29
- /package/dist/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
- /package/dist/v2/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
|
@@ -0,0 +1,1311 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getHarness2
|
|
3
|
+
} from "./server-pavzsdc6.js";
|
|
4
|
+
import {
|
|
5
|
+
isTransientSqliteError2
|
|
6
|
+
} from "./server-kb9nn0a0.js";
|
|
7
|
+
import {
|
|
8
|
+
PROMOTABLE_CATEGORIES,
|
|
9
|
+
CATEGORY_DEFAULT_TTL
|
|
10
|
+
} from "./server-fr0wbhdn.js";
|
|
11
|
+
import {
|
|
12
|
+
sanitizeDiagnosticText,
|
|
13
|
+
sessionLog2
|
|
14
|
+
} from "./server-t4k4qexw.js";
|
|
15
|
+
import {
|
|
16
|
+
managedAuthorityNoteRow
|
|
17
|
+
} from "./server-v4mewb78.js";
|
|
18
|
+
import {
|
|
19
|
+
embedTextForProject2
|
|
20
|
+
} from "./server-jvxzm1jy.js";
|
|
21
|
+
import {
|
|
22
|
+
saveEmbeddingIfHashMatches
|
|
23
|
+
} from "./server-4dhv7mqz.js";
|
|
24
|
+
import {
|
|
25
|
+
getMemorySelectColumns2,
|
|
26
|
+
isMemoryRow2,
|
|
27
|
+
toMemory2,
|
|
28
|
+
insertMemory2,
|
|
29
|
+
getMemoryByHash2,
|
|
30
|
+
buildWorkspaceMemorySqlFilter2,
|
|
31
|
+
getMemoryById2,
|
|
32
|
+
updateMemorySeenCount2
|
|
33
|
+
} from "./server-7jzrrxap.js";
|
|
34
|
+
import {
|
|
35
|
+
computeNormalizedHash
|
|
36
|
+
} from "./server-2bvekkfy.js";
|
|
37
|
+
|
|
38
|
+
// src/features/magic-context/storage-notes.ts
|
|
39
|
+
var NOTE_TYPES = new Set(["session", "smart"]);
|
|
40
|
+
var NOTE_STATUSES = new Set(["active", "pending", "ready", "dismissed"]);
|
|
41
|
+
var NOTE_CHECK_STATUSES = new Set([
|
|
42
|
+
"uncompiled",
|
|
43
|
+
"compiled",
|
|
44
|
+
"failing",
|
|
45
|
+
"fallback",
|
|
46
|
+
"parked"
|
|
47
|
+
]);
|
|
48
|
+
var CONDITION_COMPILE_STATUSES = new Set([
|
|
49
|
+
"compiled",
|
|
50
|
+
"plain",
|
|
51
|
+
"refused"
|
|
52
|
+
]);
|
|
53
|
+
var DEFAULT_SMART_STATUSES = ["pending", "ready"];
|
|
54
|
+
function toNullableString(value) {
|
|
55
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
56
|
+
}
|
|
57
|
+
function toNullableNumber(value) {
|
|
58
|
+
return typeof value === "number" ? value : null;
|
|
59
|
+
}
|
|
60
|
+
function isNoteRow(row) {
|
|
61
|
+
if (row === null || typeof row !== "object")
|
|
62
|
+
return false;
|
|
63
|
+
const candidate = row;
|
|
64
|
+
return typeof candidate.id === "number" && typeof candidate.type === "string" && NOTE_TYPES.has(candidate.type) && typeof candidate.status === "string" && NOTE_STATUSES.has(candidate.status) && typeof candidate.content === "string" && (candidate.session_id === null || typeof candidate.session_id === "string") && (candidate.project_path === null || typeof candidate.project_path === "string") && (candidate.surface_condition === null || typeof candidate.surface_condition === "string") && typeof candidate.created_at === "number" && typeof candidate.updated_at === "number" && (candidate.last_checked_at === null || typeof candidate.last_checked_at === "number") && (candidate.ready_at === null || typeof candidate.ready_at === "number") && (candidate.ready_reason === null || typeof candidate.ready_reason === "string");
|
|
65
|
+
}
|
|
66
|
+
function toNote(row) {
|
|
67
|
+
return {
|
|
68
|
+
id: row.id,
|
|
69
|
+
type: row.type,
|
|
70
|
+
status: row.status,
|
|
71
|
+
content: row.content,
|
|
72
|
+
sessionId: toNullableString(row.session_id),
|
|
73
|
+
projectPath: toNullableString(row.project_path),
|
|
74
|
+
surfaceCondition: toNullableString(row.surface_condition),
|
|
75
|
+
compiledProvider: toNullableString(row.compiled_provider),
|
|
76
|
+
compiledConfig: toNullableString(row.compiled_config),
|
|
77
|
+
compiledAt: toNullableNumber(row.compiled_at),
|
|
78
|
+
compileStatus: typeof row.compile_status === "string" && CONDITION_COMPILE_STATUSES.has(row.compile_status) ? row.compile_status : null,
|
|
79
|
+
createdAt: row.created_at,
|
|
80
|
+
updatedAt: row.updated_at,
|
|
81
|
+
lastCheckedAt: toNullableNumber(row.last_checked_at),
|
|
82
|
+
readyAt: toNullableNumber(row.ready_at),
|
|
83
|
+
readyReason: toNullableString(row.ready_reason),
|
|
84
|
+
anchorOrdinal: toNullableNumber(row.anchor_ordinal),
|
|
85
|
+
compiledCheck: toNullableString(row.compiled_check),
|
|
86
|
+
manifestJson: toNullableString(row.manifest_json),
|
|
87
|
+
checkHash: toNullableString(row.check_hash),
|
|
88
|
+
checkCron: toNullableString(row.check_cron),
|
|
89
|
+
checkVersion: toNullableNumber(row.check_version),
|
|
90
|
+
checkStatus: typeof row.check_status === "string" && NOTE_CHECK_STATUSES.has(row.check_status) ? row.check_status : null,
|
|
91
|
+
checkFailureCount: toNullableNumber(row.check_failure_count) ?? 0,
|
|
92
|
+
checkNetworkFailureCount: toNullableNumber(row.check_network_failure_count) ?? 0,
|
|
93
|
+
checkQuarantinedUntil: toNullableNumber(row.check_quarantined_until),
|
|
94
|
+
checkNextDueAt: toNullableNumber(row.check_next_due_at),
|
|
95
|
+
checkCompiledAt: toNullableNumber(row.check_compiled_at),
|
|
96
|
+
checkFalseSinceAt: toNullableNumber(row.check_false_since_at),
|
|
97
|
+
checkLastLivenessAt: toNullableNumber(row.check_last_liveness_at),
|
|
98
|
+
policyVersion: toNullableNumber(row.policy_version)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function noteCheckColumnsExist(db) {
|
|
102
|
+
try {
|
|
103
|
+
const rows = db.prepare("PRAGMA table_info(notes)").all();
|
|
104
|
+
return rows.some((row) => row.name === "compiled_check");
|
|
105
|
+
} catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
var PENDING_SESSION_NOTE_PREDICATE = "type = 'session' AND status = 'pending' AND surface_condition IS NOT NULL";
|
|
110
|
+
function healPendingSessionNotes(db) {
|
|
111
|
+
let predicate = `${PENDING_SESSION_NOTE_PREDICATE} AND NOT ${managedAuthorityNoteRow("notes")}`;
|
|
112
|
+
let healable;
|
|
113
|
+
try {
|
|
114
|
+
healable = db.prepare(`SELECT 1 FROM notes WHERE ${predicate} LIMIT 1`).get();
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (!(error instanceof Error) || !error.message.includes("no such table"))
|
|
117
|
+
throw error;
|
|
118
|
+
predicate = PENDING_SESSION_NOTE_PREDICATE;
|
|
119
|
+
healable = db.prepare(`SELECT 1 FROM notes WHERE ${predicate} LIMIT 1`).get();
|
|
120
|
+
}
|
|
121
|
+
if (healable == null)
|
|
122
|
+
return;
|
|
123
|
+
try {
|
|
124
|
+
db.prepare(`UPDATE notes SET status = 'active', surface_condition = NULL WHERE ${predicate}`).run();
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (!isTransientSqliteError2(error))
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
var SESSION_NOTE_CONDITION_ERROR = "Only a note created with a condition can have one. Write a new note with surface_condition, and dismiss this one.";
|
|
131
|
+
function getNoteById(db, noteId) {
|
|
132
|
+
healPendingSessionNotes(db);
|
|
133
|
+
const row = db.prepare("SELECT * FROM notes WHERE id = ?").get(noteId);
|
|
134
|
+
return isNoteRow(row) ? toNote(row) : null;
|
|
135
|
+
}
|
|
136
|
+
function getNoteByIdInScope(db, noteId, scope) {
|
|
137
|
+
const note = getNoteById(db, noteId);
|
|
138
|
+
return note && noteBelongsToScope(note, scope) ? note : null;
|
|
139
|
+
}
|
|
140
|
+
function noteBelongsToScope(note, scope) {
|
|
141
|
+
if (note.type === "session") {
|
|
142
|
+
return note.sessionId === scope.sessionId;
|
|
143
|
+
}
|
|
144
|
+
return note.projectPath === scope.projectPath;
|
|
145
|
+
}
|
|
146
|
+
function buildStatusClause(status) {
|
|
147
|
+
if (status === undefined) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
const statuses = Array.isArray(status) ? status : [status];
|
|
151
|
+
if (statuses.length === 0) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const placeholders = statuses.map(() => "?").join(", ");
|
|
155
|
+
return {
|
|
156
|
+
sql: `status IN (${placeholders})`,
|
|
157
|
+
params: statuses
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function getNotes(db, options = {}) {
|
|
161
|
+
healPendingSessionNotes(db);
|
|
162
|
+
const clauses = [];
|
|
163
|
+
const params = [];
|
|
164
|
+
if (options.sessionId !== undefined) {
|
|
165
|
+
clauses.push("session_id = ?");
|
|
166
|
+
params.push(options.sessionId);
|
|
167
|
+
}
|
|
168
|
+
if (options.projectPath !== undefined) {
|
|
169
|
+
clauses.push("project_path = ?");
|
|
170
|
+
params.push(options.projectPath);
|
|
171
|
+
}
|
|
172
|
+
if (options.type !== undefined) {
|
|
173
|
+
clauses.push("type = ?");
|
|
174
|
+
params.push(options.type);
|
|
175
|
+
}
|
|
176
|
+
const statusClause = buildStatusClause(options.status);
|
|
177
|
+
if (statusClause) {
|
|
178
|
+
clauses.push(statusClause.sql);
|
|
179
|
+
params.push(...statusClause.params);
|
|
180
|
+
}
|
|
181
|
+
const where = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
|
|
182
|
+
return db.prepare(`SELECT * FROM notes${where} ORDER BY created_at ASC, id ASC`).all(...params).filter(isNoteRow).map(toNote);
|
|
183
|
+
}
|
|
184
|
+
function addNote(db, type, options) {
|
|
185
|
+
const now = Date.now();
|
|
186
|
+
const result = type === "session" ? db.prepare("INSERT INTO notes (type, status, content, session_id, created_at, updated_at, harness, anchor_ordinal) VALUES ('session', 'active', ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId, now, now, getHarness2(), options.anchorOrdinal ?? null) : db.prepare("INSERT INTO notes (type, status, content, session_id, project_path, surface_condition, compiled_provider, compiled_config, compiled_at, compile_status, created_at, updated_at, harness, anchor_ordinal) VALUES ('smart', 'pending', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *").get(options.content, options.sessionId ?? null, options.projectPath, options.surfaceCondition, options.compiledProvider ?? null, options.compiledConfig ?? null, options.compiledAt ?? null, options.compileStatus ?? null, now, now, getHarness2(), options.anchorOrdinal ?? null);
|
|
187
|
+
if (!isNoteRow(result)) {
|
|
188
|
+
throw new Error("[notes] failed to insert note");
|
|
189
|
+
}
|
|
190
|
+
return toNote(result);
|
|
191
|
+
}
|
|
192
|
+
function getSessionNotes(db, sessionId) {
|
|
193
|
+
return getNotes(db, { sessionId, type: "session", status: "active" });
|
|
194
|
+
}
|
|
195
|
+
function getSmartNotes(db, projectPath, status) {
|
|
196
|
+
return getNotes(db, {
|
|
197
|
+
projectPath,
|
|
198
|
+
type: "smart",
|
|
199
|
+
status: status ?? DEFAULT_SMART_STATUSES
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function getPendingSmartNotes(db, projectPath) {
|
|
203
|
+
return getSmartNotes(db, projectPath, "pending");
|
|
204
|
+
}
|
|
205
|
+
function getReadySmartNotes(db, projectPath) {
|
|
206
|
+
return getSmartNotes(db, projectPath, "ready");
|
|
207
|
+
}
|
|
208
|
+
function updateNote(db, noteId, updates, scope) {
|
|
209
|
+
const existing = getNoteByIdInScope(db, noteId, scope);
|
|
210
|
+
if (!existing) {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
if (updates.surfaceCondition !== undefined && existing.type !== "smart") {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
const now = Date.now();
|
|
217
|
+
const sets = ["updated_at = ?"];
|
|
218
|
+
const params = [now];
|
|
219
|
+
if (updates.content !== undefined) {
|
|
220
|
+
sets.push("content = ?");
|
|
221
|
+
params.push(updates.content);
|
|
222
|
+
}
|
|
223
|
+
if (updates.sessionId !== undefined) {
|
|
224
|
+
sets.push("session_id = ?");
|
|
225
|
+
params.push(updates.sessionId);
|
|
226
|
+
}
|
|
227
|
+
const smartConditionChanged = existing.type === "smart" && updates.surfaceCondition !== undefined && updates.surfaceCondition !== existing.surfaceCondition;
|
|
228
|
+
if (updates.status !== undefined && !smartConditionChanged) {
|
|
229
|
+
sets.push("status = ?");
|
|
230
|
+
params.push(updates.status);
|
|
231
|
+
}
|
|
232
|
+
if (existing.type === "smart") {
|
|
233
|
+
if (updates.projectPath !== undefined) {
|
|
234
|
+
sets.push("project_path = ?");
|
|
235
|
+
params.push(updates.projectPath);
|
|
236
|
+
}
|
|
237
|
+
if (updates.surfaceCondition !== undefined) {
|
|
238
|
+
sets.push("surface_condition = ?");
|
|
239
|
+
params.push(updates.surfaceCondition);
|
|
240
|
+
}
|
|
241
|
+
if (smartConditionChanged) {
|
|
242
|
+
sets.push("status = 'pending'", "last_checked_at = NULL", "ready_at = NULL", "ready_reason = NULL");
|
|
243
|
+
sets.push("compiled_provider = ?", "compiled_config = ?", "compiled_at = ?", "compile_status = ?");
|
|
244
|
+
params.push(updates.compiledProvider ?? null, updates.compiledConfig ?? null, updates.compiledAt ?? null, updates.compileStatus ?? null);
|
|
245
|
+
if (noteCheckColumnsExist(db)) {
|
|
246
|
+
sets.push("compiled_check = NULL", "manifest_json = NULL", "check_hash = NULL", "check_cron = NULL", "check_version = 0", "check_status = 'uncompiled'", "check_failure_count = 0", "check_network_failure_count = 0", "check_quarantined_until = NULL", "check_next_due_at = NULL", "check_compiled_at = NULL", "check_false_since_at = NULL", "check_last_liveness_at = NULL");
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
if (updates.lastCheckedAt !== undefined) {
|
|
250
|
+
sets.push("last_checked_at = ?");
|
|
251
|
+
params.push(updates.lastCheckedAt);
|
|
252
|
+
}
|
|
253
|
+
if (updates.readyAt !== undefined) {
|
|
254
|
+
sets.push("ready_at = ?");
|
|
255
|
+
params.push(updates.readyAt);
|
|
256
|
+
}
|
|
257
|
+
if (updates.readyReason !== undefined) {
|
|
258
|
+
sets.push("ready_reason = ?");
|
|
259
|
+
params.push(updates.readyReason);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (sets.length === 1) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
params.push(noteId);
|
|
267
|
+
const result = db.prepare(`UPDATE notes SET ${sets.join(", ")} WHERE id = ? RETURNING *`).get(...params);
|
|
268
|
+
return isNoteRow(result) ? toNote(result) : null;
|
|
269
|
+
}
|
|
270
|
+
function dismissNotes(db, noteIds, scope) {
|
|
271
|
+
const now = Date.now();
|
|
272
|
+
return db.transaction(() => noteIds.map((noteId) => {
|
|
273
|
+
const existing = getNoteById(db, noteId);
|
|
274
|
+
if (!existing)
|
|
275
|
+
return { noteId, outcome: "not_found" };
|
|
276
|
+
if (!noteBelongsToScope(existing, scope)) {
|
|
277
|
+
return { noteId, outcome: "not_owned" };
|
|
278
|
+
}
|
|
279
|
+
if (existing.status === "dismissed") {
|
|
280
|
+
return { noteId, outcome: "already_dismissed" };
|
|
281
|
+
}
|
|
282
|
+
const result = db.prepare("UPDATE notes SET status = 'dismissed', updated_at = ? WHERE id = ? AND status != 'dismissed'").run(now, noteId);
|
|
283
|
+
return {
|
|
284
|
+
noteId,
|
|
285
|
+
outcome: result.changes > 0 ? "dismissed" : "already_dismissed"
|
|
286
|
+
};
|
|
287
|
+
})).immediate();
|
|
288
|
+
}
|
|
289
|
+
function dismissNote(db, noteId, scope) {
|
|
290
|
+
return dismissNotes(db, [noteId], scope)[0]?.outcome === "dismissed";
|
|
291
|
+
}
|
|
292
|
+
function markNoteReady(db, noteId, reason) {
|
|
293
|
+
const now = Date.now();
|
|
294
|
+
db.prepare("UPDATE notes SET status = 'ready', ready_at = ?, ready_reason = ?, updated_at = ?, last_checked_at = ? WHERE id = ? AND type = 'smart'").run(now, reason ?? null, now, now, noteId);
|
|
295
|
+
}
|
|
296
|
+
function markNoteChecked(db, noteId) {
|
|
297
|
+
const now = Date.now();
|
|
298
|
+
db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// src/features/magic-context/storage-primers.ts
|
|
302
|
+
var PRIMER_CANDIDATE_TTL_MS = 90 * 24 * 60 * 60 * 1000;
|
|
303
|
+
var PRIMER_CANDIDATE_MAX_AGE_MS = 180 * 24 * 60 * 60 * 1000;
|
|
304
|
+
function normalizePrimerQuestion(question) {
|
|
305
|
+
return question.trim().toLowerCase().replace(/[“”]/g, '"').replace(/[’]/g, "'").replace(/\s+/g, " ").replace(/[?.!]+$/g, "").trim();
|
|
306
|
+
}
|
|
307
|
+
function primerOccurrenceKey(candidate) {
|
|
308
|
+
return [
|
|
309
|
+
candidate.projectPath,
|
|
310
|
+
candidate.harness,
|
|
311
|
+
candidate.sessionId,
|
|
312
|
+
candidate.sourceStartMessageId,
|
|
313
|
+
candidate.sourceEndMessageId
|
|
314
|
+
].join("\x1F");
|
|
315
|
+
}
|
|
316
|
+
function primerOccurrenceUtcDay(sourceMessageTime) {
|
|
317
|
+
return new Date(sourceMessageTime).toISOString().slice(0, 10);
|
|
318
|
+
}
|
|
319
|
+
function vectorBlob(vector) {
|
|
320
|
+
if (!vector)
|
|
321
|
+
return null;
|
|
322
|
+
return new Uint8Array(vector.buffer, vector.byteOffset, vector.byteLength);
|
|
323
|
+
}
|
|
324
|
+
function blobToFloat32Array(value) {
|
|
325
|
+
if (!value)
|
|
326
|
+
return null;
|
|
327
|
+
const bytes = value instanceof ArrayBuffer ? new Uint8Array(value) : value;
|
|
328
|
+
return new Float32Array(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
|
|
329
|
+
}
|
|
330
|
+
function parseCandidateIds(raw) {
|
|
331
|
+
if (!raw)
|
|
332
|
+
return [];
|
|
333
|
+
try {
|
|
334
|
+
const parsed = JSON.parse(raw);
|
|
335
|
+
return Array.isArray(parsed) ? parsed.filter((id) => typeof id === "number" && Number.isFinite(id)) : [];
|
|
336
|
+
} catch {
|
|
337
|
+
return [];
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function parsePrimerSourceProvenance(raw) {
|
|
341
|
+
if (raw === null)
|
|
342
|
+
return null;
|
|
343
|
+
try {
|
|
344
|
+
const parsed = JSON.parse(raw);
|
|
345
|
+
if (!Array.isArray(parsed))
|
|
346
|
+
return null;
|
|
347
|
+
const provenance = [];
|
|
348
|
+
for (const value of parsed) {
|
|
349
|
+
if (!value || typeof value !== "object")
|
|
350
|
+
return null;
|
|
351
|
+
const source = value;
|
|
352
|
+
if (typeof source.candidate_id !== "number" || !Number.isFinite(source.candidate_id) || typeof source.project_path !== "string" || typeof source.harness !== "string" || typeof source.session_id !== "string" || source.source_compartment_start !== null && typeof source.source_compartment_start !== "number" || source.source_compartment_end !== null && typeof source.source_compartment_end !== "number" || typeof source.source_start_message_id !== "string" || typeof source.source_end_message_id !== "string") {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
provenance.push({
|
|
356
|
+
candidateId: source.candidate_id,
|
|
357
|
+
projectPath: source.project_path,
|
|
358
|
+
harness: source.harness,
|
|
359
|
+
sessionId: source.session_id,
|
|
360
|
+
sourceCompartmentStart: source.source_compartment_start,
|
|
361
|
+
sourceCompartmentEnd: source.source_compartment_end,
|
|
362
|
+
sourceStartMessageId: source.source_start_message_id,
|
|
363
|
+
sourceEndMessageId: source.source_end_message_id
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
return provenance;
|
|
367
|
+
} catch {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function loadPrimerSourceProvenance(db, candidateIds) {
|
|
372
|
+
const ids = [...new Set(candidateIds)].sort((a, b) => a - b);
|
|
373
|
+
if (ids.length === 0)
|
|
374
|
+
return [];
|
|
375
|
+
const placeholders = ids.map(() => "?").join(",");
|
|
376
|
+
const rows = db.prepare(`SELECT id, project_path, harness, session_id,
|
|
377
|
+
source_compartment_start, source_compartment_end,
|
|
378
|
+
source_start_message_id, source_end_message_id
|
|
379
|
+
FROM primer_candidates
|
|
380
|
+
WHERE id IN (${placeholders})
|
|
381
|
+
ORDER BY id ASC`).all(...ids);
|
|
382
|
+
return rows.map((row) => ({
|
|
383
|
+
candidateId: row.id,
|
|
384
|
+
projectPath: row.project_path,
|
|
385
|
+
harness: row.harness,
|
|
386
|
+
sessionId: row.session_id,
|
|
387
|
+
sourceCompartmentStart: row.source_compartment_start,
|
|
388
|
+
sourceCompartmentEnd: row.source_compartment_end,
|
|
389
|
+
sourceStartMessageId: row.source_start_message_id,
|
|
390
|
+
sourceEndMessageId: row.source_end_message_id
|
|
391
|
+
}));
|
|
392
|
+
}
|
|
393
|
+
function serializePrimerSourceProvenance(provenance, sourceCandidateIds) {
|
|
394
|
+
if (provenance.length === 0 && sourceCandidateIds.length > 0)
|
|
395
|
+
return null;
|
|
396
|
+
return JSON.stringify(provenance.map((source) => ({
|
|
397
|
+
candidate_id: source.candidateId,
|
|
398
|
+
project_path: source.projectPath,
|
|
399
|
+
harness: source.harness,
|
|
400
|
+
session_id: source.sessionId,
|
|
401
|
+
source_compartment_start: source.sourceCompartmentStart,
|
|
402
|
+
source_compartment_end: source.sourceCompartmentEnd,
|
|
403
|
+
source_start_message_id: source.sourceStartMessageId,
|
|
404
|
+
source_end_message_id: source.sourceEndMessageId
|
|
405
|
+
})));
|
|
406
|
+
}
|
|
407
|
+
function normalizedCandidateIds(candidateIds) {
|
|
408
|
+
return [...new Set(candidateIds)].sort((a, b) => a - b);
|
|
409
|
+
}
|
|
410
|
+
function toCandidate(row) {
|
|
411
|
+
return {
|
|
412
|
+
id: row.id,
|
|
413
|
+
projectPath: row.project_path,
|
|
414
|
+
harness: row.harness,
|
|
415
|
+
sessionId: row.session_id,
|
|
416
|
+
question: row.question,
|
|
417
|
+
normalizedQuestion: row.normalized_question,
|
|
418
|
+
sourceCompartmentStart: row.source_compartment_start,
|
|
419
|
+
sourceCompartmentEnd: row.source_compartment_end,
|
|
420
|
+
sourceStartMessageId: row.source_start_message_id,
|
|
421
|
+
sourceEndMessageId: row.source_end_message_id,
|
|
422
|
+
sourceMessageTime: row.source_message_time,
|
|
423
|
+
questionEmbedding: blobToFloat32Array(row.question_embedding),
|
|
424
|
+
questionEmbeddingModelId: row.question_embedding_model_id,
|
|
425
|
+
createdAt: row.created_at
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
function toPrimer(row) {
|
|
429
|
+
const status = row.status === "archived" ? "archived" : "active";
|
|
430
|
+
return {
|
|
431
|
+
id: row.id,
|
|
432
|
+
projectPath: row.project_path,
|
|
433
|
+
question: row.question,
|
|
434
|
+
questionEmbedding: blobToFloat32Array(row.question_embedding),
|
|
435
|
+
questionEmbeddingModelId: row.question_embedding_model_id,
|
|
436
|
+
answer: row.answer,
|
|
437
|
+
status,
|
|
438
|
+
totalSupport: row.total_support,
|
|
439
|
+
lastObservedAt: row.last_observed_at,
|
|
440
|
+
answerRefreshedAt: row.answer_refreshed_at,
|
|
441
|
+
sourceCandidateIds: parseCandidateIds(row.source_candidate_ids),
|
|
442
|
+
sourceProvenance: parsePrimerSourceProvenance(row.source_candidate_provenance),
|
|
443
|
+
createdAt: row.created_at,
|
|
444
|
+
updatedAt: row.updated_at
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
function insertPrimerCandidates(db, candidates) {
|
|
448
|
+
const ids = [];
|
|
449
|
+
const stmt = db.prepare(`
|
|
450
|
+
INSERT INTO primer_candidates (
|
|
451
|
+
project_path, harness, session_id, question, normalized_question,
|
|
452
|
+
source_compartment_start, source_compartment_end,
|
|
453
|
+
source_start_message_id, source_end_message_id, source_message_time,
|
|
454
|
+
question_embedding, question_embedding_model_id, created_at
|
|
455
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
456
|
+
ON CONFLICT(project_path, harness, session_id, source_start_message_id, source_end_message_id)
|
|
457
|
+
DO UPDATE SET
|
|
458
|
+
question = excluded.question,
|
|
459
|
+
normalized_question = excluded.normalized_question,
|
|
460
|
+
source_compartment_start = excluded.source_compartment_start,
|
|
461
|
+
source_compartment_end = excluded.source_compartment_end,
|
|
462
|
+
source_message_time = excluded.source_message_time,
|
|
463
|
+
question_embedding = COALESCE(excluded.question_embedding, primer_candidates.question_embedding),
|
|
464
|
+
question_embedding_model_id = COALESCE(excluded.question_embedding_model_id, primer_candidates.question_embedding_model_id),
|
|
465
|
+
created_at = MIN(primer_candidates.created_at, excluded.created_at)
|
|
466
|
+
`);
|
|
467
|
+
const select = db.prepare(`
|
|
468
|
+
SELECT id FROM primer_candidates
|
|
469
|
+
WHERE project_path = ? AND harness = ? AND session_id = ?
|
|
470
|
+
AND source_start_message_id = ? AND source_end_message_id = ?
|
|
471
|
+
`);
|
|
472
|
+
db.transaction(() => {
|
|
473
|
+
for (const candidate of candidates) {
|
|
474
|
+
const question = candidate.question.trim();
|
|
475
|
+
if (!question)
|
|
476
|
+
continue;
|
|
477
|
+
const normalized = candidate.normalizedQuestion ?? normalizePrimerQuestion(question);
|
|
478
|
+
stmt.run(candidate.projectPath, candidate.harness || "opencode", candidate.sessionId, question, normalized, candidate.sourceCompartmentStart ?? null, candidate.sourceCompartmentEnd ?? null, candidate.sourceStartMessageId, candidate.sourceEndMessageId, candidate.sourceMessageTime, vectorBlob(candidate.questionEmbedding), candidate.questionEmbeddingModelId ?? null, candidate.createdAt ?? Date.now());
|
|
479
|
+
const row = select.get(candidate.projectPath, candidate.harness || "opencode", candidate.sessionId, candidate.sourceStartMessageId, candidate.sourceEndMessageId);
|
|
480
|
+
if (typeof row?.id === "number")
|
|
481
|
+
ids.push(row.id);
|
|
482
|
+
}
|
|
483
|
+
}).immediate();
|
|
484
|
+
return ids;
|
|
485
|
+
}
|
|
486
|
+
function updatePrimerCandidateEmbedding(db, candidateId, vector, modelId) {
|
|
487
|
+
db.prepare("UPDATE primer_candidates SET question_embedding = ?, question_embedding_model_id = ? WHERE id = ?").run(vectorBlob(vector), modelId, candidateId);
|
|
488
|
+
}
|
|
489
|
+
function getPrimerCandidatesByIds(db, ids) {
|
|
490
|
+
if (ids.length === 0)
|
|
491
|
+
return [];
|
|
492
|
+
const placeholders = ids.map(() => "?").join(",");
|
|
493
|
+
const rows = db.prepare(`SELECT * FROM primer_candidates WHERE id IN (${placeholders})`).all(...ids);
|
|
494
|
+
return rows.map(toCandidate);
|
|
495
|
+
}
|
|
496
|
+
function getPrimerCandidatesForPromotion(db, projectPath, now = Date.now(), ttlMs = PRIMER_CANDIDATE_TTL_MS) {
|
|
497
|
+
const cutoff = now - ttlMs;
|
|
498
|
+
const rows = db.prepare(`SELECT * FROM primer_candidates
|
|
499
|
+
WHERE project_path = ? AND source_message_time >= ?
|
|
500
|
+
ORDER BY project_path ASC, harness ASC, session_id ASC, source_start_message_id ASC, source_end_message_id ASC, id ASC`).all(projectPath, cutoff);
|
|
501
|
+
return rows.map(toCandidate);
|
|
502
|
+
}
|
|
503
|
+
function countPrimerCandidatesForProject(db, projectPath) {
|
|
504
|
+
const row = db.prepare("SELECT COUNT(*) AS count FROM primer_candidates WHERE project_path = ?").get(projectPath);
|
|
505
|
+
return row?.count ?? 0;
|
|
506
|
+
}
|
|
507
|
+
function getActivePrimers(db, projectPath) {
|
|
508
|
+
const rows = db.prepare(`SELECT * FROM primers
|
|
509
|
+
WHERE project_path = ? AND status = 'active'
|
|
510
|
+
ORDER BY COALESCE(last_observed_at, created_at) DESC, id ASC`).all(projectPath);
|
|
511
|
+
return rows.map(toPrimer);
|
|
512
|
+
}
|
|
513
|
+
function createPrimer(db, input) {
|
|
514
|
+
return db.transaction(() => {
|
|
515
|
+
const now = input.now ?? Date.now();
|
|
516
|
+
const sourceCandidateIds = normalizedCandidateIds(input.sourceCandidateIds);
|
|
517
|
+
const sourceProvenance = loadPrimerSourceProvenance(db, sourceCandidateIds);
|
|
518
|
+
const info = db.prepare(`INSERT INTO primers (
|
|
519
|
+
project_path, question, question_embedding, question_embedding_model_id, answer,
|
|
520
|
+
status, total_support, last_observed_at, answer_refreshed_at,
|
|
521
|
+
source_candidate_ids, source_candidate_provenance, created_at, updated_at
|
|
522
|
+
) VALUES (?, ?, ?, ?, ?, 'active', ?, ?, NULL, ?, ?, ?, ?)`).run(input.projectPath, input.question, vectorBlob(input.questionEmbedding), input.questionEmbeddingModelId ?? null, input.answer ?? "", input.totalSupport, input.lastObservedAt, JSON.stringify(sourceCandidateIds), serializePrimerSourceProvenance(sourceProvenance, sourceCandidateIds), now, now);
|
|
523
|
+
return Number(info.lastInsertRowid);
|
|
524
|
+
}).immediate();
|
|
525
|
+
}
|
|
526
|
+
function updatePrimerSupport(db, input) {
|
|
527
|
+
db.transaction(() => {
|
|
528
|
+
const sourceCandidateIds = normalizedCandidateIds(input.sourceCandidateIds);
|
|
529
|
+
const allowedIds = new Set(sourceCandidateIds);
|
|
530
|
+
const existingRow = db.prepare("SELECT source_candidate_provenance FROM primers WHERE id = ?").get(input.primerId);
|
|
531
|
+
const provenanceByCandidateId = new Map;
|
|
532
|
+
for (const source of parsePrimerSourceProvenance(existingRow?.source_candidate_provenance ?? null) ?? []) {
|
|
533
|
+
if (allowedIds.has(source.candidateId)) {
|
|
534
|
+
provenanceByCandidateId.set(source.candidateId, source);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
for (const source of loadPrimerSourceProvenance(db, sourceCandidateIds)) {
|
|
538
|
+
provenanceByCandidateId.set(source.candidateId, source);
|
|
539
|
+
}
|
|
540
|
+
const sourceProvenance = [...provenanceByCandidateId.values()].sort((a, b) => a.candidateId - b.candidateId);
|
|
541
|
+
db.prepare(`UPDATE primers
|
|
542
|
+
SET question_embedding = COALESCE(?, question_embedding),
|
|
543
|
+
question_embedding_model_id = COALESCE(?, question_embedding_model_id),
|
|
544
|
+
total_support = ?,
|
|
545
|
+
last_observed_at = ?,
|
|
546
|
+
source_candidate_ids = ?,
|
|
547
|
+
source_candidate_provenance = ?,
|
|
548
|
+
updated_at = ?
|
|
549
|
+
WHERE id = ?`).run(vectorBlob(input.questionEmbedding), input.questionEmbeddingModelId ?? null, input.totalSupport, input.lastObservedAt, JSON.stringify(sourceCandidateIds), serializePrimerSourceProvenance(sourceProvenance, sourceCandidateIds), input.now ?? Date.now(), input.primerId);
|
|
550
|
+
}).immediate();
|
|
551
|
+
}
|
|
552
|
+
function updatePrimerAnswer(db, primerId, answer, refreshedAt = Date.now()) {
|
|
553
|
+
db.prepare("UPDATE primers SET answer = ?, answer_refreshed_at = ?, updated_at = ? WHERE id = ?").run(answer, refreshedAt, refreshedAt, primerId);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// src/shared/user-facing-codes.ts
|
|
557
|
+
var USER_FACING_FAILURES = {
|
|
558
|
+
historian_unavailable: {
|
|
559
|
+
code: "MC-H01",
|
|
560
|
+
sentence: "History compression could not finish this turn.",
|
|
561
|
+
action: "It will retry automatically."
|
|
562
|
+
},
|
|
563
|
+
historian_saved_history_misaligned: {
|
|
564
|
+
code: "MC-H03",
|
|
565
|
+
sentence: "History compression is paused because this session's saved summaries no longer line up with its messages.",
|
|
566
|
+
action: "Run /ctx-recomp to rebuild them."
|
|
567
|
+
},
|
|
568
|
+
history_boundary_unresolved: {
|
|
569
|
+
code: "MC-H04",
|
|
570
|
+
sentence: "This request was not sent: the message that marks where this session's history summary ends is missing from the OpenCode store, and without it the request is larger than the model's context window.",
|
|
571
|
+
action: "Run /ctx-recomp to rebuild the history summary."
|
|
572
|
+
},
|
|
573
|
+
history_over_window_unmanaged: {
|
|
574
|
+
code: "MC-H06",
|
|
575
|
+
sentence: "This request was not sent: this session's history is larger than the model's context window, and Magic Context does not have a summary of it yet to send in its place.",
|
|
576
|
+
action: "Send your message again once history compression has caught up, or switch to a model with a larger context window."
|
|
577
|
+
},
|
|
578
|
+
frozen_history_over_window: {
|
|
579
|
+
code: "MC-H07",
|
|
580
|
+
sentence: "This request was not sent: the conversation is larger than the context window the provider reported, and the compressed history Magic Context has ready does not fit either.",
|
|
581
|
+
action: "Run /ctx-flush to compress it now, then send your message again."
|
|
582
|
+
},
|
|
583
|
+
historian_window_too_small: {
|
|
584
|
+
code: "MC-H05",
|
|
585
|
+
sentence: "History compression is paused because the history model's context window is too small for its instructions.",
|
|
586
|
+
action: "Set historian.model in magic-context.jsonc to a model with a larger context window."
|
|
587
|
+
},
|
|
588
|
+
recomp_unavailable: {
|
|
589
|
+
code: "MC-R01",
|
|
590
|
+
sentence: "History compression could not be rebuilt.",
|
|
591
|
+
action: "Run /ctx-recomp again."
|
|
592
|
+
},
|
|
593
|
+
dream_provider_timeout: {
|
|
594
|
+
code: "MC-D01",
|
|
595
|
+
sentence: "Memory maintenance took too long to respond.",
|
|
596
|
+
action: "Run /ctx-dream again."
|
|
597
|
+
},
|
|
598
|
+
dream_provider_error: {
|
|
599
|
+
code: "MC-D02",
|
|
600
|
+
sentence: "Memory maintenance could not reach its model.",
|
|
601
|
+
action: "Check the model connection, then run /ctx-dream again."
|
|
602
|
+
},
|
|
603
|
+
dream_local_refusal: {
|
|
604
|
+
code: "MC-D12",
|
|
605
|
+
sentence: "Memory maintenance was refused before reaching the model.",
|
|
606
|
+
action: "Check the hidden-request diagnostic in the Magic Context log before retrying."
|
|
607
|
+
},
|
|
608
|
+
dream_step_limit: {
|
|
609
|
+
code: "MC-D10",
|
|
610
|
+
sentence: "Memory maintenance stopped at its hidden agent step limit.",
|
|
611
|
+
action: "This task needs less work per run; changing the model connection will not help."
|
|
612
|
+
},
|
|
613
|
+
dream_token_budget: {
|
|
614
|
+
code: "MC-D11",
|
|
615
|
+
sentence: "Memory maintenance reached its prompt-token budget.",
|
|
616
|
+
action: "The unfinished items will be retried on the next run."
|
|
617
|
+
},
|
|
618
|
+
dream_empty_completion: {
|
|
619
|
+
code: "MC-D03",
|
|
620
|
+
sentence: "Memory maintenance received no usable response.",
|
|
621
|
+
action: "Run /ctx-dream again."
|
|
622
|
+
},
|
|
623
|
+
dream_no_models: {
|
|
624
|
+
code: "MC-D04",
|
|
625
|
+
sentence: "Memory maintenance has no model available.",
|
|
626
|
+
action: "Check the model settings, then run /ctx-dream again."
|
|
627
|
+
},
|
|
628
|
+
dream_child_aborted: {
|
|
629
|
+
code: "MC-D05",
|
|
630
|
+
sentence: "Memory maintenance was interrupted.",
|
|
631
|
+
action: "Run /ctx-dream again."
|
|
632
|
+
},
|
|
633
|
+
dream_parse_failed: {
|
|
634
|
+
code: "MC-D06",
|
|
635
|
+
sentence: "Memory maintenance could not use the model response.",
|
|
636
|
+
action: "Run /ctx-dream again."
|
|
637
|
+
},
|
|
638
|
+
dream_unknown: {
|
|
639
|
+
code: "MC-D07",
|
|
640
|
+
sentence: "Memory maintenance could not finish.",
|
|
641
|
+
action: "Run /ctx-dream again."
|
|
642
|
+
},
|
|
643
|
+
dreamer_tick_blocked: {
|
|
644
|
+
code: "MC-D09",
|
|
645
|
+
sentence: "Background maintenance is not running: its last pass stopped before it reached the scheduled tasks.",
|
|
646
|
+
action: "It is retried automatically; if it keeps happening, check the Magic Context log for the stage that stopped and run `npx @cortexkit/magic-context doctor`."
|
|
647
|
+
},
|
|
648
|
+
dream_task_needs_tool_loop: {
|
|
649
|
+
code: "MC-D08",
|
|
650
|
+
sentence: "Some memory maintenance tasks need a tool loop this host does not provide.",
|
|
651
|
+
action: "The remaining tasks still run; the listed ones are skipped on this host."
|
|
652
|
+
},
|
|
653
|
+
embedding_substitution_rejected: {
|
|
654
|
+
code: "MC-E01",
|
|
655
|
+
sentence: "Search indexing could not use the selected model.",
|
|
656
|
+
action: "Check the embedding model setting, then run /ctx-embed start again."
|
|
657
|
+
},
|
|
658
|
+
embedding_http_error: {
|
|
659
|
+
code: "MC-E02",
|
|
660
|
+
sentence: "The search indexing provider refused the request.",
|
|
661
|
+
action: "Check the provider connection and credentials, then run /ctx-embed start again."
|
|
662
|
+
},
|
|
663
|
+
embedding_transport_error: {
|
|
664
|
+
code: "MC-E03",
|
|
665
|
+
sentence: "Search indexing could not reach its provider.",
|
|
666
|
+
action: "Check the connection, then run /ctx-embed start again."
|
|
667
|
+
},
|
|
668
|
+
embedding_invalid_envelope: {
|
|
669
|
+
code: "MC-E04",
|
|
670
|
+
sentence: "Search indexing received an unsupported response.",
|
|
671
|
+
action: "Check the embedding endpoint, then run /ctx-embed start again."
|
|
672
|
+
},
|
|
673
|
+
embedding_empty_result: {
|
|
674
|
+
code: "MC-E05",
|
|
675
|
+
sentence: "Search indexing received no usable result.",
|
|
676
|
+
action: "Run /ctx-embed start again."
|
|
677
|
+
},
|
|
678
|
+
embedding_certification_refusal: {
|
|
679
|
+
code: "MC-E06",
|
|
680
|
+
sentence: "Search indexing is not ready for this provider.",
|
|
681
|
+
action: "Finish the provider setup, or set a fallback provider in the embedding settings, then run /ctx-embed start again."
|
|
682
|
+
},
|
|
683
|
+
embedding_credential_required: {
|
|
684
|
+
code: "MC-E07",
|
|
685
|
+
sentence: "Search indexing needs provider credentials.",
|
|
686
|
+
action: "Sign in to the provider, then run /ctx-embed start again."
|
|
687
|
+
},
|
|
688
|
+
embedding_local_binding_missing: {
|
|
689
|
+
code: "MC-E08",
|
|
690
|
+
sentence: "Local search indexing is unavailable on this system.",
|
|
691
|
+
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
692
|
+
},
|
|
693
|
+
embedding_local_fs_unavailable: {
|
|
694
|
+
code: "MC-E09",
|
|
695
|
+
sentence: "Local search indexing cannot save its model files.",
|
|
696
|
+
action: "Update or reinstall Magic Context, then retry."
|
|
697
|
+
},
|
|
698
|
+
embedding_local_download_failure: {
|
|
699
|
+
code: "MC-E10",
|
|
700
|
+
sentence: "Local search indexing could not download its model.",
|
|
701
|
+
action: "Check the network connection, then retry."
|
|
702
|
+
},
|
|
703
|
+
embedding_local_runtime_error: {
|
|
704
|
+
code: "MC-E11",
|
|
705
|
+
sentence: "Local search indexing could not start.",
|
|
706
|
+
action: "Run `npx @cortexkit/magic-context doctor`, then retry."
|
|
707
|
+
},
|
|
708
|
+
embedding_unavailable: {
|
|
709
|
+
code: "MC-E12",
|
|
710
|
+
sentence: "Search indexing could not finish.",
|
|
711
|
+
action: "Run /ctx-embed start again."
|
|
712
|
+
},
|
|
713
|
+
status_unavailable: {
|
|
714
|
+
code: "MC-S01",
|
|
715
|
+
sentence: "Magic Context status is temporarily unavailable.",
|
|
716
|
+
action: "Retry /ctx-status in a moment."
|
|
717
|
+
},
|
|
718
|
+
transform_update_failed: {
|
|
719
|
+
code: "MC-S02",
|
|
720
|
+
sentence: "The last context update did not finish.",
|
|
721
|
+
action: "Send another message to retry."
|
|
722
|
+
},
|
|
723
|
+
transform_pass_degraded: {
|
|
724
|
+
code: "MC-S06",
|
|
725
|
+
sentence: "This request was not sent: Magic Context could not finish preparing it, and without that preparation it could be far larger than the previous request.",
|
|
726
|
+
action: "Send your message again."
|
|
727
|
+
},
|
|
728
|
+
configuration_warning: {
|
|
729
|
+
code: "MC-S03",
|
|
730
|
+
sentence: "Some configuration settings could not be applied.",
|
|
731
|
+
action: "Fix the configuration warning shown in /ctx-status, then restart."
|
|
732
|
+
},
|
|
733
|
+
status_log_unavailable: {
|
|
734
|
+
code: "MC-S04",
|
|
735
|
+
sentence: "Some diagnostic details could not be saved.",
|
|
736
|
+
action: "Retry /ctx-status in a moment."
|
|
737
|
+
},
|
|
738
|
+
memory_writes_paused: {
|
|
739
|
+
code: "MC-C01",
|
|
740
|
+
sentence: "Memory writes are paused while the engine syncs.",
|
|
741
|
+
action: "Retry in a moment."
|
|
742
|
+
},
|
|
743
|
+
memory_access_unavailable: {
|
|
744
|
+
code: "MC-C02",
|
|
745
|
+
sentence: "Memory access is temporarily unavailable.",
|
|
746
|
+
action: "Retry in a moment."
|
|
747
|
+
},
|
|
748
|
+
note_changes_paused: {
|
|
749
|
+
code: "MC-C03",
|
|
750
|
+
sentence: "Note changes are paused while the engine syncs.",
|
|
751
|
+
action: "Retry in a moment."
|
|
752
|
+
},
|
|
753
|
+
note_access_unavailable: {
|
|
754
|
+
code: "MC-C04",
|
|
755
|
+
sentence: "Notes are temporarily unavailable.",
|
|
756
|
+
action: "Retry in a moment."
|
|
757
|
+
},
|
|
758
|
+
context_cleanup_paused: {
|
|
759
|
+
code: "MC-C05",
|
|
760
|
+
sentence: "Context cleanup is paused while the engine syncs.",
|
|
761
|
+
action: "Retry in a moment."
|
|
762
|
+
},
|
|
763
|
+
partial_history_unavailable: {
|
|
764
|
+
code: "MC-C06",
|
|
765
|
+
sentence: "Partial history compression is not available in the current mode.",
|
|
766
|
+
action: "Run /ctx-recomp without a range."
|
|
767
|
+
},
|
|
768
|
+
smart_note_conditions_unavailable: {
|
|
769
|
+
code: "MC-C08",
|
|
770
|
+
sentence: "Conditional notes are not available in the current mode.",
|
|
771
|
+
action: "Save a regular note without a condition."
|
|
772
|
+
},
|
|
773
|
+
history_compression_paused: {
|
|
774
|
+
code: "MC-C09",
|
|
775
|
+
sentence: "History compression is paused while the engine syncs.",
|
|
776
|
+
action: "Retry in a moment."
|
|
777
|
+
},
|
|
778
|
+
history_compression_needs_message: {
|
|
779
|
+
code: "MC-C12",
|
|
780
|
+
sentence: "History compression has not seen this session since Magic Context reconnected.",
|
|
781
|
+
action: "Send a message in this session first, then run /ctx-wrapup again."
|
|
782
|
+
},
|
|
783
|
+
context_service_unavailable: {
|
|
784
|
+
code: "MC-C10",
|
|
785
|
+
sentence: "Magic Context is temporarily unavailable.",
|
|
786
|
+
action: "Retry in a moment."
|
|
787
|
+
},
|
|
788
|
+
context_db_missing: {
|
|
789
|
+
code: "MC-C15",
|
|
790
|
+
sentence: "Magic Context has no context.db.",
|
|
791
|
+
action: "Run `npx @cortexkit/magic-context doctor store init`, then restart ck-mc."
|
|
792
|
+
},
|
|
793
|
+
single_store_migration_required: {
|
|
794
|
+
code: "MC-C14",
|
|
795
|
+
sentence: "Magic Context's Rust mode needs a one-time migration of its store.",
|
|
796
|
+
action: "Quit OpenCode and every ck-mc process, then run `magic-context doctor single-store migrate`."
|
|
797
|
+
},
|
|
798
|
+
store_ahead_of_binary: {
|
|
799
|
+
code: "MC-C13",
|
|
800
|
+
sentence: "Magic Context refused to start: its store (store.db) was migrated by a newer ck-mc build than the one running.",
|
|
801
|
+
action: "Update ck-mc, or roll back by restoring ck-mc together with context.db and store.db from the same backup."
|
|
802
|
+
},
|
|
803
|
+
compaction_marker_missing: {
|
|
804
|
+
code: "MC-C11",
|
|
805
|
+
sentence: "The history boundary marker is missing from the OpenCode store, so requests carry the full session.",
|
|
806
|
+
action: "It is retried on every message; if this persists, run `/ctx-flush`."
|
|
807
|
+
},
|
|
808
|
+
memory_mirror_stalled: {
|
|
809
|
+
code: "MC-M01",
|
|
810
|
+
sentence: "Memory synchronization stopped before the host mirror caught up.",
|
|
811
|
+
action: "Send another message to resume it, or run `ck doctor drain-authority`."
|
|
812
|
+
},
|
|
813
|
+
memory_authority_mismatch: {
|
|
814
|
+
code: "MC-M02",
|
|
815
|
+
sentence: "Memory authority is inconsistent between the host and module.",
|
|
816
|
+
action: "Run `ck doctor drain-authority` before changing Rust mode."
|
|
817
|
+
},
|
|
818
|
+
dreamer_task_failing: {
|
|
819
|
+
code: "MC-S05",
|
|
820
|
+
sentence: "A background maintenance task keeps failing on its schedule.",
|
|
821
|
+
action: "Check the Magic Context log for the failing task and its error."
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
function renderUserFacingFailure(key, style = "markdown") {
|
|
825
|
+
const failure = USER_FACING_FAILURES[key];
|
|
826
|
+
const action = style === "plain" ? failure.action.replaceAll("`", "") : failure.action;
|
|
827
|
+
return `${failure.sentence} ${action} (${failure.code})`;
|
|
828
|
+
}
|
|
829
|
+
function userFacingFailureCode(key) {
|
|
830
|
+
return USER_FACING_FAILURES[key].code;
|
|
831
|
+
}
|
|
832
|
+
var CAPABILITY_FAILURES = {
|
|
833
|
+
memory_write: "memory_writes_paused",
|
|
834
|
+
memory_access: "memory_access_unavailable",
|
|
835
|
+
note_change: "note_changes_paused",
|
|
836
|
+
note_access: "note_access_unavailable",
|
|
837
|
+
context_cleanup: "context_cleanup_paused",
|
|
838
|
+
partial_history: "partial_history_unavailable",
|
|
839
|
+
smart_note_condition: "smart_note_conditions_unavailable",
|
|
840
|
+
history_compression: "history_compression_paused",
|
|
841
|
+
context_service: "context_service_unavailable"
|
|
842
|
+
};
|
|
843
|
+
function renderCapabilityRefusal(capability) {
|
|
844
|
+
return renderUserFacingFailure(CAPABILITY_FAILURES[capability]);
|
|
845
|
+
}
|
|
846
|
+
var DREAM_FAILURE_KEYS = {
|
|
847
|
+
provider_timeout: "dream_provider_timeout",
|
|
848
|
+
provider_error: "dream_provider_error",
|
|
849
|
+
local_refusal: "dream_local_refusal",
|
|
850
|
+
step_limit: "dream_step_limit",
|
|
851
|
+
token_budget: "dream_token_budget",
|
|
852
|
+
empty_completion: "dream_empty_completion",
|
|
853
|
+
no_models: "dream_no_models",
|
|
854
|
+
child_aborted: "dream_child_aborted",
|
|
855
|
+
parse_failed: "dream_parse_failed",
|
|
856
|
+
unknown: "dream_unknown"
|
|
857
|
+
};
|
|
858
|
+
var EMBEDDING_FAILURE_KEYS = {
|
|
859
|
+
substitution_rejected: "embedding_substitution_rejected",
|
|
860
|
+
http_error: "embedding_http_error",
|
|
861
|
+
transport_error: "embedding_transport_error",
|
|
862
|
+
invalid_envelope: "embedding_invalid_envelope",
|
|
863
|
+
empty_result: "embedding_empty_result",
|
|
864
|
+
certification_refusal: "embedding_certification_refusal",
|
|
865
|
+
credential_required: "embedding_credential_required",
|
|
866
|
+
local_binding_missing: "embedding_local_binding_missing",
|
|
867
|
+
local_fs_unavailable: "embedding_local_fs_unavailable",
|
|
868
|
+
local_download_failure: "embedding_local_download_failure",
|
|
869
|
+
local_runtime_error: "embedding_local_runtime_error"
|
|
870
|
+
};
|
|
871
|
+
function renderDreamFailure(failureClass, style = "markdown", refusalReason) {
|
|
872
|
+
const rendered = renderUserFacingFailure(DREAM_FAILURE_KEYS[failureClass], style);
|
|
873
|
+
return failureClass === "local_refusal" && refusalReason ? `${rendered} Reason: ${sanitizeDiagnosticText(refusalReason).slice(0, 500)}` : rendered;
|
|
874
|
+
}
|
|
875
|
+
function dreamFailureCode(failureClass) {
|
|
876
|
+
return userFacingFailureCode(DREAM_FAILURE_KEYS[failureClass]);
|
|
877
|
+
}
|
|
878
|
+
function renderEmbeddingFailure(failureClass, style = "markdown") {
|
|
879
|
+
return renderUserFacingFailure(EMBEDDING_FAILURE_KEYS[failureClass], style);
|
|
880
|
+
}
|
|
881
|
+
// src/features/magic-context/memory/promotion.ts
|
|
882
|
+
function isPromotableCategory(category) {
|
|
883
|
+
return PROMOTABLE_CATEGORIES.some((promotableCategory) => promotableCategory === category);
|
|
884
|
+
}
|
|
885
|
+
function resolveExpiresAt(category) {
|
|
886
|
+
const ttl = CATEGORY_DEFAULT_TTL[category];
|
|
887
|
+
return ttl === undefined ? null : Date.now() + ttl;
|
|
888
|
+
}
|
|
889
|
+
function promoteSessionFactsDurable(db, sessionId, projectPath, facts) {
|
|
890
|
+
const newMemoryRefs = [];
|
|
891
|
+
let factsPromoted = 0;
|
|
892
|
+
for (const fact of facts) {
|
|
893
|
+
if (!fact || typeof fact.category !== "string" || typeof fact.content !== "string" || fact.content.trim().length === 0) {
|
|
894
|
+
continue;
|
|
895
|
+
}
|
|
896
|
+
if (!isPromotableCategory(fact.category)) {
|
|
897
|
+
continue;
|
|
898
|
+
}
|
|
899
|
+
const normalizedHash = computeNormalizedHash(fact.content);
|
|
900
|
+
const existingMemory = getMemoryByHash2(db, projectPath, fact.category, normalizedHash);
|
|
901
|
+
if (existingMemory) {
|
|
902
|
+
updateMemorySeenCount2(db, existingMemory.id);
|
|
903
|
+
factsPromoted += 1;
|
|
904
|
+
continue;
|
|
905
|
+
}
|
|
906
|
+
const memoryInput = {
|
|
907
|
+
projectPath,
|
|
908
|
+
category: fact.category,
|
|
909
|
+
content: fact.content,
|
|
910
|
+
sourceSessionId: sessionId,
|
|
911
|
+
sourceType: "historian",
|
|
912
|
+
expiresAt: resolveExpiresAt(fact.category)
|
|
913
|
+
};
|
|
914
|
+
const memory = insertMemory2(db, memoryInput);
|
|
915
|
+
newMemoryRefs.push({ memoryId: memory.id, content: memory.content });
|
|
916
|
+
factsPromoted += 1;
|
|
917
|
+
}
|
|
918
|
+
return { newMemoryRefs, factsPromoted };
|
|
919
|
+
}
|
|
920
|
+
async function embedPromotedFacts(db, sessionId, projectPath, refs) {
|
|
921
|
+
for (const ref of refs) {
|
|
922
|
+
await embedAndStoreMemory(db, sessionId, projectPath, ref.memoryId, ref.content);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
async function embedAndStoreMemory(db, sessionId, projectPath, memoryId, content) {
|
|
926
|
+
try {
|
|
927
|
+
const hashBeforeEmbed = getMemoryById2(db, memoryId)?.normalizedHash;
|
|
928
|
+
if (!hashBeforeEmbed) {
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
const result = await embedTextForProject2(projectPath, content);
|
|
932
|
+
if (result) {
|
|
933
|
+
db.transaction(() => {
|
|
934
|
+
saveEmbeddingIfHashMatches(db, memoryId, result.vector, result.modelId, hashBeforeEmbed);
|
|
935
|
+
}).immediate();
|
|
936
|
+
}
|
|
937
|
+
} catch (error) {
|
|
938
|
+
sessionLog2(sessionId, `memory embedding failed for memory ${memoryId}:`, error);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
// src/features/magic-context/memory/storage-memory-fts.ts
|
|
942
|
+
var DEFAULT_SEARCH_LIMIT = 10;
|
|
943
|
+
var searchStatements = new WeakMap;
|
|
944
|
+
var datedSearchStatements = new WeakMap;
|
|
945
|
+
var unionSearchStatements = new Map;
|
|
946
|
+
var datedUnionSearchStatements = new Map;
|
|
947
|
+
function getSearchStatement(db, dated = false) {
|
|
948
|
+
const statements = dated ? datedSearchStatements : searchStatements;
|
|
949
|
+
let stmt = statements.get(db);
|
|
950
|
+
if (!stmt) {
|
|
951
|
+
stmt = db.prepare(`SELECT ${getMemorySelectColumns2(db)} FROM memories_fts INNER JOIN memories ON memories.id = memories_fts.rowid WHERE memories.project_path = ? AND memories.status IN ('active', 'permanent') AND (memories.expires_at IS NULL OR memories.expires_at > ?)${dated ? " AND memories.created_at BETWEEN ? AND ?" : ""} AND memories_fts MATCH ? ORDER BY bm25(memories_fts), memories.updated_at DESC, memories.id ASC LIMIT ?`);
|
|
952
|
+
statements.set(db, stmt);
|
|
953
|
+
}
|
|
954
|
+
return stmt;
|
|
955
|
+
}
|
|
956
|
+
function getUnionSearchStatement(db, arity, dated = false) {
|
|
957
|
+
const statementRegistry = dated ? datedUnionSearchStatements : unionSearchStatements;
|
|
958
|
+
let statements = statementRegistry.get(arity);
|
|
959
|
+
if (!statements) {
|
|
960
|
+
statements = new WeakMap;
|
|
961
|
+
statementRegistry.set(arity, statements);
|
|
962
|
+
}
|
|
963
|
+
let stmt = statements.get(db);
|
|
964
|
+
if (!stmt) {
|
|
965
|
+
const placeholders = Array.from({ length: arity }, () => "?").join(", ");
|
|
966
|
+
stmt = db.prepare(`SELECT ${getMemorySelectColumns2(db)} FROM memories_fts INNER JOIN memories ON memories.id = memories_fts.rowid WHERE memories.project_path IN (${placeholders}) AND memories.status IN ('active', 'permanent') AND (memories.expires_at IS NULL OR memories.expires_at > ?)${dated ? " AND memories.created_at BETWEEN ? AND ?" : ""} AND memories_fts MATCH ? ORDER BY bm25(memories_fts), memories.updated_at DESC, memories.id ASC LIMIT ?`);
|
|
967
|
+
statements.set(db, stmt);
|
|
968
|
+
}
|
|
969
|
+
return stmt;
|
|
970
|
+
}
|
|
971
|
+
function uniqueProjectPaths(projectPaths) {
|
|
972
|
+
return [...new Set(projectPaths.filter((path) => path.length > 0))];
|
|
973
|
+
}
|
|
974
|
+
function relaxedFtsQuery(query) {
|
|
975
|
+
const tokens = [...new Set(query.match(/[\p{L}\p{N}_]+/gu) ?? [])].filter((token) => token.length > 2 || /\d/.test(token)).slice(0, 16);
|
|
976
|
+
return tokens.map((token) => `"${token.replace(/"/g, '""')}"`).join(" OR ");
|
|
977
|
+
}
|
|
978
|
+
function sanitizeFtsQuery(query) {
|
|
979
|
+
const tokens = query.replaceAll("\x00", " ").split(/\s+/).filter((token) => token.length > 0);
|
|
980
|
+
if (tokens.length === 0)
|
|
981
|
+
return "";
|
|
982
|
+
return tokens.map((token) => `"${token.replace(/"/g, '""')}"`).join(" ");
|
|
983
|
+
}
|
|
984
|
+
function searchMemoriesFTS(db, projectPath, query, limit = DEFAULT_SEARCH_LIMIT, dateRange = null) {
|
|
985
|
+
const trimmedQuery = query.trim();
|
|
986
|
+
if (trimmedQuery.length === 0 || limit <= 0) {
|
|
987
|
+
return [];
|
|
988
|
+
}
|
|
989
|
+
const sanitized = sanitizeFtsQuery(trimmedQuery);
|
|
990
|
+
if (sanitized.length === 0) {
|
|
991
|
+
return [];
|
|
992
|
+
}
|
|
993
|
+
let rows = getSearchStatement(db, dateRange !== null).all(projectPath, Date.now(), ...dateRange === null ? [] : [dateRange.from, dateRange.to], sanitized, limit).filter(isMemoryRow2);
|
|
994
|
+
if (rows.length === 0) {
|
|
995
|
+
const relaxed = relaxedFtsQuery(trimmedQuery);
|
|
996
|
+
if (relaxed)
|
|
997
|
+
rows = getSearchStatement(db, dateRange !== null).all(projectPath, Date.now(), ...dateRange === null ? [] : [dateRange.from, dateRange.to], relaxed, limit).filter(isMemoryRow2);
|
|
998
|
+
}
|
|
999
|
+
return rows.map(toMemory2);
|
|
1000
|
+
}
|
|
1001
|
+
function searchMemoriesFTSUnion(db, projectPaths, query, limit = DEFAULT_SEARCH_LIMIT, ownIdentities, shareCategories, dateRange = null) {
|
|
1002
|
+
const identities = uniqueProjectPaths(projectPaths);
|
|
1003
|
+
if (identities.length === 0)
|
|
1004
|
+
return [];
|
|
1005
|
+
const sharingFilter = buildWorkspaceMemorySqlFilter2({
|
|
1006
|
+
identities,
|
|
1007
|
+
ownIdentities,
|
|
1008
|
+
shareCategories,
|
|
1009
|
+
tableName: "memories",
|
|
1010
|
+
includeClassificationFields: (() => {
|
|
1011
|
+
const columns = db.prepare("PRAGMA table_info(memories)").all();
|
|
1012
|
+
return columns.some((row) => row.name === "shareable") && columns.some((row) => row.name === "scope");
|
|
1013
|
+
})()
|
|
1014
|
+
});
|
|
1015
|
+
if (identities.length === 1 && !sharingFilter.active) {
|
|
1016
|
+
return searchMemoriesFTS(db, identities[0], query, limit, dateRange);
|
|
1017
|
+
}
|
|
1018
|
+
const trimmedQuery = query.trim();
|
|
1019
|
+
if (trimmedQuery.length === 0 || limit <= 0)
|
|
1020
|
+
return [];
|
|
1021
|
+
const sanitized = sanitizeFtsQuery(trimmedQuery);
|
|
1022
|
+
if (sanitized.length === 0)
|
|
1023
|
+
return [];
|
|
1024
|
+
let rows = sharingFilter.active ? db.prepare(`SELECT ${getMemorySelectColumns2(db)} FROM memories_fts INNER JOIN memories ON memories.id = memories_fts.rowid WHERE memories.project_path IN (${identities.map(() => "?").join(", ")}) AND memories.status IN ('active', 'permanent') AND (memories.expires_at IS NULL OR memories.expires_at > ?)${dateRange === null ? "" : " AND memories.created_at BETWEEN ? AND ?"} AND memories_fts MATCH ?${sharingFilter.clause} ORDER BY bm25(memories_fts), memories.updated_at DESC, memories.id ASC LIMIT ?`).all(...identities, Date.now(), ...dateRange === null ? [] : [dateRange.from, dateRange.to], sanitized, ...sharingFilter.params, limit).filter(isMemoryRow2) : getUnionSearchStatement(db, identities.length, dateRange !== null).all(...identities, Date.now(), ...dateRange === null ? [] : [dateRange.from, dateRange.to], sanitized, limit).filter(isMemoryRow2);
|
|
1025
|
+
if (rows.length === 0) {
|
|
1026
|
+
const relaxed = relaxedFtsQuery(trimmedQuery);
|
|
1027
|
+
if (relaxed) {
|
|
1028
|
+
rows = (sharingFilter.active ? db.prepare(`SELECT ${getMemorySelectColumns2(db)} FROM memories_fts INNER JOIN memories ON memories.id = memories_fts.rowid WHERE memories.project_path IN (${identities.map(() => "?").join(", ")}) AND memories.status IN ('active', 'permanent') AND (memories.expires_at IS NULL OR memories.expires_at > ?)${dateRange === null ? "" : " AND memories.created_at BETWEEN ? AND ?"} AND memories_fts MATCH ?${sharingFilter.clause} ORDER BY bm25(memories_fts), memories.updated_at DESC, memories.id ASC LIMIT ?`) : getUnionSearchStatement(db, identities.length, dateRange !== null)).all(...identities, Date.now(), ...dateRange === null ? [] : [dateRange.from, dateRange.to], relaxed, ...sharingFilter.params, limit).filter(isMemoryRow2);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
return rows.map(toMemory2);
|
|
1032
|
+
}
|
|
1033
|
+
// src/features/magic-context/memory/storage-memory-verifications.ts
|
|
1034
|
+
var MEMORY_VERIFICATION_SENTINEL = "";
|
|
1035
|
+
function uniqueSortedFiles(files) {
|
|
1036
|
+
return Array.from(new Set(files.filter((file) => file !== MEMORY_VERIFICATION_SENTINEL))).sort();
|
|
1037
|
+
}
|
|
1038
|
+
function recordMemoryMapping(db, memoryId, normalizedFiles, now, mappingOrigin = "mapper") {
|
|
1039
|
+
const realFiles = uniqueSortedFiles(normalizedFiles);
|
|
1040
|
+
const filesToWrite = realFiles.length > 0 ? realFiles : [MEMORY_VERIFICATION_SENTINEL];
|
|
1041
|
+
db.prepare("DELETE FROM memory_verifications WHERE memory_id = ?").run(memoryId);
|
|
1042
|
+
const insert = db.prepare("INSERT INTO memory_verifications (memory_id, file_path, verified_at, mapped_at, mapping_origin) VALUES (?, ?, 0, ?, ?)");
|
|
1043
|
+
for (const file of filesToWrite) {
|
|
1044
|
+
insert.run(memoryId, file, now, mappingOrigin);
|
|
1045
|
+
}
|
|
1046
|
+
return filesToWrite.length;
|
|
1047
|
+
}
|
|
1048
|
+
function recordMemoryVerifications(db, memoryId, normalizedFiles, now) {
|
|
1049
|
+
const realFiles = uniqueSortedFiles(normalizedFiles);
|
|
1050
|
+
const filesToWrite = realFiles.length > 0 ? realFiles : [MEMORY_VERIFICATION_SENTINEL];
|
|
1051
|
+
db.prepare("DELETE FROM memory_verifications WHERE memory_id = ?").run(memoryId);
|
|
1052
|
+
const insert = db.prepare("INSERT INTO memory_verifications (memory_id, file_path, verified_at, mapped_at, mapping_origin) VALUES (?, ?, ?, ?, 'mapper')");
|
|
1053
|
+
for (const file of filesToWrite) {
|
|
1054
|
+
insert.run(memoryId, file, now, now);
|
|
1055
|
+
}
|
|
1056
|
+
return filesToWrite.length;
|
|
1057
|
+
}
|
|
1058
|
+
function getUnmappedMemoryIds(db, memoryIds) {
|
|
1059
|
+
const ids = Array.from(new Set(memoryIds.filter(Number.isInteger)));
|
|
1060
|
+
if (ids.length === 0)
|
|
1061
|
+
return [];
|
|
1062
|
+
const rows = db.prepare("SELECT DISTINCT memory_id FROM memory_verifications WHERE memory_id IN (SELECT value FROM json_each(?))").all(JSON.stringify(ids));
|
|
1063
|
+
const mapped = new Set(rows.map((r) => r.memory_id));
|
|
1064
|
+
return ids.filter((id) => !mapped.has(id));
|
|
1065
|
+
}
|
|
1066
|
+
function clearMemoryVerifications(db, memoryId) {
|
|
1067
|
+
db.prepare("DELETE FROM memory_verifications WHERE memory_id = ?").run(memoryId);
|
|
1068
|
+
}
|
|
1069
|
+
function getMemoryVerifications(db, memoryIds) {
|
|
1070
|
+
const ids = Array.from(new Set(memoryIds.filter(Number.isInteger)));
|
|
1071
|
+
const result = new Map;
|
|
1072
|
+
if (ids.length === 0)
|
|
1073
|
+
return result;
|
|
1074
|
+
const rows = db.prepare(`SELECT memory_id, file_path, verified_at, mapped_at, mapping_origin
|
|
1075
|
+
FROM memory_verifications
|
|
1076
|
+
WHERE memory_id IN (SELECT value FROM json_each(?))
|
|
1077
|
+
ORDER BY memory_id, file_path`).all(JSON.stringify(ids));
|
|
1078
|
+
for (const row of rows) {
|
|
1079
|
+
const existing = result.get(row.memory_id) ?? {
|
|
1080
|
+
files: [],
|
|
1081
|
+
hasSentinel: false,
|
|
1082
|
+
mappingOrigin: "mapper",
|
|
1083
|
+
verifiedAt: 0,
|
|
1084
|
+
mappedAt: 0
|
|
1085
|
+
};
|
|
1086
|
+
if (row.file_path === MEMORY_VERIFICATION_SENTINEL) {
|
|
1087
|
+
existing.hasSentinel = true;
|
|
1088
|
+
} else if (!existing.files.includes(row.file_path)) {
|
|
1089
|
+
existing.files.push(row.file_path);
|
|
1090
|
+
}
|
|
1091
|
+
if (row.mapping_origin === "host_rejected_fallback") {
|
|
1092
|
+
existing.mappingOrigin = "host_rejected_fallback";
|
|
1093
|
+
}
|
|
1094
|
+
existing.verifiedAt = Math.max(existing.verifiedAt, row.verified_at);
|
|
1095
|
+
existing.mappedAt = Math.max(existing.mappedAt, row.mapped_at ?? 0);
|
|
1096
|
+
result.set(row.memory_id, existing);
|
|
1097
|
+
}
|
|
1098
|
+
for (const state of result.values()) {
|
|
1099
|
+
state.files.sort();
|
|
1100
|
+
}
|
|
1101
|
+
return result;
|
|
1102
|
+
}
|
|
1103
|
+
// src/features/magic-context/memory/verification-paths.ts
|
|
1104
|
+
import { execFile } from "node:child_process";
|
|
1105
|
+
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
1106
|
+
import path from "node:path";
|
|
1107
|
+
import { promisify } from "node:util";
|
|
1108
|
+
var execFileAsync = promisify(execFile);
|
|
1109
|
+
var GIT_TIMEOUT_MS = 1e4;
|
|
1110
|
+
var defaultExecFileForVerificationPaths = async (file, args, options) => await execFileAsync(file, [...args], {
|
|
1111
|
+
...options,
|
|
1112
|
+
windowsHide: true
|
|
1113
|
+
});
|
|
1114
|
+
var execFileForVerificationPaths = defaultExecFileForVerificationPaths;
|
|
1115
|
+
async function runGit(cwd, args) {
|
|
1116
|
+
try {
|
|
1117
|
+
const result = await execFileForVerificationPaths("git", args, {
|
|
1118
|
+
cwd,
|
|
1119
|
+
timeout: GIT_TIMEOUT_MS,
|
|
1120
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
1121
|
+
encoding: "utf8",
|
|
1122
|
+
windowsHide: true
|
|
1123
|
+
});
|
|
1124
|
+
return String(result.stdout);
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
if (error.killed || error.code === "ETIMEDOUT") {
|
|
1127
|
+
throw new Error(`Git verification command git ${args.join(" ")} timed out after ${GIT_TIMEOUT_MS}ms`, {
|
|
1128
|
+
cause: error
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
return null;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
function toPosixPath(value) {
|
|
1135
|
+
return value.split(path.sep).join("/");
|
|
1136
|
+
}
|
|
1137
|
+
function isWithin(root, candidate) {
|
|
1138
|
+
const rel = path.relative(root, candidate);
|
|
1139
|
+
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
1140
|
+
}
|
|
1141
|
+
function safeRealpath(value) {
|
|
1142
|
+
try {
|
|
1143
|
+
return realpathSync.native(value);
|
|
1144
|
+
} catch {
|
|
1145
|
+
return null;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
async function resolveGitTopLevel(cwd) {
|
|
1149
|
+
const stdout = await runGit(cwd, ["rev-parse", "--show-toplevel"]);
|
|
1150
|
+
const root = stdout?.trim();
|
|
1151
|
+
return root ? safeRealpath(root) ?? path.resolve(root) : null;
|
|
1152
|
+
}
|
|
1153
|
+
async function readGitHead(cwd) {
|
|
1154
|
+
const stdout = await runGit(cwd, ["rev-parse", "HEAD"]);
|
|
1155
|
+
const head = stdout?.trim();
|
|
1156
|
+
return head && /^[0-9a-f]{40}$/i.test(head) ? head : null;
|
|
1157
|
+
}
|
|
1158
|
+
async function readGitChangedFilesSince(cwd, revision, knownGitRoot) {
|
|
1159
|
+
if (!/^[0-9a-f]{7,40}$/i.test(revision))
|
|
1160
|
+
return null;
|
|
1161
|
+
const gitRoot = knownGitRoot ?? await resolveGitTopLevel(cwd);
|
|
1162
|
+
if (!gitRoot)
|
|
1163
|
+
return null;
|
|
1164
|
+
const stdout = await runGit(gitRoot, ["diff", "--name-only", "-z", revision]);
|
|
1165
|
+
if (stdout === null)
|
|
1166
|
+
return null;
|
|
1167
|
+
return new Set(stdout.split("\x00").filter(Boolean));
|
|
1168
|
+
}
|
|
1169
|
+
async function readGitFileChangeTimesSince(cwd, sinceMs, knownGitRoot) {
|
|
1170
|
+
const gitRoot = knownGitRoot ?? await resolveGitTopLevel(cwd);
|
|
1171
|
+
if (!gitRoot)
|
|
1172
|
+
return null;
|
|
1173
|
+
const sinceSec = Math.max(0, Math.floor(sinceMs / 1000));
|
|
1174
|
+
const stdout = await runGit(gitRoot, [
|
|
1175
|
+
"log",
|
|
1176
|
+
`--since=@${sinceSec}`,
|
|
1177
|
+
"--name-only",
|
|
1178
|
+
"--format=%ct"
|
|
1179
|
+
]);
|
|
1180
|
+
if (stdout === null)
|
|
1181
|
+
return null;
|
|
1182
|
+
const times = new Map;
|
|
1183
|
+
let currentMs = 0;
|
|
1184
|
+
for (const rawLine of stdout.split(`
|
|
1185
|
+
`)) {
|
|
1186
|
+
const line = rawLine.trimEnd();
|
|
1187
|
+
if (line === "")
|
|
1188
|
+
continue;
|
|
1189
|
+
if (/^\d+$/.test(line)) {
|
|
1190
|
+
currentMs = Number.parseInt(line, 10) * 1000;
|
|
1191
|
+
continue;
|
|
1192
|
+
}
|
|
1193
|
+
if (currentMs > 0 && !times.has(line)) {
|
|
1194
|
+
times.set(line, currentMs);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
return times;
|
|
1198
|
+
}
|
|
1199
|
+
async function gitTrackedPath(gitRoot, repoRelativePath) {
|
|
1200
|
+
const stdout = await runGit(gitRoot, [
|
|
1201
|
+
"ls-files",
|
|
1202
|
+
"-z",
|
|
1203
|
+
"--full-name",
|
|
1204
|
+
"--error-unmatch",
|
|
1205
|
+
"--",
|
|
1206
|
+
repoRelativePath
|
|
1207
|
+
]);
|
|
1208
|
+
const fallbackStdout = stdout === null ? await runGit(gitRoot, ["ls-files", "-z", "--full-name"]) : null;
|
|
1209
|
+
if (stdout === null && fallbackStdout === null)
|
|
1210
|
+
return null;
|
|
1211
|
+
const matches = (stdout ?? fallbackStdout ?? "").split("\x00").filter(Boolean);
|
|
1212
|
+
if (matches.length === 0)
|
|
1213
|
+
return null;
|
|
1214
|
+
return matches.find((match) => match === repoRelativePath) ?? matches.find((match) => match.toLowerCase() === repoRelativePath.toLowerCase()) ?? (matches.length === 1 ? matches[0] : null);
|
|
1215
|
+
}
|
|
1216
|
+
function verificationFileExists(baseRoot, filePath) {
|
|
1217
|
+
if (!filePath || filePath === ".")
|
|
1218
|
+
return false;
|
|
1219
|
+
const root = path.resolve(baseRoot);
|
|
1220
|
+
const candidate = path.resolve(root, filePath);
|
|
1221
|
+
return isWithin(root, candidate) && existsSync(candidate);
|
|
1222
|
+
}
|
|
1223
|
+
async function normalizeVerificationFiles(args) {
|
|
1224
|
+
const cwd = path.resolve(args.cwd);
|
|
1225
|
+
const gitRoot = await resolveGitTopLevel(cwd);
|
|
1226
|
+
const root = gitRoot ?? cwd;
|
|
1227
|
+
const rootReal = safeRealpath(root) ?? root;
|
|
1228
|
+
const warnings = [];
|
|
1229
|
+
const normalized = [];
|
|
1230
|
+
let trackedPaths;
|
|
1231
|
+
for (const raw of args.files) {
|
|
1232
|
+
const value = typeof raw === "string" ? raw.trim() : "";
|
|
1233
|
+
if (!value) {
|
|
1234
|
+
warnings.push("Skipped blank verification path.");
|
|
1235
|
+
continue;
|
|
1236
|
+
}
|
|
1237
|
+
if (value === ".") {
|
|
1238
|
+
warnings.push('Skipped verification path "." (repo/project root is not a file).');
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
const candidate = path.resolve(cwd, value);
|
|
1242
|
+
const candidateReal = safeRealpath(candidate);
|
|
1243
|
+
if (candidateReal && !isWithin(rootReal, candidateReal)) {
|
|
1244
|
+
warnings.push(`Skipped verification path "${value}" because it resolves outside the project.`);
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
if (!candidateReal && !isWithin(path.resolve(root), candidate)) {
|
|
1248
|
+
warnings.push(`Skipped verification path "${value}" because it escapes the project.`);
|
|
1249
|
+
continue;
|
|
1250
|
+
}
|
|
1251
|
+
if (path.resolve(root) === candidate) {
|
|
1252
|
+
warnings.push(`Skipped verification path "${value}" because it is the repo/project root.`);
|
|
1253
|
+
continue;
|
|
1254
|
+
}
|
|
1255
|
+
if (existsSync(candidate)) {
|
|
1256
|
+
try {
|
|
1257
|
+
if (statSync(candidate).isDirectory()) {
|
|
1258
|
+
warnings.push(`Skipped verification path "${value}" because it is a directory.`);
|
|
1259
|
+
continue;
|
|
1260
|
+
}
|
|
1261
|
+
} catch {
|
|
1262
|
+
warnings.push(`Skipped verification path "${value}" because it could not be inspected.`);
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
if (gitRoot) {
|
|
1267
|
+
const repoRelative = toPosixPath(path.relative(gitRoot, candidateReal ?? candidate));
|
|
1268
|
+
if (!repoRelative || repoRelative === "." || repoRelative.startsWith("../")) {
|
|
1269
|
+
warnings.push(`Skipped verification path "${value}" because it is not inside the git repo.`);
|
|
1270
|
+
continue;
|
|
1271
|
+
}
|
|
1272
|
+
if (!trackedPaths) {
|
|
1273
|
+
let trackedOutput = null;
|
|
1274
|
+
try {
|
|
1275
|
+
trackedOutput = await runGit(gitRoot, ["ls-files", "-z", "--full-name"]);
|
|
1276
|
+
} catch {}
|
|
1277
|
+
trackedPaths = new Set(trackedOutput?.split("\x00").filter(Boolean) ?? []);
|
|
1278
|
+
}
|
|
1279
|
+
const tracked = trackedPaths.has(repoRelative) ? repoRelative : await gitTrackedPath(gitRoot, repoRelative);
|
|
1280
|
+
if (!tracked) {
|
|
1281
|
+
warnings.push(`Skipped verification path "${value}" because it is not a tracked git file.`);
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
if (candidateReal && tracked !== repoRelative) {
|
|
1285
|
+
const realRelative = toPosixPath(path.relative(gitRoot, candidateReal));
|
|
1286
|
+
if (realRelative !== tracked) {
|
|
1287
|
+
warnings.push(`Skipped verification path "${value}" because it is not a tracked git file.`);
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
normalized.push(tracked);
|
|
1292
|
+
} else {
|
|
1293
|
+
if (!existsSync(candidate)) {
|
|
1294
|
+
warnings.push(`Skipped verification path "${value}" because it does not exist.`);
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
const projectRelative = toPosixPath(path.relative(cwd, candidate));
|
|
1298
|
+
if (!projectRelative || projectRelative === "." || projectRelative.startsWith("../")) {
|
|
1299
|
+
warnings.push(`Skipped verification path "${value}" because it is not inside the project.`);
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
normalized.push(projectRelative);
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
return {
|
|
1306
|
+
files: Array.from(new Set(normalized)).sort(),
|
|
1307
|
+
warnings,
|
|
1308
|
+
gitRoot
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
export { SESSION_NOTE_CONDITION_ERROR, getNoteByIdInScope, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, updateNote, dismissNotes, dismissNote, markNoteReady, markNoteChecked, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, insertPrimerCandidates, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, USER_FACING_FAILURES, renderUserFacingFailure, userFacingFailureCode, renderCapabilityRefusal, renderDreamFailure, dreamFailureCode, renderEmbeddingFailure, promoteSessionFactsDurable, embedPromotedFacts, relaxedFtsQuery, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles };
|