@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
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
Priority,
|
|
3
|
+
AdmissionClass,
|
|
4
|
+
SocketClosedError,
|
|
5
|
+
SocketTimeoutError,
|
|
6
|
+
StaleRouteHandleError,
|
|
7
|
+
SubcClient,
|
|
8
|
+
isConsumerReconnectTransient
|
|
9
|
+
} from "./index-vkbqdnkj.js";
|
|
4
10
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
getHarness2
|
|
12
|
+
} from "./index-pavzsdc6.js";
|
|
13
|
+
import {
|
|
14
|
+
getDataDir
|
|
15
|
+
} from "./index-0sahzkwr.js";
|
|
16
|
+
import {
|
|
17
|
+
log2
|
|
18
|
+
} from "./index-nsjyysj0.js";
|
|
19
|
+
import {
|
|
20
|
+
buildCanonicalChunkTextFromFts,
|
|
21
|
+
loadCompartmentChunkEmbeddingsForSearch
|
|
22
|
+
} from "./index-b7mv1jx3.js";
|
|
11
23
|
import {
|
|
12
|
-
loadCompartmentChunkEmbeddingsForSearch,
|
|
13
|
-
getIndexedMessageCorpusSize,
|
|
14
24
|
recordEmbeddingMeasurement,
|
|
15
|
-
getNotes,
|
|
16
|
-
getActivePrimers,
|
|
17
|
-
cosineSimilarity,
|
|
18
25
|
saveCommitEmbedding,
|
|
19
26
|
loadProjectCommitEmbeddings,
|
|
20
27
|
loadUnembeddedCommits,
|
|
@@ -22,29 +29,813 @@ import {
|
|
|
22
29
|
upsertCommits,
|
|
23
30
|
getLatestIndexedCommitSha,
|
|
24
31
|
enforceProjectCap,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
contentSha2562,
|
|
33
|
+
getShadowEmbeddingMeasurementCohort2,
|
|
34
|
+
getPrimaryEmbeddingMeasurementCohort2,
|
|
35
|
+
embedShadowTextForProject2,
|
|
36
|
+
enqueueShadowEmbeddingItems2,
|
|
37
|
+
getProjectEmbeddingSnapshot2,
|
|
38
|
+
embedItemsForProject2
|
|
39
|
+
} from "./index-kp5qe690.js";
|
|
40
|
+
import {
|
|
41
|
+
getProjectEmbeddings2
|
|
42
|
+
} from "./index-4dhv7mqz.js";
|
|
43
|
+
import {
|
|
44
|
+
cosineSimilarity,
|
|
33
45
|
isEmbeddingEnabled,
|
|
34
46
|
embedText,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
ensureMemoryEmbeddings2
|
|
48
|
+
} from "./index-peshmj6h.js";
|
|
49
|
+
import {
|
|
50
|
+
ModuleMemoryAuthorityError2,
|
|
51
|
+
getMemoriesByProject2,
|
|
52
|
+
getMemoriesByProjects2,
|
|
53
|
+
updateMemoryRetrievalCount2
|
|
54
|
+
} from "./index-7jzrrxap.js";
|
|
55
|
+
import {
|
|
56
|
+
USER_FACING_FAILURES,
|
|
57
|
+
getNotes,
|
|
58
|
+
getActivePrimers,
|
|
40
59
|
relaxedFtsQuery,
|
|
41
60
|
sanitizeFtsQuery,
|
|
42
61
|
searchMemoriesFTS,
|
|
43
62
|
searchMemoriesFTSUnion
|
|
44
|
-
} from "./index-
|
|
63
|
+
} from "./index-kmpvemph.js";
|
|
64
|
+
import {
|
|
65
|
+
isRecord
|
|
66
|
+
} from "./index-nydv6g8r.js";
|
|
67
|
+
import {
|
|
68
|
+
getIndexedMessageCorpusSize
|
|
69
|
+
} from "./index-hj2q50k0.js";
|
|
70
|
+
import {
|
|
71
|
+
resolveWorkspaceShareCategories,
|
|
72
|
+
resolveWorkspaceIdentitySet,
|
|
73
|
+
expandWorkspaceIdentitySetWithAliases,
|
|
74
|
+
resolveStoredPathWorkspaceIdentity,
|
|
75
|
+
sourceNameForMemory
|
|
76
|
+
} from "./index-nm6a8xpd.js";
|
|
45
77
|
import {
|
|
46
78
|
isKnownAutocommit
|
|
47
|
-
} from "./index-
|
|
79
|
+
} from "./index-8ajstryz.js";
|
|
80
|
+
|
|
81
|
+
// src/hooks/magic-context/module-transport.ts
|
|
82
|
+
import { realpathSync } from "node:fs";
|
|
83
|
+
import { join } from "node:path";
|
|
84
|
+
|
|
85
|
+
// src/hooks/magic-context/reply-pages.ts
|
|
86
|
+
import { createHash } from "node:crypto";
|
|
87
|
+
var MAX_REPLY_BYTES = 128 * 1024 * 1024;
|
|
88
|
+
var MAX_PAGE_BYTES = 512 * 1024;
|
|
89
|
+
function fail() {
|
|
90
|
+
throw Object.assign(new Error("Incomplete or invalid module reply; abandon this pass"), {
|
|
91
|
+
code: "reply_page_invalid"
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
async function assembleReplyPages(response, fetchPage) {
|
|
95
|
+
if (!isRecord(response) || !("reply_page" in response))
|
|
96
|
+
return response;
|
|
97
|
+
const first = response.reply_page;
|
|
98
|
+
if (!isRecord(first))
|
|
99
|
+
fail();
|
|
100
|
+
const { id, total, bytes } = first;
|
|
101
|
+
if (typeof id !== "string" || !/^[a-f0-9]{64}$/.test(id) || typeof total !== "number" || !Number.isSafeInteger(total) || total < 2 || total > 4096 || typeof bytes !== "number" || !Number.isSafeInteger(bytes) || bytes <= 0 || bytes > MAX_REPLY_BYTES)
|
|
102
|
+
fail();
|
|
103
|
+
const chunks = [];
|
|
104
|
+
let received = 0;
|
|
105
|
+
for (let index = 0;index < total; index += 1) {
|
|
106
|
+
const envelope = index === 0 ? response : await fetchPage(id, index);
|
|
107
|
+
if (!isRecord(envelope) || !isRecord(envelope.reply_page))
|
|
108
|
+
fail();
|
|
109
|
+
const page = envelope.reply_page;
|
|
110
|
+
if (page.id !== id || page.index !== index || page.total !== total || page.bytes !== bytes || typeof page.data !== "string")
|
|
111
|
+
fail();
|
|
112
|
+
if (Buffer.byteLength(JSON.stringify(envelope)) > MAX_PAGE_BYTES)
|
|
113
|
+
fail();
|
|
114
|
+
const chunk = Buffer.from(page.data, "utf8");
|
|
115
|
+
received += chunk.length;
|
|
116
|
+
if (received > bytes)
|
|
117
|
+
fail();
|
|
118
|
+
chunks.push(chunk);
|
|
119
|
+
}
|
|
120
|
+
if (received !== bytes)
|
|
121
|
+
fail();
|
|
122
|
+
const rebuilt = Buffer.concat(chunks, received);
|
|
123
|
+
if (createHash("sha256").update(rebuilt).digest("hex") !== id)
|
|
124
|
+
fail();
|
|
125
|
+
return JSON.parse(rebuilt.toString("utf8"));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/hooks/magic-context/single-store-refusal.ts
|
|
129
|
+
var SINGLE_STORE_MIGRATION_REQUIRED_CODE = "single_store_migration_required";
|
|
130
|
+
function renderSingleStoreMigrationRequiredRefusal() {
|
|
131
|
+
const failure = USER_FACING_FAILURES.single_store_migration_required;
|
|
132
|
+
return `${failure.sentence} ${failure.action} (${failure.code})`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
class SingleStoreMigrationRequiredError extends Error {
|
|
136
|
+
code = SINGLE_STORE_MIGRATION_REQUIRED_CODE;
|
|
137
|
+
constructor(options) {
|
|
138
|
+
super(renderSingleStoreMigrationRequiredRefusal(), options);
|
|
139
|
+
this.name = "SingleStoreMigrationRequiredError";
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function singleStoreMigrationRequiredFailure(error) {
|
|
143
|
+
let current = error;
|
|
144
|
+
const seen = new Set;
|
|
145
|
+
while (current !== null && typeof current === "object" && !seen.has(current)) {
|
|
146
|
+
seen.add(current);
|
|
147
|
+
if (current instanceof SingleStoreMigrationRequiredError)
|
|
148
|
+
return current;
|
|
149
|
+
const frame = current;
|
|
150
|
+
if (frame.code === SINGLE_STORE_MIGRATION_REQUIRED_CODE || frame.code === "single_store_state_split") {
|
|
151
|
+
return new SingleStoreMigrationRequiredError({ cause: error });
|
|
152
|
+
}
|
|
153
|
+
current = frame.cause;
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
function projectNeedsSingleStoreMigration(db, projectPath) {
|
|
158
|
+
const table = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'authority_managed'").get();
|
|
159
|
+
return Boolean(table && db.prepare("SELECT 1 FROM authority_managed WHERE project_path = ?").get(projectPath));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/hooks/magic-context/store-ahead-refusal.ts
|
|
163
|
+
var STORE_AHEAD_OF_BINARY_CODE = "store_ahead_of_binary";
|
|
164
|
+
function renderStoreAheadOfBinaryRefusal(versions) {
|
|
165
|
+
const failure = USER_FACING_FAILURES.store_ahead_of_binary;
|
|
166
|
+
const sentence = versions ? `Magic Context refused to start: its store (store.db) is at schema v${versions.dbVersion} but this ck-mc build only knows up to v${versions.binaryMax}.` : failure.sentence;
|
|
167
|
+
return `${sentence} ${failure.action} (${failure.code})`;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
class StoreAheadOfBinaryError extends Error {
|
|
171
|
+
code = STORE_AHEAD_OF_BINARY_CODE;
|
|
172
|
+
versions;
|
|
173
|
+
constructor(versions, options) {
|
|
174
|
+
super(renderStoreAheadOfBinaryRefusal(versions), options);
|
|
175
|
+
this.name = "StoreAheadOfBinaryError";
|
|
176
|
+
this.versions = versions;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function isRecord2(value) {
|
|
180
|
+
return value !== null && typeof value === "object";
|
|
181
|
+
}
|
|
182
|
+
function nonNegativeInteger(value) {
|
|
183
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
184
|
+
}
|
|
185
|
+
function versionsFromDetail(detail) {
|
|
186
|
+
if (!isRecord2(detail))
|
|
187
|
+
return null;
|
|
188
|
+
const dbVersion = nonNegativeInteger(detail.db_version);
|
|
189
|
+
const binaryMax = nonNegativeInteger(detail.binary_max);
|
|
190
|
+
return dbVersion !== null && binaryMax !== null ? { dbVersion, binaryMax } : null;
|
|
191
|
+
}
|
|
192
|
+
function versionsFromMessage(message) {
|
|
193
|
+
if (typeof message !== "string")
|
|
194
|
+
return null;
|
|
195
|
+
const match = /db_version=(\d+) binary_max=(\d+)/.exec(message) ?? /schema v(\d+) but this ck-mc build only knows up to v(\d+)/.exec(message);
|
|
196
|
+
if (!match)
|
|
197
|
+
return null;
|
|
198
|
+
return { dbVersion: Number(match[1]), binaryMax: Number(match[2]) };
|
|
199
|
+
}
|
|
200
|
+
function storeAheadOfBinaryFailure(error) {
|
|
201
|
+
let current = error;
|
|
202
|
+
const seen = new Set;
|
|
203
|
+
while (isRecord2(current) && !seen.has(current)) {
|
|
204
|
+
seen.add(current);
|
|
205
|
+
if (current instanceof StoreAheadOfBinaryError)
|
|
206
|
+
return current;
|
|
207
|
+
if (current.code === STORE_AHEAD_OF_BINARY_CODE) {
|
|
208
|
+
const versions = versionsFromDetail(current.detail) ?? versionsFromMessage(current.message);
|
|
209
|
+
return new StoreAheadOfBinaryError(versions, { cause: error });
|
|
210
|
+
}
|
|
211
|
+
current = current.cause;
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/hooks/magic-context/module-transport.ts
|
|
217
|
+
var DEFAULT_MODULE_ID = "magic-context";
|
|
218
|
+
var CONNECT_BACKOFF_INITIAL_MS = 1000;
|
|
219
|
+
var CONNECT_BACKOFF_MAX_MS = 30000;
|
|
220
|
+
var CONNECT_BACKOFF_WAIT_BUDGET_MS = 12000;
|
|
221
|
+
var CONNECT_BACKOFF_WAIT_JITTER_MS = 100;
|
|
222
|
+
var HANDSHAKE_TIMEOUT_MS = 2000;
|
|
223
|
+
var MODULE_SEND_TIMEOUT_MS = 15000;
|
|
224
|
+
var TRANSFORM_PAGE_UPLOAD_TIMEOUT_MS = 5000;
|
|
225
|
+
var TRANSFORM_COLD_START_EXECUTE_TIMEOUT_MS = 15000;
|
|
226
|
+
var TRANSFORM_COLD_START_EXECUTE_TIMEOUT_PER_MESSAGE_MS = 2;
|
|
227
|
+
var TRANSFORM_COLD_START_EXECUTE_TIMEOUT_MAX_MS = 90000;
|
|
228
|
+
function transformColdStartExecuteTimeoutMs(seedMessageCount) {
|
|
229
|
+
const messages = Number.isSafeInteger(seedMessageCount) ? Math.max(0, seedMessageCount) : 0;
|
|
230
|
+
return Math.min(TRANSFORM_COLD_START_EXECUTE_TIMEOUT_MAX_MS, TRANSFORM_COLD_START_EXECUTE_TIMEOUT_MS + messages * TRANSFORM_COLD_START_EXECUTE_TIMEOUT_PER_MESSAGE_MS);
|
|
231
|
+
}
|
|
232
|
+
var MAX_WRAPUP_REQUEST_BUDGET_MS = 3800000;
|
|
233
|
+
var SERIAL_LANE_MAX_WAITERS = 16;
|
|
234
|
+
var SERIAL_LANE_MAX_WAITERS_PER_SESSION = 8;
|
|
235
|
+
var SERIAL_LANE_MIN_REMAINING_MS = 25;
|
|
236
|
+
var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
|
|
237
|
+
function getDefaultSubcConnectionFile() {
|
|
238
|
+
return join(getDataDir(), "cortexkit", "run", "subc-connection.json");
|
|
239
|
+
}
|
|
240
|
+
function errorChainSome(error, predicate) {
|
|
241
|
+
let current = error;
|
|
242
|
+
const seen = new Set;
|
|
243
|
+
while (isRecord(current) && !seen.has(current)) {
|
|
244
|
+
seen.add(current);
|
|
245
|
+
if (predicate(current))
|
|
246
|
+
return true;
|
|
247
|
+
current = current.cause;
|
|
248
|
+
}
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
function isStaleOrDeadRouteFailure(error) {
|
|
252
|
+
return errorChainSome(error, (current) => {
|
|
253
|
+
const code = typeof current.code === "string" ? current.code : "";
|
|
254
|
+
const name = typeof current.name === "string" ? current.name : "";
|
|
255
|
+
const message = typeof current.message === "string" ? current.message : "";
|
|
256
|
+
return [
|
|
257
|
+
"stale_route_handle",
|
|
258
|
+
"route_closed",
|
|
259
|
+
"unknown_channel",
|
|
260
|
+
"unrecognized_channel",
|
|
261
|
+
"route_gone"
|
|
262
|
+
].includes(code) || name === "StaleRouteHandleError" || /route handle \(\d+,\s*\d+\) is not live on the current connection/i.test(message) || /\b(?:unknown|unrecognized) channel\b/i.test(message);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function isDeadlineFailure(error) {
|
|
266
|
+
if (error instanceof SocketTimeoutError)
|
|
267
|
+
return true;
|
|
268
|
+
return errorChainSome(error, (current) => {
|
|
269
|
+
const code = typeof current.code === "string" ? current.code : "";
|
|
270
|
+
return ["ETIMEDOUT", "request_deadline", "deadline_exceeded_no_drop_observed"].includes(code);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function isConnectionFailure(error) {
|
|
274
|
+
if (error instanceof SocketClosedError || error instanceof SocketTimeoutError || error instanceof StaleRouteHandleError || isConsumerReconnectTransient(error) || isStaleOrDeadRouteFailure(error)) {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
return errorChainSome(error, (current) => {
|
|
278
|
+
const code = typeof current.code === "string" ? current.code : "";
|
|
279
|
+
const message = typeof current.message === "string" ? current.message : "";
|
|
280
|
+
return [
|
|
281
|
+
"ENOENT",
|
|
282
|
+
"ECONNREFUSED",
|
|
283
|
+
"ECONNRESET",
|
|
284
|
+
"EPIPE",
|
|
285
|
+
"ETIMEDOUT",
|
|
286
|
+
"request_deadline",
|
|
287
|
+
"deadline_exceeded_no_drop_observed",
|
|
288
|
+
"connection_dropped",
|
|
289
|
+
"SUBC_CONNECTION_BACKOFF"
|
|
290
|
+
].includes(code) || /\bclient closed\b|\bconnection closed\b|\bclosed the connection\b/i.test(message);
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
function routeOpenWithoutAmbientConsumerIdentity(client, target, identity, options = {}) {
|
|
294
|
+
return client.routeOpen(target, identity, {
|
|
295
|
+
...options,
|
|
296
|
+
consumerIdentity: null
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function isModuleTransportGenerationChangedResult(value) {
|
|
300
|
+
return isRecord(value) && value.transport_status === "connection_generation_changed" && typeof value.previous_generation === "number" && typeof value.current_generation === "number";
|
|
301
|
+
}
|
|
302
|
+
function moduleRequestBody(body, method) {
|
|
303
|
+
if (!isRecord(body))
|
|
304
|
+
return body;
|
|
305
|
+
const facade = typeof body.name === "string" && isRecord(body.arguments);
|
|
306
|
+
return { ...body, ...facade ? {} : { method }, accept_reply_pages: true };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
class SubcModuleTransport {
|
|
310
|
+
connectionFile;
|
|
311
|
+
moduleId;
|
|
312
|
+
requestTimeoutMs;
|
|
313
|
+
routeSessionPrefix;
|
|
314
|
+
client = null;
|
|
315
|
+
routes = new Map;
|
|
316
|
+
routeOpenings = new Map;
|
|
317
|
+
canonicalRootCache = new Map;
|
|
318
|
+
sessionLanes = new Map;
|
|
319
|
+
queuedLaneWaiters = 0;
|
|
320
|
+
wrapupSessions = new Map;
|
|
321
|
+
nextProbeMs = 0;
|
|
322
|
+
connectionPromise = null;
|
|
323
|
+
backoffMs = CONNECT_BACKOFF_INITIAL_MS;
|
|
324
|
+
connectionGeneration = 0;
|
|
325
|
+
stateSyncCapabilityCache = null;
|
|
326
|
+
getCachedStateSyncCapabilities() {
|
|
327
|
+
const cached = this.stateSyncCapabilityCache;
|
|
328
|
+
if (!cached || cached.generation !== this.connectionGeneration)
|
|
329
|
+
return;
|
|
330
|
+
return cached.capabilities;
|
|
331
|
+
}
|
|
332
|
+
invalidateStateSyncCapabilities() {
|
|
333
|
+
this.stateSyncCapabilityCache = null;
|
|
334
|
+
}
|
|
335
|
+
async stateSyncCapabilities(args) {
|
|
336
|
+
const cached = this.getCachedStateSyncCapabilities();
|
|
337
|
+
if (cached)
|
|
338
|
+
return cached;
|
|
339
|
+
const response = await this.call({
|
|
340
|
+
sessionId: args.sessionId,
|
|
341
|
+
projectRoot: args.projectRoot,
|
|
342
|
+
method: "session.status",
|
|
343
|
+
body: { method: "session.status", v: 1, session_id: args.sessionId }
|
|
344
|
+
});
|
|
345
|
+
const raw = isRecord(response) ? response : {};
|
|
346
|
+
const value = isRecord(raw.result) ? raw.result : raw;
|
|
347
|
+
const epochs = isRecord(value.epochs) ? value.epochs : {};
|
|
348
|
+
const capabilities = {
|
|
349
|
+
state_sync_deltas: epochs.state_sync_deltas === true,
|
|
350
|
+
...epochs.state_sync_resume === true ? { state_sync_resume: true } : {}
|
|
351
|
+
};
|
|
352
|
+
this.stateSyncCapabilityCache = { generation: this.connectionGeneration, capabilities };
|
|
353
|
+
return capabilities;
|
|
354
|
+
}
|
|
355
|
+
constructor(connectionFile, moduleId = DEFAULT_MODULE_ID, requestTimeoutMs = MODULE_SEND_TIMEOUT_MS, routeSessionPrefix = "") {
|
|
356
|
+
this.connectionFile = connectionFile;
|
|
357
|
+
this.moduleId = moduleId;
|
|
358
|
+
this.requestTimeoutMs = requestTimeoutMs;
|
|
359
|
+
this.routeSessionPrefix = routeSessionPrefix;
|
|
360
|
+
}
|
|
361
|
+
deadlineError(detail) {
|
|
362
|
+
const error = new Error(`module transport deadline expired ${detail}`);
|
|
363
|
+
error.code = "ETIMEDOUT";
|
|
364
|
+
return error;
|
|
365
|
+
}
|
|
366
|
+
laneTimeoutError() {
|
|
367
|
+
return this.deadlineError("while queued");
|
|
368
|
+
}
|
|
369
|
+
connectionChangedError(detail) {
|
|
370
|
+
const error = new Error(detail);
|
|
371
|
+
error.code = "ECONNRESET";
|
|
372
|
+
return error;
|
|
373
|
+
}
|
|
374
|
+
async beforeDeadline(operation, deadlineMs, detail) {
|
|
375
|
+
operation.catch(() => {});
|
|
376
|
+
const remainingMs = deadlineMs - Date.now();
|
|
377
|
+
if (remainingMs <= 0)
|
|
378
|
+
throw this.deadlineError(detail);
|
|
379
|
+
let timer;
|
|
380
|
+
try {
|
|
381
|
+
return await Promise.race([
|
|
382
|
+
operation,
|
|
383
|
+
new Promise((_resolve, reject) => {
|
|
384
|
+
timer = setTimeout(() => reject(this.deadlineError(detail)), remainingMs);
|
|
385
|
+
})
|
|
386
|
+
]);
|
|
387
|
+
} finally {
|
|
388
|
+
if (timer)
|
|
389
|
+
clearTimeout(timer);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
cleanupLane(sessionId, lane) {
|
|
393
|
+
if (!lane.active && lane.waiters.length === 0 && this.sessionLanes.get(sessionId) === lane) {
|
|
394
|
+
this.sessionLanes.delete(sessionId);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
laneRelease(sessionId, lane) {
|
|
398
|
+
let released = false;
|
|
399
|
+
return () => {
|
|
400
|
+
if (released)
|
|
401
|
+
return;
|
|
402
|
+
released = true;
|
|
403
|
+
lane.active = false;
|
|
404
|
+
this.dispatchNextLaneWaiter(sessionId, lane);
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
dispatchNextLaneWaiter(sessionId, lane) {
|
|
408
|
+
if (lane.active)
|
|
409
|
+
return;
|
|
410
|
+
while (lane.waiters.length > 0) {
|
|
411
|
+
const waiter = lane.waiters.shift();
|
|
412
|
+
if (!waiter)
|
|
413
|
+
continue;
|
|
414
|
+
this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
|
|
415
|
+
if (waiter.settled)
|
|
416
|
+
continue;
|
|
417
|
+
waiter.settled = true;
|
|
418
|
+
clearTimeout(waiter.timer);
|
|
419
|
+
waiter.signal?.removeEventListener("abort", waiter.onAbort);
|
|
420
|
+
if (waiter.signal?.aborted) {
|
|
421
|
+
waiter.reject(waiter.signal.reason ?? new Error("module transport call aborted"));
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
if (waiter.deadlineMs - Date.now() < SERIAL_LANE_MIN_REMAINING_MS) {
|
|
425
|
+
waiter.reject(this.laneTimeoutError());
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
lane.active = true;
|
|
429
|
+
waiter.resolve(this.laneRelease(sessionId, lane));
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
this.cleanupLane(sessionId, lane);
|
|
433
|
+
}
|
|
434
|
+
queueFullError() {
|
|
435
|
+
const error = new Error("module transport queue is full");
|
|
436
|
+
error.code = "EBUSY";
|
|
437
|
+
return error;
|
|
438
|
+
}
|
|
439
|
+
acquireCorrectnessLane(sessionId, signal, deadlineMs) {
|
|
440
|
+
if (signal?.aborted) {
|
|
441
|
+
return Promise.reject(signal.reason ?? new Error("module transport call aborted"));
|
|
442
|
+
}
|
|
443
|
+
if (deadlineMs - Date.now() < SERIAL_LANE_MIN_REMAINING_MS) {
|
|
444
|
+
return Promise.reject(this.laneTimeoutError());
|
|
445
|
+
}
|
|
446
|
+
const lane = this.sessionLanes.get(sessionId) ?? { active: false, waiters: [] };
|
|
447
|
+
this.sessionLanes.set(sessionId, lane);
|
|
448
|
+
if (!lane.active && lane.waiters.length === 0) {
|
|
449
|
+
lane.active = true;
|
|
450
|
+
return Promise.resolve(this.laneRelease(sessionId, lane));
|
|
451
|
+
}
|
|
452
|
+
if (this.queuedLaneWaiters >= SERIAL_LANE_MAX_WAITERS || lane.waiters.length >= SERIAL_LANE_MAX_WAITERS_PER_SESSION) {
|
|
453
|
+
return Promise.reject(this.queueFullError());
|
|
454
|
+
}
|
|
455
|
+
return new Promise((resolve, reject) => {
|
|
456
|
+
const waiter = {};
|
|
457
|
+
const removeAndReject = (error) => {
|
|
458
|
+
if (waiter.settled)
|
|
459
|
+
return;
|
|
460
|
+
waiter.settled = true;
|
|
461
|
+
clearTimeout(waiter.timer);
|
|
462
|
+
signal?.removeEventListener("abort", waiter.onAbort);
|
|
463
|
+
const index = lane.waiters.indexOf(waiter);
|
|
464
|
+
if (index >= 0) {
|
|
465
|
+
lane.waiters.splice(index, 1);
|
|
466
|
+
this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
|
|
467
|
+
}
|
|
468
|
+
reject(error);
|
|
469
|
+
this.cleanupLane(sessionId, lane);
|
|
470
|
+
};
|
|
471
|
+
waiter.signal = signal;
|
|
472
|
+
waiter.deadlineMs = deadlineMs;
|
|
473
|
+
waiter.resolve = resolve;
|
|
474
|
+
waiter.reject = reject;
|
|
475
|
+
waiter.settled = false;
|
|
476
|
+
waiter.onAbort = () => removeAndReject(signal?.reason ?? new Error("module transport call aborted"));
|
|
477
|
+
waiter.timer = setTimeout(() => removeAndReject(this.laneTimeoutError()), Math.max(0, deadlineMs - Date.now()));
|
|
478
|
+
signal?.addEventListener("abort", waiter.onAbort, { once: true });
|
|
479
|
+
lane.waiters.push(waiter);
|
|
480
|
+
this.queuedLaneWaiters += 1;
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
async call(args) {
|
|
484
|
+
const callStartedAt = performance.now();
|
|
485
|
+
const timings = {
|
|
486
|
+
lane: 0,
|
|
487
|
+
route: 0,
|
|
488
|
+
encode: 0,
|
|
489
|
+
issue: 0,
|
|
490
|
+
responseWait: 0,
|
|
491
|
+
settle: 0
|
|
492
|
+
};
|
|
493
|
+
const wrapupInFlight = (this.wrapupSessions.get(args.sessionId) ?? 0) > 0;
|
|
494
|
+
const attemptTimeoutMs = args.timeoutMs ?? (args.method === "session.wrapup" || args.method === "session.status" && wrapupInFlight ? MAX_WRAPUP_REQUEST_BUDGET_MS : args.attemptClass === "transform_series_execute" ? TRANSFORM_COLD_START_EXECUTE_TIMEOUT_MS : args.method === "transform" ? Math.min(this.requestTimeoutMs, TRANSFORM_PAGE_UPLOAD_TIMEOUT_MS) : this.requestTimeoutMs);
|
|
495
|
+
const tracksWrapup = args.method === "session.wrapup";
|
|
496
|
+
if (tracksWrapup) {
|
|
497
|
+
this.wrapupSessions.set(args.sessionId, (this.wrapupSessions.get(args.sessionId) ?? 0) + 1);
|
|
498
|
+
}
|
|
499
|
+
const finishWrapupTracking = () => {
|
|
500
|
+
if (!tracksWrapup)
|
|
501
|
+
return;
|
|
502
|
+
const remaining = (this.wrapupSessions.get(args.sessionId) ?? 1) - 1;
|
|
503
|
+
if (remaining > 0)
|
|
504
|
+
this.wrapupSessions.set(args.sessionId, remaining);
|
|
505
|
+
else
|
|
506
|
+
this.wrapupSessions.delete(args.sessionId);
|
|
507
|
+
};
|
|
508
|
+
const laneDeadlineMs = Date.now() + attemptTimeoutMs;
|
|
509
|
+
let releaseLane = () => {};
|
|
510
|
+
try {
|
|
511
|
+
const outsideSessionOrder = args.method.startsWith("historian.");
|
|
512
|
+
if (!args.bypassSessionLane && !outsideSessionOrder) {
|
|
513
|
+
releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, laneDeadlineMs);
|
|
514
|
+
}
|
|
515
|
+
} catch (error) {
|
|
516
|
+
finishWrapupTracking();
|
|
517
|
+
if (args.method === "state_sync" && isDeadlineFailure(error)) {
|
|
518
|
+
const body = isRecord(args.body) ? args.body : {};
|
|
519
|
+
throw Object.assign(new Error(`state_sync timeout stage=correctness_lane page=${body.seed_batch_index ?? 0}/${body.seed_batch_total ?? 1} series=${body.seed_id ?? "delta"} budget_ms=${attemptTimeoutMs}`), {
|
|
520
|
+
code: "state_sync_timeout",
|
|
521
|
+
stage: "correctness_lane",
|
|
522
|
+
page: body.seed_batch_index ?? 0,
|
|
523
|
+
pages: body.seed_batch_total ?? 1,
|
|
524
|
+
series: body.seed_id ?? null,
|
|
525
|
+
cause: error
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
throw error;
|
|
529
|
+
}
|
|
530
|
+
timings.lane = performance.now() - callStartedAt;
|
|
531
|
+
let rejectAbort;
|
|
532
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
533
|
+
rejectAbort = reject;
|
|
534
|
+
});
|
|
535
|
+
aborted.catch(() => {});
|
|
536
|
+
const onAbort = () => rejectAbort(args.signal?.reason ?? new Error("module transport call aborted"));
|
|
537
|
+
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
538
|
+
try {
|
|
539
|
+
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
540
|
+
let ensuredRoute = null;
|
|
541
|
+
let initialResponseReceived = false;
|
|
542
|
+
try {
|
|
543
|
+
if (args.signal?.aborted) {
|
|
544
|
+
throw args.signal.reason ?? new Error("module transport call aborted");
|
|
545
|
+
}
|
|
546
|
+
const attemptDeadlineMs = Date.now() + attemptTimeoutMs;
|
|
547
|
+
const routeStartedAt = performance.now();
|
|
548
|
+
ensuredRoute = await this.ensureRoute(args.sessionId, args.projectRoot, attemptDeadlineMs, args.signal);
|
|
549
|
+
if (args.signal?.aborted) {
|
|
550
|
+
throw args.signal.reason ?? new Error("module transport call aborted");
|
|
551
|
+
}
|
|
552
|
+
timings.route += performance.now() - routeStartedAt;
|
|
553
|
+
const encodeStartedAt = performance.now();
|
|
554
|
+
const body = args.body instanceof Uint8Array ? args.body : Buffer.from(JSON.stringify(moduleRequestBody(args.body, args.method)));
|
|
555
|
+
timings.encode += performance.now() - encodeStartedAt;
|
|
556
|
+
const issueStartedAt = performance.now();
|
|
557
|
+
const request = ensuredRoute.client.request(ensuredRoute.route, body, {
|
|
558
|
+
priority: Priority.Background,
|
|
559
|
+
admissionClass: AdmissionClass.Normal,
|
|
560
|
+
timeoutMs: Math.max(1, attemptDeadlineMs - Date.now())
|
|
561
|
+
});
|
|
562
|
+
timings.issue += performance.now() - issueStartedAt;
|
|
563
|
+
const waitStartedAt = performance.now();
|
|
564
|
+
const response = await this.beforeDeadline(Promise.race([request, aborted]), attemptDeadlineMs, "waiting for the module response");
|
|
565
|
+
timings.responseWait += performance.now() - waitStartedAt;
|
|
566
|
+
initialResponseReceived = true;
|
|
567
|
+
if (this.client !== ensuredRoute.client || this.connectionGeneration !== ensuredRoute.generation) {
|
|
568
|
+
throw this.connectionChangedError("subc connection changed while awaiting the module response");
|
|
569
|
+
}
|
|
570
|
+
const pageRoute = ensuredRoute;
|
|
571
|
+
const assembled = await assembleReplyPages(response, async (id, index) => {
|
|
572
|
+
if (args.signal?.aborted)
|
|
573
|
+
throw args.signal.reason;
|
|
574
|
+
const page = await this.beforeDeadline(Promise.race([
|
|
575
|
+
pageRoute.client.request(pageRoute.route, Buffer.from(JSON.stringify({
|
|
576
|
+
method: "reply.page",
|
|
577
|
+
reply_page_id: id,
|
|
578
|
+
reply_page_index: index
|
|
579
|
+
})), {
|
|
580
|
+
priority: Priority.Background,
|
|
581
|
+
admissionClass: AdmissionClass.Normal,
|
|
582
|
+
timeoutMs: Math.max(1, attemptDeadlineMs - Date.now())
|
|
583
|
+
}),
|
|
584
|
+
aborted
|
|
585
|
+
]), attemptDeadlineMs, "waiting for a module reply page");
|
|
586
|
+
if (this.client !== pageRoute.client || this.connectionGeneration !== pageRoute.generation) {
|
|
587
|
+
throw this.connectionChangedError("subc connection changed during reply paging");
|
|
588
|
+
}
|
|
589
|
+
return page;
|
|
590
|
+
});
|
|
591
|
+
return assembled;
|
|
592
|
+
} catch (error) {
|
|
593
|
+
if (args.signal?.aborted)
|
|
594
|
+
throw args.signal.reason ?? error;
|
|
595
|
+
const migration = singleStoreMigrationRequiredFailure(error);
|
|
596
|
+
if (migration)
|
|
597
|
+
throw migration;
|
|
598
|
+
const storeAhead = storeAheadOfBinaryFailure(error);
|
|
599
|
+
if (storeAhead)
|
|
600
|
+
throw storeAhead;
|
|
601
|
+
if (args.method === "state_sync" && isDeadlineFailure(error)) {
|
|
602
|
+
const body = isRecord(args.body) ? args.body : {};
|
|
603
|
+
throw Object.assign(new Error(`state_sync timeout stage=module_ack page=${body.seed_batch_index ?? 0}/${body.seed_batch_total ?? 1} series=${body.seed_id ?? "delta"} budget_ms=${attemptTimeoutMs}`), {
|
|
604
|
+
code: "state_sync_timeout",
|
|
605
|
+
stage: "module_ack",
|
|
606
|
+
page: body.seed_batch_index ?? 0,
|
|
607
|
+
pages: body.seed_batch_total ?? 1,
|
|
608
|
+
series: body.seed_id ?? null,
|
|
609
|
+
cause: error
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
if (args.attemptClass === "transform_series_execute" && isDeadlineFailure(error)) {
|
|
613
|
+
throw error;
|
|
614
|
+
}
|
|
615
|
+
if (isConnectionFailure(error)) {
|
|
616
|
+
const previousGeneration = ensuredRoute?.generation ?? this.connectionGeneration;
|
|
617
|
+
if (ensuredRoute) {
|
|
618
|
+
this.dropRoute(ensuredRoute.routeKey, ensuredRoute.route);
|
|
619
|
+
this.invalidateConnection(ensuredRoute.client);
|
|
620
|
+
} else {
|
|
621
|
+
this.invalidateConnection();
|
|
622
|
+
}
|
|
623
|
+
const locallyUnsent = isRecord(error) && error.name === "StaleRouteHandleError" && error.code === "stale_route_handle";
|
|
624
|
+
if (attempt === 0 && ensuredRoute && !initialResponseReceived && locallyUnsent && !args.generationSensitive) {
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (args.method === "transform") {
|
|
628
|
+
if (!ensuredRoute)
|
|
629
|
+
throw error;
|
|
630
|
+
throw Object.assign(new Error("Transform transport interrupted; abandon this pass"), { code: "transform_transport_interrupted", cause: error });
|
|
631
|
+
}
|
|
632
|
+
if (args.generationSensitive && !args.signal?.aborted) {
|
|
633
|
+
return {
|
|
634
|
+
transport_status: "connection_generation_changed",
|
|
635
|
+
previous_generation: previousGeneration,
|
|
636
|
+
current_generation: this.connectionGeneration
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
if (attempt === 0 && !args.signal?.aborted)
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
throw error;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
throw new Error("module transport route retry exhausted");
|
|
646
|
+
} finally {
|
|
647
|
+
args.signal?.removeEventListener("abort", onAbort);
|
|
648
|
+
finishWrapupTracking();
|
|
649
|
+
releaseLane();
|
|
650
|
+
timings.settle = Math.max(0, performance.now() - callStartedAt - timings.lane - timings.route - timings.encode - timings.issue - timings.responseWait);
|
|
651
|
+
args.onTimings?.(timings);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
async deleteSession(sessionId, projectRoot) {
|
|
655
|
+
await this.call({
|
|
656
|
+
sessionId,
|
|
657
|
+
projectRoot,
|
|
658
|
+
method: "session.delete",
|
|
659
|
+
body: { method: "session.delete", v: 1, session_id: sessionId }
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
closeSession(sessionId) {
|
|
663
|
+
const client = this.client;
|
|
664
|
+
const prefix = `${sessionId}\x00`;
|
|
665
|
+
const routes = [...this.routes.entries()].filter(([key]) => key.startsWith(prefix));
|
|
666
|
+
for (const [key, cachedRoute] of routes) {
|
|
667
|
+
this.routes.delete(key);
|
|
668
|
+
if (client) {
|
|
669
|
+
client.closeRoute(cachedRoute.route).catch((error) => {
|
|
670
|
+
if (this.client === client && isConnectionFailure(error)) {
|
|
671
|
+
this.invalidateConnection(client);
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
if (routes.length === 0 && this.sessionLanes.get(sessionId)?.active) {
|
|
677
|
+
this.invalidateConnection(client);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
async ensureRoute(sessionId, rawProjectRoot, deadlineMs = Date.now() + this.requestTimeoutMs, signal) {
|
|
681
|
+
const projectRoot = this.canonicalRoot(rawProjectRoot);
|
|
682
|
+
const routeKey = `${sessionId}\x00${projectRoot}`;
|
|
683
|
+
const client = await this.ensureConnected(signal);
|
|
684
|
+
const generation = this.connectionGeneration;
|
|
685
|
+
const existing = this.routes.get(routeKey);
|
|
686
|
+
if (existing?.generation === generation) {
|
|
687
|
+
return { client, route: existing.route, routeKey, generation };
|
|
688
|
+
}
|
|
689
|
+
if (existing)
|
|
690
|
+
this.routes.delete(routeKey);
|
|
691
|
+
const opening = this.routeOpenings.get(routeKey);
|
|
692
|
+
if (opening?.client === client && opening.generation === generation) {
|
|
693
|
+
return await opening.promise;
|
|
694
|
+
}
|
|
695
|
+
const promise = (async () => {
|
|
696
|
+
const target = { kind: "tool_provider", module_id: this.moduleId };
|
|
697
|
+
const identity = {
|
|
698
|
+
project_root: projectRoot,
|
|
699
|
+
harness: getHarness2(),
|
|
700
|
+
session: `${this.routeSessionPrefix}${sessionId}`
|
|
701
|
+
};
|
|
702
|
+
const route = await this.beforeDeadline(routeOpenWithoutAmbientConsumerIdentity(client, target, identity), deadlineMs, "opening the module route");
|
|
703
|
+
if (this.client !== client || generation !== this.connectionGeneration) {
|
|
704
|
+
await client.closeRoute(route).catch(() => {
|
|
705
|
+
return;
|
|
706
|
+
});
|
|
707
|
+
throw this.connectionChangedError("subc connection changed while opening module route");
|
|
708
|
+
}
|
|
709
|
+
this.routes.set(routeKey, { route, generation });
|
|
710
|
+
return { client, route, routeKey, generation };
|
|
711
|
+
})();
|
|
712
|
+
const routeOpening = { client, generation, promise };
|
|
713
|
+
this.routeOpenings.set(routeKey, routeOpening);
|
|
714
|
+
try {
|
|
715
|
+
return await promise;
|
|
716
|
+
} finally {
|
|
717
|
+
if (this.routeOpenings.get(routeKey) === routeOpening) {
|
|
718
|
+
this.routeOpenings.delete(routeKey);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
dropRoute(routeKey, route) {
|
|
723
|
+
const existing = this.routes.get(routeKey);
|
|
724
|
+
if (!existing || route && existing.route !== route)
|
|
725
|
+
return;
|
|
726
|
+
this.routes.delete(routeKey);
|
|
727
|
+
}
|
|
728
|
+
canonicalRoot(root) {
|
|
729
|
+
const cached = this.canonicalRootCache.get(root);
|
|
730
|
+
if (cached !== undefined) {
|
|
731
|
+
this.canonicalRootCache.delete(root);
|
|
732
|
+
this.canonicalRootCache.set(root, cached);
|
|
733
|
+
return cached;
|
|
734
|
+
}
|
|
735
|
+
let resolved = root;
|
|
736
|
+
try {
|
|
737
|
+
resolved = realpathSync.native(root);
|
|
738
|
+
} catch {}
|
|
739
|
+
this.canonicalRootCache.set(root, resolved);
|
|
740
|
+
while (this.canonicalRootCache.size > CANONICAL_ROOT_CACHE_MAX_ENTRIES) {
|
|
741
|
+
const oldestRoot = this.canonicalRootCache.keys().next().value;
|
|
742
|
+
if (oldestRoot === undefined)
|
|
743
|
+
break;
|
|
744
|
+
this.canonicalRootCache.delete(oldestRoot);
|
|
745
|
+
}
|
|
746
|
+
return resolved;
|
|
747
|
+
}
|
|
748
|
+
connectClient() {
|
|
749
|
+
return SubcClient.connect({
|
|
750
|
+
connectionFile: this.connectionFile,
|
|
751
|
+
handshakeTimeoutMs: HANDSHAKE_TIMEOUT_MS
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
backoffActiveError() {
|
|
755
|
+
const error = new Error(`subc connection backoff active until ${this.nextProbeMs}`);
|
|
756
|
+
error.code = "SUBC_CONNECTION_BACKOFF";
|
|
757
|
+
return error;
|
|
758
|
+
}
|
|
759
|
+
sleepAbortable(durationMs, signal) {
|
|
760
|
+
return new Promise((resolve, reject) => {
|
|
761
|
+
if (signal?.aborted) {
|
|
762
|
+
reject(signal.reason ?? new Error("module transport call aborted"));
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
const onAbort = () => {
|
|
766
|
+
clearTimeout(timer);
|
|
767
|
+
signal?.removeEventListener("abort", onAbort);
|
|
768
|
+
reject(signal?.reason ?? new Error("module transport call aborted"));
|
|
769
|
+
};
|
|
770
|
+
const timer = setTimeout(() => {
|
|
771
|
+
signal?.removeEventListener("abort", onAbort);
|
|
772
|
+
resolve();
|
|
773
|
+
}, Math.max(0, durationMs));
|
|
774
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
async ensureConnected(signal) {
|
|
778
|
+
if (this.client)
|
|
779
|
+
return this.client;
|
|
780
|
+
if (this.connectionPromise)
|
|
781
|
+
return await this.connectionPromise;
|
|
782
|
+
let now = Date.now();
|
|
783
|
+
if (now < this.nextProbeMs) {
|
|
784
|
+
const remainingMs = this.nextProbeMs - now;
|
|
785
|
+
if (remainingMs > CONNECT_BACKOFF_WAIT_BUDGET_MS)
|
|
786
|
+
throw this.backoffActiveError();
|
|
787
|
+
const jitterMs = Math.floor(Math.random() * CONNECT_BACKOFF_WAIT_JITTER_MS);
|
|
788
|
+
await this.sleepAbortable(remainingMs + jitterMs, signal);
|
|
789
|
+
if (this.client)
|
|
790
|
+
return this.client;
|
|
791
|
+
if (this.connectionPromise)
|
|
792
|
+
return await this.connectionPromise;
|
|
793
|
+
now = Date.now();
|
|
794
|
+
if (now < this.nextProbeMs)
|
|
795
|
+
throw this.backoffActiveError();
|
|
796
|
+
}
|
|
797
|
+
const generation = this.connectionGeneration;
|
|
798
|
+
const connecting = (async () => {
|
|
799
|
+
let candidate = null;
|
|
800
|
+
try {
|
|
801
|
+
candidate = await this.connectClient();
|
|
802
|
+
if (generation !== this.connectionGeneration) {
|
|
803
|
+
candidate.close();
|
|
804
|
+
throw this.connectionChangedError("subc connection attempt was superseded");
|
|
805
|
+
}
|
|
806
|
+
this.client = candidate;
|
|
807
|
+
this.routes.clear();
|
|
808
|
+
this.backoffMs = CONNECT_BACKOFF_INITIAL_MS;
|
|
809
|
+
this.nextProbeMs = 0;
|
|
810
|
+
return candidate;
|
|
811
|
+
} catch (error) {
|
|
812
|
+
candidate?.close();
|
|
813
|
+
if (generation === this.connectionGeneration)
|
|
814
|
+
this.invalidateConnection();
|
|
815
|
+
this.nextProbeMs = Date.now() + this.backoffMs;
|
|
816
|
+
this.backoffMs = Math.min(this.backoffMs * 2, CONNECT_BACKOFF_MAX_MS);
|
|
817
|
+
throw error;
|
|
818
|
+
}
|
|
819
|
+
})();
|
|
820
|
+
this.connectionPromise = connecting;
|
|
821
|
+
try {
|
|
822
|
+
return await connecting;
|
|
823
|
+
} finally {
|
|
824
|
+
if (this.connectionPromise === connecting)
|
|
825
|
+
this.connectionPromise = null;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
invalidateConnection(client = this.client) {
|
|
829
|
+
if (client && this.client !== client)
|
|
830
|
+
return;
|
|
831
|
+
this.connectionGeneration += 1;
|
|
832
|
+
this.invalidateStateSyncCapabilities();
|
|
833
|
+
this.client = null;
|
|
834
|
+
this.routes.clear();
|
|
835
|
+
this.routeOpenings.clear();
|
|
836
|
+
client?.close();
|
|
837
|
+
}
|
|
838
|
+
}
|
|
48
839
|
|
|
49
840
|
// src/features/magic-context/git-commits/git-log-reader.ts
|
|
50
841
|
import { execFile } from "node:child_process";
|
|
@@ -96,19 +887,19 @@ async function readGitCommitsResult(directory, options = {}) {
|
|
|
96
887
|
} catch (error) {
|
|
97
888
|
const message = error instanceof Error ? error.message : String(error);
|
|
98
889
|
if (exclusion && message.includes("bad object")) {
|
|
99
|
-
|
|
890
|
+
log2(`[git-commits] indexed tip ${exclusion.slice(0, 7)} is missing for ${projectLabel}; reading the full window`);
|
|
100
891
|
return readGitCommitsResult(directory, { ...options, excludeReachableFrom: undefined });
|
|
101
892
|
}
|
|
102
893
|
const failure = classifyGitLogFailure(message);
|
|
103
894
|
if (failure === "transient") {
|
|
104
|
-
|
|
895
|
+
log2(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
|
|
105
896
|
} else {
|
|
106
|
-
|
|
897
|
+
log2(`[git-commits] ${projectLabel} is not indexable (${failure})`);
|
|
107
898
|
}
|
|
108
899
|
return { commits: [], failure };
|
|
109
900
|
}
|
|
110
901
|
if (stdout.trim().length === 0) {
|
|
111
|
-
|
|
902
|
+
log2(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
|
|
112
903
|
}
|
|
113
904
|
return { commits: parseGitLogOutput(stdout), failure: null };
|
|
114
905
|
}
|
|
@@ -169,7 +960,7 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
169
960
|
nonIndexable: false
|
|
170
961
|
};
|
|
171
962
|
if (indexInProgress.has(projectPath)) {
|
|
172
|
-
|
|
963
|
+
log2(`[git-commits] index already in progress for ${projectPath}, skipping`);
|
|
173
964
|
return result;
|
|
174
965
|
}
|
|
175
966
|
indexInProgress.add(projectPath);
|
|
@@ -190,21 +981,21 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
|
|
|
190
981
|
}
|
|
191
982
|
if (commits.length === 0) {
|
|
192
983
|
result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
|
|
193
|
-
|
|
984
|
+
log2(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed?.slice(0, 7) ?? "none"} evicted=${result.evicted})`);
|
|
194
985
|
return result;
|
|
195
986
|
}
|
|
196
|
-
|
|
987
|
+
log2(`[git-commits] read ${commits.length} commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed?.slice(0, 7) ?? "none"})`);
|
|
197
988
|
const upsert = upsertCommits(db, projectPath, commits);
|
|
198
989
|
result.inserted = upsert.inserted;
|
|
199
990
|
result.updated = upsert.updated;
|
|
200
991
|
result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
|
|
201
|
-
const snapshot =
|
|
992
|
+
const snapshot = getProjectEmbeddingSnapshot2(projectPath);
|
|
202
993
|
if (options.skipEmbed || !snapshot?.gitCommitEnabled) {
|
|
203
|
-
|
|
994
|
+
log2(`[git-commits] indexed ${projectPath}: scanned=${result.scanned} inserted=${result.inserted} updated=${result.updated} evicted=${result.evicted} embedded=0 (embedding skipped: skipEmbed=${options.skipEmbed === true} gitCommitEnabled=${snapshot?.gitCommitEnabled === true})`);
|
|
204
995
|
return result;
|
|
205
996
|
}
|
|
206
997
|
result.embedded = await embedUnembeddedCommits(db, projectPath);
|
|
207
|
-
|
|
998
|
+
log2(`[git-commits] indexed ${projectPath}: scanned=${result.scanned} inserted=${result.inserted} updated=${result.updated} evicted=${result.evicted} embedded=${result.embedded}`);
|
|
208
999
|
return result;
|
|
209
1000
|
} finally {
|
|
210
1001
|
indexInProgress.delete(projectPath);
|
|
@@ -214,7 +1005,7 @@ async function embedUnembeddedCommits(db, projectPath) {
|
|
|
214
1005
|
if (embedInProgress.has(projectPath)) {
|
|
215
1006
|
return 0;
|
|
216
1007
|
}
|
|
217
|
-
const snapshot =
|
|
1008
|
+
const snapshot = getProjectEmbeddingSnapshot2(projectPath);
|
|
218
1009
|
if (!snapshot?.gitCommitEnabled) {
|
|
219
1010
|
return 0;
|
|
220
1011
|
}
|
|
@@ -229,10 +1020,10 @@ async function embedUnembeddedCommits(db, projectPath) {
|
|
|
229
1020
|
break;
|
|
230
1021
|
let embeddedThisBatch = 0;
|
|
231
1022
|
try {
|
|
232
|
-
const result = await
|
|
1023
|
+
const result = await embedItemsForProject2(projectPath, rows.map((row) => ({
|
|
233
1024
|
id: `commit:${row.sha}`,
|
|
234
1025
|
text: row.message,
|
|
235
|
-
contentSha256:
|
|
1026
|
+
contentSha256: contentSha2562(row.message)
|
|
236
1027
|
})), undefined, db, projectPath);
|
|
237
1028
|
if (!result)
|
|
238
1029
|
break;
|
|
@@ -245,9 +1036,9 @@ async function embedUnembeddedCommits(db, projectPath) {
|
|
|
245
1036
|
embeddedThisBatch += 1;
|
|
246
1037
|
}
|
|
247
1038
|
}).immediate();
|
|
248
|
-
|
|
1039
|
+
enqueueShadowEmbeddingItems2(projectPath, "commit", rows.filter((row) => result.vectors.has(`commit:${row.sha}`)).map((row) => row.sha));
|
|
249
1040
|
} catch (error) {
|
|
250
|
-
|
|
1041
|
+
log2(`[git-commits] embed batch failed for ${projectPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
251
1042
|
break;
|
|
252
1043
|
}
|
|
253
1044
|
if (embeddedThisBatch === 0)
|
|
@@ -258,7 +1049,7 @@ async function embedUnembeddedCommits(db, projectPath) {
|
|
|
258
1049
|
}
|
|
259
1050
|
if (total > 0) {
|
|
260
1051
|
const totalEmbedded = countEmbeddedCommits(db, projectPath, snapshot.modelId);
|
|
261
|
-
|
|
1052
|
+
log2(`[git-commits] embedded ${total} commits for ${projectPath} (total embedded: ${totalEmbedded})`);
|
|
262
1053
|
}
|
|
263
1054
|
return total;
|
|
264
1055
|
} finally {
|
|
@@ -395,7 +1186,7 @@ function searchGitCommitsSync(db, projectPath, query, options) {
|
|
|
395
1186
|
ftsCandidates.push(rowToCommit(row));
|
|
396
1187
|
}
|
|
397
1188
|
} catch (error) {
|
|
398
|
-
|
|
1189
|
+
log2(`[git-commits] FTS query failed for "${trimmed}": ${error instanceof Error ? error.message : String(error)}`);
|
|
399
1190
|
}
|
|
400
1191
|
}
|
|
401
1192
|
if (ftsCandidates.length === 0) {
|
|
@@ -426,6 +1217,19 @@ function searchGitCommitsSync(db, projectPath, query, options) {
|
|
|
426
1217
|
for (const row of rows)
|
|
427
1218
|
bySha.set(row.sha, rowToCommit(row));
|
|
428
1219
|
}
|
|
1220
|
+
if (options.captureLanes) {
|
|
1221
|
+
const fts = [...bySha.values()].filter((commit) => ftsScores.has(commit.sha)).map((commit) => ({
|
|
1222
|
+
commit,
|
|
1223
|
+
matchType: "fts",
|
|
1224
|
+
score: (ftsScores.get(commit.sha) ?? 0) * singleSourcePenalty
|
|
1225
|
+
})).sort((a, b) => b.score - a.score || b.commit.committedAtMs - a.commit.committedAtMs).slice(0, 25);
|
|
1226
|
+
const vector = [...bySha.values()].filter((commit) => (semanticScores.get(commit.sha) ?? 0) > 0).map((commit) => ({
|
|
1227
|
+
commit,
|
|
1228
|
+
matchType: "semantic",
|
|
1229
|
+
score: semanticScores.get(commit.sha) ?? 0
|
|
1230
|
+
})).sort((a, b) => b.score - a.score || b.commit.committedAtMs - a.commit.committedAtMs).slice(0, 25);
|
|
1231
|
+
options.captureLanes(fts, vector);
|
|
1232
|
+
}
|
|
429
1233
|
const results = [];
|
|
430
1234
|
for (const [sha, commit] of bySha.entries()) {
|
|
431
1235
|
const sem = semanticScores.get(sha);
|
|
@@ -565,7 +1369,7 @@ function withMessageFtsSessionFilter(db, sessionId, read) {
|
|
|
565
1369
|
}
|
|
566
1370
|
|
|
567
1371
|
// src/features/magic-context/search-measurement.ts
|
|
568
|
-
import { createHash } from "node:crypto";
|
|
1372
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
569
1373
|
function resultId(result) {
|
|
570
1374
|
switch (result.source) {
|
|
571
1375
|
case "memory":
|
|
@@ -584,15 +1388,15 @@ function resultId(result) {
|
|
|
584
1388
|
}
|
|
585
1389
|
async function recordShadowMeasurement(args) {
|
|
586
1390
|
try {
|
|
587
|
-
const shadowCohort =
|
|
1391
|
+
const shadowCohort = getShadowEmbeddingMeasurementCohort2(args.projectPath);
|
|
588
1392
|
if (!shadowCohort)
|
|
589
1393
|
return;
|
|
590
|
-
const primaryCohort =
|
|
1394
|
+
const primaryCohort = getPrimaryEmbeddingMeasurementCohort2(args.projectPath);
|
|
591
1395
|
const shadowStartedAt = Date.now();
|
|
592
1396
|
let shadowFailed = false;
|
|
593
1397
|
let shadowResults = [];
|
|
594
1398
|
try {
|
|
595
|
-
const vector = await
|
|
1399
|
+
const vector = await embedShadowTextForProject2(args.projectPath, args.query);
|
|
596
1400
|
if (!vector) {
|
|
597
1401
|
shadowFailed = true;
|
|
598
1402
|
} else {
|
|
@@ -648,11 +1452,273 @@ async function recordShadowMeasurement(args) {
|
|
|
648
1452
|
}
|
|
649
1453
|
});
|
|
650
1454
|
} catch (error) {
|
|
651
|
-
|
|
1455
|
+
log2("[magic-context] shadow embedding measurement failed:", error);
|
|
652
1456
|
}
|
|
653
1457
|
}
|
|
654
1458
|
function sha256(value) {
|
|
655
|
-
return
|
|
1459
|
+
return createHash2("sha256").update(value).digest("hex");
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
// src/features/magic-context/search-rerank.ts
|
|
1463
|
+
var RERANK_MODEL = "gte-reranker-modernbert-base-f32";
|
|
1464
|
+
var RERANK_LANE_LIMIT = 25;
|
|
1465
|
+
var DEADLINE_MS = 1500;
|
|
1466
|
+
function isProseQuery(query) {
|
|
1467
|
+
const text = query.trim();
|
|
1468
|
+
if (!text || /[\n;]|^["'`]|["'`]$/.test(text))
|
|
1469
|
+
return false;
|
|
1470
|
+
if (/^(?:error\b|cannot\b|failed\b|panic\b|traceback\b|assertion\b|SQLITE_|TypeError\b|ReferenceError\b|SyntaxError\b)/i.test(text))
|
|
1471
|
+
return false;
|
|
1472
|
+
if (/\b(?:[A-Z][A-Z_]+:|\w*(?:Error|Exception):)|\bat\s+\S+\s*\(/.test(text))
|
|
1473
|
+
return false;
|
|
1474
|
+
const words = text.replace(/[?!.]$/, "").split(/\s+/);
|
|
1475
|
+
if (words.length < 3)
|
|
1476
|
+
return false;
|
|
1477
|
+
const plain = words.filter((word) => /^[a-zA-Z]+(?:['’-][a-zA-Z]+)*$/.test(word));
|
|
1478
|
+
if (/^(?:how|why|what|where|when|which|who)\b/i.test(text))
|
|
1479
|
+
return plain.length >= 3;
|
|
1480
|
+
return words.length >= 4 && plain.length >= 3 && !/[\\/]|::|=/.test(text);
|
|
1481
|
+
}
|
|
1482
|
+
function emptySearchLanes() {
|
|
1483
|
+
return {
|
|
1484
|
+
memory_fts: [],
|
|
1485
|
+
memory_vector: [],
|
|
1486
|
+
primer_fts: [],
|
|
1487
|
+
primer_vector: [],
|
|
1488
|
+
message_fts: [],
|
|
1489
|
+
chunk_vector: [],
|
|
1490
|
+
git_fts: [],
|
|
1491
|
+
git_vector: [],
|
|
1492
|
+
notes: []
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
function searchResultKey(hit) {
|
|
1496
|
+
switch (hit.source) {
|
|
1497
|
+
case "memory":
|
|
1498
|
+
return `memory:${hit.memoryId}`;
|
|
1499
|
+
case "primer":
|
|
1500
|
+
return `primer:${hit.primerId}`;
|
|
1501
|
+
case "message":
|
|
1502
|
+
return `message:${hit.messageId}`;
|
|
1503
|
+
case "compartment":
|
|
1504
|
+
return `compartment:${hit.compartmentId}`;
|
|
1505
|
+
case "git_commit":
|
|
1506
|
+
return `git_commit:${hit.sha}`;
|
|
1507
|
+
case "note":
|
|
1508
|
+
return `note:${hit.noteId}`;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
function fuseSearchLanes(lanes) {
|
|
1512
|
+
const compartments = lanes.chunk_vector.filter((hit) => hit.source === "compartment");
|
|
1513
|
+
const fused = new Map;
|
|
1514
|
+
for (const [name, lane] of Object.entries(lanes)) {
|
|
1515
|
+
const seen = new Set;
|
|
1516
|
+
lane.slice(0, RERANK_LANE_LIMIT).forEach((original, index) => {
|
|
1517
|
+
const hit = name === "message_fts" && original.source === "message" ? compartments.find((chunk) => original.messageOrdinal >= chunk.startOrdinal && original.messageOrdinal <= chunk.endOrdinal) ?? original : original;
|
|
1518
|
+
const key = searchResultKey(hit);
|
|
1519
|
+
if (seen.has(key))
|
|
1520
|
+
return;
|
|
1521
|
+
seen.add(key);
|
|
1522
|
+
const prior = fused.get(key);
|
|
1523
|
+
const score = 1 / (60 + index + 1);
|
|
1524
|
+
if (prior)
|
|
1525
|
+
prior.score += score;
|
|
1526
|
+
else
|
|
1527
|
+
fused.set(key, { hit, score, order: fused.size });
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
return [...fused.values()].sort((a, b) => b.score - a.score || a.order - b.order).slice(0, 20).map((row) => row.hit);
|
|
1531
|
+
}
|
|
1532
|
+
function truncateUtf8(text, bytes) {
|
|
1533
|
+
const buffer = Buffer.from(text);
|
|
1534
|
+
let end = Math.min(buffer.length, bytes);
|
|
1535
|
+
while (end > 0 && end < buffer.length && (buffer[end] & 192) === 128)
|
|
1536
|
+
end--;
|
|
1537
|
+
return buffer.subarray(0, end).toString("utf8");
|
|
1538
|
+
}
|
|
1539
|
+
function candidateText(location, title, body) {
|
|
1540
|
+
const header = `${truncateUtf8(location.replaceAll(`
|
|
1541
|
+
`, " "), 200)}
|
|
1542
|
+
${truncateUtf8(title.replaceAll(`
|
|
1543
|
+
`, " "), 120)}
|
|
1544
|
+
`;
|
|
1545
|
+
return header + truncateUtf8(body, 1024 - Buffer.byteLength(header));
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
class RerankFailure extends Error {
|
|
1549
|
+
reason;
|
|
1550
|
+
constructor(reason) {
|
|
1551
|
+
super(reason);
|
|
1552
|
+
this.reason = reason;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
function unwrap(value) {
|
|
1556
|
+
if (!value || typeof value !== "object")
|
|
1557
|
+
throw new RerankFailure("validation");
|
|
1558
|
+
const outer = value;
|
|
1559
|
+
const body = outer.result ?? outer;
|
|
1560
|
+
if (!body || typeof body !== "object")
|
|
1561
|
+
throw new RerankFailure("validation");
|
|
1562
|
+
if (body.error) {
|
|
1563
|
+
const error = body.error;
|
|
1564
|
+
throw new RerankFailure(error.code ?? "synapse_error");
|
|
1565
|
+
}
|
|
1566
|
+
return body;
|
|
1567
|
+
}
|
|
1568
|
+
function pinReranker(value) {
|
|
1569
|
+
const body = unwrap(value);
|
|
1570
|
+
const models = body.models;
|
|
1571
|
+
const model = Array.isArray(models) ? models.find((row) => row?.model_id === RERANK_MODEL) : null;
|
|
1572
|
+
if (model?.certified !== true || model.fingerprints?.length !== 1 || typeof model.fingerprints[0] !== "string" || !/^[a-f0-9]{64}$/.test(model.fingerprints[0]) || !Number.isSafeInteger(body.table_epoch))
|
|
1573
|
+
throw new RerankFailure("catalog_validation");
|
|
1574
|
+
return { fingerprint: model.fingerprints[0], tableEpoch: body.table_epoch };
|
|
1575
|
+
}
|
|
1576
|
+
var loggedReasons = new Set;
|
|
1577
|
+
function logRerankFallback(reason) {
|
|
1578
|
+
if (loggedReasons.has(reason))
|
|
1579
|
+
return;
|
|
1580
|
+
loggedReasons.add(reason);
|
|
1581
|
+
log2(`[ctx_search] rerank fallback (${reason}); retaining original ranking`);
|
|
1582
|
+
}
|
|
1583
|
+
function reasonOf(error) {
|
|
1584
|
+
if (error instanceof RerankFailure)
|
|
1585
|
+
return error.reason;
|
|
1586
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
1587
|
+
const code = String(error.code);
|
|
1588
|
+
return ["ENOENT", "ECONNREFUSED"].includes(code) ? "missing_synapse" : code;
|
|
1589
|
+
}
|
|
1590
|
+
return "synapse_error";
|
|
1591
|
+
}
|
|
1592
|
+
async function bounded(promise) {
|
|
1593
|
+
let timer;
|
|
1594
|
+
try {
|
|
1595
|
+
return await Promise.race([
|
|
1596
|
+
promise,
|
|
1597
|
+
new Promise((_, reject) => {
|
|
1598
|
+
timer = setTimeout(() => reject(new RerankFailure("deadline_exceeded")), DEADLINE_MS);
|
|
1599
|
+
})
|
|
1600
|
+
]);
|
|
1601
|
+
} finally {
|
|
1602
|
+
clearTimeout(timer);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
var connections = new Map;
|
|
1606
|
+
async function connect(connectionFile) {
|
|
1607
|
+
let connection = connections.get(connectionFile);
|
|
1608
|
+
if (!connection) {
|
|
1609
|
+
connection = SubcClient.connect({ connectionFile });
|
|
1610
|
+
connections.set(connectionFile, connection);
|
|
1611
|
+
connection.catch(() => connections.delete(connectionFile));
|
|
1612
|
+
}
|
|
1613
|
+
return bounded(connection);
|
|
1614
|
+
}
|
|
1615
|
+
async function prepareReranker(projectRoot, sessionId, connectionFile, injectedClient) {
|
|
1616
|
+
try {
|
|
1617
|
+
if (injectedClient === null)
|
|
1618
|
+
throw new RerankFailure("missing_synapse");
|
|
1619
|
+
const client = injectedClient ?? await connect(connectionFile ?? getDefaultSubcConnectionFile());
|
|
1620
|
+
const identity = {
|
|
1621
|
+
project_root: projectRoot,
|
|
1622
|
+
harness: "magic-context",
|
|
1623
|
+
session: sessionId
|
|
1624
|
+
};
|
|
1625
|
+
const lane = pinReranker(await bounded(client.call("synapse", "models.list", {}, { timeoutMs: DEADLINE_MS, targetKind: "management_surface", identity })));
|
|
1626
|
+
return { client, lane, identity };
|
|
1627
|
+
} catch (error) {
|
|
1628
|
+
logRerankFallback(reasonOf(error));
|
|
1629
|
+
return null;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
async function rerankSearchResults(session, query, baseline, pool, texts, limit) {
|
|
1633
|
+
if (!pool.length)
|
|
1634
|
+
return baseline;
|
|
1635
|
+
try {
|
|
1636
|
+
if (pool.length > 20 || texts.length !== pool.length || texts.some((text) => Buffer.byteLength(text) > 1024))
|
|
1637
|
+
throw new RerankFailure("validation");
|
|
1638
|
+
const body = unwrap(await bounded(session.client.call("synapse", "rerank.score", {
|
|
1639
|
+
model: RERANK_MODEL,
|
|
1640
|
+
query,
|
|
1641
|
+
candidates: texts,
|
|
1642
|
+
required_fingerprint: session.lane.fingerprint,
|
|
1643
|
+
allow_equivalent: false,
|
|
1644
|
+
accept_declared: false,
|
|
1645
|
+
max_queue_ms: 100,
|
|
1646
|
+
deadline_ms: DEADLINE_MS
|
|
1647
|
+
}, {
|
|
1648
|
+
timeoutMs: DEADLINE_MS,
|
|
1649
|
+
targetKind: "management_surface",
|
|
1650
|
+
identity: session.identity
|
|
1651
|
+
})));
|
|
1652
|
+
if (body.fingerprint !== session.lane.fingerprint)
|
|
1653
|
+
throw new RerankFailure("fingerprint_mismatch");
|
|
1654
|
+
if (body.table_epoch !== session.lane.tableEpoch)
|
|
1655
|
+
throw new RerankFailure("epoch_mismatch");
|
|
1656
|
+
if (!Array.isArray(body.scores) || body.scores.length !== pool.length || body.scores.some((score) => typeof score !== "number" || !Number.isFinite(score)))
|
|
1657
|
+
throw new RerankFailure("validation");
|
|
1658
|
+
const scores = body.scores;
|
|
1659
|
+
return pool.map((hit, index) => ({ hit, index, score: scores[index] })).sort((a, b) => b.score - a.score || a.index - b.index).slice(0, limit).map((row) => row.hit);
|
|
1660
|
+
} catch (error) {
|
|
1661
|
+
logRerankFallback(reasonOf(error));
|
|
1662
|
+
return baseline;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
function candidateTexts(db, sessionId, projectPath, pool) {
|
|
1666
|
+
return pool.map((hit) => {
|
|
1667
|
+
const id = searchResultKey(hit).split(":").slice(1).join(":");
|
|
1668
|
+
let location = `${hit.source} ${id} ${projectPath}`;
|
|
1669
|
+
let title = hit.content.split(`
|
|
1670
|
+
`)[0];
|
|
1671
|
+
let body = hit.content;
|
|
1672
|
+
switch (hit.source) {
|
|
1673
|
+
case "memory": {
|
|
1674
|
+
const row = db.prepare("SELECT content FROM memories WHERE id=?").get(hit.memoryId);
|
|
1675
|
+
body = row.content;
|
|
1676
|
+
title = body.split(`
|
|
1677
|
+
`)[0];
|
|
1678
|
+
break;
|
|
1679
|
+
}
|
|
1680
|
+
case "primer": {
|
|
1681
|
+
const row = db.prepare("SELECT question, answer FROM primers WHERE id=?").get(hit.primerId);
|
|
1682
|
+
title = row.question;
|
|
1683
|
+
body = `Q: ${row.question}
|
|
1684
|
+
A: ${row.answer}`;
|
|
1685
|
+
break;
|
|
1686
|
+
}
|
|
1687
|
+
case "git_commit": {
|
|
1688
|
+
const row = db.prepare("SELECT message FROM git_commits WHERE sha=?").get(hit.sha);
|
|
1689
|
+
body = row.message;
|
|
1690
|
+
title = `${hit.shortSha} ${body.split(`
|
|
1691
|
+
`)[0]}`;
|
|
1692
|
+
break;
|
|
1693
|
+
}
|
|
1694
|
+
case "note": {
|
|
1695
|
+
const row = db.prepare("SELECT content, ready_reason AS reason FROM notes WHERE id=?").get(hit.noteId);
|
|
1696
|
+
body = `${row.content}${row.reason ? `
|
|
1697
|
+
Reason: ${row.reason}` : ""}`;
|
|
1698
|
+
title = body.split(`
|
|
1699
|
+
`)[0];
|
|
1700
|
+
break;
|
|
1701
|
+
}
|
|
1702
|
+
case "message": {
|
|
1703
|
+
const mapped = db.prepare(`SELECT f.content FROM message_fts_rowid_map m
|
|
1704
|
+
JOIN message_history_fts f ON f.rowid=m.fts_rowid
|
|
1705
|
+
WHERE m.session_id=? AND m.message_ordinal=? AND f.message_id=?`).get(sessionId, hit.messageOrdinal, hit.messageId);
|
|
1706
|
+
const row = mapped ?? db.prepare("SELECT content FROM message_history_fts WHERE session_id=? AND message_id=? ORDER BY CAST(message_ordinal AS INTEGER) LIMIT 1").get(sessionId, hit.messageId);
|
|
1707
|
+
body = row.content;
|
|
1708
|
+
title = `${hit.role}: ${body.split(`
|
|
1709
|
+
`)[0]}`;
|
|
1710
|
+
location = `message ${hit.messageId} ${sessionId} @${hit.messageOrdinal}`;
|
|
1711
|
+
break;
|
|
1712
|
+
}
|
|
1713
|
+
case "compartment": {
|
|
1714
|
+
title = hit.title;
|
|
1715
|
+
location = `compartment ${hit.compartmentId} ${hit.sessionId} @${hit.startOrdinal}-${hit.endOrdinal}`;
|
|
1716
|
+
body = buildCanonicalChunkTextFromFts(db, hit.sessionId, hit.startOrdinal, hit.endOrdinal) ?? "";
|
|
1717
|
+
break;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
return candidateText(location, title, body);
|
|
1721
|
+
});
|
|
656
1722
|
}
|
|
657
1723
|
|
|
658
1724
|
// src/features/magic-context/search.ts
|
|
@@ -677,13 +1743,34 @@ var sessionFirstMessageSearchDiagnosticStatements = new WeakMap;
|
|
|
677
1743
|
var messageSearchDiagnosticStatementsWithDateRange = new WeakMap;
|
|
678
1744
|
var batchedMessageSearchStatements = new WeakMap;
|
|
679
1745
|
var batchedFtsCountStatements = new WeakMap;
|
|
680
|
-
function
|
|
1746
|
+
function createUnifiedSearchDiagnostics2() {
|
|
681
1747
|
return {
|
|
682
1748
|
suppressedVisibleMemoryIds: [],
|
|
683
1749
|
suppressedLiveMessageMatches: 0,
|
|
684
1750
|
gitCommitUnavailable: null
|
|
685
1751
|
};
|
|
686
1752
|
}
|
|
1753
|
+
function searchMessageHistory2(db, request) {
|
|
1754
|
+
const diagnostics = request.collectDiagnostics ? createUnifiedSearchDiagnostics2() : undefined;
|
|
1755
|
+
const capture = request.captureLimit ? { limit: request.captureLimit, results: [] } : undefined;
|
|
1756
|
+
const results = searchMessages({
|
|
1757
|
+
db,
|
|
1758
|
+
sessionId: request.sessionId,
|
|
1759
|
+
query: request.query,
|
|
1760
|
+
limit: request.limit,
|
|
1761
|
+
maxOrdinal: request.maxOrdinal,
|
|
1762
|
+
probes: request.probes,
|
|
1763
|
+
relaxedRecall: request.relaxedRecall,
|
|
1764
|
+
diagnostics,
|
|
1765
|
+
dateRange: request.dateRange,
|
|
1766
|
+
capture
|
|
1767
|
+
});
|
|
1768
|
+
return {
|
|
1769
|
+
results,
|
|
1770
|
+
laneResults: capture?.results,
|
|
1771
|
+
suppressedLiveMessageMatches: diagnostics?.suppressedLiveMessageMatches ?? 0
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
687
1774
|
function normalizeLimit(limit) {
|
|
688
1775
|
if (typeof limit !== "number" || !Number.isFinite(limit)) {
|
|
689
1776
|
return DEFAULT_UNIFIED_SEARCH_LIMIT;
|
|
@@ -703,7 +1790,7 @@ function timestampIsInRange(timestamp, range) {
|
|
|
703
1790
|
}
|
|
704
1791
|
var ID_SHAPED_QUERY_MAX_TOKENS = 5;
|
|
705
1792
|
var ID_SHAPED_TOKEN = /^#?\d+$/;
|
|
706
|
-
function
|
|
1793
|
+
function parseIdShapedQuery2(query) {
|
|
707
1794
|
const trimmed = query.trim();
|
|
708
1795
|
if (trimmed.length === 0) {
|
|
709
1796
|
return null;
|
|
@@ -978,8 +2065,8 @@ async function getSemanticScores(args) {
|
|
|
978
2065
|
return semanticScores;
|
|
979
2066
|
}
|
|
980
2067
|
if (!args.workspace?.isWorkspaced) {
|
|
981
|
-
const cachedEmbeddings =
|
|
982
|
-
const embeddings = args.backfillMemoryEmbeddings === false ? cachedEmbeddings : await
|
|
2068
|
+
const cachedEmbeddings = getProjectEmbeddings2(args.db, args.projectPath, args.queryModelId);
|
|
2069
|
+
const embeddings = args.backfillMemoryEmbeddings === false ? cachedEmbeddings : await ensureMemoryEmbeddings2({
|
|
983
2070
|
db: args.db,
|
|
984
2071
|
projectIdentity: args.projectPath,
|
|
985
2072
|
memories: args.memories,
|
|
@@ -1006,8 +2093,8 @@ async function getSemanticScores(args) {
|
|
|
1006
2093
|
}
|
|
1007
2094
|
const ownMemories = memoriesByIdentity.get(args.projectPath) ?? [];
|
|
1008
2095
|
if (ownMemories.length > 0 && args.backfillMemoryEmbeddings !== false) {
|
|
1009
|
-
const ownEmbeddings =
|
|
1010
|
-
await
|
|
2096
|
+
const ownEmbeddings = getProjectEmbeddings2(args.db, args.projectPath, args.queryModelId);
|
|
2097
|
+
await ensureMemoryEmbeddings2({
|
|
1011
2098
|
db: args.db,
|
|
1012
2099
|
projectIdentity: args.projectPath,
|
|
1013
2100
|
memories: ownMemories,
|
|
@@ -1018,7 +2105,7 @@ async function getSemanticScores(args) {
|
|
|
1018
2105
|
const memberMemories = memoriesByIdentity.get(identity) ?? [];
|
|
1019
2106
|
if (memberMemories.length === 0)
|
|
1020
2107
|
continue;
|
|
1021
|
-
const cachedEmbeddings =
|
|
2108
|
+
const cachedEmbeddings = getProjectEmbeddings2(args.db, identity, args.queryModelId);
|
|
1022
2109
|
for (const memory of memberMemories) {
|
|
1023
2110
|
const memoryEmbedding = cachedEmbeddings.get(memory.id);
|
|
1024
2111
|
if (!memoryEmbedding || memoryEmbedding.modelId !== args.queryModelId)
|
|
@@ -1032,7 +2119,7 @@ function getFtsMatches(args) {
|
|
|
1032
2119
|
try {
|
|
1033
2120
|
return args.workspace?.isWorkspaced ? searchMemoriesFTSUnion(args.db, args.workspace.expandedIdentities, args.query, args.limit, args.workspace.ownIdentities, args.workspace.shareCategories, args.dateRange) : searchMemoriesFTS(args.db, args.projectPath, args.query, args.limit, args.dateRange);
|
|
1034
2121
|
} catch (error) {
|
|
1035
|
-
|
|
2122
|
+
log2(`[search] FTS query failed for "${args.query}": ${error instanceof Error ? error.message : String(error)}`);
|
|
1036
2123
|
return [];
|
|
1037
2124
|
}
|
|
1038
2125
|
}
|
|
@@ -1047,7 +2134,7 @@ function selectSemanticCandidates(args) {
|
|
|
1047
2134
|
if (args.queryModelId && args.queryModelId !== "off") {
|
|
1048
2135
|
const embeddingProjects = args.workspace?.isWorkspaced ? args.workspace.identities : [args.projectPath];
|
|
1049
2136
|
for (const projectPath of embeddingProjects) {
|
|
1050
|
-
const storedEmbeddings =
|
|
2137
|
+
const storedEmbeddings = getProjectEmbeddings2(args.db, projectPath, args.queryModelId);
|
|
1051
2138
|
for (const memoryId of storedEmbeddings.keys()) {
|
|
1052
2139
|
candidateIds.add(memoryId);
|
|
1053
2140
|
}
|
|
@@ -1073,7 +2160,7 @@ function mergeMemoryResults(args) {
|
|
|
1073
2160
|
score = SEMANTIC_WEIGHT * semanticScore + FTS_WEIGHT * ftsScore;
|
|
1074
2161
|
matchType = "hybrid";
|
|
1075
2162
|
} else if (semanticScore !== undefined) {
|
|
1076
|
-
score = semanticScore * SINGLE_SOURCE_PENALTY;
|
|
2163
|
+
score = semanticScore * (args.singleSourcePenalty ?? SINGLE_SOURCE_PENALTY);
|
|
1077
2164
|
matchType = "semantic";
|
|
1078
2165
|
} else if (ftsScore !== undefined) {
|
|
1079
2166
|
score = ftsScore * SINGLE_SOURCE_PENALTY;
|
|
@@ -1110,7 +2197,7 @@ async function searchMemories(args) {
|
|
|
1110
2197
|
if (!args.memoryEnabled) {
|
|
1111
2198
|
return { results: [], suppressedVisibleIds: [] };
|
|
1112
2199
|
}
|
|
1113
|
-
const unfilteredMemories = args.workspace?.isWorkspaced ?
|
|
2200
|
+
const unfilteredMemories = args.workspace?.isWorkspaced ? getMemoriesByProjects2(args.db, args.workspace.expandedIdentities, ["active", "permanent"], Date.now(), args.workspace.ownIdentities, args.workspace.shareCategories) : getMemoriesByProject2(args.db, args.projectPath);
|
|
1114
2201
|
const memories = unfilteredMemories.filter((memory) => timestampIsInRange(memory.createdAt, args.dateRange));
|
|
1115
2202
|
if (memories.length === 0) {
|
|
1116
2203
|
return { results: [], suppressedVisibleIds: [] };
|
|
@@ -1141,25 +2228,45 @@ async function searchMemories(args) {
|
|
|
1141
2228
|
queryModelId: args.queryModelId,
|
|
1142
2229
|
workspace: args.workspace
|
|
1143
2230
|
});
|
|
2231
|
+
const sourceNameByMemoryId = sourceNamesForSearchMemories({
|
|
2232
|
+
memories,
|
|
2233
|
+
projectPath: args.projectPath,
|
|
2234
|
+
workspace: args.workspace ?? {
|
|
2235
|
+
identities: [args.projectPath],
|
|
2236
|
+
expandedIdentities: [args.projectPath],
|
|
2237
|
+
namesByIdentity: new Map,
|
|
2238
|
+
canonicalIdentityByStoredPath: new Map([[args.projectPath, args.projectPath]]),
|
|
2239
|
+
ownIdentities: [args.projectPath],
|
|
2240
|
+
shareCategories: null,
|
|
2241
|
+
isWorkspaced: false
|
|
2242
|
+
}
|
|
2243
|
+
});
|
|
2244
|
+
if (args.lanes) {
|
|
2245
|
+
args.lanes.memory_fts = mergeMemoryResults({
|
|
2246
|
+
memories,
|
|
2247
|
+
semanticScores: new Map,
|
|
2248
|
+
ftsScores,
|
|
2249
|
+
sourceNameByMemoryId,
|
|
2250
|
+
limit: 25,
|
|
2251
|
+
visibleMemoryIds: args.visibleMemoryIds
|
|
2252
|
+
}).results;
|
|
2253
|
+
args.lanes.memory_vector = mergeMemoryResults({
|
|
2254
|
+
memories,
|
|
2255
|
+
semanticScores,
|
|
2256
|
+
ftsScores: new Map,
|
|
2257
|
+
sourceNameByMemoryId,
|
|
2258
|
+
singleSourcePenalty: 1,
|
|
2259
|
+
limit: 25,
|
|
2260
|
+
visibleMemoryIds: args.visibleMemoryIds
|
|
2261
|
+
}).results;
|
|
2262
|
+
}
|
|
1144
2263
|
return mergeMemoryResults({
|
|
1145
2264
|
memories,
|
|
1146
2265
|
semanticScores,
|
|
1147
2266
|
ftsScores,
|
|
1148
2267
|
limit: args.limit,
|
|
1149
2268
|
visibleMemoryIds: args.visibleMemoryIds,
|
|
1150
|
-
sourceNameByMemoryId
|
|
1151
|
-
memories,
|
|
1152
|
-
projectPath: args.projectPath,
|
|
1153
|
-
workspace: args.workspace ?? {
|
|
1154
|
-
identities: [args.projectPath],
|
|
1155
|
-
expandedIdentities: [args.projectPath],
|
|
1156
|
-
namesByIdentity: new Map,
|
|
1157
|
-
canonicalIdentityByStoredPath: new Map([[args.projectPath, args.projectPath]]),
|
|
1158
|
-
ownIdentities: [args.projectPath],
|
|
1159
|
-
shareCategories: null,
|
|
1160
|
-
isWorkspaced: false
|
|
1161
|
-
}
|
|
1162
|
-
})
|
|
2269
|
+
sourceNameByMemoryId
|
|
1163
2270
|
});
|
|
1164
2271
|
}
|
|
1165
2272
|
function linearDecayScore(rank, total) {
|
|
@@ -1292,7 +2399,9 @@ function searchMessages(args) {
|
|
|
1292
2399
|
}
|
|
1293
2400
|
function searchMessagesInSnapshot(args, sessionFirst) {
|
|
1294
2401
|
const cutoff = args.maxOrdinal != null && args.maxOrdinal >= 0 ? args.maxOrdinal : null;
|
|
1295
|
-
const
|
|
2402
|
+
const baselineFetchLimit = cutoff !== null ? args.limit * 3 : args.limit;
|
|
2403
|
+
const captureFetchLimit = args.capture ? cutoff !== null ? args.capture.limit * 3 : args.capture.limit : 0;
|
|
2404
|
+
const fetchLimit = Math.max(baselineFetchLimit, captureFetchLimit);
|
|
1296
2405
|
const baseQuery = sanitizeFtsQuery(args.query.trim());
|
|
1297
2406
|
const probes = args.probes ?? [];
|
|
1298
2407
|
if (probes.length === 0) {
|
|
@@ -1312,15 +2421,20 @@ function searchMessagesInSnapshot(args, sessionFirst) {
|
|
|
1312
2421
|
args.diagnostics.suppressedLiveMessageMatches = outcome.suppressedCount;
|
|
1313
2422
|
}
|
|
1314
2423
|
const rows = outcome.rows.length > 0 || !args.relaxedRecall ? outcome.rows : runMessageFtsQuery(args.db, args.sessionId, relaxedFtsQuery(args.query), fetchLimit, cutoff, args.dateRange, sessionFirst);
|
|
1315
|
-
const
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
2424
|
+
const renderRows = (limit) => {
|
|
2425
|
+
const filtered = rows.slice(0, limit);
|
|
2426
|
+
return filtered.map((row, rank) => ({
|
|
2427
|
+
source: "message",
|
|
2428
|
+
content: previewText(row.content),
|
|
2429
|
+
score: linearDecayScore(rank, filtered.length),
|
|
2430
|
+
messageOrdinal: row.messageOrdinal,
|
|
2431
|
+
messageId: row.messageId,
|
|
2432
|
+
role: row.role
|
|
2433
|
+
}));
|
|
2434
|
+
};
|
|
2435
|
+
if (args.capture)
|
|
2436
|
+
args.capture.results = renderRows(args.capture.limit);
|
|
2437
|
+
return renderRows(args.limit);
|
|
1324
2438
|
}
|
|
1325
2439
|
const sanitizedProbes = probes.map((probe) => ({ probe, query: sanitizeFtsQuery(probe) })).filter((entry) => entry.query.length > 0);
|
|
1326
2440
|
const corpusSize = getIndexedMessageCorpusSize(args.db, args.sessionId, cutoff);
|
|
@@ -1360,39 +2474,44 @@ function searchMessagesInSnapshot(args, sessionFirst) {
|
|
|
1360
2474
|
queryLists.push({ rows: rowsByQuery[queryIndex] ?? [], weight });
|
|
1361
2475
|
queryIndex += 1;
|
|
1362
2476
|
});
|
|
1363
|
-
const
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
existing
|
|
1370
|
-
|
|
1371
|
-
|
|
2477
|
+
const rankProbeLists = (rowLimit, resultLimit) => {
|
|
2478
|
+
const fused = new Map;
|
|
2479
|
+
for (const list of queryLists) {
|
|
2480
|
+
list.rows.slice(0, rowLimit).forEach((row, rank) => {
|
|
2481
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
2482
|
+
const existing = fused.get(row.messageId);
|
|
2483
|
+
if (existing) {
|
|
2484
|
+
existing.score += rrf;
|
|
2485
|
+
} else {
|
|
2486
|
+
fused.set(row.messageId, { row, score: rrf });
|
|
2487
|
+
}
|
|
2488
|
+
});
|
|
2489
|
+
}
|
|
2490
|
+
for (const entry of fused.values()) {
|
|
2491
|
+
let best = 0;
|
|
2492
|
+
for (const probe of probes) {
|
|
2493
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
2494
|
+
if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
|
|
2495
|
+
best = weight;
|
|
2496
|
+
}
|
|
1372
2497
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
for (const entry of fused.values()) {
|
|
1376
|
-
let best = 0;
|
|
1377
|
-
for (const probe of probes) {
|
|
1378
|
-
const weight = probeWeights.get(probe) ?? 0;
|
|
1379
|
-
if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
|
|
1380
|
-
best = weight;
|
|
2498
|
+
if (best > 0) {
|
|
2499
|
+
entry.score += best * VERBATIM_RANK_BONUS;
|
|
1381
2500
|
}
|
|
1382
2501
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
2502
|
+
const ranked = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.row.messageOrdinal - b.row.messageOrdinal).slice(0, resultLimit);
|
|
2503
|
+
return ranked.map((entry, rank) => ({
|
|
2504
|
+
source: "message",
|
|
2505
|
+
content: previewText(entry.row.content),
|
|
2506
|
+
score: linearDecayScore(rank, ranked.length),
|
|
2507
|
+
messageOrdinal: entry.row.messageOrdinal,
|
|
2508
|
+
messageId: entry.row.messageId,
|
|
2509
|
+
role: entry.row.role
|
|
2510
|
+
}));
|
|
2511
|
+
};
|
|
2512
|
+
if (args.capture)
|
|
2513
|
+
args.capture.results = rankProbeLists(captureFetchLimit, args.capture.limit);
|
|
2514
|
+
return rankProbeLists(baselineFetchLimit, args.limit);
|
|
1396
2515
|
}
|
|
1397
2516
|
var NOTE_SEARCHABLE_STATUSES = ["active", "pending", "ready"];
|
|
1398
2517
|
var MAX_NOTE_KEYWORD_SCORE = 3.5;
|
|
@@ -1662,12 +2781,17 @@ function toGitCommitResult(hit) {
|
|
|
1662
2781
|
function searchGitCommits(args) {
|
|
1663
2782
|
if (args.limit <= 0)
|
|
1664
2783
|
return [];
|
|
2784
|
+
const lanes = args.lanes;
|
|
1665
2785
|
const hits = searchGitCommitsSync(args.db, args.projectPath, args.query, {
|
|
1666
2786
|
limit: args.limit,
|
|
1667
2787
|
queryEmbedding: args.queryEmbedding,
|
|
1668
2788
|
queryModelId: args.queryModelId,
|
|
1669
2789
|
from: args.dateRange?.from,
|
|
1670
|
-
to: args.dateRange?.to
|
|
2790
|
+
to: args.dateRange?.to,
|
|
2791
|
+
captureLanes: lanes ? (fts, vector) => {
|
|
2792
|
+
lanes.git_fts = fts.map(toGitCommitResult);
|
|
2793
|
+
lanes.git_vector = vector.map(toGitCommitResult);
|
|
2794
|
+
} : undefined
|
|
1671
2795
|
});
|
|
1672
2796
|
return hits.map(toGitCommitResult);
|
|
1673
2797
|
}
|
|
@@ -1689,13 +2813,44 @@ function searchPrimers(args) {
|
|
|
1689
2813
|
WHERE primers_fts MATCH ? AND p.project_path = ? AND p.status = 'active'
|
|
1690
2814
|
${args.dateRange === null ? "" : "AND p.created_at BETWEEN ? AND ?"}
|
|
1691
2815
|
ORDER BY rank ASC
|
|
1692
|
-
LIMIT ?`).all(ftsQuery, args.projectPath, ...args.dateRange === null ? [] : [args.dateRange.from, args.dateRange.to], args.limit * 3);
|
|
1693
|
-
rows.
|
|
1694
|
-
|
|
2816
|
+
LIMIT ?`).all(ftsQuery, args.projectPath, ...args.dateRange === null ? [] : [args.dateRange.from, args.dateRange.to], args.lanes ? Math.max(args.limit * 3, 225) : args.limit * 3);
|
|
2817
|
+
const baselineRows = rows.slice(0, args.limit * 3);
|
|
2818
|
+
baselineRows.forEach((row, index) => {
|
|
2819
|
+
ftsRanks.set(row.id, linearDecayScore(index, baselineRows.length));
|
|
1695
2820
|
});
|
|
2821
|
+
if (args.lanes) {
|
|
2822
|
+
const byId = new Map(primers.map((primer) => [primer.id, primer]));
|
|
2823
|
+
args.lanes.primer_fts = rows.flatMap((row, index) => {
|
|
2824
|
+
const primer = byId.get(row.id);
|
|
2825
|
+
return primer ? [
|
|
2826
|
+
{
|
|
2827
|
+
source: "primer",
|
|
2828
|
+
primerId: primer.id,
|
|
2829
|
+
content: previewText(primerText(primer)),
|
|
2830
|
+
question: primer.question,
|
|
2831
|
+
support: primer.totalSupport,
|
|
2832
|
+
lastObservedAt: primer.lastObservedAt,
|
|
2833
|
+
matchType: "fts",
|
|
2834
|
+
score: linearDecayScore(index, rows.length)
|
|
2835
|
+
}
|
|
2836
|
+
] : [];
|
|
2837
|
+
}).slice(0, 25);
|
|
2838
|
+
}
|
|
1696
2839
|
}
|
|
2840
|
+
const vectorResults = [];
|
|
1697
2841
|
const scored = primers.map((primer) => {
|
|
1698
2842
|
const semantic = args.queryEmbedding && primer.questionEmbedding && primer.questionEmbeddingModelId === args.queryModelId ? normalizeCosineScore(cosineSimilarity(args.queryEmbedding, primer.questionEmbedding)) : 0;
|
|
2843
|
+
if (args.lanes && semantic > 0)
|
|
2844
|
+
vectorResults.push({
|
|
2845
|
+
source: "primer",
|
|
2846
|
+
primerId: primer.id,
|
|
2847
|
+
content: previewText(primerText(primer)),
|
|
2848
|
+
question: primer.question,
|
|
2849
|
+
support: primer.totalSupport,
|
|
2850
|
+
lastObservedAt: primer.lastObservedAt,
|
|
2851
|
+
matchType: "semantic",
|
|
2852
|
+
score: semantic
|
|
2853
|
+
});
|
|
1699
2854
|
const fts = ftsRanks.get(primer.id) ?? 0;
|
|
1700
2855
|
if (semantic <= 0 && fts <= 0)
|
|
1701
2856
|
return null;
|
|
@@ -1711,6 +2866,8 @@ function searchPrimers(args) {
|
|
|
1711
2866
|
matchType: semantic > 0 && fts > 0 ? "hybrid" : semantic > 0 ? "semantic" : "fts"
|
|
1712
2867
|
};
|
|
1713
2868
|
}).filter((result) => result !== null).sort((a, b) => b.score - a.score || b.support - a.support || a.primerId - b.primerId).slice(0, args.limit);
|
|
2869
|
+
if (args.lanes)
|
|
2870
|
+
args.lanes.primer_vector = vectorResults.sort((a, b) => b.score - a.score || b.support - a.support || a.primerId - b.primerId).slice(0, 25);
|
|
1714
2871
|
return scored;
|
|
1715
2872
|
}
|
|
1716
2873
|
function resolveSources(sources) {
|
|
@@ -1737,7 +2894,7 @@ function memoriesToIdLookupResults(args) {
|
|
|
1737
2894
|
sourceName: args.sourceNameByMemoryId?.get(memory.id)
|
|
1738
2895
|
}));
|
|
1739
2896
|
}
|
|
1740
|
-
function
|
|
2897
|
+
function resolveMemoriesByIdsForSearch2(args) {
|
|
1741
2898
|
if (args.diagnostics) {
|
|
1742
2899
|
args.diagnostics.suppressedVisibleMemoryIds = [];
|
|
1743
2900
|
}
|
|
@@ -1745,7 +2902,7 @@ function resolveMemoriesByIdsForSearch(args) {
|
|
|
1745
2902
|
return null;
|
|
1746
2903
|
}
|
|
1747
2904
|
const workspace = resolveSearchWorkspaceContext(args.db, args.projectPath);
|
|
1748
|
-
const fetched = workspace.isWorkspaced ?
|
|
2905
|
+
const fetched = workspace.isWorkspaced ? getMemoriesByProjects2(args.db, workspace.expandedIdentities, ["active", "permanent", "archived"], Date.now(), workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject2(args.db, args.projectPath, ["active", "permanent", "archived"]);
|
|
1749
2906
|
if (fetched.length === 0) {
|
|
1750
2907
|
return null;
|
|
1751
2908
|
}
|
|
@@ -1781,13 +2938,15 @@ function resolveMemoriesByIdsForSearch(args) {
|
|
|
1781
2938
|
})
|
|
1782
2939
|
});
|
|
1783
2940
|
}
|
|
1784
|
-
async function
|
|
2941
|
+
async function unifiedSearch2(db, sessionId, projectPath, query, options = {}) {
|
|
1785
2942
|
const trimmedQuery = query.trim();
|
|
1786
2943
|
const measurementStartedAt = Date.now();
|
|
1787
2944
|
if (trimmedQuery.length === 0 || options.signal?.aborted) {
|
|
1788
2945
|
return [];
|
|
1789
2946
|
}
|
|
1790
2947
|
const limit = normalizeLimit(options.limit);
|
|
2948
|
+
const reranker = options.explicitSearch && options.rerank !== false && isProseQuery(trimmedQuery) ? await prepareReranker(projectPath, sessionId, options.rerankConnectionFile, options.rerankClient) : null;
|
|
2949
|
+
const lanes = reranker || options.captureRerankLanes ? emptySearchLanes() : undefined;
|
|
1791
2950
|
const dateRange = normalizeDateRange(options.from, options.to);
|
|
1792
2951
|
const tierLimit = Math.max(limit * 3, DEFAULT_UNIFIED_SEARCH_LIMIT);
|
|
1793
2952
|
if (options.diagnostics) {
|
|
@@ -1812,28 +2971,44 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
1812
2971
|
const runCompartmentChunks = runMessages && embeddingEnabled;
|
|
1813
2972
|
const needsEmbedding = (runMemory || runGitCommits || runCompartmentChunks || runPrimers) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
1814
2973
|
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error) => {
|
|
1815
|
-
|
|
2974
|
+
log2(`[search] query embedding failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1816
2975
|
return null;
|
|
1817
2976
|
}) : Promise.resolve(null);
|
|
1818
2977
|
await Promise.resolve();
|
|
1819
2978
|
if (options.signal?.aborted)
|
|
1820
2979
|
return [];
|
|
1821
2980
|
const messageProbes = options.explicitSearch ? extractLiteralProbes(trimmedQuery) : [];
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
2981
|
+
let messageResults = [];
|
|
2982
|
+
if (runMessages) {
|
|
2983
|
+
const messageRequest = {
|
|
2984
|
+
sessionId,
|
|
2985
|
+
query: trimmedQuery,
|
|
2986
|
+
limit: tierLimit,
|
|
2987
|
+
captureLimit: lanes ? 75 : undefined,
|
|
2988
|
+
maxOrdinal: options.maxMessageOrdinal,
|
|
2989
|
+
probes: messageProbes,
|
|
2990
|
+
relaxedRecall: options.explicitSearch,
|
|
2991
|
+
collectDiagnostics: options.diagnostics !== undefined,
|
|
2992
|
+
dateRange
|
|
2993
|
+
};
|
|
2994
|
+
const delegated = options.searchMessageHistory ? await options.searchMessageHistory(messageRequest).catch((error) => {
|
|
2995
|
+
log2(`[search] off-thread message search failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2996
|
+
return null;
|
|
2997
|
+
}) : null;
|
|
2998
|
+
if (delegated && options.signal?.aborted)
|
|
2999
|
+
return [];
|
|
3000
|
+
const outcome = delegated ?? searchMessageHistory2(db, messageRequest);
|
|
3001
|
+
if (options.diagnostics) {
|
|
3002
|
+
options.diagnostics.suppressedLiveMessageMatches = outcome.suppressedLiveMessageMatches;
|
|
3003
|
+
}
|
|
3004
|
+
messageResults = outcome.results;
|
|
3005
|
+
if (lanes)
|
|
3006
|
+
lanes.message_fts = (outcome.laneResults ?? outcome.results).slice(0, 25);
|
|
3007
|
+
}
|
|
1833
3008
|
const capturedQuery = await queryEmbeddingPromise;
|
|
1834
3009
|
if (options.signal?.aborted)
|
|
1835
3010
|
return [];
|
|
1836
|
-
const embeddingSnapshot =
|
|
3011
|
+
const embeddingSnapshot = getProjectEmbeddingSnapshot2(projectPath);
|
|
1837
3012
|
const queryContract = capturedQuery instanceof Float32Array || capturedQuery === null ? null : capturedQuery;
|
|
1838
3013
|
const generationIsCurrent = queryContract === null || embeddingSnapshot !== null && embeddingSnapshot.generation === queryContract.generation;
|
|
1839
3014
|
const queryEmbedding = generationIsCurrent ? queryContract?.vector ?? (capturedQuery instanceof Float32Array ? capturedQuery : null) : null;
|
|
@@ -1845,14 +3020,16 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
1845
3020
|
sessionId,
|
|
1846
3021
|
projectPath,
|
|
1847
3022
|
queryEmbedding,
|
|
1848
|
-
limit: tierLimit,
|
|
3023
|
+
limit: lanes ? Math.max(tierLimit, 25) : tierLimit,
|
|
1849
3024
|
maxOrdinal: options.maxMessageOrdinal,
|
|
1850
3025
|
modelId: chunkModelId && chunkModelId !== "off" ? chunkModelId : null,
|
|
1851
3026
|
dateRange
|
|
1852
3027
|
}) : [];
|
|
3028
|
+
if (lanes)
|
|
3029
|
+
lanes.chunk_vector = compartmentResults.slice(0, 25);
|
|
1853
3030
|
const messageLikeResults = mergeMessageAndCompartmentResults({
|
|
1854
3031
|
messages: messageResults,
|
|
1855
|
-
compartments: compartmentResults,
|
|
3032
|
+
compartments: compartmentResults.slice(0, tierLimit),
|
|
1856
3033
|
limit: tierLimit
|
|
1857
3034
|
});
|
|
1858
3035
|
const [memoryOutcome, gitCommitResults, primerResults, noteResults] = await Promise.all([
|
|
@@ -1867,6 +3044,7 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
1867
3044
|
workspace,
|
|
1868
3045
|
visibleMemoryIds: options.visibleMemoryIds,
|
|
1869
3046
|
backfillMemoryEmbeddings: options.backfillMemoryEmbeddings,
|
|
3047
|
+
lanes,
|
|
1870
3048
|
dateRange
|
|
1871
3049
|
}) : Promise.resolve({
|
|
1872
3050
|
results: [],
|
|
@@ -1879,7 +3057,8 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
1879
3057
|
limit: tierLimit,
|
|
1880
3058
|
queryEmbedding,
|
|
1881
3059
|
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null,
|
|
1882
|
-
dateRange
|
|
3060
|
+
dateRange,
|
|
3061
|
+
lanes
|
|
1883
3062
|
})) : Promise.resolve([]),
|
|
1884
3063
|
runPrimers ? Promise.resolve(searchPrimers({
|
|
1885
3064
|
db,
|
|
@@ -1888,14 +3067,15 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
1888
3067
|
limit: tierLimit,
|
|
1889
3068
|
queryEmbedding,
|
|
1890
3069
|
queryModelId: embeddingModelId && embeddingModelId !== "off" ? embeddingModelId : null,
|
|
1891
|
-
dateRange
|
|
3070
|
+
dateRange,
|
|
3071
|
+
lanes
|
|
1892
3072
|
})) : Promise.resolve([]),
|
|
1893
3073
|
runNotes ? Promise.resolve(searchNotes({
|
|
1894
3074
|
db,
|
|
1895
3075
|
sessionId,
|
|
1896
3076
|
projectPath,
|
|
1897
3077
|
query: trimmedQuery,
|
|
1898
|
-
limit: tierLimit,
|
|
3078
|
+
limit: lanes ? Math.max(tierLimit, 25) : tierLimit,
|
|
1899
3079
|
probes: messageProbes,
|
|
1900
3080
|
dateRange
|
|
1901
3081
|
})) : Promise.resolve([])
|
|
@@ -1903,24 +3083,38 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
1903
3083
|
if (options.diagnostics) {
|
|
1904
3084
|
options.diagnostics.suppressedVisibleMemoryIds = memoryOutcome.suppressedVisibleIds;
|
|
1905
3085
|
}
|
|
1906
|
-
|
|
3086
|
+
let results = [
|
|
1907
3087
|
...memoryOutcome.results,
|
|
1908
3088
|
...primerResults,
|
|
1909
3089
|
...messageLikeResults,
|
|
1910
3090
|
...gitCommitResults,
|
|
1911
3091
|
...noteResults
|
|
1912
3092
|
].sort(compareUnifiedResults).slice(0, limit);
|
|
3093
|
+
const originalResults = results;
|
|
3094
|
+
const originalLatencyMs = Date.now() - measurementStartedAt;
|
|
3095
|
+
if (lanes) {
|
|
3096
|
+
lanes.notes = noteResults.slice(0, 25);
|
|
3097
|
+
options.captureRerankLanes?.(lanes);
|
|
3098
|
+
}
|
|
3099
|
+
if (reranker && lanes) {
|
|
3100
|
+
const pool = fuseSearchLanes(lanes);
|
|
3101
|
+
try {
|
|
3102
|
+
results = await rerankSearchResults(reranker, trimmedQuery, results, pool, candidateTexts(db, sessionId, projectPath, pool), limit);
|
|
3103
|
+
} catch {
|
|
3104
|
+
logRerankFallback("candidate_validation");
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
1913
3107
|
if (!options.measurementDisabled) {
|
|
1914
3108
|
recordShadowMeasurement({
|
|
1915
3109
|
db,
|
|
1916
3110
|
sessionId,
|
|
1917
3111
|
projectPath,
|
|
1918
3112
|
query: trimmedQuery,
|
|
1919
|
-
options,
|
|
1920
|
-
primaryResults:
|
|
3113
|
+
options: { ...options, rerank: false, captureRerankLanes: undefined },
|
|
3114
|
+
primaryResults: originalResults,
|
|
1921
3115
|
primaryQuery: queryContract,
|
|
1922
|
-
primaryLatencyMs:
|
|
1923
|
-
search:
|
|
3116
|
+
primaryLatencyMs: originalLatencyMs,
|
|
3117
|
+
search: unifiedSearch2
|
|
1924
3118
|
});
|
|
1925
3119
|
}
|
|
1926
3120
|
const countRetrievals = options.countRetrievals ?? true;
|
|
@@ -1930,9 +3124,9 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
1930
3124
|
db.transaction(() => {
|
|
1931
3125
|
for (const memoryId of memoryIds) {
|
|
1932
3126
|
try {
|
|
1933
|
-
|
|
3127
|
+
updateMemoryRetrievalCount2(db, memoryId);
|
|
1934
3128
|
} catch (error) {
|
|
1935
|
-
if (error instanceof
|
|
3129
|
+
if (error instanceof ModuleMemoryAuthorityError2)
|
|
1936
3130
|
continue;
|
|
1937
3131
|
throw error;
|
|
1938
3132
|
}
|
|
@@ -2032,7 +3226,7 @@ function formatSearchDiagnosticLines(results, diagnostics) {
|
|
|
2032
3226
|
}
|
|
2033
3227
|
return lines;
|
|
2034
3228
|
}
|
|
2035
|
-
function
|
|
3229
|
+
function formatSearchResults2(query, results, currentSessionId, diagnostics) {
|
|
2036
3230
|
const diagnosticLines = formatSearchDiagnosticLines(results, diagnostics);
|
|
2037
3231
|
if (results.length === 0) {
|
|
2038
3232
|
if (diagnosticLines.length > 0) {
|
|
@@ -2060,4 +3254,4 @@ ${bodyParts.join(`
|
|
|
2060
3254
|
`)}`;
|
|
2061
3255
|
}
|
|
2062
3256
|
|
|
2063
|
-
export { indexCommitsForProject, embedUnembeddedCommits,
|
|
3257
|
+
export { renderSingleStoreMigrationRequiredRefusal, SingleStoreMigrationRequiredError, singleStoreMigrationRequiredFailure, projectNeedsSingleStoreMigration, STORE_AHEAD_OF_BINARY_CODE, storeAheadOfBinaryFailure, TRANSFORM_PAGE_UPLOAD_TIMEOUT_MS, transformColdStartExecuteTimeoutMs, MAX_WRAPUP_REQUEST_BUDGET_MS, getDefaultSubcConnectionFile, isModuleTransportGenerationChangedResult, SubcModuleTransport, indexCommitsForProject, embedUnembeddedCommits, createUnifiedSearchDiagnostics2, searchMessageHistory2, parseIdShapedQuery2, resolveMemoriesByIdsForSearch2, unifiedSearch2, formatSearchResults2 };
|