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