@cortexkit/opencode-magic-context 0.49.34 → 0.49.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/auto-search-worker.js +163 -155
- package/dist/chunk-embedding-write-worker.js +70 -66
- package/dist/{compaction-marker-candidates-31h86ph0.js → compaction-marker-candidates-5p1qkve9.js} +5 -2
- package/dist/compaction-marker-candidates-worker.js +24 -23
- package/dist/{compartment-chunk-embedding-5q5gj67r.js → compartment-chunk-embedding-ypktm0tk.js} +10 -8
- package/dist/{conflict-warning-hook-xgskea1v.js → conflict-warning-hook-b75jn458.js} +11 -9
- package/dist/{context-p3xrarzt.js → context-969z683s.js} +1839 -746
- package/dist/{derive-budgets-pqybnx09.js → derive-budgets-htj16n4x.js} +3 -2
- package/dist/embedding-backfill-rma0v2ct.js +28 -0
- package/dist/embedding-worker-process.js +2 -1
- package/dist/embedding-worker.js +6 -5
- package/dist/expand-attachments-h33jbgyz.js +21 -0
- package/dist/features/magic-context/auto-search-diagnostics.d.ts +21 -0
- package/dist/features/magic-context/auto-search-diagnostics.d.ts.map +1 -0
- package/dist/features/magic-context/compaction-marker-candidates.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts +5 -3
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-gate.d.ts +2 -0
- package/dist/features/magic-context/dreamer/verify-gate.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-state.d.ts +9 -0
- package/dist/features/magic-context/dreamer/verify-state.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify.d.ts +2 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/migration-worker-client.d.ts +3 -0
- package/dist/features/magic-context/migration-worker-client.d.ts.map +1 -1
- package/dist/features/magic-context/migration-worker.d.ts +15 -0
- package/dist/features/magic-context/migration-worker.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts +2 -2
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/search-rerank.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +4 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +1 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +4 -0
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/store-generation-rebase-labels.d.ts +6 -0
- package/dist/features/magic-context/store-generation-rebase-labels.d.ts.map +1 -0
- package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
- package/dist/features/magic-context/work-metrics-carry-storage.d.ts +10 -0
- package/dist/features/magic-context/work-metrics-carry-storage.d.ts.map +1 -0
- package/dist/{history-owner-36wp3mkb.js → history-owner-0z620wgz.js} +3 -2
- package/dist/hooks/magic-context/apply-operations.d.ts +20 -3
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-observation.d.ts +13 -0
- package/dist/hooks/magic-context/auto-search-observation.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts +10 -2
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-marker-publication.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-commit-hashes.d.ts +4 -0
- package/dist/hooks/magic-context/compartment-commit-hashes.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts +1 -0
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-completeness.d.ts +15 -0
- package/dist/hooks/magic-context/final-wire-completeness.d.ts.map +1 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/issue-423-fixture.d.ts +1 -1
- package/dist/hooks/magic-context/issue-423-fixture.d.ts.map +1 -1
- package/dist/hooks/magic-context/issue-424-fixture.d.ts +1 -1
- package/dist/hooks/magic-context/issue-424-fixture.d.ts.map +1 -1
- package/dist/hooks/magic-context/project-structural-sentinels.d.ts +25 -0
- package/dist/hooks/magic-context/project-structural-sentinels.d.ts.map +1 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts +8 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +11 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +2 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts +2 -0
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/release-recovery-prefix.d.ts +9 -0
- package/dist/hooks/magic-context/release-recovery-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-structural-noise.d.ts +6 -3
- package/dist/hooks/magic-context/strip-structural-noise.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-context-state.d.ts +3 -0
- package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +3 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-cpjk5jd2.js → index-1d042x6w.js} +16 -14
- package/dist/{index-2743x98y.js → index-21fgrfrf.js} +35 -142
- package/dist/index-2amn2s73.js +123 -0
- package/dist/{index-c7phnbvk.js → index-2p37txes.js} +1 -1
- package/dist/index-2qbtqg1w.js +529 -0
- package/dist/{index-9gpw8hrm.js → index-2rs7912w.js} +4 -4
- package/dist/{index-m1x9ghk5.js → index-4ks89h5a.js} +37 -7
- package/dist/{index-b88dwwrh.js → index-4xyjr62e.js} +1 -1
- package/dist/index-4y35msh5.js +531 -0
- package/dist/index-66a50f3e.js +777 -0
- package/dist/index-72czy45z.js +4557 -0
- package/dist/index-7v05d9b7.js +58 -0
- package/dist/{index-qgh1qwjj.js → index-850vthn3.js} +9 -3
- package/dist/{index-np3rgfw4.js → index-8jjjmhab.js} +15 -4
- package/dist/index-96ztjvkn.js +204 -0
- package/dist/{index-fm36bjv4.js → index-9fgmkfaf.js} +22 -277
- package/dist/{index-atekmqef.js → index-9tdvbdv1.js} +508 -5547
- package/dist/{index-xrnsygfq.js → index-9wnbnx8f.js} +1 -1
- package/dist/{index-waktfbjy.js → index-ae1ar4v1.js} +4 -4
- package/dist/{index-v15ne3a3.js → index-b1ydbp95.js} +2 -2
- package/dist/{index-nxrsns5x.js → index-c5dzns43.js} +75 -75
- package/dist/{index-v7287tzq.js → index-dcjkw41m.js} +19 -8
- package/dist/{index-hbx7m8he.js → index-dfdg2cgg.js} +338 -86
- package/dist/{index-spwjbkc7.js → index-dnqqqc5f.js} +1 -1
- package/dist/{index-04z754rd.js → index-dz48h1wx.js} +33 -5
- package/dist/{index-rrv26qjz.js → index-fw42ms3m.js} +1 -1
- package/dist/{index-t5pck3ss.js → index-fxbk7gk3.js} +1 -1
- package/dist/{index-wfybj1dw.js → index-g4t7850m.js} +2 -2
- package/dist/{index-97spytxq.js → index-gnmhbyyc.js} +583 -474
- package/dist/{index-4pnsgvfk.js → index-hacf2tyx.js} +1 -1
- package/dist/index-j105mf16.js +270 -0
- package/dist/{index-gkee6p4g.js → index-jggt5gf2.js} +3 -3
- package/dist/{index-s1n8dd2n.js → index-jkanybgq.js} +2 -2
- package/dist/{index-h7tgn49j.js → index-jrfre9ah.js} +5 -222
- package/dist/{index-kfyb3k6n.js → index-jz5bk7xd.js} +2 -2
- package/dist/{index-7kkphb6c.js → index-nj360hcs.js} +4 -4
- package/dist/{index-07vskjn8.js → index-pp8vdn01.js} +15 -13
- package/dist/index-prw8apnc.js +194 -0
- package/dist/{index-rverk2vz.js → index-r2epb000.js} +34 -4
- package/dist/{index-7g9dr8gy.js → index-tn9drm1a.js} +125 -143
- package/dist/{index-kq5w68dp.js → index-txs8tce6.js} +1 -1
- package/dist/{index-rfxzazzy.js → index-ty4vhe4n.js} +5 -5
- package/dist/{index-y1qwzvxn.js → index-vd2ywmfe.js} +2 -2
- package/dist/{index-0677w9sd.js → index-wcwhhtdh.js} +58 -23
- package/dist/index-wh9fxds5.js +265 -0
- package/dist/{index-51rdvtkz.js → index-xd2p95m7.js} +3 -3
- package/dist/{index-as2amvn3.js → index-xnm0wq1r.js} +6 -531
- package/dist/{index-ftr84kkv.js → index-ys7j6679.js} +7 -5
- package/dist/index-z4p0ry94.js +222 -0
- package/dist/index-z9zygwse.js +89 -0
- package/dist/index.js +86 -74
- package/dist/{logger-94kew5wm.js → logger-qwnbcfj9.js} +2 -1
- package/dist/{message-fts-rowid-map-va36knh4.js → message-fts-rowid-map-t6qsyg9s.js} +7 -5
- package/dist/{message-index-bounded-qh91fdr3.js → message-index-bounded-wfk6aqxk.js} +15 -13
- package/dist/{message-time-backfill-4qva0b4f.js → message-time-backfill-39bm498k.js} +3 -2
- package/dist/migration-worker.js +55 -48
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{project-embedding-registry-6yex0r9f.js → project-embedding-registry-3yyegjma.js} +16 -13
- package/dist/raw-ordinal-warmup-worker.js +114 -113
- package/dist/{read-session-chunk-kaghtr75.js → read-session-chunk-26yrrhyz.js} +18 -12
- package/dist/{read-session-raw-b2sd67v4.js → read-session-raw-j7c9w57v.js} +5 -3
- package/dist/recomp-orchestrator-wk509qkp.js +69 -0
- package/dist/render-h1qarr8a.js +44 -0
- package/dist/{safe-notification-target-mkr9yzvr.js → safe-notification-target-wztd7bgk.js} +3 -2
- package/dist/search-5h9fydyq.js +54 -0
- package/dist/search-archive-q79hyqxs.js +29 -0
- package/dist/{send-session-notification-vz86nt79.js → send-session-notification-14p3yje4.js} +9 -7
- package/dist/shared/model-suggestion-retry.d.ts +7 -0
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/prompt-async-transport.d.ts.map +1 -1
- package/dist/shared/reusable-worker-entry.d.ts +4 -0
- package/dist/shared/reusable-worker-entry.d.ts.map +1 -0
- package/dist/shared/reusable-worker.d.ts +6 -0
- package/dist/shared/reusable-worker.d.ts.map +1 -0
- package/dist/shared/reusable-worker.fixture.d.ts +2 -0
- package/dist/shared/reusable-worker.fixture.d.ts.map +1 -0
- package/dist/shared/worker-shutdown.d.ts +1 -1
- package/dist/shared/worker-shutdown.d.ts.map +1 -1
- package/dist/{storage-tags-6hvkk01c.js → storage-tags-vj0yj7ed.js} +5 -4
- package/dist/store-reader-yh19h38c.js +14 -0
- package/dist/store-s3eykdjt.js +21 -0
- package/dist/tools/ctx-expand/render.d.ts +5 -3
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -1
- package/dist/tools/ctx-expand/tools.d.ts +2 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-expand/v2-archive-reader.d.ts +33 -0
- package/dist/tools/ctx-expand/v2-archive-reader.d.ts.map +1 -0
- package/dist/{transform-postprocess-phase-ph38mhrs.js → transform-postprocess-phase-4gj0mtcg.js} +39 -32
- package/dist/v2/auto-search-worker.js +163 -155
- package/dist/v2/chunk-embedding-write-worker.js +71 -67
- package/dist/v2/compaction-marker-candidates-worker.js +24 -23
- package/dist/v2/{compaction-marker-candidates-m4vmye3w.js → compaction-marker-candidates-yeb2ky46.js} +6 -3
- package/dist/v2/{compartment-chunk-embedding-rc31e6md.js → compartment-chunk-embedding-qfk791bd.js} +11 -9
- package/dist/v2/{context-s60hcatx.js → context-bxr039be.js} +2678 -1246
- package/dist/v2/{derive-budgets-knf763tt.js → derive-budgets-sa0v7bz0.js} +4 -3
- package/dist/v2/embedding-backfill-00tw59rx.js +27 -0
- package/dist/v2/embedding-worker-process.js +2 -1
- package/dist/v2/embedding-worker.js +6 -5
- package/dist/v2/expand-attachments-h33jbgyz.js +21 -0
- package/dist/v2/fold/code-mode-catalog.d.ts +3 -0
- package/dist/v2/fold/code-mode-catalog.d.ts.map +1 -0
- package/dist/v2/fold/idle.d.ts +16 -0
- package/dist/v2/fold/idle.d.ts.map +1 -0
- package/dist/v2/fold/manual-baseline.d.ts +8 -0
- package/dist/v2/fold/manual-baseline.d.ts.map +1 -0
- package/dist/v2/fold/native-replay-v3.d.ts +75 -0
- package/dist/v2/fold/native-replay-v3.d.ts.map +1 -0
- package/dist/v2/fold/native-replay.d.ts +81 -8
- package/dist/v2/fold/native-replay.d.ts.map +1 -1
- package/dist/v2/fold/policy.d.ts +2 -1
- package/dist/v2/fold/policy.d.ts.map +1 -1
- package/dist/v2/fold/restore.d.ts.map +1 -1
- package/dist/v2/fold/summary.d.ts +4 -0
- package/dist/v2/fold/summary.d.ts.map +1 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/{history-owner-ad0crnrn.js → history-owner-fpka43cn.js} +3 -2
- package/dist/v2/hooks/channel2.d.ts +6 -0
- package/dist/v2/hooks/channel2.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/expand-attachments.d.ts +8 -0
- package/dist/v2/hooks/expand-attachments.d.ts.map +1 -0
- package/dist/v2/hooks/overflow-recovery.d.ts +45 -0
- package/dist/v2/hooks/overflow-recovery.d.ts.map +1 -0
- package/dist/v2/hooks/restore-rows.d.ts +12 -2
- package/dist/v2/hooks/restore-rows.d.ts.map +1 -1
- package/dist/v2/hooks/store.d.ts +7 -2
- package/dist/v2/hooks/store.d.ts.map +1 -1
- package/dist/v2/hooks/synthetic-admission.d.ts +7 -0
- package/dist/v2/hooks/synthetic-admission.d.ts.map +1 -0
- package/dist/v2/hooks/usage-persist.d.ts.map +1 -1
- package/dist/v2/{logger-p34mjtja.js → logger-4cj6d03m.js} +2 -1
- package/dist/v2/{message-fts-rowid-map-78awh03v.js → message-fts-rowid-map-z86avy0n.js} +8 -6
- package/dist/v2/{message-index-bounded-4htdr1j6.js → message-index-bounded-w14496s9.js} +16 -14
- package/dist/v2/{message-time-backfill-zvthw6xb.js → message-time-backfill-0c4h7sg6.js} +3 -2
- package/dist/v2/migration-worker.js +56 -49
- package/dist/v2/ordinal-range.fixture.d.ts +7 -0
- package/dist/v2/ordinal-range.fixture.d.ts.map +1 -0
- package/dist/v2/{project-embedding-registry-1x5qe2fy.js → project-embedding-registry-jqq2qeqb.js} +17 -14
- package/dist/v2/raw-ordinal-warmup-worker.js +114 -113
- package/dist/v2/{read-session-chunk-1fa9qzwb.js → read-session-chunk-tqnh1ret.js} +18 -12
- package/dist/v2/{read-session-raw-5x088amc.js → read-session-raw-qpp6x9kg.js} +6 -4
- package/dist/v2/recomp-orchestrator-9cjk6aej.js +68 -0
- package/dist/v2/render-5dz1knf2.js +43 -0
- package/dist/v2/{safe-notification-target-khnzg57c.js → safe-notification-target-gphhast7.js} +3 -2
- package/dist/v2/search-8yfet25y.js +52 -0
- package/dist/v2/search-archive-z6z9jqwf.js +28 -0
- package/dist/v2/{send-session-notification-x5nzy34v.js → send-session-notification-kxp47tsw.js} +9 -7
- package/dist/v2/{server-cpjk5jd2.js → server-1d042x6w.js} +16 -14
- package/dist/v2/server-2amn2s73.js +123 -0
- package/dist/v2/{server-6g98c227.js → server-3schkz95.js} +4 -4
- package/dist/v2/server-468mya5v.js +209 -0
- package/dist/v2/{server-z2wft9zv.js → server-5by3vdzs.js} +562 -5560
- package/dist/v2/{server-qjvk4a9t.js → server-69m30b21.js} +1 -1
- package/dist/v2/server-6emy0v9a.js +531 -0
- package/dist/v2/{server-vr4szghm.js → server-6vzh6wej.js} +3 -3
- package/dist/v2/{server-ajxhrgjv.js → server-7094pk3w.js} +80 -19
- package/dist/v2/{server-ab8017gw.js → server-7acq7815.js} +34 -141
- package/dist/v2/server-7v05d9b7.js +58 -0
- package/dist/v2/{server-24g8r2d0.js → server-7zacmty5.js} +75 -75
- package/dist/v2/{server-3mz2qh5a.js → server-969cdpmg.js} +1 -1
- package/dist/v2/server-96ztjvkn.js +204 -0
- package/dist/v2/{server-grakwy1v.js → server-a9w5f0yw.js} +37 -7
- package/dist/v2/{server-835q39kd.js → server-avdveykk.js} +3 -3
- package/dist/v2/{server-qc915kw2.js → server-bez34e60.js} +4 -4
- package/dist/v2/{server-h1byrhwx.js → server-cp1a03vc.js} +19 -8
- package/dist/v2/{server-bsgd4dk1.js → server-dcws5831.js} +2 -2
- package/dist/v2/{server-m1pfg2d4.js → server-dfq5vb8j.js} +4 -4
- package/dist/v2/server-e51xmr4d.js +194 -0
- package/dist/v2/server-ef1mskas.js +777 -0
- package/dist/v2/{server-1bw1wcbp.js → server-f0j864ma.js} +1 -1
- package/dist/v2/{server-jw5qe9y8.js → server-g3gqq4ac.js} +18 -217
- package/dist/v2/{server-2aasmpsp.js → server-gkse1wyz.js} +5 -5
- package/dist/v2/{server-6495nmn9.js → server-jb6tjyeb.js} +5 -222
- package/dist/v2/{server-qvy4qavp.js → server-jd7vzwn4.js} +125 -143
- package/dist/v2/{server-a7x00tw8.js → server-mfn1yf9d.js} +1 -1
- package/dist/v2/{server-awr8qa4c.js → server-nmyganc8.js} +2 -2
- package/dist/v2/{server-tkdabx8q.js → server-nq3cb7be.js} +5 -530
- package/dist/v2/server-qjyp27vf.js +270 -0
- package/dist/v2/{server-gyy4k6mf.js → server-qmmkhz2z.js} +1 -1
- package/dist/v2/{server-29qp8nz4.js → server-qxzbmtqt.js} +1 -1
- package/dist/v2/{server-806rzhs6.js → server-r4430x9m.js} +10 -4
- package/dist/v2/{server-53eh1r8r.js → server-sd8hvzte.js} +2 -2
- package/dist/v2/{server-k3t06fxr.js → server-sefxj8k1.js} +1 -1
- package/dist/v2/server-t8y64xj7.js +4513 -0
- package/dist/v2/{server-6vd2n183.js → server-tnzbk64q.js} +35 -5
- package/dist/v2/{server-v77xa5wj.js → server-tpt7bwq8.js} +1 -1
- package/dist/v2/{server-51779zs2.js → server-v0p37hm2.js} +4 -1
- package/dist/v2/{server-nxas8v1d.js → server-xfjjbrkt.js} +15 -4
- package/dist/v2/{server-cqjvxyrp.js → server-xy7w7hrd.js} +2 -2
- package/dist/v2/server-ypf1ap0v.js +529 -0
- package/dist/v2/server-z4p0ry94.js +222 -0
- package/dist/v2/server-z9zygwse.js +89 -0
- package/dist/v2/{server-ab1g0wn9.js → server-zzgtgqmd.js} +2 -2
- package/dist/v2/server.js +7 -6
- package/dist/v2/{storage-tags-18nbaanf.js → storage-tags-cw07ky67.js} +5 -4
- package/dist/v2/store-reader-cgx47zkp.js +14 -0
- package/dist/v2/store-reader.d.ts +9 -2
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/v2/store-z3qe67cg.js +21 -0
- package/dist/v2/v2-archive-reader-z7wr42ry.js +11 -0
- package/dist/v2/{wrapup-orchestrator-wxf7n5k6.js → wrapup-orchestrator-j1v62bkj.js} +50 -42
- package/dist/v2-archive-reader-028z6kck.js +11 -0
- package/dist/wrapup-orchestrator-xg9avt2p.js +56 -0
- package/package.json +1 -1
- package/src/shared/model-suggestion-retry.ts +1 -1
- package/src/shared/prompt-async-transport.test.ts +64 -3
- package/src/shared/prompt-async-transport.ts +61 -16
- package/src/shared/reusable-worker-entry.ts +58 -0
- package/src/shared/reusable-worker-reset.test.ts +108 -0
- package/src/shared/reusable-worker.fixture.ts +35 -0
- package/src/shared/reusable-worker.test.ts +253 -0
- package/src/shared/reusable-worker.ts +240 -0
- package/src/shared/sqlite-transaction-mode-guard.test.ts +2 -0
- package/src/shared/worker-shutdown.ts +21 -17
- package/dist/embedding-backfill-0jgtqxen.js +0 -25
- package/dist/recomp-orchestrator-0y983w7h.js +0 -62
- package/dist/search-archive-1kw2rp19.js +0 -26
- package/dist/search-p684j8ww.js +0 -50
- package/dist/v2/embedding-backfill-f43hd8y6.js +0 -24
- package/dist/v2/recomp-orchestrator-7q9nvxte.js +0 -61
- package/dist/v2/search-archive-xfp51s0g.js +0 -25
- package/dist/v2/search-wf8rqxhm.js +0 -48
- package/dist/wrapup-orchestrator-ys2nrkkb.js +0 -49
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runManagedWrapup2
|
|
3
|
+
} from "./index-pp8vdn01.js";
|
|
4
|
+
import"./index-ys7j6679.js";
|
|
5
|
+
import"./index-9tdvbdv1.js";
|
|
6
|
+
import"./index-850vthn3.js";
|
|
7
|
+
import"./index-sd3egckz.js";
|
|
8
|
+
import"./index-xnm0wq1r.js";
|
|
9
|
+
import"./index-ty4vhe4n.js";
|
|
10
|
+
import"./index-jjvbk92s.js";
|
|
11
|
+
import"./index-21fgrfrf.js";
|
|
12
|
+
import"./index-4dhv7mqz.js";
|
|
13
|
+
import"./index-72czy45z.js";
|
|
14
|
+
import"./index-2qbtqg1w.js";
|
|
15
|
+
import"./index-2rs7912w.js";
|
|
16
|
+
import"./index-2amn2s73.js";
|
|
17
|
+
import"./index-66a50f3e.js";
|
|
18
|
+
import"./index-dnqqqc5f.js";
|
|
19
|
+
import"./index-ae1ar4v1.js";
|
|
20
|
+
import"./index-qt1qqasc.js";
|
|
21
|
+
import"./index-tn9drm1a.js";
|
|
22
|
+
import"./index-8jjjmhab.js";
|
|
23
|
+
import"./index-1zx87sdm.js";
|
|
24
|
+
import"./index-vd2ywmfe.js";
|
|
25
|
+
import"./index-x8a7jmkh.js";
|
|
26
|
+
import"./index-fw42ms3m.js";
|
|
27
|
+
import"./index-xd2p95m7.js";
|
|
28
|
+
import"./index-c5dzns43.js";
|
|
29
|
+
import"./index-jz5bk7xd.js";
|
|
30
|
+
import"./index-dcjkw41m.js";
|
|
31
|
+
import"./index-g4t7850m.js";
|
|
32
|
+
import"./index-9fgmkfaf.js";
|
|
33
|
+
import"./index-fb3zxn06.js";
|
|
34
|
+
import"./index-nj360hcs.js";
|
|
35
|
+
import"./index-fr0wbhdn.js";
|
|
36
|
+
import"./index-txs8tce6.js";
|
|
37
|
+
import"./index-b1ydbp95.js";
|
|
38
|
+
import"./index-wh9fxds5.js";
|
|
39
|
+
import"./index-2p37txes.js";
|
|
40
|
+
import"./index-jkanybgq.js";
|
|
41
|
+
import"./index-9wnbnx8f.js";
|
|
42
|
+
import"./index-r2epb000.js";
|
|
43
|
+
import"./index-96ztjvkn.js";
|
|
44
|
+
import"./index-v0p37hm2.js";
|
|
45
|
+
import"./index-58e3y90n.js";
|
|
46
|
+
import"./index-fxbk7gk3.js";
|
|
47
|
+
import"./index-4xyjr62e.js";
|
|
48
|
+
import"./index-gzy5w8ya.js";
|
|
49
|
+
import"./index-jrfre9ah.js";
|
|
50
|
+
import"./index-g2q4htwp.js";
|
|
51
|
+
import"./index-pavzsdc6.js";
|
|
52
|
+
import"./index-z4p0ry94.js";
|
|
53
|
+
import"./index-1d042x6w.js";
|
|
54
|
+
export {
|
|
55
|
+
runManagedWrapup2 as runManagedWrapup
|
|
56
|
+
};
|
package/package.json
CHANGED
|
@@ -429,7 +429,7 @@ async function promptWithTimeout(
|
|
|
429
429
|
* instance-scoped fiber that `POST /session/{id}/abort` interrupts. Best-effort —
|
|
430
430
|
* a failure here must not mask the original timeout/abort error.
|
|
431
431
|
*/
|
|
432
|
-
async function abortChildRun(client: Client, sessionId: string): Promise<void> {
|
|
432
|
+
export async function abortChildRun(client: Client, sessionId: string): Promise<void> {
|
|
433
433
|
if (!client) return;
|
|
434
434
|
try {
|
|
435
435
|
// Bound the abort call: it's best-effort cleanup, and if the abort
|
|
@@ -17,7 +17,7 @@ type Message = {
|
|
|
17
17
|
finish?: string;
|
|
18
18
|
error?: unknown;
|
|
19
19
|
};
|
|
20
|
-
parts: Array<{ type: string; text?: string }>;
|
|
20
|
+
parts: Array<{ type: string; text?: string; error?: unknown }>;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -165,6 +165,42 @@ describe("promptAsyncAndWaitForIdle", () => {
|
|
|
165
165
|
).rejects.toThrow("did not start a run");
|
|
166
166
|
});
|
|
167
167
|
|
|
168
|
+
test("ignores provider errors and retry parts from before the current send", async () => {
|
|
169
|
+
const host = asyncHost({
|
|
170
|
+
plan: ["busy", "settle"],
|
|
171
|
+
initialMessages: [
|
|
172
|
+
{
|
|
173
|
+
info: {
|
|
174
|
+
id: "old-error",
|
|
175
|
+
role: "assistant",
|
|
176
|
+
time: { created: 0 },
|
|
177
|
+
error: { name: "APIError" },
|
|
178
|
+
},
|
|
179
|
+
parts: [{ type: "retry", error: { name: "APIError" } }],
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
});
|
|
183
|
+
await promptAsyncAndWaitForIdle(host.client, request(), { pollIntervalMs: 1 });
|
|
184
|
+
expect(host.polls()).toBe(2);
|
|
185
|
+
expect(host.abort).not.toHaveBeenCalled();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("accepts a successfully settled assistant that retains an earlier retry part", async () => {
|
|
189
|
+
const host = asyncHost({ plan: ["settle"] });
|
|
190
|
+
const read = host.list.getMockImplementation()!;
|
|
191
|
+
host.list.mockImplementation(async () => {
|
|
192
|
+
const result = await read();
|
|
193
|
+
const last = result.data.at(-1);
|
|
194
|
+
if (last?.info.finish === "stop") {
|
|
195
|
+
last.parts.push({ type: "retry", error: { name: "APIError" } });
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
});
|
|
199
|
+
await promptAsyncAndWaitForIdle(host.client, request(), { pollIntervalMs: 1 });
|
|
200
|
+
expect(host.polls()).toBe(1);
|
|
201
|
+
expect(host.abort).not.toHaveBeenCalled();
|
|
202
|
+
});
|
|
203
|
+
|
|
168
204
|
test("surfaces a rejected prompt_async request", async () => {
|
|
169
205
|
const host = asyncHost({ plan: ["settle"] });
|
|
170
206
|
host.promptAsync.mockImplementation(async () => ({
|
|
@@ -653,9 +689,11 @@ describe("prompt_async transport and the first-output deadline", () => {
|
|
|
653
689
|
* busy forever; "partial" streams a text part and then stays busy; "answer"
|
|
654
690
|
* settles with a final assistant message on the next poll.
|
|
655
691
|
*/
|
|
656
|
-
function modelHost(
|
|
692
|
+
function modelHost(
|
|
693
|
+
behaviours: Record<string, "dead" | "partial" | "answer" | "error" | "retry">,
|
|
694
|
+
) {
|
|
657
695
|
const messages: Message[] = [];
|
|
658
|
-
let current: "dead" | "partial" | "answer" | null = null;
|
|
696
|
+
let current: "dead" | "partial" | "answer" | "error" | "retry" | null = null;
|
|
659
697
|
const sent: string[] = [];
|
|
660
698
|
const promptAsync = mock(
|
|
661
699
|
async (request: { body: { model?: { providerID: string; modelID: string } } }) => {
|
|
@@ -684,6 +722,16 @@ describe("prompt_async transport and the first-output deadline", () => {
|
|
|
684
722
|
return { data: true };
|
|
685
723
|
});
|
|
686
724
|
const status = mock(async () => {
|
|
725
|
+
if (current === "error" || current === "retry") {
|
|
726
|
+
const last = messages.at(-1)!;
|
|
727
|
+
const error = {
|
|
728
|
+
name: "APIError",
|
|
729
|
+
data: { statusCode: 429, message: "Free usage limit reached" },
|
|
730
|
+
};
|
|
731
|
+
if (current === "error") last.info.error = error;
|
|
732
|
+
else last.parts = [{ type: "retry", error }];
|
|
733
|
+
return { data: { "ses-child": { type: current === "retry" ? "retry" : "busy" } } };
|
|
734
|
+
}
|
|
687
735
|
if (current === "dead" || current === "partial")
|
|
688
736
|
return { data: { "ses-child": { type: "busy" } } };
|
|
689
737
|
if (current === "answer") {
|
|
@@ -751,4 +799,17 @@ describe("prompt_async transport and the first-output deadline", () => {
|
|
|
751
799
|
await expect(runChain(host, 200, 40)).rejects.toThrow("prompt timed out after 200ms");
|
|
752
800
|
expect(host.sent).toEqual(["opencode/free-model"]);
|
|
753
801
|
});
|
|
802
|
+
|
|
803
|
+
for (const failure of ["error", "retry"] as const) {
|
|
804
|
+
test(`a recorded provider ${failure} stops the host retry loop and immediately tries the fallback`, async () => {
|
|
805
|
+
const host = modelHost({ "opencode/free-model": failure });
|
|
806
|
+
const startedAt = Date.now();
|
|
807
|
+
const result = await runChain(host, 5_000, 5_000);
|
|
808
|
+
expect(result.attempt.label).toBe("anthropic/claude-sonnet-5-5");
|
|
809
|
+
expect(host.sent).toEqual(["opencode/free-model", "anthropic/claude-sonnet-5-5"]);
|
|
810
|
+
expect(host.abort).toHaveBeenCalledTimes(1);
|
|
811
|
+
expect(host.abort).toHaveBeenCalledWith({ path: { id: "ses-child" } });
|
|
812
|
+
expect(Date.now() - startedAt).toBeLessThan(2_000);
|
|
813
|
+
});
|
|
814
|
+
}
|
|
754
815
|
});
|
|
@@ -14,7 +14,11 @@ import {
|
|
|
14
14
|
import { describeAssistantError } from "./assistant-message-extractor";
|
|
15
15
|
import { sessionLog } from "./logger";
|
|
16
16
|
import type { PromptArgs, PromptTransport } from "./model-suggestion-retry";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
abortChildRun,
|
|
19
|
+
noteModelActivityMonitored,
|
|
20
|
+
noteModelOutputReceived,
|
|
21
|
+
} from "./model-suggestion-retry";
|
|
18
22
|
|
|
19
23
|
type Client = ReturnType<typeof createOpencodeClient> | undefined;
|
|
20
24
|
|
|
@@ -196,6 +200,28 @@ function messageId(message: unknown): string | null {
|
|
|
196
200
|
return typeof id === "string" ? id : null;
|
|
197
201
|
}
|
|
198
202
|
|
|
203
|
+
function recordedAssistantError(message: unknown): unknown {
|
|
204
|
+
const info = infoOf(message);
|
|
205
|
+
if (info.error != null) return info.error;
|
|
206
|
+
// A completed step can retain retry parts from a provider attempt that
|
|
207
|
+
// already recovered before this poll. Its successful settlement wins.
|
|
208
|
+
if (isSettledAssistant(message)) return undefined;
|
|
209
|
+
const parts = (message as { parts?: unknown[] } | null)?.parts;
|
|
210
|
+
if (!Array.isArray(parts)) return undefined;
|
|
211
|
+
// OpenCode records a failed provider attempt as a retry part before it
|
|
212
|
+
// settles the assistant row or emits session.error.
|
|
213
|
+
const retry = parts
|
|
214
|
+
.slice()
|
|
215
|
+
.reverse()
|
|
216
|
+
.find(
|
|
217
|
+
(part) =>
|
|
218
|
+
part !== null &&
|
|
219
|
+
typeof part === "object" &&
|
|
220
|
+
(part as { type?: unknown }).type === "retry",
|
|
221
|
+
) as { error?: unknown } | undefined;
|
|
222
|
+
return retry?.error ?? undefined;
|
|
223
|
+
}
|
|
224
|
+
|
|
199
225
|
/** An assistant message the host has finished writing, successfully or not. */
|
|
200
226
|
function isSettledAssistant(message: unknown): boolean {
|
|
201
227
|
const info = infoOf(message);
|
|
@@ -355,6 +381,26 @@ export async function promptAsyncAndWaitForIdle(
|
|
|
355
381
|
// Dispatch can fail before an assistant row exists. The plugin event hook
|
|
356
382
|
// retains that provider/model error while this child is actively awaited.
|
|
357
383
|
activeSessionErrors.set(sessionId, undefined);
|
|
384
|
+
const failForHostError = async (hostError: unknown): Promise<never> => {
|
|
385
|
+
// Stop the host's retry loop before handing the attempt to our model
|
|
386
|
+
// chain; otherwise the failed model keeps making requests in parallel.
|
|
387
|
+
await abortChildRun(client, sessionId);
|
|
388
|
+
const error = new Error(
|
|
389
|
+
`Host recorded session error: ${describeAssistantError(hostError)}`,
|
|
390
|
+
);
|
|
391
|
+
Object.assign(error, {
|
|
392
|
+
name: "DreamerProviderOutputFailureError",
|
|
393
|
+
transient: true,
|
|
394
|
+
[HOST_SESSION_ERROR]: true,
|
|
395
|
+
hostError,
|
|
396
|
+
});
|
|
397
|
+
annotateSubagentInvocationError(error, {
|
|
398
|
+
attemptedModel: requestModelRef(request),
|
|
399
|
+
modelConfigKey: options.modelConfigKey,
|
|
400
|
+
hostError,
|
|
401
|
+
});
|
|
402
|
+
throw error;
|
|
403
|
+
};
|
|
358
404
|
try {
|
|
359
405
|
let sent: unknown;
|
|
360
406
|
try {
|
|
@@ -395,24 +441,23 @@ export async function promptAsyncAndWaitForIdle(
|
|
|
395
441
|
await sleep(pollIntervalMs, signal);
|
|
396
442
|
const hostError = activeSessionErrors.get(sessionId);
|
|
397
443
|
if (hostError !== undefined) {
|
|
398
|
-
|
|
399
|
-
`Host recorded session error: ${describeAssistantError(hostError)}`,
|
|
400
|
-
);
|
|
401
|
-
Object.assign(error, {
|
|
402
|
-
name: "DreamerProviderOutputFailureError",
|
|
403
|
-
transient: true,
|
|
404
|
-
[HOST_SESSION_ERROR]: true,
|
|
405
|
-
hostError,
|
|
406
|
-
});
|
|
407
|
-
annotateSubagentInvocationError(error, {
|
|
408
|
-
attemptedModel: requestModelRef(request),
|
|
409
|
-
modelConfigKey: options.modelConfigKey,
|
|
410
|
-
hostError,
|
|
411
|
-
});
|
|
412
|
-
throw error;
|
|
444
|
+
await failForHostError(hostError);
|
|
413
445
|
}
|
|
414
446
|
const status = await readStatus(session, sessionId, dir, signal);
|
|
415
447
|
const messages = await readMessages(session, sessionId, dir, signal);
|
|
448
|
+
const latestAssistant = messages
|
|
449
|
+
.slice()
|
|
450
|
+
.reverse()
|
|
451
|
+
.find((message) => {
|
|
452
|
+
const id = messageId(message);
|
|
453
|
+
return (
|
|
454
|
+
id !== null &&
|
|
455
|
+
!completionBaseline.has(id) &&
|
|
456
|
+
infoOf(message).role === "assistant"
|
|
457
|
+
);
|
|
458
|
+
});
|
|
459
|
+
const assistantError = recordedAssistantError(latestAssistant);
|
|
460
|
+
if (assistantError !== undefined) await failForHostError(assistantError);
|
|
416
461
|
if (
|
|
417
462
|
!sawOutput &&
|
|
418
463
|
messages.some((message) => {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { type MessagePort, parentPort, workerData } from "node:worker_threads";
|
|
3
|
+
|
|
4
|
+
/** Dispatch each job with new per-job state and a port whose messages are matched by job id. */
|
|
5
|
+
export function serveWorkerJobs<T>(
|
|
6
|
+
run: (data: T, port: MessagePort) => Promise<void> | void,
|
|
7
|
+
autoClose = true,
|
|
8
|
+
): void {
|
|
9
|
+
if (!parentPort) throw new Error("worker requires a parent port");
|
|
10
|
+
const parent = parentPort;
|
|
11
|
+
if (!workerData?.reusableWorker) {
|
|
12
|
+
void Promise.resolve(run(workerData, parent)).catch(rethrow);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let active: { id: number; port: EventEmitter } | undefined;
|
|
16
|
+
parent.on("message", (message: { jobId: number; start?: T; value?: unknown }) => {
|
|
17
|
+
if (!("start" in message)) {
|
|
18
|
+
if (active?.id === message.jobId) active.port.emit("message", message.value);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (active) throw new Error("reusable worker received overlapping jobs");
|
|
22
|
+
const id = message.jobId;
|
|
23
|
+
let closed = false;
|
|
24
|
+
const port = Object.assign(new EventEmitter(), {
|
|
25
|
+
postMessage(value: unknown, transferList?: readonly object[]) {
|
|
26
|
+
if (!closed) parent.postMessage({ jobId: id, value }, transferList as never);
|
|
27
|
+
},
|
|
28
|
+
close() {
|
|
29
|
+
if (closed) return;
|
|
30
|
+
closed = true;
|
|
31
|
+
port.removeAllListeners();
|
|
32
|
+
active = undefined;
|
|
33
|
+
parent.postMessage({
|
|
34
|
+
jobId: id,
|
|
35
|
+
finished: true,
|
|
36
|
+
code: Number(process.exitCode) || 0,
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
active = { id, port };
|
|
41
|
+
try {
|
|
42
|
+
void Promise.resolve(run(message.start as T, port as unknown as MessagePort))
|
|
43
|
+
.then(() => {
|
|
44
|
+
if (autoClose) port.close();
|
|
45
|
+
})
|
|
46
|
+
.catch(rethrow);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
rethrow(error);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function rethrow(error: unknown): void {
|
|
54
|
+
// Bun 1.3 aborts the host for a microtask throw; a timer reports a Worker error.
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
throw error;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { expect, spyOn, test } from "bun:test";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { once } from "node:events";
|
|
4
|
+
import { writeFileSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import * as timers from "node:timers";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { resetReusableWorkersForTests, reuseWorker } from "./reusable-worker";
|
|
9
|
+
import { withTestTempDir } from "./test-temp-dir";
|
|
10
|
+
|
|
11
|
+
test("a temporary caller clock cannot replace the pool's idle timer", async () => {
|
|
12
|
+
const clock = spyOn(globalThis, "setTimeout").mockReturnValue(
|
|
13
|
+
0 as unknown as ReturnType<typeof setTimeout>,
|
|
14
|
+
);
|
|
15
|
+
try {
|
|
16
|
+
const worker = reuseWorker(new URL("./reusable-worker.fixture.ts", import.meta.url), {
|
|
17
|
+
workerData: { path: "caller-clock" },
|
|
18
|
+
});
|
|
19
|
+
const message = once(worker, "message");
|
|
20
|
+
const exit = once(worker, "exit");
|
|
21
|
+
await message;
|
|
22
|
+
await exit;
|
|
23
|
+
expect(clock).not.toHaveBeenCalled();
|
|
24
|
+
} finally {
|
|
25
|
+
clock.mockRestore();
|
|
26
|
+
await resetReusableWorkersForTests();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("reset clears idle timers and waits for active and queued leases to exit", async () => {
|
|
31
|
+
const entry = new URL("./reusable-worker.fixture.ts", import.meta.url);
|
|
32
|
+
const schedules = spyOn(timers, "setTimeout");
|
|
33
|
+
const cancellations = spyOn(timers, "clearTimeout");
|
|
34
|
+
const idleMs = 12_345;
|
|
35
|
+
async function runIdle() {
|
|
36
|
+
const worker = reuseWorker(entry, { workerData: { path: "reset-idle" } }, idleMs);
|
|
37
|
+
const message = once(worker, "message");
|
|
38
|
+
const exit = once(worker, "exit");
|
|
39
|
+
const [reply] = await message;
|
|
40
|
+
await exit;
|
|
41
|
+
return reply.threadId as number;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const previousThread = await runIdle();
|
|
45
|
+
const timerIndex = schedules.mock.calls.findIndex(([, delay]) => delay === idleMs);
|
|
46
|
+
expect(timerIndex).toBeGreaterThanOrEqual(0);
|
|
47
|
+
const idleTimer = schedules.mock.results[timerIndex]?.value;
|
|
48
|
+
const active = reuseWorker(entry, { workerData: { path: "reset-active", hang: true } });
|
|
49
|
+
const queued = reuseWorker(entry, {
|
|
50
|
+
workerData: { path: "reset-active", value: "queued" },
|
|
51
|
+
});
|
|
52
|
+
const replies: unknown[] = [];
|
|
53
|
+
queued.on("message", (message) => replies.push(message));
|
|
54
|
+
const activeExit = once(active, "exit");
|
|
55
|
+
const queuedExit = once(queued, "exit");
|
|
56
|
+
await Promise.resolve();
|
|
57
|
+
await Promise.all([resetReusableWorkersForTests(), activeExit, queuedExit]);
|
|
58
|
+
expect(cancellations).toHaveBeenCalledWith(idleTimer);
|
|
59
|
+
expect(replies).toEqual([]);
|
|
60
|
+
expect(await runIdle()).not.toBe(previousThread);
|
|
61
|
+
} finally {
|
|
62
|
+
schedules.mockRestore();
|
|
63
|
+
cancellations.mockRestore();
|
|
64
|
+
await resetReusableWorkersForTests();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("the shared preload stops pooled workers between test cases", () => {
|
|
69
|
+
withTestTempDir("reusable-worker-boundaries-", (dir) => {
|
|
70
|
+
writeFileSync(
|
|
71
|
+
join(dir, "boundaries.test.ts"),
|
|
72
|
+
`import { expect, test } from "bun:test";
|
|
73
|
+
import { once } from "node:events";
|
|
74
|
+
import { reuseWorker } from ${JSON.stringify(new URL("./reusable-worker.ts", import.meta.url).href)};
|
|
75
|
+
const entry = new URL(${JSON.stringify(new URL("./reusable-worker.fixture.ts", import.meta.url).href)});
|
|
76
|
+
let previousThread;
|
|
77
|
+
async function run() {
|
|
78
|
+
const worker = reuseWorker(entry, { workerData: { path: "test-boundaries" } });
|
|
79
|
+
const message = once(worker, "message");
|
|
80
|
+
const exit = once(worker, "exit");
|
|
81
|
+
const [reply] = await message;
|
|
82
|
+
await exit;
|
|
83
|
+
return reply.threadId;
|
|
84
|
+
}
|
|
85
|
+
test("finishes with an idle pooled worker", async () => {
|
|
86
|
+
previousThread = await run();
|
|
87
|
+
expect(previousThread).toBeGreaterThan(0);
|
|
88
|
+
});
|
|
89
|
+
test("cannot inherit the previous test's pooled worker", async () => {
|
|
90
|
+
expect(await run()).not.toBe(previousThread);
|
|
91
|
+
});`,
|
|
92
|
+
);
|
|
93
|
+
const child = spawnSync(
|
|
94
|
+
process.execPath,
|
|
95
|
+
[
|
|
96
|
+
"test",
|
|
97
|
+
"--preload",
|
|
98
|
+
fileURLToPath(new URL("../../test-preload.ts", import.meta.url)),
|
|
99
|
+
join(dir, "boundaries.test.ts"),
|
|
100
|
+
],
|
|
101
|
+
{ cwd: dir, encoding: "utf8", timeout: 5_000, windowsHide: true },
|
|
102
|
+
);
|
|
103
|
+
const output = child.stdout + child.stderr;
|
|
104
|
+
expect(output).toContain("2 pass");
|
|
105
|
+
expect(output).toContain("0 fail");
|
|
106
|
+
expect(child.status).toBe(0);
|
|
107
|
+
});
|
|
108
|
+
}, 10_000);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { parentPort, threadId } from "node:worker_threads";
|
|
2
|
+
import { serveWorkerJobs } from "./reusable-worker-entry";
|
|
3
|
+
|
|
4
|
+
serveWorkerJobs<{
|
|
5
|
+
crash?: boolean;
|
|
6
|
+
hang?: boolean;
|
|
7
|
+
late?: boolean;
|
|
8
|
+
exitCode?: boolean;
|
|
9
|
+
value?: string;
|
|
10
|
+
shared?: SharedArrayBuffer;
|
|
11
|
+
}>(async (input, port) => {
|
|
12
|
+
if (input.crash) throw new Error("injected worker crash");
|
|
13
|
+
if (input.hang) return await new Promise<void>(() => {});
|
|
14
|
+
if (input.exitCode) process.exitCode = 1;
|
|
15
|
+
if (input.shared) {
|
|
16
|
+
const state = new Int32Array(input.shared);
|
|
17
|
+
port.postMessage({ threadId, shared: Atomics.load(state, 0) });
|
|
18
|
+
await new Promise<void>((resolve) =>
|
|
19
|
+
port.once("message", () => {
|
|
20
|
+
port.postMessage({ threadId, shared: Atomics.add(state, 0, 1) });
|
|
21
|
+
resolve();
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
port.close();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (input.late)
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
port.postMessage({ value: "stale" });
|
|
30
|
+
// Bypass the job port to verify the owner ignores a mismatched job id.
|
|
31
|
+
parentPort?.postMessage({ jobId: -1, value: { value: "stale" } });
|
|
32
|
+
}, 20);
|
|
33
|
+
port.postMessage({ threadId, value: input.value });
|
|
34
|
+
port.close();
|
|
35
|
+
});
|