@cortexkit/opencode-magic-context 0.46.1 → 0.48.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 +112 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/live-run-config.d.ts.map +1 -1
- package/dist/config/migrate-config-location.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 +21 -9
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-7fj2b9jw.js → conflict-warning-hook-w8cykrnf.js} +12 -9
- package/dist/{context-sh2m2vde.js → context-m0cy262m.js} +1785 -913
- package/dist/{derive-budgets-7nj7r1rv.js → derive-budgets-sg0xsq7s.js} +4 -3
- package/dist/embedding-activity-g1dhes6g.js +10 -0
- package/dist/embedding-backfill-9rcm1mfy.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-gates.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/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/overflow-detection.d.ts +2 -0
- package/dist/features/magic-context/overflow-detection.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/project-embedding-registry.d.ts +7 -0
- package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +31 -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/session-project-storage.d.ts +8 -2
- package/dist/features/magic-context/session-project-storage.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-historian-runs.d.ts +2 -5
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +12 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +6 -0
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts +30 -0
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +148 -3
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -0
- 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/transform-decision-log.d.ts +4 -2
- 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 +10 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-blocking.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-blocking.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-deadline.d.ts +7 -0
- package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-host-review.fixture.d.ts +3 -0
- package/dist/hooks/magic-context/auto-search-host-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-lock-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-lock-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-long-lock-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-long-lock-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-omp-host-review.fixture.d.ts +4 -0
- package/dist/hooks/magic-context/auto-search-omp-host-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-omp-loader.fixture.d.ts +3 -0
- package/dist/hooks/magic-context/auto-search-omp-loader.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-snapshot.fixture.d.ts +4 -0
- package/dist/hooks/magic-context/auto-search-snapshot.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts +98 -0
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-worker.d.ts +2 -0
- package/dist/hooks/magic-context/auto-search-worker.d.ts.map +1 -0
- package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +1 -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-runner-types.d.ts +3 -5
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts +2 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts +3 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/historian-drain-gate.d.ts +11 -0
- package/dist/hooks/magic-context/historian-drain-gate.d.ts.map +1 -0
- 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-assistant-turn.d.ts +25 -0
- package/dist/hooks/magic-context/latest-assistant-turn.d.ts.map +1 -0
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +61 -0
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -0
- 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/module-wire.d.ts.map +1 -1
- 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/opencode-proven-floor.d.ts +6 -0
- package/dist/hooks/magic-context/opencode-proven-floor.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.map +1 -1
- package/dist/hooks/magic-context/protected-tail-boundary.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 +12 -0
- 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 +83 -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-status.d.ts +15 -0
- package/dist/hooks/magic-context/reasoning-budget-status.d.ts.map +1 -0
- package/dist/hooks/magic-context/reasoning-budget.d.ts +40 -0
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -0
- package/dist/hooks/magic-context/reasoning-removal.d.ts +6 -6
- package/dist/hooks/magic-context/reasoning-removal.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +45 -1
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/strip-content.d.ts +21 -5
- 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 +21 -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/tool-drop-target.d.ts +5 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts +3 -28
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +28 -6
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +11 -3
- 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-hpecdzec.js → index-0an7742d.js} +6820 -6587
- package/dist/index-0qhce371.js +120 -0
- package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
- package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
- package/dist/index-14cjxt20.js +819 -0
- package/dist/{v2/server-51dv1pr5.js → index-1qb0z7wa.js} +301 -27
- package/dist/index-2bvekkfy.js +11 -0
- package/dist/{index-sj29b3z2.js → index-2y0s2hep.js} +3 -3
- package/dist/index-4dhv7mqz.js +131 -0
- package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
- package/dist/index-5zygecde.js +152 -0
- package/dist/{index-sjthx78w.js → index-692jzy0p.js} +16879 -22907
- package/dist/index-72nhv486.js +2307 -0
- package/dist/index-7jzrrxap.js +931 -0
- package/dist/index-7mx8v0pw.js +3591 -0
- package/dist/index-8ajstryz.js +18 -0
- package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
- package/dist/{index-hybnrwq0.js → index-8j7gqj40.js} +131 -128
- package/dist/index-bdckkfw6.js +3261 -0
- package/dist/{index-8x2v7gg9.js → index-bhvjj0ys.js} +158 -2455
- package/dist/index-c43kr12f.js +3030 -0
- package/dist/index-cb7emxgj.js +984 -0
- package/dist/index-d9vfe7xq.js +16 -0
- package/dist/{index-5gq3b2ya.js → index-db7zwa3v.js} +147 -209
- package/dist/index-dhwzyd54.js +1142 -0
- package/dist/{index-8da2zjhz.js → index-eeezr5zz.js} +9 -7
- package/dist/{index-pkbcrdqs.js → index-f0h6xwqm.js} +3412 -4552
- package/dist/index-fb3zxn06.js +13 -0
- package/dist/index-fbv1dn35.js +171 -0
- package/dist/index-fr0wbhdn.js +43 -0
- package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
- package/dist/{index-fzbvakh0.js → index-jcbd3znx.js} +3 -3
- package/dist/{index-5p8jdswx.js → index-k1xb52kd.js} +20 -13
- package/dist/index-k9nnwad5.js +3532 -0
- package/dist/{v2/server-fg34g6a5.js → index-kb9nn0a0.js} +309 -52
- package/dist/index-knh4y330.js +566 -0
- package/dist/{index-q4yp4b52.js → index-mfkzp7qj.js} +28 -28
- package/dist/{index-sgthv3f7.js → index-mmyh6d8f.js} +4 -4
- package/dist/index-pavzsdc6.js +17 -0
- package/dist/{index-0d3g3461.js → index-pdecwzrd.js} +19 -16
- package/dist/index-pg50n748.js +1060 -0
- package/dist/index-q2tqeqde.js +2106 -0
- package/dist/index-q7h7csab.js +3469 -0
- package/dist/index-qt1qqasc.js +22 -0
- package/dist/{index-majxda46.js → index-ty64eqcn.js} +28 -18
- package/dist/{index-7qw742ev.js → index-yq8n9qcb.js} +25 -44
- package/dist/{index-sfnj6h8h.js → index-z8e0psj8.js} +20 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1061 -260
- package/dist/logger-d3wex3dz.js +20 -0
- package/dist/message-index-bounded-7ezbgddp.js +124 -0
- package/dist/{v2/message-time-backfill-r6qkem1x.js → message-time-backfill-brbd63hv.js} +8 -6
- package/dist/migration-worker.js +25 -16
- 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 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler-report.d.ts +2 -0
- package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -0
- package/dist/plugin/host-stall-profiler.d.ts +3 -0
- package/dist/plugin/host-stall-profiler.d.ts.map +1 -0
- package/dist/plugin/messages-transform.d.ts +21 -19
- 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-7qzptcw7.js +88 -0
- package/dist/raw-ordinal-warmup-worker.js +60 -0
- package/dist/{read-session-chunk-egz7r68d.js → read-session-chunk-6k83m4fj.js} +15 -9
- package/dist/read-session-raw-3g9qy1xa.js +58 -0
- package/dist/recomp-orchestrator-d3fp1cy0.js +57 -0
- package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-5ffqq32m.js} +4 -2
- package/dist/search-epax1ecv.js +45 -0
- package/dist/{v2/send-session-notification-qs0j78v6.js → send-session-notification-erecz4y4.js} +10 -6
- package/dist/shared/auto-search-lifecycle.d.ts +7 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -0
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/historian-tool-expansions.d.ts +1 -1
- package/dist/shared/historian-tool-expansions.d.ts.map +1 -1
- package/dist/shared/historian-tool-template.d.ts +2 -2
- package/dist/shared/historian-tool-template.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/model-resolution.d.ts +2 -3
- package/dist/shared/model-resolution.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +46 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/status-view.d.ts.map +1 -1
- package/dist/shared/user-facing-codes.d.ts +0 -5
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/shared/window-geometry.d.ts +4 -0
- package/dist/shared/window-geometry.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-d3b0v2ss.js +131 -0
- package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- 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-search/tools.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-bqhz6vdr.js → transform-postprocess-phase-spcy2qre.js} +35 -17
- package/dist/transformers-node-wasm.js +18415 -18415
- package/dist/v2/auto-search-worker.js +112 -0
- package/dist/v2/{context-zecmzk5s.js → context-sf98kstd.js} +8378 -8530
- package/dist/v2/{derive-budgets-kdgp4s3r.js → derive-budgets-3vc0y84t.js} +4 -3
- package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
- package/dist/v2/embedding-backfill-vn8g1nh1.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-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 +1 -2
- package/dist/v2/hooks/dream-trigger.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-mxd0ym09.js +19 -0
- package/dist/v2/message-index-bounded-dy3s2k1e.js +123 -0
- package/dist/{message-time-backfill-68gj6t3e.js → v2/message-time-backfill-gtx1pwk1.js} +7 -7
- package/dist/v2/migration-worker.js +24 -15
- package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/v2/project-embedding-registry-1tgba5dv.js +86 -0
- package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
- package/dist/v2/{read-session-chunk-8vjp6581.js → read-session-chunk-rh4khdkv.js} +14 -8
- package/dist/v2/read-session-raw-bsbmf0vj.js +57 -0
- package/dist/v2/recomp-orchestrator-az61rfcg.js +57 -0
- package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-73ax1p5v.js} +3 -3
- package/dist/v2/search-nzkwrc6n.js +45 -0
- package/dist/{send-session-notification-dyw42dtr.js → v2/send-session-notification-6km439kn.js} +9 -7
- package/dist/{index-5eqk6z3s.js → v2/server-1r6pmz4f.js} +301 -27
- package/dist/v2/server-2bvekkfy.js +11 -0
- package/dist/v2/server-2fbhp79z.js +3205 -0
- package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
- package/dist/v2/server-4dhv7mqz.js +131 -0
- package/dist/v2/{server-xa4xe3rv.js → server-4k748ke6.js} +11 -1053
- package/dist/v2/{server-vs5gpnd4.js → server-52awr2mw.js} +81 -145
- package/dist/v2/{server-1qbnzc80.js → server-5m3dt5r1.js} +136 -148
- package/dist/v2/server-686jg6eb.js +3508 -0
- package/dist/v2/server-7jzrrxap.js +931 -0
- package/dist/v2/server-7wwc2nga.js +3023 -0
- package/dist/v2/server-8ajstryz.js +18 -0
- package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
- package/dist/v2/server-8pyt7hev.js +3408 -0
- package/dist/v2/server-8tqanswc.js +984 -0
- package/dist/v2/{server-14vq4kpm.js → server-aan4q8mx.js} +3 -3
- package/dist/v2/server-d9vfe7xq.js +16 -0
- package/dist/v2/server-e0vdaae2.js +3591 -0
- package/dist/v2/server-ezhze64f.js +1048 -0
- package/dist/v2/server-fb3zxn06.js +13 -0
- package/dist/v2/server-fr0wbhdn.js +43 -0
- package/dist/v2/server-g5r0n3b6.js +1137 -0
- package/dist/v2/server-gjcr4w98.js +154 -0
- package/dist/v2/server-k228xhjg.js +171 -0
- package/dist/v2/{server-jc7y02q0.js → server-k8x2rbxc.js} +5119 -10948
- package/dist/{index-fg34g6a5.js → v2/server-kb9nn0a0.js} +309 -52
- package/dist/v2/{server-g0fjrkta.js → server-mfkzp7qj.js} +28 -28
- package/dist/v2/server-pavzsdc6.js +17 -0
- package/dist/v2/server-psqc7e9n.js +2106 -0
- package/dist/v2/server-qt1qqasc.js +22 -0
- package/dist/v2/server-qye6ykf7.js +120 -0
- package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
- package/dist/v2/server-sggvvzhb.js +759 -0
- package/dist/v2/{server-y8maxeft.js → server-v06jcv0w.js} +16 -13
- package/dist/v2/server-vqpf3167.js +1048 -0
- package/dist/v2/{server-c5gz8wph.js → server-x2g40a71.js} +2048 -2059
- package/dist/v2/{server-wvjvfhck.js → server-xdfwt6kh.js} +20 -16
- package/dist/v2/{server-mcfawjgc.js → server-xxm59eww.js} +25 -44
- package/dist/v2/server-yczc713m.js +564 -0
- package/dist/v2/{server-3n4q9xme.js → server-z2037m6z.js} +4 -4
- package/dist/v2/{server-e29d7p7c.js → server-zm570tr2.js} +166 -160
- package/dist/v2/{server-6r257mf5.js → server-zxhgvsf9.js} +3 -3
- 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-w4tv77sn.js +130 -0
- package/dist/v2/store-reader.d.ts +16 -0
- 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-0snhvwcv.js → wrapup-orchestrator-mz7efs7w.js} +51 -27
- package/dist/wrapup-orchestrator-amzta1t4.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 +8 -0
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/live-run-config.test.ts +37 -1
- package/src/config/live-run-config.ts +28 -0
- package/src/config/migrate-config-location.ts +10 -3
- 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 +6 -5
- package/src/config/schema/magic-context.ts +34 -16
- package/src/features/magic-context/dreamer/task-registry.ts +6 -0
- package/src/shared/auto-search-lifecycle.ts +27 -0
- package/src/shared/conflict-detector.test.ts +56 -0
- package/src/shared/conflict-detector.ts +16 -5
- package/src/shared/historian-tool-defaults.json +6 -6
- package/src/shared/historian-tool-expansions.ts +65 -8
- package/src/shared/historian-tool-preview-defaults.json +13 -0
- package/src/shared/historian-tool-template.ts +48 -14
- 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/model-resolution.test.ts +54 -17
- package/src/shared/model-resolution.ts +6 -17
- package/src/shared/sqlite-640-review-r2.test.ts +136 -0
- package/src/shared/sqlite-640-review.test.ts +183 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +18 -0
- package/src/shared/sqlite.test.ts +52 -0
- package/src/shared/sqlite.ts +423 -37
- package/src/shared/stable-json-linear.test.ts +109 -0
- package/src/shared/stable-json.ts +37 -7
- package/src/shared/status-view.test.ts +6 -1
- package/src/shared/status-view.ts +15 -1
- package/src/shared/tag-transcript.ts +6 -0
- package/src/shared/user-facing-codes.ts +2 -6
- package/src/shared/window-geometry.ts +10 -0
- 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-3h0ybwah.js +0 -6540
- package/dist/index-r5hmbx3t.js +0 -7773
- package/dist/recomp-orchestrator-y15j0rb9.js +0 -39
- package/dist/v2/recomp-orchestrator-8ejxvrzz.js +0 -39
- package/dist/v2/server-frbm99q5.js +0 -7698
- package/dist/v2/server-qp5hx1ad.js +0 -6366
- package/dist/wrapup-orchestrator-39amhv9s.js +0 -26
- /package/dist/{index-en1k8h8m.js → index-2pp04pmg.js} +0 -0
- /package/dist/v2/{index-en1k8h8m.js → index-2pp04pmg.js} +0 -0
package/src/shared/sqlite.ts
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
43
43
|
import { statSync } from "node:fs";
|
|
44
|
+
|
|
44
45
|
// Type import only — runtime is loaded dynamically below. @types/better-sqlite3
|
|
45
46
|
// has the richest definitions and is a structural superset of the API surface
|
|
46
47
|
// we use, so calls typed against BetterSqlite3 work under bun:sqlite and
|
|
@@ -169,13 +170,51 @@ export class SqliteRuntimeUnavailableError extends Error {
|
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
// Node requests this warning during node:sqlite's module evaluation, although
|
|
174
|
+
// warning delivery happens later. Intercept only the request while importing;
|
|
175
|
+
// replacing warning listeners would not suppress the default stderr output.
|
|
176
|
+
function isNodeSqliteExperimentalWarning(args: unknown[]): boolean {
|
|
177
|
+
const [warning, options] = args;
|
|
178
|
+
const message = warning instanceof Error ? warning.message : warning;
|
|
179
|
+
const type =
|
|
180
|
+
typeof options === "string"
|
|
181
|
+
? options
|
|
182
|
+
: options && typeof options === "object"
|
|
183
|
+
? (options as { type?: unknown }).type
|
|
184
|
+
: undefined;
|
|
185
|
+
return (
|
|
186
|
+
type === "ExperimentalWarning" &&
|
|
187
|
+
typeof message === "string" &&
|
|
188
|
+
message.startsWith("SQLite is an experimental feature")
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function importSqliteModuleForRuntime(
|
|
193
|
+
runtime: SqliteRuntime,
|
|
194
|
+
specifier: string,
|
|
195
|
+
importer: (specifier: string) => Promise<SqliteModule>,
|
|
196
|
+
): Promise<SqliteModule> {
|
|
197
|
+
if (runtime !== "Node.js") return importer(specifier);
|
|
198
|
+
|
|
199
|
+
const originalEmitWarning = process.emitWarning;
|
|
200
|
+
process.emitWarning = function (this: unknown, ...args: unknown[]): void {
|
|
201
|
+
if (isNodeSqliteExperimentalWarning(args)) return;
|
|
202
|
+
Reflect.apply(originalEmitWarning, this, args);
|
|
203
|
+
} as typeof process.emitWarning;
|
|
204
|
+
try {
|
|
205
|
+
return await importer(specifier);
|
|
206
|
+
} finally {
|
|
207
|
+
process.emitWarning = originalEmitWarning;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
172
211
|
export async function loadSqliteModule(
|
|
173
212
|
runtime: SqliteRuntime = detectSqliteRuntime(),
|
|
174
213
|
importer: (specifier: string) => Promise<SqliteModule> = importSqliteModule,
|
|
175
214
|
): Promise<SqliteModule> {
|
|
176
215
|
const specifier = runtime === "Bun" ? bunSpec : nodeSpec;
|
|
177
216
|
try {
|
|
178
|
-
return await
|
|
217
|
+
return await importSqliteModuleForRuntime(runtime, specifier, importer);
|
|
179
218
|
} catch (error) {
|
|
180
219
|
if (isModuleNotFoundError(error, specifier)) {
|
|
181
220
|
throw new SqliteRuntimeUnavailableError(runtime, specifier, error);
|
|
@@ -234,6 +273,110 @@ export interface SqliteMemoryStats {
|
|
|
234
273
|
const trackedSqliteConnections = new Map<number, TrackedSqliteConnection>();
|
|
235
274
|
let nextSqliteConnectionSequence = 1;
|
|
236
275
|
|
|
276
|
+
/**
|
|
277
|
+
* Columns of Magic Context's `tags` table (context.db) that never decide which
|
|
278
|
+
* message a tag belongs to, its number, its type, or its reasoning token estimate.
|
|
279
|
+
*/
|
|
280
|
+
const TAG_COLUMNS_OUTSIDE_IDENTITY = new Set([
|
|
281
|
+
"status",
|
|
282
|
+
"drop_mode",
|
|
283
|
+
"byte_size",
|
|
284
|
+
"input_byte_size",
|
|
285
|
+
"reasoning_byte_size",
|
|
286
|
+
"token_count",
|
|
287
|
+
"input_token_count",
|
|
288
|
+
"caveman_depth",
|
|
289
|
+
"entry_fingerprint",
|
|
290
|
+
"tool_name",
|
|
291
|
+
"harness",
|
|
292
|
+
]);
|
|
293
|
+
|
|
294
|
+
let tagIdentityWriteGeneration = 0;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Whether a write statement may change an existing `tags` row's identity
|
|
298
|
+
* (session, number, type, owner message, reasoning token count) or remove a
|
|
299
|
+
* row. Plain appends without an explicit `id`, and updates that assign only
|
|
300
|
+
* columns in {@link TAG_COLUMNS_OUTSIDE_IDENTITY}, cannot; everything else that
|
|
301
|
+
* names the table is treated as if it could, including DDL and multi-statement
|
|
302
|
+
* scripts. Erring towards true only costs a cache rebuild.
|
|
303
|
+
*/
|
|
304
|
+
export function mayChangeTagIdentity(sql: string): boolean {
|
|
305
|
+
if (!/\btags\b/i.test(sql) || /^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql)) return false;
|
|
306
|
+
if (/^\s*WITH\b/i.test(sql) && !/\b(?:INSERT|UPDATE|DELETE|REPLACE)\b/i.test(sql)) return false;
|
|
307
|
+
// One statement only: a script can hide a DELETE behind a harmless first statement.
|
|
308
|
+
if (/;\s*\S/.test(sql) || /\bREPLACE\b/i.test(sql) || /\bON\s+CONFLICT\b/i.test(sql))
|
|
309
|
+
return true;
|
|
310
|
+
const insert = /^\s*INSERT\s+INTO\s+(?:main\.)?["`]?tags["`]?\s*\(([^)]*)\)/i.exec(sql);
|
|
311
|
+
if (insert) {
|
|
312
|
+
const columns = (insert[1] ?? "").split(",").map((column) =>
|
|
313
|
+
column
|
|
314
|
+
.trim()
|
|
315
|
+
.replace(/["`[\]]/g, "")
|
|
316
|
+
.toLowerCase(),
|
|
317
|
+
);
|
|
318
|
+
return columns.includes("id") || columns.includes("rowid");
|
|
319
|
+
}
|
|
320
|
+
const update = /^\s*UPDATE\s+(?:main\.)?["`]?tags["`]?\s+SET\s+([\s\S]*?)\bWHERE\b/i.exec(sql);
|
|
321
|
+
if (update && !/\bSELECT\b/i.test(sql)) {
|
|
322
|
+
// Provably identity-free only when every top-level assignment is a plain
|
|
323
|
+
// `column = ...` naming an allowed column. A tuple assignment such as
|
|
324
|
+
// `(tag_number, reasoning_token_count) = (...)`, or anything this cannot
|
|
325
|
+
// read, counts as an identity write.
|
|
326
|
+
const assignments = topLevelCommaSegments(update[1] ?? "");
|
|
327
|
+
if (!assignments) return true;
|
|
328
|
+
return !assignments.every((assignment) => {
|
|
329
|
+
const column = /^\s*["`]?(\w+)["`]?\s*=(?!=)/.exec(assignment)?.[1];
|
|
330
|
+
return column !== undefined && TAG_COLUMNS_OUTSIDE_IDENTITY.has(column.toLowerCase());
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Split SQL text at commas outside parentheses and quotes. Returns null when
|
|
338
|
+
* the parentheses or quotes do not balance.
|
|
339
|
+
*/
|
|
340
|
+
function topLevelCommaSegments(text: string): string[] | null {
|
|
341
|
+
const segments: string[] = [];
|
|
342
|
+
let depth = 0;
|
|
343
|
+
let quote: string | null = null;
|
|
344
|
+
let start = 0;
|
|
345
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
346
|
+
const char = text[index];
|
|
347
|
+
if (quote) {
|
|
348
|
+
// A doubled quote inside a quoted run is an escaped quote.
|
|
349
|
+
if (char === quote) {
|
|
350
|
+
if (text[index + 1] === quote) index += 1;
|
|
351
|
+
else quote = null;
|
|
352
|
+
}
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (char === "'" || char === '"' || char === "`") quote = char;
|
|
356
|
+
else if (char === "(") depth += 1;
|
|
357
|
+
else if (char === ")") {
|
|
358
|
+
depth -= 1;
|
|
359
|
+
if (depth < 0) return null;
|
|
360
|
+
} else if (char === "," && depth === 0) {
|
|
361
|
+
segments.push(text.slice(start, index));
|
|
362
|
+
start = index + 1;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (quote || depth !== 0) return null;
|
|
366
|
+
segments.push(text.slice(start));
|
|
367
|
+
return segments;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Counts executions, on any connection this process opened, of statements for
|
|
372
|
+
* which {@link mayChangeTagIdentity} is true. A cache built from `tags` stays
|
|
373
|
+
* valid for this process's own writes while the count is unchanged; commits by
|
|
374
|
+
* other connections show up in `PRAGMA data_version` instead.
|
|
375
|
+
*/
|
|
376
|
+
export function getTagIdentityWriteGeneration(): number {
|
|
377
|
+
return tagIdentityWriteGeneration;
|
|
378
|
+
}
|
|
379
|
+
|
|
237
380
|
/** Route native Bun and Node transaction entry through the same acquisition retry.
|
|
238
381
|
* Native Bun transaction wrappers execute BEGIN internally, bypassing an exec override,
|
|
239
382
|
* so both runtimes use this small synchronous wrapper instead. Writable handles
|
|
@@ -245,6 +388,7 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
|
|
|
245
388
|
configurable: true,
|
|
246
389
|
writable: true,
|
|
247
390
|
value: (sql: string) => {
|
|
391
|
+
if (/^\s*(?:COMMIT|END)\b/i.test(sql)) assertTransformWrite();
|
|
248
392
|
if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
|
|
249
393
|
// A transaction that ended without passing through exec (for
|
|
250
394
|
// example an automatic rollback) must not be timed as this one.
|
|
@@ -256,8 +400,15 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
|
|
|
256
400
|
}
|
|
257
401
|
if (WRITER_TRANSACTION_END.test(sql) && openWriterTransactions.has(db))
|
|
258
402
|
return endWriterTransaction(db, () => nativeExec(sql), sql);
|
|
259
|
-
if (
|
|
260
|
-
|
|
403
|
+
if (
|
|
404
|
+
!/^\s*(?:SELECT|EXPLAIN|PRAGMA|COMMIT|END|ROLLBACK|SAVEPOINT|RELEASE)\b/i.test(sql)
|
|
405
|
+
) {
|
|
406
|
+
try {
|
|
407
|
+
return withAutocommitTimeout(db, () => nativeExec(sql));
|
|
408
|
+
} finally {
|
|
409
|
+
if (mayChangeTagIdentity(sql)) tagIdentityWriteGeneration += 1;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
261
412
|
return nativeExec(sql);
|
|
262
413
|
},
|
|
263
414
|
});
|
|
@@ -270,15 +421,22 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
|
|
|
270
421
|
// SELECT/EXPLAIN cannot acquire a writer. Treat CTEs conservatively:
|
|
271
422
|
// WITH can introduce INSERT/UPDATE/DELETE as well as a read query.
|
|
272
423
|
if (!readonly && !/^\s*(?:SELECT|EXPLAIN|PRAGMA)\b/i.test(sql)) {
|
|
424
|
+
const changesTagIdentity = mayChangeTagIdentity(sql);
|
|
273
425
|
for (const method of ["run", "get", "all"] as const) {
|
|
274
426
|
const execute = statement[method].bind(statement);
|
|
275
427
|
Object.defineProperty(statement, method, {
|
|
276
428
|
configurable: true,
|
|
277
429
|
// biome-ignore lint/suspicious/noExplicitAny: retain SQLite's native binding overloads.
|
|
278
|
-
value: (...args: any[]) =>
|
|
279
|
-
|
|
430
|
+
value: (...args: any[]) => {
|
|
431
|
+
try {
|
|
432
|
+
return withAutocommitTimeout(db, () => execute(...args));
|
|
433
|
+
} finally {
|
|
434
|
+
if (changesTagIdentity) tagIdentityWriteGeneration += 1;
|
|
435
|
+
}
|
|
436
|
+
},
|
|
280
437
|
});
|
|
281
438
|
}
|
|
439
|
+
if (changesTagIdentity) wrapRemainingTagWriteForms(statement);
|
|
282
440
|
}
|
|
283
441
|
return statement;
|
|
284
442
|
},
|
|
@@ -329,6 +487,43 @@ function installTransactionRouting(db: BetterSqlite3.Database, readonly: boolean
|
|
|
329
487
|
});
|
|
330
488
|
}
|
|
331
489
|
|
|
490
|
+
/**
|
|
491
|
+
* Count tag identity writes made through the statement forms the transaction
|
|
492
|
+
* routing does not wrap. `iterate()` runs the statement while its result is
|
|
493
|
+
* consumed, so the generation moves both when iteration starts and when it
|
|
494
|
+
* ends: a summary read in between is then rebuilt on its next read.
|
|
495
|
+
*/
|
|
496
|
+
// biome-ignore lint/suspicious/noExplicitAny: statements from both backends share these method names.
|
|
497
|
+
function wrapRemainingTagWriteForms(statement: any): void {
|
|
498
|
+
if (typeof statement.iterate === "function") {
|
|
499
|
+
const iterate = statement.iterate.bind(statement);
|
|
500
|
+
Object.defineProperty(statement, "iterate", {
|
|
501
|
+
configurable: true,
|
|
502
|
+
value: function* (...args: unknown[]) {
|
|
503
|
+
tagIdentityWriteGeneration += 1;
|
|
504
|
+
try {
|
|
505
|
+
yield* iterate(...args);
|
|
506
|
+
} finally {
|
|
507
|
+
tagIdentityWriteGeneration += 1;
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
if (typeof statement.values === "function") {
|
|
513
|
+
const values = statement.values.bind(statement);
|
|
514
|
+
Object.defineProperty(statement, "values", {
|
|
515
|
+
configurable: true,
|
|
516
|
+
value: (...args: unknown[]) => {
|
|
517
|
+
try {
|
|
518
|
+
return values(...args);
|
|
519
|
+
} finally {
|
|
520
|
+
tagIdentityWriteGeneration += 1;
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
332
527
|
function trackSqliteConnection(
|
|
333
528
|
db: BetterSqlite3.Database,
|
|
334
529
|
filename: unknown,
|
|
@@ -430,6 +625,23 @@ function buildNodeSqliteDatabaseClass(DatabaseSync: any): typeof BetterSqlite3 {
|
|
|
430
625
|
|
|
431
626
|
export const Database: typeof BetterSqlite3 = TrackedDatabase;
|
|
432
627
|
|
|
628
|
+
/** The constructor path, without querying SQLite on the prompt thread. */
|
|
629
|
+
export function getSqliteDatabasePath(db: Database): string | null {
|
|
630
|
+
for (const connection of trackedSqliteConnections.values()) {
|
|
631
|
+
if (connection.reference.deref() === db) {
|
|
632
|
+
return connection.filename === ":memory:" || connection.filename === "<buffer>"
|
|
633
|
+
? null
|
|
634
|
+
: connection.filename;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
// Native Bun/better-sqlite3 handles can reach readers without our constructor
|
|
638
|
+
// wrapper. Their filename is still available without a SQLite query.
|
|
639
|
+
const native = db as unknown as { filename?: unknown; name?: unknown };
|
|
640
|
+
const path = native.filename ?? native.name;
|
|
641
|
+
if (typeof path === "string" && path !== ":memory:" && path !== "") return path;
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
|
|
433
645
|
function pragmaValue(db: BetterSqlite3.Database, name: string): unknown {
|
|
434
646
|
const row = db.prepare(`PRAGMA ${name}`).get() as Record<string, unknown> | undefined;
|
|
435
647
|
if (!row) return undefined;
|
|
@@ -556,6 +768,33 @@ interface StatementOwner {
|
|
|
556
768
|
const statementOwners = new WeakMap<Database, StatementOwner>();
|
|
557
769
|
const FIRST_PRUNE_AT = 256;
|
|
558
770
|
|
|
771
|
+
/**
|
|
772
|
+
* Bun's default close (`sqlite3_close_v2`) only releases the native connection
|
|
773
|
+
* once every statement created by prepare() is finalized. The close override
|
|
774
|
+
* in ownPreparedStatement can finalize only statements that are still
|
|
775
|
+
* reachable. Once the garbage collector
|
|
776
|
+
* has marked a one-shot statement dead, its weak reference is already cleared,
|
|
777
|
+
* but the statement is finalized only when its memory is later swept. Until
|
|
778
|
+
* then the closed connection keeps the database, WAL and shared-memory files
|
|
779
|
+
* open, for an unbounded time.
|
|
780
|
+
*
|
|
781
|
+
* `close(true)` finalizes every outstanding statement, reachable or not, and
|
|
782
|
+
* releases the connection immediately. When the caller did not ask for errors
|
|
783
|
+
* and that close fails, fall back to the caller's own close so a teardown path
|
|
784
|
+
* never starts throwing; the fallback can defer the release as before.
|
|
785
|
+
*/
|
|
786
|
+
function closeReleasingStatements(
|
|
787
|
+
close: (...args: unknown[]) => unknown,
|
|
788
|
+
args: unknown[],
|
|
789
|
+
): unknown {
|
|
790
|
+
if (args[0] === true) return close(true);
|
|
791
|
+
try {
|
|
792
|
+
return close(true);
|
|
793
|
+
} catch {
|
|
794
|
+
return close(...args);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
559
798
|
function ownPreparedStatement(db: Database, statement: Statement): Statement {
|
|
560
799
|
const finalizable = statement as FinalizableStatement;
|
|
561
800
|
// Node finalizes its statements on close and exposes no finalize() method.
|
|
@@ -579,7 +818,7 @@ function ownPreparedStatement(db: Database, statement: Statement): Statement {
|
|
|
579
818
|
}
|
|
580
819
|
}
|
|
581
820
|
references.clear();
|
|
582
|
-
const result = close
|
|
821
|
+
const result = closeReleasingStatements(close, args);
|
|
583
822
|
if (failure) throw failure;
|
|
584
823
|
return result;
|
|
585
824
|
},
|
|
@@ -617,7 +856,12 @@ export function prepareCachedStatement(db: Database, sql: string): Statement {
|
|
|
617
856
|
|
|
618
857
|
const privilegeDepth = new WeakMap<Database, number>();
|
|
619
858
|
const transformPassScope = new AsyncLocalStorage<
|
|
620
|
-
|
|
859
|
+
| {
|
|
860
|
+
active: boolean;
|
|
861
|
+
remainingWaitMs: number;
|
|
862
|
+
guard?: { assert(): void; remainingMs(): number };
|
|
863
|
+
}
|
|
864
|
+
| undefined
|
|
621
865
|
>();
|
|
622
866
|
const admissionScope = new AsyncLocalStorage<boolean>();
|
|
623
867
|
const backgroundWriterScope = new AsyncLocalStorage<boolean>();
|
|
@@ -632,22 +876,31 @@ export function withSqliteBackgroundWriter<T>(operation: () => T): T {
|
|
|
632
876
|
export function withSqliteTransformPass<T>(operation: () => T): T {
|
|
633
877
|
const existing = transformPassScope.getStore();
|
|
634
878
|
if (existing?.active) return operation();
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
879
|
+
const reservation = reserveForegroundSqliteTurn();
|
|
880
|
+
const run = (release: () => void): T => {
|
|
881
|
+
const lease = { active: true, remainingWaitMs: FOREGROUND_IN_PASS_BUSY_TIMEOUT_MS };
|
|
882
|
+
return transformPassScope.run(lease, () => {
|
|
883
|
+
try {
|
|
884
|
+
const result = operation();
|
|
885
|
+
if (result && typeof (result as { then?: unknown }).then === "function") {
|
|
886
|
+
return Promise.resolve(result).finally(() => {
|
|
887
|
+
lease.active = false;
|
|
888
|
+
release();
|
|
889
|
+
}) as T;
|
|
890
|
+
}
|
|
891
|
+
lease.active = false;
|
|
892
|
+
release();
|
|
893
|
+
return result;
|
|
894
|
+
} catch (error) {
|
|
895
|
+
lease.active = false;
|
|
896
|
+
release();
|
|
897
|
+
throw error;
|
|
643
898
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
}
|
|
650
|
-
});
|
|
899
|
+
});
|
|
900
|
+
};
|
|
901
|
+
// Foreground callers racing maintenance are awaited transforms. Idle
|
|
902
|
+
// synchronous callers keep the existing immediate return/throw behavior.
|
|
903
|
+
return typeof reservation === "function" ? run(reservation) : (reservation.then(run) as T);
|
|
651
904
|
}
|
|
652
905
|
|
|
653
906
|
/** Start detached maintenance work without borrowing a foreground pass's budget. */
|
|
@@ -655,6 +908,17 @@ export function withoutSqliteTransformPass<T>(operation: () => T): T {
|
|
|
655
908
|
return transformPassScope.run(undefined, operation);
|
|
656
909
|
}
|
|
657
910
|
|
|
911
|
+
/** Attach the adapter's existing generation/cancellation/deadline guard to writes. */
|
|
912
|
+
export function guardSqliteTransformPass(guard: { assert(): void; remainingMs(): number }): void {
|
|
913
|
+
const lease = transformPassScope.getStore();
|
|
914
|
+
if (lease) lease.guard = guard;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/** Check the attached generation/cancellation/deadline guard before SQL or cache publication. */
|
|
918
|
+
export function assertTransformWrite(): void {
|
|
919
|
+
if (!backgroundWriterScope.getStore()) transformPassScope.getStore()?.guard?.assert();
|
|
920
|
+
}
|
|
921
|
+
|
|
658
922
|
/** Bun names SQLite codes; node:sqlite exposes the numeric (possibly extended) errcode. */
|
|
659
923
|
export function isTransientSqliteError(error: unknown): boolean {
|
|
660
924
|
if (!error || typeof error !== "object") return false;
|
|
@@ -698,6 +962,7 @@ interface WriterAcquisition {
|
|
|
698
962
|
startedAt: number;
|
|
699
963
|
attempts: number;
|
|
700
964
|
claimed: boolean;
|
|
965
|
+
remainingMs?: () => number;
|
|
701
966
|
}
|
|
702
967
|
|
|
703
968
|
/** A write transaction whose BEGIN went through `acquireShort` and has not ended yet. */
|
|
@@ -724,6 +989,7 @@ function foregroundWaitLease() {
|
|
|
724
989
|
* native API cannot separate lock waiting from statement execution. Exhaustion
|
|
725
990
|
* switches to zero-wait acquisition, not a refusal when the writer is free. */
|
|
726
991
|
function withAutocommitTimeout<T>(db: Database, operation: () => T): T {
|
|
992
|
+
assertTransformWrite();
|
|
727
993
|
const lease = foregroundWaitLease();
|
|
728
994
|
if (isInTransaction(db) || (!lease && !backgroundWriterScope.getStore())) return operation();
|
|
729
995
|
const previous = pragmaNumber(db, "busy_timeout");
|
|
@@ -749,6 +1015,7 @@ function withAutocommitTimeout<T>(db: Database, operation: () => T): T {
|
|
|
749
1015
|
|
|
750
1016
|
/** The connection is never handed back to another caller with a shortened timeout. */
|
|
751
1017
|
function acquireShort(db: Database, acquire: () => unknown, site: string): void {
|
|
1018
|
+
assertTransformWrite();
|
|
752
1019
|
const started = performance.now();
|
|
753
1020
|
const previous = pragmaNumber(db, "busy_timeout");
|
|
754
1021
|
const outer = writerAcquisitionScope.getStore();
|
|
@@ -763,7 +1030,12 @@ function acquireShort(db: Database, acquire: () => unknown, site: string): void
|
|
|
763
1030
|
// stays short. An ordinary BEGIN inside a transform pass cannot yield;
|
|
764
1031
|
// give that single attempt enough time for a brief writer to finish.
|
|
765
1032
|
const lease = foregroundWaitLease();
|
|
766
|
-
const timeout =
|
|
1033
|
+
const timeout = Math.floor(
|
|
1034
|
+
Math.min(
|
|
1035
|
+
lease ? lease.remainingWaitMs : SHORT_BUSY_TIMEOUT_MS,
|
|
1036
|
+
owner?.remainingMs?.() ?? lease?.guard?.remainingMs() ?? Infinity,
|
|
1037
|
+
),
|
|
1038
|
+
);
|
|
767
1039
|
db.exec(`PRAGMA busy_timeout=${timeout}`);
|
|
768
1040
|
acquire();
|
|
769
1041
|
acquiredAt = performance.now();
|
|
@@ -799,16 +1071,20 @@ function acquireShort(db: Database, acquire: () => unknown, site: string): void
|
|
|
799
1071
|
* `acquireShort`, then report how long the writer waited for the lock
|
|
800
1072
|
* (`acquire_ms`) and how long it then held it (`hold_ms`) when either crosses
|
|
801
1073
|
* the threshold. A long hold blocks every other process's writer, so it is
|
|
802
|
-
* worth seeing even when the lock itself came quickly.
|
|
1074
|
+
* worth seeing even when the lock itself came quickly. The native end statement's
|
|
1075
|
+
* `end_ms` is reported separately, so a slow FTS merge or checkpoint at COMMIT
|
|
1076
|
+
* is not mistaken for acquisition time.
|
|
803
1077
|
*/
|
|
804
1078
|
function endWriterTransaction(db: Database, end: () => unknown, sql: string): unknown {
|
|
805
1079
|
let ended = false;
|
|
1080
|
+
const endStarted = performance.now();
|
|
806
1081
|
try {
|
|
807
1082
|
const result = end();
|
|
808
1083
|
ended = true;
|
|
809
1084
|
return result;
|
|
810
1085
|
} finally {
|
|
811
1086
|
const open = openWriterTransactions.get(db);
|
|
1087
|
+
const endMs = performance.now() - endStarted;
|
|
812
1088
|
// A COMMIT that failed with the transaction still open has not ended it.
|
|
813
1089
|
if (open && !isInTransaction(db)) {
|
|
814
1090
|
openWriterTransactions.delete(db);
|
|
@@ -820,7 +1096,7 @@ function endWriterTransaction(db: Database, end: () => unknown, sql: string): un
|
|
|
820
1096
|
? "committed"
|
|
821
1097
|
: "failed";
|
|
822
1098
|
reportSqliteDiagnostic(
|
|
823
|
-
`sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} attempts=${open.attempts} outcome=${outcome}`,
|
|
1099
|
+
`sqlite writer site=${open.site} lane=${open.lane} acquire_ms=${Math.round(open.acquireMs)} hold_ms=${Math.round(holdMs)} end_ms=${Math.round(endMs)} attempts=${open.attempts} outcome=${outcome}`,
|
|
824
1100
|
);
|
|
825
1101
|
}
|
|
826
1102
|
}
|
|
@@ -871,11 +1147,28 @@ export async function beginSqliteWriterAsync(db: Database, site: string): Promis
|
|
|
871
1147
|
}
|
|
872
1148
|
|
|
873
1149
|
/** Retry admission before any turn work, yielding between short lock attempts. */
|
|
874
|
-
export async function withAsyncPrivilegedWriter<T>(
|
|
1150
|
+
export async function withAsyncPrivilegedWriter<T>(
|
|
1151
|
+
db: Database,
|
|
1152
|
+
operation: () => T,
|
|
1153
|
+
options: {
|
|
1154
|
+
signal?: AbortSignal;
|
|
1155
|
+
beforeRetry?: (error: SqliteAcquisitionBusyError) => void;
|
|
1156
|
+
jitter?: boolean;
|
|
1157
|
+
budgetMs?: number;
|
|
1158
|
+
assertCurrentPass?: () => void;
|
|
1159
|
+
} = {},
|
|
1160
|
+
): Promise<T> {
|
|
875
1161
|
const started = performance.now();
|
|
1162
|
+
const budgetMs = Math.max(
|
|
1163
|
+
0,
|
|
1164
|
+
Math.min(FOREGROUND_ACQUISITION_BUDGET_MS, options.budgetMs ?? Infinity),
|
|
1165
|
+
);
|
|
876
1166
|
let attempts = 0;
|
|
877
1167
|
for (;;) {
|
|
1168
|
+
options.signal?.throwIfAborted();
|
|
1169
|
+
options.assertCurrentPass?.();
|
|
878
1170
|
attempts++;
|
|
1171
|
+
let entered = false;
|
|
879
1172
|
try {
|
|
880
1173
|
const acquisition: WriterAcquisition = {
|
|
881
1174
|
site: "privileged_writer",
|
|
@@ -883,35 +1176,51 @@ export async function withAsyncPrivilegedWriter<T>(db: Database, operation: () =
|
|
|
883
1176
|
startedAt: started,
|
|
884
1177
|
attempts,
|
|
885
1178
|
claimed: false,
|
|
1179
|
+
remainingMs: () => Math.max(0, budgetMs - (performance.now() - started)),
|
|
886
1180
|
};
|
|
887
1181
|
// The acquisition and hold of this transaction are reported when it
|
|
888
1182
|
// commits or rolls back (see endWriterTransaction).
|
|
889
1183
|
return admissionScope.run(true, () =>
|
|
890
1184
|
withSqliteTransformPass(() =>
|
|
891
1185
|
writerAcquisitionScope.run(acquisition, () =>
|
|
892
|
-
withPrivilegedWriter(db,
|
|
1186
|
+
withPrivilegedWriter(db, () => {
|
|
1187
|
+
entered = true;
|
|
1188
|
+
return operation();
|
|
1189
|
+
}),
|
|
893
1190
|
),
|
|
894
1191
|
),
|
|
895
1192
|
);
|
|
896
1193
|
} catch (error) {
|
|
897
1194
|
// A callback failure can occur after writes; only retry a failed BEGIN.
|
|
898
|
-
if (!(error instanceof SqliteAcquisitionBusyError)) throw error;
|
|
1195
|
+
if (entered || !(error instanceof SqliteAcquisitionBusyError)) throw error;
|
|
1196
|
+
// Adapters may serve a validated saved request instead of waiting.
|
|
1197
|
+
// This runs only after a failed BEGIN, never after callback writes.
|
|
1198
|
+
options.beforeRetry?.(error);
|
|
899
1199
|
const elapsed = performance.now() - started;
|
|
900
|
-
if (elapsed >=
|
|
1200
|
+
if (elapsed >= budgetMs) {
|
|
901
1201
|
reportSqliteDiagnostic(
|
|
902
1202
|
`sqlite writer site=privileged_writer lane=foreground acquire_ms=${Math.round(elapsed)} attempts=${attempts} outcome=busy`,
|
|
903
1203
|
);
|
|
904
1204
|
throw error;
|
|
905
1205
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
attempts === 1 ? 500 : 1000,
|
|
911
|
-
FOREGROUND_ACQUISITION_BUDGET_MS - elapsed,
|
|
912
|
-
),
|
|
913
|
-
),
|
|
1206
|
+
const backoff = attempts === 1 ? 500 : 1000;
|
|
1207
|
+
const delay = Math.min(
|
|
1208
|
+
options.jitter ? backoff * (0.8 + Math.random() * 0.4) : backoff,
|
|
1209
|
+
budgetMs - elapsed,
|
|
914
1210
|
);
|
|
1211
|
+
await new Promise<void>((resolve, reject) => {
|
|
1212
|
+
const abort = () => {
|
|
1213
|
+
clearTimeout(timer);
|
|
1214
|
+
options.signal?.removeEventListener("abort", abort);
|
|
1215
|
+
reject(options.signal?.reason ?? new Error("Writer wait aborted"));
|
|
1216
|
+
};
|
|
1217
|
+
const timer = setTimeout(() => {
|
|
1218
|
+
options.signal?.removeEventListener("abort", abort);
|
|
1219
|
+
resolve();
|
|
1220
|
+
}, delay);
|
|
1221
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
1222
|
+
if (options.signal?.aborted) abort();
|
|
1223
|
+
});
|
|
915
1224
|
}
|
|
916
1225
|
}
|
|
917
1226
|
}
|
|
@@ -986,3 +1295,80 @@ export function withPrivilegedWriter<T>(db: Database, operation: () => T): T {
|
|
|
986
1295
|
throw error;
|
|
987
1296
|
}
|
|
988
1297
|
}
|
|
1298
|
+
|
|
1299
|
+
// Process-local admission only; SQLite remains the cross-process writer arbiter.
|
|
1300
|
+
const indexCoordinationKey = Symbol.for("magic-context.index-foreground-coordination.v1");
|
|
1301
|
+
const indexCoordinationHeap = globalThis as unknown as Record<
|
|
1302
|
+
symbol,
|
|
1303
|
+
SharedArrayBuffer | undefined
|
|
1304
|
+
>;
|
|
1305
|
+
const indexCoordinationBuffer =
|
|
1306
|
+
indexCoordinationHeap[indexCoordinationKey] ??
|
|
1307
|
+
new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT);
|
|
1308
|
+
indexCoordinationHeap[indexCoordinationKey] = indexCoordinationBuffer;
|
|
1309
|
+
const indexCoordinationState = new Int32Array(indexCoordinationBuffer);
|
|
1310
|
+
// Slots: foreground interest, current maintenance owner, next owner token.
|
|
1311
|
+
|
|
1312
|
+
export function indexCoordinationInput(): {
|
|
1313
|
+
indexCoordination: SharedArrayBuffer;
|
|
1314
|
+
indexOwner: number;
|
|
1315
|
+
} {
|
|
1316
|
+
return {
|
|
1317
|
+
indexCoordination: indexCoordinationBuffer,
|
|
1318
|
+
indexOwner: Atomics.add(indexCoordinationState, 2, 1) + 1,
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
const yieldIndexTurn = () => new Promise<void>((resolve) => setTimeout(resolve, 1));
|
|
1323
|
+
|
|
1324
|
+
/** Announce interest before waiting, so no maintenance chunk overtakes a foreground turn. */
|
|
1325
|
+
function reserveForegroundSqliteTurn(): (() => void) | Promise<() => void> {
|
|
1326
|
+
Atomics.add(indexCoordinationState, 0, 1);
|
|
1327
|
+
const release = () => {
|
|
1328
|
+
Atomics.sub(indexCoordinationState, 0, 1);
|
|
1329
|
+
Atomics.notify(indexCoordinationState, 0);
|
|
1330
|
+
};
|
|
1331
|
+
if (Atomics.load(indexCoordinationState, 1) === 0) return release;
|
|
1332
|
+
return (async () => {
|
|
1333
|
+
while (Atomics.load(indexCoordinationState, 1) !== 0) await yieldIndexTurn();
|
|
1334
|
+
return release;
|
|
1335
|
+
})();
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
export function releaseIndexOwner(input: {
|
|
1339
|
+
indexCoordination?: SharedArrayBuffer;
|
|
1340
|
+
indexOwner?: number;
|
|
1341
|
+
}): void {
|
|
1342
|
+
if (!input.indexCoordination || !input.indexOwner) return;
|
|
1343
|
+
const shared = new Int32Array(input.indexCoordination);
|
|
1344
|
+
Atomics.compareExchange(shared, 1, input.indexOwner, 0);
|
|
1345
|
+
Atomics.notify(shared, 1);
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
/** One synchronous transaction per permit; release the permit before yielding. */
|
|
1349
|
+
export async function withIndexChunk<T>(
|
|
1350
|
+
input: { indexCoordination?: SharedArrayBuffer; indexOwner?: number },
|
|
1351
|
+
operation: () => T,
|
|
1352
|
+
): Promise<T> {
|
|
1353
|
+
if (!input.indexCoordination || !input.indexOwner) return operation();
|
|
1354
|
+
const shared = new Int32Array(input.indexCoordination);
|
|
1355
|
+
for (;;) {
|
|
1356
|
+
if (
|
|
1357
|
+
Atomics.load(shared, 0) === 0 &&
|
|
1358
|
+
Atomics.compareExchange(shared, 1, 0, input.indexOwner) === 0
|
|
1359
|
+
) {
|
|
1360
|
+
if (Atomics.load(shared, 0) === 0) break;
|
|
1361
|
+
releaseIndexOwner(input);
|
|
1362
|
+
}
|
|
1363
|
+
await yieldIndexTurn();
|
|
1364
|
+
}
|
|
1365
|
+
try {
|
|
1366
|
+
return await operation();
|
|
1367
|
+
} finally {
|
|
1368
|
+
releaseIndexOwner(input);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
export async function yieldIndexChunk(): Promise<void> {
|
|
1373
|
+
await yieldIndexTurn();
|
|
1374
|
+
}
|