@cortexkit/opencode-magic-context 0.47.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/magic-context-prompt.d.ts +1 -1
- package/dist/agents/magic-context-prompt.d.ts.map +1 -1
- package/dist/{announcement-y35wzg2r.js → announcement-fp14dw0n.js} +3 -2
- package/dist/auto-search-worker.js +27 -30
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/mural-model-deprecation.d.ts +15 -0
- package/dist/config/mural-model-deprecation.d.ts.map +1 -0
- package/dist/config/project-security.d.ts +0 -3
- package/dist/config/project-security.d.ts.map +1 -1
- package/dist/config/schema/magic-context.d.ts +10 -6
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/{conflict-warning-hook-z44ynfz7.js → conflict-warning-hook-kzx4dmk1.js} +12 -10
- package/dist/{context-wq4ffwyb.js → context-nj5f293n.js} +2765 -1925
- package/dist/{derive-budgets-ke12jnnh.js → derive-budgets-qz5rrr08.js} +4 -3
- package/dist/embedding-activity-g1dhes6g.js +10 -0
- package/dist/embedding-backfill-aetxv1vt.js +21 -0
- package/dist/embedding-cache-mgyr73ef.js +16 -0
- package/dist/embedding-worker.js +11 -9
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +1 -0
- package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-config.d.ts +3 -3
- package/dist/features/magic-context/dreamer/task-config.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -1
- package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-registry.d.ts +1 -0
- package/dist/features/magic-context/dreamer/task-registry.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts +2 -0
- package/dist/features/magic-context/git-commits/search-git-commits.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +16 -3
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-bounded.d.ts +17 -0
- package/dist/features/magic-context/message-index-bounded.d.ts.map +1 -0
- package/dist/features/magic-context/message-index.d.ts +7 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/mural/render-trigger.d.ts +7 -4
- package/dist/features/magic-context/mural/render-trigger.d.ts.map +1 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
- package/dist/features/magic-context/search-rerank.d.ts +35 -0
- package/dist/features/magic-context/search-rerank.d.ts.map +1 -0
- package/dist/features/magic-context/search.d.ts +40 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/session-activity.d.ts.map +1 -1
- package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
- package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +13 -2
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta.d.ts +1 -1
- package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
- package/dist/features/magic-context/storage-session-tables.d.ts +2 -0
- package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +153 -4
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/storage.d.ts +1 -1
- package/dist/features/magic-context/storage.d.ts.map +1 -1
- package/dist/features/magic-context/subagent-token-capture.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +2 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +4 -1
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/harness-e4avh192.js +10 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts +24 -0
- package/dist/hooks/magic-context/auto-search-replay.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts +34 -3
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
- package/dist/hooks/magic-context/command-handler.d.ts +3 -0
- package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/emergency-fail-closed.d.ts +28 -0
- package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
- package/dist/hooks/magic-context/historian-host-runner.d.ts +8 -0
- package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook.d.ts +3 -2
- package/dist/hooks/magic-context/hook.d.ts.map +1 -1
- package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts +7 -0
- package/dist/hooks/magic-context/latest-thinking-recovery.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-persist.d.ts +4 -3
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-replay.d.ts +13 -8
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +139 -2
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/message-search-accepting-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-r2-warmup-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/oc-stall-search-review.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts +63 -0
- package/dist/hooks/magic-context/opencode1-to-model-messages.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
- package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-silent-worker.fixture.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts +2 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup-worker.d.ts.map +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +87 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +19 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +118 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +36 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +41 -1
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts +8 -1
- package/dist/hooks/magic-context/shared-compartment-boundaries.d.ts.map +1 -1
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +14 -2
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +8 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts +6 -0
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +13 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +9 -2
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
- package/dist/{index-q6hef7fh.js → index-0sahzkwr.js} +6 -19
- package/dist/{index-k5bdx1bx.js → index-0w56v4fm.js} +3 -5
- package/dist/{index-5gq3b2ya.js → index-1bt88epp.js} +227 -205
- package/dist/{index-cwf6s3ay.js → index-1g30axtz.js} +3279 -2907
- package/dist/{index-5a2r0p9f.js → index-1r0k9js3.js} +20 -13
- package/dist/index-2bvekkfy.js +11 -0
- package/dist/{index-6d9e1m08.js → index-2jcbj7r1.js} +13301 -13225
- package/dist/index-2jgwttpt.js +3269 -0
- package/dist/index-4dhv7mqz.js +131 -0
- package/dist/{index-sj29b3z2.js → index-4mjhqadz.js} +3 -3
- package/dist/{index-0c82743p.js → index-57mrqed8.js} +17 -15
- package/dist/{index-b35pxds2.js → index-58e3y90n.js} +1 -18
- package/dist/index-7jzrrxap.js +931 -0
- package/dist/index-8ajstryz.js +18 -0
- package/dist/{index-sfpzqvdz.js → index-8cd2j99z.js} +2 -3
- package/dist/{index-6wkcswft.js → index-9qjqq45k.js} +29 -19
- package/dist/{index-adwfkpex.js → index-9rt53q79.js} +23 -23
- package/dist/index-b7mv1jx3.js +1060 -0
- package/dist/index-d9vfe7xq.js +16 -0
- package/dist/{index-gg8j07zz.js → index-ezmszwbd.js} +8 -6
- package/dist/index-fb3zxn06.js +13 -0
- package/dist/index-fr0wbhdn.js +43 -0
- package/dist/{index-mc22ayvf.js → index-ghc9f0n7.js} +11 -9
- package/dist/index-gzcmtmar.js +171 -0
- package/dist/{index-w2t4ah5j.js → index-h2py7207.js} +6762 -7400
- package/dist/index-h2wc01qk.js +120 -0
- package/dist/index-h5zfkjyk.js +1277 -0
- package/dist/{index-92bp57hg.js → index-ha87j7a8.js} +1343 -149
- package/dist/index-hj2q50k0.js +856 -0
- package/dist/{index-wx8a6bw3.js → index-kb9nn0a0.js} +270 -53
- package/dist/index-kmpvemph.js +1314 -0
- package/dist/index-kp5qe690.js +3030 -0
- package/dist/{index-m5fe6jch.js → index-kq57tdf0.js} +152 -2453
- package/dist/{v2/server-fq7kq32k.js → index-mfkzp7qj.js} +1 -16
- package/dist/{v2/server-njt3np1k.js → index-nm6a8xpd.js} +220 -961
- package/dist/{index-hybnrwq0.js → index-nsjyysj0.js} +137 -130
- package/dist/index-nydv6g8r.js +3569 -0
- package/dist/index-pavzsdc6.js +17 -0
- package/dist/index-peshmj6h.js +152 -0
- package/dist/index-pxwp2hjk.js +571 -0
- package/dist/{v2/server-yr3zj7e7.js → index-qt1qqasc.js} +6 -7
- package/dist/{v2/server-51dv1pr5.js → index-qx53vezw.js} +301 -27
- package/dist/{index-rrrsepyw.js → index-s4j7t92z.js} +90 -85
- package/dist/{index-9pk9exrb.js → index-stbr4ce6.js} +18 -18
- package/dist/{index-fzbvakh0.js → index-tqf7yg27.js} +3 -3
- package/dist/index-vkbqdnkj.js +2307 -0
- package/dist/{index-8da2zjhz.js → index-z1tjp257.js} +9 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +608 -349
- package/dist/logger-ewak5q1s.js +20 -0
- package/dist/message-index-bounded-h0mrd4pr.js +124 -0
- package/dist/{v2/message-time-backfill-1f9tzvcs.js → message-time-backfill-8x06r9kx.js} +8 -6
- package/dist/migration-worker.js +25 -18
- package/dist/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/plugin/dream-timer.d.ts +1 -1
- package/dist/plugin/dream-timer.d.ts.map +1 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
- package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler-report.d.ts +1 -66
- package/dist/plugin/host-stall-profiler-report.d.ts.map +1 -1
- package/dist/plugin/host-stall-profiler.d.ts +2 -95
- package/dist/plugin/host-stall-profiler.d.ts.map +1 -1
- package/dist/plugin/messages-transform.d.ts +0 -13
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/plugin/tool-registry.d.ts.map +1 -1
- package/dist/project-embedding-registry-rtt0djyb.js +88 -0
- package/dist/raw-ordinal-warmup-worker.js +60 -0
- package/dist/{read-session-chunk-4jey7hpt.js → read-session-chunk-ty89v75e.js} +17 -9
- package/dist/read-session-raw-8sjbc9h0.js +60 -0
- package/dist/recomp-orchestrator-4f1yyd1q.js +57 -0
- package/dist/{v2/safe-notification-target-eb1n1vfb.js → safe-notification-target-q0cyrx3x.js} +4 -2
- package/dist/search-pz4f4wge.js +45 -0
- package/dist/{v2/send-session-notification-c0wtscea.js → send-session-notification-38cd5dqt.js} +10 -7
- package/dist/shared/auto-search-lifecycle.d.ts +14 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
- package/dist/shared/conflict-detector.d.ts.map +1 -1
- package/dist/shared/host-stall-profiler-bun.d.ts +46 -0
- package/dist/shared/host-stall-profiler-bun.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-common.d.ts +58 -0
- package/dist/shared/host-stall-profiler-common.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-node.d.ts +36 -0
- package/dist/shared/host-stall-profiler-node.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler-report.d.ts +68 -0
- package/dist/shared/host-stall-profiler-report.d.ts.map +1 -0
- package/dist/shared/host-stall-profiler.d.ts +5 -0
- package/dist/shared/host-stall-profiler.d.ts.map +1 -0
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/model-resolution.d.ts +2 -3
- package/dist/shared/model-resolution.d.ts.map +1 -1
- package/dist/shared/models-dev-temperature.d.ts +18 -0
- package/dist/shared/models-dev-temperature.d.ts.map +1 -0
- package/dist/shared/project-directory-key.d.ts +16 -0
- package/dist/shared/project-directory-key.d.ts.map +1 -1
- package/dist/shared/sqlite.d.ts +30 -0
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/subagent-temperature.d.ts +46 -0
- package/dist/shared/subagent-temperature.d.ts.map +1 -0
- package/dist/shared/user-facing-codes.d.ts +0 -5
- package/dist/shared/user-facing-codes.d.ts.map +1 -1
- package/dist/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/sqlite-mhjkerzq.js +46 -0
- package/dist/storage-memory-07fx57k6.js +71 -0
- package/dist/storage-tags-k0pda32s.js +133 -0
- package/dist/{task-config-v81k8jvk.js → task-config-cgpg0nvh.js} +2 -2
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-note/constants.d.ts +4 -0
- package/dist/tools/ctx-note/constants.d.ts.map +1 -1
- package/dist/tools/ctx-note/tools.d.ts +1 -0
- package/dist/tools/ctx-note/tools.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/tools.d.ts.map +1 -1
- package/dist/tools/ctx-search/types.d.ts +1 -0
- package/dist/tools/ctx-search/types.d.ts.map +1 -1
- package/dist/tools/parameter-descriptions.d.ts +2 -2
- package/dist/tools/parameter-descriptions.d.ts.map +1 -1
- package/dist/{transform-postprocess-phase-z5hzpsxv.js → transform-postprocess-phase-tck4g20s.js} +35 -20
- package/dist/transformers-node-wasm.js +18415 -18415
- package/dist/v2/auto-search-worker.js +27 -30
- package/dist/v2/{context-14v1hr8b.js → context-crbt6p1y.js} +4708 -4218
- package/dist/v2/{derive-budgets-nc9avxz8.js → derive-budgets-fgej9j46.js} +4 -3
- package/dist/v2/embedding-activity-g1dhes6g.js +10 -0
- package/dist/v2/embedding-backfill-ph1qfyn3.js +21 -0
- package/dist/v2/embedding-cache-mgyr73ef.js +16 -0
- package/dist/v2/embedding-worker.js +12 -9
- package/dist/v2/fold/host-media.d.ts +4 -0
- package/dist/v2/fold/host-media.d.ts.map +1 -1
- package/dist/v2/fold/memory-cache.d.ts +70 -0
- package/dist/v2/fold/memory-cache.d.ts.map +1 -0
- package/dist/v2/fold/native-codec.d.ts +10 -0
- package/dist/v2/fold/native-codec.d.ts.map +1 -0
- package/dist/v2/fold/native-replay.d.ts +58 -0
- package/dist/v2/fold/native-replay.d.ts.map +1 -0
- package/dist/v2/fold/policy.d.ts +24 -0
- package/dist/v2/fold/policy.d.ts.map +1 -0
- package/dist/v2/harness-e4avh192.js +10 -0
- package/dist/v2/hidden-child-native.d.ts.map +1 -1
- package/dist/v2/hidden-completion.d.ts +7 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts +2 -2
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/dream-manual.d.ts +1 -1
- package/dist/v2/hooks/dream-manual.d.ts.map +1 -1
- package/dist/v2/hooks/dream-timer.d.ts.map +1 -1
- package/dist/v2/hooks/dream-trigger.d.ts +5 -3
- package/dist/v2/hooks/dream-trigger.d.ts.map +1 -1
- package/dist/v2/hooks/generate.d.ts +9 -2
- package/dist/v2/hooks/generate.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/tools.d.ts.map +1 -1
- package/dist/v2/hooks/types.d.ts +6 -0
- package/dist/v2/hooks/types.d.ts.map +1 -1
- package/dist/v2/logger-pj02s7sr.js +19 -0
- package/dist/v2/message-index-bounded-xwqdywxg.js +123 -0
- package/dist/{message-time-backfill-r5epkzj3.js → v2/message-time-backfill-cje68egj.js} +7 -7
- package/dist/v2/migration-worker.js +24 -17
- package/dist/v2/{model-resolution-xhfmyyvy.js → model-resolution-nx97z3x7.js} +1 -1
- package/dist/v2/project-embedding-registry-d6m7tyxr.js +86 -0
- package/dist/v2/raw-ordinal-warmup-worker.js +60 -0
- package/dist/v2/{read-session-chunk-gyyv7w2r.js → read-session-chunk-8p5mdryx.js} +16 -8
- package/dist/v2/read-session-raw-j8dvp7f4.js +59 -0
- package/dist/v2/recomp-orchestrator-ckfgt6wq.js +57 -0
- package/dist/{safe-notification-target-43r8jsxw.js → v2/safe-notification-target-y3p1hce9.js} +3 -3
- package/dist/v2/search-ym8rehhz.js +45 -0
- package/dist/{send-session-notification-0m68ms3n.js → v2/send-session-notification-5m0yapqx.js} +9 -8
- package/dist/v2/{server-rz514f14.js → server-19zjmn02.js} +2044 -2060
- package/dist/v2/server-1tk82krw.js +796 -0
- package/dist/v2/server-2bvekkfy.js +11 -0
- package/dist/v2/{server-ajzeteqw.js → server-2ra6pwf3.js} +1 -18
- package/dist/v2/server-2s6ayq3t.js +1048 -0
- package/dist/v2/{server-fcdehk1s.js → server-2s9qz6n7.js} +4 -4
- package/dist/v2/server-3j4d00kf.js +171 -0
- package/dist/v2/{server-14vq4kpm.js → server-3t0q2cqx.js} +3 -3
- package/dist/v2/server-4dhv7mqz.js +131 -0
- package/dist/v2/server-4ez8mntn.js +3213 -0
- package/dist/v2/{server-6r257mf5.js → server-676xw7at.js} +3 -3
- package/dist/v2/{server-vs5gpnd4.js → server-6byqfbqf.js} +165 -145
- package/dist/v2/server-7ekna9zs.js +120 -0
- package/dist/v2/server-7h861yms.js +1272 -0
- package/dist/v2/server-7jzrrxap.js +931 -0
- package/dist/v2/server-8ajstryz.js +18 -0
- package/dist/v2/{server-sfpzqvdz.js → server-8cd2j99z.js} +2 -3
- package/dist/v2/{server-cpepxy2q.js → server-8k2agx29.js} +14 -12
- package/dist/v2/server-c5rrgrcd.js +3545 -0
- package/dist/v2/server-d9vfe7xq.js +16 -0
- package/dist/v2/server-fb3zxn06.js +13 -0
- package/dist/v2/server-fr0wbhdn.js +43 -0
- package/dist/v2/{server-y10vbq6y.js → server-hb6xhh9q.js} +11 -1053
- package/dist/v2/server-jvxzm1jy.js +3023 -0
- package/dist/v2/{server-wx8a6bw3.js → server-kb9nn0a0.js} +270 -53
- package/dist/{index-5eqk6z3s.js → v2/server-kzns2hbz.js} +301 -27
- package/dist/{index-rrbbspwh.js → v2/server-mfkzp7qj.js} +1 -16
- package/dist/v2/server-pavzsdc6.js +17 -0
- package/dist/v2/{server-vd4e7174.js → server-pj4pjv02.js} +21 -17
- package/dist/v2/{server-e0c1b7a7.js → server-q4ph9bwn.js} +1340 -148
- package/dist/{index-yr3zj7e7.js → v2/server-qt1qqasc.js} +6 -7
- package/dist/v2/{server-qdjnb2z1.js → server-r5p3b1wy.js} +11 -9
- package/dist/v2/{server-d0sraw7m.js → server-sa8jvrfc.js} +291 -286
- package/dist/v2/server-ss95ky04.js +1048 -0
- package/dist/v2/{server-1qbnzc80.js → server-t4k4qexw.js} +142 -150
- package/dist/{index-x3kwrmqk.js → v2/server-v4mewb78.js} +35 -792
- package/dist/v2/server-w32kmdez.js +154 -0
- package/dist/v2/{server-nf82q6pt.js → server-x4hscabv.js} +5547 -5449
- package/dist/v2/server-xwz4dqh9.js +569 -0
- package/dist/v2/{server-efhwzx05.js → server-ycw9qqcy.js} +23 -23
- package/dist/v2/{server-50hvkg3v.js → server-zm570tr2.js} +160 -158
- package/dist/v2/server-zp53y8js.js +1311 -0
- package/dist/v2/server.js +16 -14
- package/dist/v2/sqlite-context-pragmas-mv9jqwjh.js +6 -0
- package/dist/v2/sqlite-mhjkerzq.js +46 -0
- package/dist/v2/storage-memory-07fx57k6.js +71 -0
- package/dist/v2/storage-tags-8vw924zn.js +132 -0
- package/dist/v2/store-reader.d.ts +24 -2
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/v2/{task-config-tbndqyny.js → task-config-x0hq3qfd.js} +2 -2
- package/dist/v2/transformers-node-wasm.js +18415 -18415
- package/dist/v2/tui/index.d.ts.map +1 -1
- package/dist/v2/tui/types.d.ts +1 -10
- package/dist/v2/tui/types.d.ts.map +1 -1
- package/dist/v2/{wrapup-orchestrator-nbz854vc.js → wrapup-orchestrator-a7efxaax.js} +51 -30
- package/dist/wrapup-orchestrator-barbc6h9.js +44 -0
- package/package.json +4 -3
- package/src/agents/magic-context-prompt.ts +27 -2
- package/src/agents/smart-notes-enabled.test.ts +294 -0
- package/src/agents/smart-notes-on.golden.json +70 -0
- package/src/config/index.test.ts +67 -1
- package/src/config/index.ts +2 -0
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/mural-model-deprecation.ts +24 -0
- package/src/config/project-security.hostile-matrix.test.ts +4 -44
- package/src/config/project-security.test.ts +9 -14
- package/src/config/project-security.ts +13 -55
- package/src/config/schema/magic-context.test.ts +2 -2
- package/src/config/schema/magic-context.ts +16 -10
- package/src/features/magic-context/dreamer/task-registry.ts +6 -0
- package/src/shared/auto-search-lifecycle.ts +43 -0
- package/src/shared/conflict-detector.test.ts +56 -0
- package/src/shared/conflict-detector.ts +16 -5
- package/src/shared/host-stall-profiler-bun.ts +358 -0
- package/src/shared/host-stall-profiler-common.ts +159 -0
- package/src/shared/host-stall-profiler-node.test.ts +234 -0
- package/src/shared/host-stall-profiler-node.ts +274 -0
- package/src/shared/host-stall-profiler-report.ts +248 -0
- package/src/shared/host-stall-profiler.ts +57 -0
- package/src/shared/logger.test.ts +38 -0
- package/src/shared/logger.ts +10 -2
- package/src/shared/model-resolution.test.ts +54 -17
- package/src/shared/model-resolution.ts +6 -17
- package/src/shared/models-dev-temperature.ts +107 -0
- package/src/shared/project-directory-key.test.ts +59 -0
- package/src/shared/project-directory-key.ts +20 -0
- package/src/shared/sqlite.test.ts +52 -0
- package/src/shared/sqlite.ts +339 -23
- package/src/shared/stable-json-linear.test.ts +109 -0
- package/src/shared/stable-json.ts +37 -7
- package/src/shared/subagent-temperature.test.ts +270 -0
- package/src/shared/subagent-temperature.ts +110 -0
- package/src/shared/user-facing-codes.ts +2 -6
- package/src/shared/write-transaction-attribution.test.ts +2 -2
- package/src/v2/tui/host-contract.test.ts +41 -67
- package/src/v2/tui/index.ts +6 -214
- package/src/v2/tui/types.ts +5 -17
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts +0 -45
- package/dist/features/magic-context/checkout-claim-fake-subc.test-support.d.ts.map +0 -1
- package/dist/features/magic-context/checkout-claim.d.ts +0 -155
- package/dist/features/magic-context/checkout-claim.d.ts.map +0 -1
- package/dist/index-bb36vgr3.js +0 -6608
- package/dist/index-fnn5pjtt.js +0 -6554
- package/dist/recomp-orchestrator-rervg6q4.js +0 -42
- package/dist/v2/recomp-orchestrator-42vjba7p.js +0 -42
- package/dist/v2/server-3trjk1hx.js +0 -6360
- package/dist/v2/server-nm9n3aqq.js +0 -6461
- package/dist/wrapup-orchestrator-b2dztrar.js +0 -29
- /package/dist/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
- /package/dist/v2/{index-5prbx026.js → index-2pp04pmg.js} +0 -0
|
@@ -0,0 +1,3213 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UNKNOWN_FIT_RATIO,
|
|
3
|
+
resolveDecisionCalibration,
|
|
4
|
+
hasMeasuredDecisionCalibration,
|
|
5
|
+
providerMass
|
|
6
|
+
} from "./server-1zx87sdm.js";
|
|
7
|
+
import {
|
|
8
|
+
stripTagPrefix,
|
|
9
|
+
isRecord,
|
|
10
|
+
estimateImageTokensFromDataUrl,
|
|
11
|
+
estimateToolAttachmentImageTokens,
|
|
12
|
+
providerVisiblePart,
|
|
13
|
+
getCandidateToolOwners2,
|
|
14
|
+
pickNearestPriorOwner2
|
|
15
|
+
} from "./server-c5rrgrcd.js";
|
|
16
|
+
import {
|
|
17
|
+
OMO_INTERNAL_INITIATOR_MARKER,
|
|
18
|
+
isSystemDirective,
|
|
19
|
+
hasMeaningfulUserText2,
|
|
20
|
+
extractTexts2,
|
|
21
|
+
extractToolResultBodyTokens,
|
|
22
|
+
extractToolCallSummaries,
|
|
23
|
+
hasTokenizerForFit,
|
|
24
|
+
tokenCountUsesByteBound,
|
|
25
|
+
estimateTokens,
|
|
26
|
+
createTokenCountMemo,
|
|
27
|
+
normalizeText,
|
|
28
|
+
compactRole,
|
|
29
|
+
formatBlock,
|
|
30
|
+
compactTextForSummary,
|
|
31
|
+
mergeCommitHashes
|
|
32
|
+
} from "./server-kzns2hbz.js";
|
|
33
|
+
import {
|
|
34
|
+
sessionLog2
|
|
35
|
+
} from "./server-t4k4qexw.js";
|
|
36
|
+
import {
|
|
37
|
+
stableStringify
|
|
38
|
+
} from "./server-6byqfbqf.js";
|
|
39
|
+
import {
|
|
40
|
+
renderToolTemplate
|
|
41
|
+
} from "./server-mfkzp7qj.js";
|
|
42
|
+
import {
|
|
43
|
+
readRawSessionMessagesFromDb2,
|
|
44
|
+
readRawSessionMessagePageFromDb2,
|
|
45
|
+
readRawSessionMessageSummaryPageFromDb2,
|
|
46
|
+
countRawSessionMessageOrdinalsFromDb2,
|
|
47
|
+
readRawSessionMessageIdOrdinalsForRangeFromDb2,
|
|
48
|
+
readRawSessionMessageOrdinalPageFromDb2,
|
|
49
|
+
countStoredRawSessionMessagesFromDb2,
|
|
50
|
+
readRawSessionTailFromDb2,
|
|
51
|
+
readRawSessionMessagePartsByIdFromDb2,
|
|
52
|
+
readRawSessionMessageOrdinalByIdFromDb2,
|
|
53
|
+
readRawSessionMessageByIdFromDb2,
|
|
54
|
+
hasRawSessionMessageByIdFromDb2,
|
|
55
|
+
readRawSeedTailFromDb2,
|
|
56
|
+
readRawSessionBoundaryEndpointsFromDb2,
|
|
57
|
+
prewarmRawSessionOrdinalsForDb
|
|
58
|
+
} from "./server-7h861yms.js";
|
|
59
|
+
import {
|
|
60
|
+
openCodeDbExists,
|
|
61
|
+
withReadOnlySessionDb,
|
|
62
|
+
getRawSessionMessageCountFromDb,
|
|
63
|
+
getMessageTimesFromOpenCodeDb
|
|
64
|
+
} from "./server-pj4pjv02.js";
|
|
65
|
+
import {
|
|
66
|
+
getToolDefinitionMeasurementSignature,
|
|
67
|
+
getLargestMeasuredToolDefinitionTokens,
|
|
68
|
+
getMeasuredToolDefinitionTokens
|
|
69
|
+
} from "./server-7ekna9zs.js";
|
|
70
|
+
import {
|
|
71
|
+
canonicalModelIdentity
|
|
72
|
+
} from "./server-avwt563y.js";
|
|
73
|
+
|
|
74
|
+
// src/features/magic-context/overflow-detection.ts
|
|
75
|
+
var OVERFLOW_PATTERNS = [
|
|
76
|
+
/prompt is too long/i,
|
|
77
|
+
/input is too long for requested model/i,
|
|
78
|
+
/exceeds the context window/i,
|
|
79
|
+
/input token count.*exceeds the maximum/i,
|
|
80
|
+
/maximum prompt length is \d+/i,
|
|
81
|
+
/reduce the length of the messages/i,
|
|
82
|
+
/maximum context length is \d+ tokens/i,
|
|
83
|
+
/maximum model length is \d+/i,
|
|
84
|
+
/exceeds the limit of \d+/i,
|
|
85
|
+
/exceeds the available context size/i,
|
|
86
|
+
/greater than the context length/i,
|
|
87
|
+
/context window exceeds limit/i,
|
|
88
|
+
/exceeded model token limit/i,
|
|
89
|
+
/context[_ ]length[_ ]exceeded/i,
|
|
90
|
+
/request entity too large/i,
|
|
91
|
+
/context length is only \d+ tokens/i,
|
|
92
|
+
/input length.*exceeds.*context length/i,
|
|
93
|
+
/prompt too long; exceeded (?:max )?context length/i,
|
|
94
|
+
/too large for model with \d+ maximum context length/i,
|
|
95
|
+
/model_context_window_exceeded/i,
|
|
96
|
+
/context size has been exceeded/i,
|
|
97
|
+
/prepared prompt exceeds engine max_context/i,
|
|
98
|
+
/prompt exceeds (?:the )?.{0,32}\bmax_context\b/i
|
|
99
|
+
];
|
|
100
|
+
var LIMIT_EXTRACTION_PATTERNS = [
|
|
101
|
+
{ pattern: /maximum prompt length is (\d+)/i, provenance: "prompt_only" },
|
|
102
|
+
{
|
|
103
|
+
pattern: /maximum context length is (\d+) tokens?/i,
|
|
104
|
+
provenance: "combined"
|
|
105
|
+
},
|
|
106
|
+
{ pattern: /maximum model length is (\d+)/i, provenance: "combined" },
|
|
107
|
+
{ pattern: /context length is only (\d+) tokens?/i, provenance: "combined" },
|
|
108
|
+
{ pattern: /exceeds the limit of (\d+)/i, provenance: "unknown" },
|
|
109
|
+
{
|
|
110
|
+
pattern: /too large for model with (\d+) maximum context length/i,
|
|
111
|
+
provenance: "combined"
|
|
112
|
+
},
|
|
113
|
+
{ pattern: /context size[^0-9]{0,40}(\d{4,})\s*tokens?/i, provenance: "combined" },
|
|
114
|
+
{ pattern: /exceeds? the context length of (\d+)/i, provenance: "combined" },
|
|
115
|
+
{
|
|
116
|
+
pattern: />\s*(\d+)\s*(?:tokens?\s*)?(?:maximum|max|limit)\b/i,
|
|
117
|
+
provenance: "prompt_only"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
pattern: /maximum number of tokens allowed\s*\(?\s*(\d+)/i,
|
|
121
|
+
provenance: "prompt_only"
|
|
122
|
+
},
|
|
123
|
+
{ pattern: /prepared prompt exceeds engine max_context\s+(\d+)/i, provenance: "unknown" },
|
|
124
|
+
{ pattern: /prompt exceeds (?:the )?.{0,32}\bmax_context\s+(\d+)/i, provenance: "unknown" },
|
|
125
|
+
{ pattern: /max(?:imum)?.*context.*?(\d+)/i, provenance: "unknown" }
|
|
126
|
+
];
|
|
127
|
+
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
128
|
+
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
129
|
+
function extractErrorMessage(error) {
|
|
130
|
+
if (!error)
|
|
131
|
+
return "";
|
|
132
|
+
if (typeof error === "string")
|
|
133
|
+
return error;
|
|
134
|
+
if (typeof error === "object") {
|
|
135
|
+
const obj = error;
|
|
136
|
+
const nested = obj.error;
|
|
137
|
+
if (nested && typeof nested.message === "string" && nested.message.length > 0) {
|
|
138
|
+
return nested.message;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (error instanceof Error)
|
|
142
|
+
return error.message;
|
|
143
|
+
if (typeof error === "object") {
|
|
144
|
+
const obj = error;
|
|
145
|
+
if (typeof obj.message === "string")
|
|
146
|
+
return obj.message;
|
|
147
|
+
if (typeof obj.responseBody === "string")
|
|
148
|
+
return obj.responseBody;
|
|
149
|
+
try {
|
|
150
|
+
return JSON.stringify(error);
|
|
151
|
+
} catch {
|
|
152
|
+
return String(error);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return String(error);
|
|
156
|
+
}
|
|
157
|
+
function extractExplicitHttpStatus(error) {
|
|
158
|
+
if (!error || typeof error !== "object")
|
|
159
|
+
return;
|
|
160
|
+
const seen = new Set;
|
|
161
|
+
const queue = [error];
|
|
162
|
+
while (queue.length > 0) {
|
|
163
|
+
const current = queue.shift();
|
|
164
|
+
if (!current || seen.has(current))
|
|
165
|
+
continue;
|
|
166
|
+
seen.add(current);
|
|
167
|
+
const record = current;
|
|
168
|
+
for (const key of ["status", "statusCode", "status_code"]) {
|
|
169
|
+
const value = record[key];
|
|
170
|
+
if (typeof value === "number")
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
for (const value of Object.values(record)) {
|
|
174
|
+
if (value && typeof value === "object")
|
|
175
|
+
queue.push(value);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
function detectLatestTurnThinkingMismatch(error) {
|
|
181
|
+
const status = extractExplicitHttpStatus(error);
|
|
182
|
+
return (status === undefined || status === 400) && /(?:thinking|redacted_thinking)[\s\S]*latest assistant (?:message|turn)[\s\S]*cannot be modified/i.test(extractErrorMessage(error));
|
|
183
|
+
}
|
|
184
|
+
var PREFIX_BOUND_THINKING_MODELS = [
|
|
185
|
+
["fable", 5, 1],
|
|
186
|
+
["opus", 5, 5],
|
|
187
|
+
["sonnet", 5, 5],
|
|
188
|
+
["haiku", 5, 5]
|
|
189
|
+
];
|
|
190
|
+
var PREFIX_BOUND_THINKING_PATTERN = new RegExp(`(?:^|[-_.:/])(?:${PREFIX_BOUND_THINKING_MODELS.map(([family, major, minor]) => `${family}[-_.]?${major}[-_.]${minor}`).join("|")})(?:$|[-_.:/@])`, "i");
|
|
191
|
+
function isPrefixBoundThinkingModel(_providerID, modelID) {
|
|
192
|
+
if (!modelID)
|
|
193
|
+
return false;
|
|
194
|
+
return PREFIX_BOUND_THINKING_PATTERN.test(modelID);
|
|
195
|
+
}
|
|
196
|
+
function isFable51ThinkingBindingModel(providerID, modelID) {
|
|
197
|
+
if (providerID?.toLowerCase() !== "anthropic" || !modelID)
|
|
198
|
+
return false;
|
|
199
|
+
return /(?:^|[-_.])fable[-_.]?5[-_.]1(?:$|[-_.])/i.test(modelID);
|
|
200
|
+
}
|
|
201
|
+
function detectOverflow(error) {
|
|
202
|
+
const message = extractErrorMessage(error);
|
|
203
|
+
if (!message) {
|
|
204
|
+
return { isOverflow: false };
|
|
205
|
+
}
|
|
206
|
+
const hasStatus413 = /\b413\b/.test(message) && /(entity|payload|context|prompt)/i.test(message);
|
|
207
|
+
let matched;
|
|
208
|
+
for (const pattern of OVERFLOW_PATTERNS) {
|
|
209
|
+
if (pattern.test(message)) {
|
|
210
|
+
matched = pattern;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (!matched && !hasStatus413) {
|
|
215
|
+
return { isOverflow: false };
|
|
216
|
+
}
|
|
217
|
+
const reportedLimit = parseReportedLimit(message);
|
|
218
|
+
const reportedInputTokens = parseReportedInputTokens(message);
|
|
219
|
+
return {
|
|
220
|
+
isOverflow: true,
|
|
221
|
+
reportedInputTokens,
|
|
222
|
+
reportedLimit: reportedLimit?.value,
|
|
223
|
+
reportedLimitProvenance: reportedLimit?.provenance,
|
|
224
|
+
matchedPattern: matched?.source
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function parseReportedInputTokens(message) {
|
|
228
|
+
if (!message)
|
|
229
|
+
return;
|
|
230
|
+
const patterns = [
|
|
231
|
+
/prompt is too long:\s*(\d+)/i,
|
|
232
|
+
/input token count\s*\(?\s*(\d+)/i,
|
|
233
|
+
/input length\s*(\d+)/i,
|
|
234
|
+
/prompt was\s*(\d+)/i,
|
|
235
|
+
/messages resulted in\s*(\d+)\s*tokens?/i
|
|
236
|
+
];
|
|
237
|
+
for (const pattern of patterns) {
|
|
238
|
+
const raw = message.match(pattern)?.[1];
|
|
239
|
+
if (!raw)
|
|
240
|
+
continue;
|
|
241
|
+
const value = Number.parseInt(raw, 10);
|
|
242
|
+
if (Number.isFinite(value) && value > 0)
|
|
243
|
+
return value;
|
|
244
|
+
}
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
function parseReportedLimit(message) {
|
|
248
|
+
if (!message)
|
|
249
|
+
return;
|
|
250
|
+
for (const { pattern, provenance } of LIMIT_EXTRACTION_PATTERNS) {
|
|
251
|
+
const match = message.match(pattern);
|
|
252
|
+
if (!match)
|
|
253
|
+
continue;
|
|
254
|
+
const raw = match[1];
|
|
255
|
+
if (!raw)
|
|
256
|
+
continue;
|
|
257
|
+
const value = Number.parseInt(raw, 10);
|
|
258
|
+
if (!Number.isFinite(value))
|
|
259
|
+
continue;
|
|
260
|
+
if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
|
|
261
|
+
continue;
|
|
262
|
+
return { value, provenance };
|
|
263
|
+
}
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
// src/shared/historian-tool-defaults.json
|
|
267
|
+
var historian_tool_defaults_default = {
|
|
268
|
+
ctx_note: "Note ${input.action} ${input.note_ids}: ${input.content} → ${output.truncate(160)}",
|
|
269
|
+
ctx_memory: "Memory ${input.action} ${input.category} ${input.ids}: ${input.content} → ${output.truncate(160)}",
|
|
270
|
+
todowrite: 'Todos (${input.todos.count}): ${input.todos.each("${status}: ${content}")}',
|
|
271
|
+
question: 'Asked user: ${input.questions[*].question.join(" / ")} → ${output}',
|
|
272
|
+
task: "Task ${input.subagent_type}: ${input.prompt.truncate(600)} → ${output.truncate(200)}",
|
|
273
|
+
ask: 'Asked: ${input.question} [options: ${input.options.join(" / ")}] ${input.text}${input.resolution} → ${output.truncate(300)}',
|
|
274
|
+
peer_send: "PM ${input.recipient}: ${input.message}",
|
|
275
|
+
board: 'Board ${input.verb}${input.board_lane}: ${input.ops.each("${op} ${lane_label} ${item}${props.text}${lane.items} ${state}${props.state}${lane.status}${id}${title}")}',
|
|
276
|
+
room: "Room ${input.action} ${input.room_label}: ${input.room_detail}",
|
|
277
|
+
work: "Work ${input.action} ${input.title}${input.id}: ${input.prompt.truncate(600)}${input.notes.truncate(600)} → ${output.truncate(160)}",
|
|
278
|
+
knowhow: "Looked up how-to: ${input.query}${input.id}"
|
|
279
|
+
};
|
|
280
|
+
// src/shared/historian-tool-preview-defaults.json
|
|
281
|
+
var historian_tool_preview_defaults_default = {
|
|
282
|
+
ctx_note: "Note ${input.action} ${input.note_ids}: ${input.content} → ${output.truncate(160)}",
|
|
283
|
+
ctx_memory: "Memory ${input.action} ${input.category} ${input.ids}: ${input.content} → ${output.truncate(160)}",
|
|
284
|
+
todowrite: 'Todos (${input.todos.count}): ${input.todos.each("${status}: ${content}")}',
|
|
285
|
+
question: 'Asked user: ${input.questions[*].question.join(" / ")} → ${output}',
|
|
286
|
+
task: "Task ${input.subagent_type}: ${input.prompt} → ${output.truncate(200)}",
|
|
287
|
+
ask: 'Asked: ${input.question.truncate(250)} [options: ${input.options.join(" / ")}] ${input.resolution} → ${output.truncate(300)}',
|
|
288
|
+
peer_send: "PM to ${input.agent}${input.agent_id}: ${input.message.truncate(400)}",
|
|
289
|
+
board: 'Board ${input.verb}: ${input.ops.each("${op} ${item}${lane.title} ${state}${lane.status}${props.text} ${lane.items[*].text}")}',
|
|
290
|
+
room: "Room ${input.action} ${input.room_id}: ${input.text.truncate(400)}",
|
|
291
|
+
work: "Work ${input.action} ${input.id}: ${input.prompt_file}${input.prompt.truncate(200)}${input.notes.truncate(200)} → ${output.truncate(160)}",
|
|
292
|
+
knowhow: "Looked up how-to: ${input.query}${input.id}"
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// src/shared/historian-tool-expansions.ts
|
|
296
|
+
function builtinInput(tool, input) {
|
|
297
|
+
if (!input || typeof input !== "object")
|
|
298
|
+
return input;
|
|
299
|
+
const i = input;
|
|
300
|
+
if (tool === "peer_send") {
|
|
301
|
+
const external = i.external;
|
|
302
|
+
const recipient = i.reply_to_pmid ? `reply to ${i.reply_to_pmid}` : i.agent || i.agent_id ? `to ${i.agent || i.agent_id}` : external?.session_id || i.session_id ? `to session ${external?.session_id || i.session_id}` : "to unknown recipient";
|
|
303
|
+
return { ...i, recipient };
|
|
304
|
+
}
|
|
305
|
+
if (tool === "room") {
|
|
306
|
+
return {
|
|
307
|
+
...i,
|
|
308
|
+
room_label: i.room_id || i.title,
|
|
309
|
+
room_detail: i.action === "create" || i.action === "invite" ? `invitees: ${renderToolTemplate("${input.invitees}", i)}` : i.text
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
if (tool === "board") {
|
|
313
|
+
return {
|
|
314
|
+
...i,
|
|
315
|
+
board_lane: i.lane ? ` ${i.lane}` : "",
|
|
316
|
+
ops: Array.isArray(i.ops) ? i.ops.map((op) => op && typeof op === "object" ? {
|
|
317
|
+
...op,
|
|
318
|
+
lane_label: typeof op.lane === "string" ? op.lane : op.lane?.title || op.lane?.id
|
|
319
|
+
} : op) : i.ops
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return input;
|
|
323
|
+
}
|
|
324
|
+
function expandToolPart(part, overrides, legacyPreview = false) {
|
|
325
|
+
if (!part || typeof part !== "object")
|
|
326
|
+
return null;
|
|
327
|
+
const p = part;
|
|
328
|
+
if (p.type !== "tool" || typeof p.tool !== "string")
|
|
329
|
+
return null;
|
|
330
|
+
const builtinDefaults = legacyPreview ? historian_tool_preview_defaults_default : historian_tool_defaults_default;
|
|
331
|
+
const overridden = overrides && Object.hasOwn(overrides, p.tool);
|
|
332
|
+
const template = overridden ? overrides[p.tool] : Object.hasOwn(builtinDefaults, p.tool) ? builtinDefaults[p.tool] : undefined;
|
|
333
|
+
if (typeof template !== "string")
|
|
334
|
+
return null;
|
|
335
|
+
const state = p.state;
|
|
336
|
+
const input = overridden || legacyPreview ? state?.input : builtinInput(p.tool, state?.input);
|
|
337
|
+
return renderToolTemplate(template, input, state?.output ?? state?.error, legacyPreview);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// src/hooks/magic-context/host-served-rows.ts
|
|
341
|
+
var HOST_UNSERVED_ROW = "hostUnservedRow";
|
|
342
|
+
function markHostUnservedRow(target) {
|
|
343
|
+
Object.defineProperty(target, HOST_UNSERVED_ROW, {
|
|
344
|
+
value: true,
|
|
345
|
+
enumerable: false,
|
|
346
|
+
configurable: true
|
|
347
|
+
});
|
|
348
|
+
return target;
|
|
349
|
+
}
|
|
350
|
+
function isHostUnservedRow(value) {
|
|
351
|
+
return typeof value === "object" && value !== null && value[HOST_UNSERVED_ROW] === true;
|
|
352
|
+
}
|
|
353
|
+
function retreatPastHostUnservedRows(messages, exclusiveEnd, floor) {
|
|
354
|
+
if (!messages.some(isHostUnservedRow))
|
|
355
|
+
return exclusiveEnd;
|
|
356
|
+
const byOrdinal = new Map(messages.map((message) => [message.ordinal, message]));
|
|
357
|
+
let end = exclusiveEnd;
|
|
358
|
+
while (end - 1 >= floor && isHostUnservedRow(byOrdinal.get(end - 1)))
|
|
359
|
+
end -= 1;
|
|
360
|
+
return end;
|
|
361
|
+
}
|
|
362
|
+
function snapTerminalCompartmentToServedRow(compartments, lines) {
|
|
363
|
+
if (!lines.some(isHostUnservedRow))
|
|
364
|
+
return { compartments: [...compartments], snapped: false };
|
|
365
|
+
const byOrdinal = new Map(lines.map((line) => [line.ordinal, line]));
|
|
366
|
+
const result = [...compartments];
|
|
367
|
+
let snapped = false;
|
|
368
|
+
while (result.length > 0) {
|
|
369
|
+
const last = result[result.length - 1];
|
|
370
|
+
if (!isHostUnservedRow(byOrdinal.get(last.endMessage)))
|
|
371
|
+
break;
|
|
372
|
+
snapped = true;
|
|
373
|
+
let served;
|
|
374
|
+
for (let ordinal = last.endMessage - 1;ordinal >= last.startMessage; ordinal -= 1) {
|
|
375
|
+
const line = byOrdinal.get(ordinal);
|
|
376
|
+
if (line && !isHostUnservedRow(line)) {
|
|
377
|
+
served = line;
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
if (!served) {
|
|
382
|
+
result.pop();
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
result[result.length - 1] = {
|
|
386
|
+
...last,
|
|
387
|
+
endMessage: served.ordinal,
|
|
388
|
+
endMessageId: served.messageId
|
|
389
|
+
};
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
return { compartments: result, snapped };
|
|
393
|
+
}
|
|
394
|
+
function isHostRenderedSystemMessage(message) {
|
|
395
|
+
const id = message.info.id;
|
|
396
|
+
return (typeof id !== "string" || id.length === 0) && message.info.role === "system";
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// src/hooks/magic-context/read-session-true-raw-tokens.ts
|
|
400
|
+
function completedToolArcCrossesBoundary(invOrdinal, resOrdinal, boundary) {
|
|
401
|
+
return invOrdinal < boundary && boundary <= resOrdinal;
|
|
402
|
+
}
|
|
403
|
+
var MAX_MESSAGE_CACHE_ENTRIES = 1e5;
|
|
404
|
+
var MAX_MESSAGE_CACHE_KEY_BYTES = 64 * 1024 * 1024;
|
|
405
|
+
var FNV1A_32_OFFSET = 2166136261;
|
|
406
|
+
var FNV1A_32_PRIME = 16777619;
|
|
407
|
+
var messageEstimateCache = new Map;
|
|
408
|
+
var messageEstimateKeysByField = new Map;
|
|
409
|
+
var messageEstimateCacheBytes = 0;
|
|
410
|
+
var EMPTY_BREAKDOWN = {
|
|
411
|
+
text: 0,
|
|
412
|
+
reasoning: 0,
|
|
413
|
+
toolInput: 0,
|
|
414
|
+
toolOutput: 0,
|
|
415
|
+
image: 0,
|
|
416
|
+
other: 0,
|
|
417
|
+
total: 0
|
|
418
|
+
};
|
|
419
|
+
function addBreakdown(target, kind, value) {
|
|
420
|
+
if (kind === "total")
|
|
421
|
+
return;
|
|
422
|
+
const safeValue = Number.isFinite(value) && value > 0 ? Math.round(value) : 0;
|
|
423
|
+
target[kind] += safeValue;
|
|
424
|
+
target.total += safeValue;
|
|
425
|
+
}
|
|
426
|
+
function estimateStructured(value) {
|
|
427
|
+
if (typeof value === "string")
|
|
428
|
+
return estimateTokens(value);
|
|
429
|
+
if (value === undefined || value === null)
|
|
430
|
+
return 0;
|
|
431
|
+
return estimateTokens(stableStringify(value));
|
|
432
|
+
}
|
|
433
|
+
function firstStringField(record, fields) {
|
|
434
|
+
for (const field of fields) {
|
|
435
|
+
const value = record[field];
|
|
436
|
+
if (typeof value === "string" && value.length > 0)
|
|
437
|
+
return value;
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
function stringValue(value) {
|
|
442
|
+
if (typeof value === "string")
|
|
443
|
+
return value;
|
|
444
|
+
if (value === undefined || value === null)
|
|
445
|
+
return "";
|
|
446
|
+
return stableStringify(value);
|
|
447
|
+
}
|
|
448
|
+
function textFromToolResultContent(content) {
|
|
449
|
+
if (typeof content === "string")
|
|
450
|
+
return content;
|
|
451
|
+
if (Array.isArray(content)) {
|
|
452
|
+
const pieces = [];
|
|
453
|
+
for (const entry of content) {
|
|
454
|
+
if (typeof entry === "string") {
|
|
455
|
+
pieces.push(entry);
|
|
456
|
+
} else if (isRecord(entry)) {
|
|
457
|
+
const text = firstStringField(entry, ["text", "content", "value"]);
|
|
458
|
+
pieces.push(text ?? stableStringify(entry));
|
|
459
|
+
} else if (entry !== null && entry !== undefined) {
|
|
460
|
+
pieces.push(String(entry));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return pieces.join(`
|
|
464
|
+
`);
|
|
465
|
+
}
|
|
466
|
+
return stringValue(content);
|
|
467
|
+
}
|
|
468
|
+
function looksImageLike(part) {
|
|
469
|
+
const type = typeof part.type === "string" ? part.type.toLowerCase() : "";
|
|
470
|
+
const mime = typeof part.mime === "string" ? part.mime.toLowerCase() : "";
|
|
471
|
+
const mediaType = typeof part.mediaType === "string" ? part.mediaType.toLowerCase() : "";
|
|
472
|
+
return type.includes("image") || mime.startsWith("image/") || mediaType.startsWith("image/") || part.image_url !== undefined || part.imageUrl !== undefined || part.image !== undefined;
|
|
473
|
+
}
|
|
474
|
+
function defaultImageTokenHeuristic(part) {
|
|
475
|
+
if (isRecord(part)) {
|
|
476
|
+
const width = part.width;
|
|
477
|
+
const height = part.height;
|
|
478
|
+
if (typeof width === "number" && typeof height === "number" && width > 0 && height > 0) {
|
|
479
|
+
return Math.max(256, Math.min(4096, Math.ceil(width * height / 750)));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return 1024;
|
|
483
|
+
}
|
|
484
|
+
function partType(part) {
|
|
485
|
+
return typeof part.type === "string" ? part.type : "";
|
|
486
|
+
}
|
|
487
|
+
function hasOwn(record, key) {
|
|
488
|
+
return Object.hasOwn(record, key);
|
|
489
|
+
}
|
|
490
|
+
function recursiveByteLength(value) {
|
|
491
|
+
if (value === null || value === undefined)
|
|
492
|
+
return 0;
|
|
493
|
+
if (typeof value === "string")
|
|
494
|
+
return value.length;
|
|
495
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
496
|
+
return String(value).length;
|
|
497
|
+
}
|
|
498
|
+
if (Array.isArray(value)) {
|
|
499
|
+
return value.reduce((sum, item) => sum + recursiveByteLength(item), value.length);
|
|
500
|
+
}
|
|
501
|
+
if (isRecord(value)) {
|
|
502
|
+
let total = Object.keys(value).length;
|
|
503
|
+
for (const [key, child] of Object.entries(value)) {
|
|
504
|
+
total += key.length + recursiveByteLength(child);
|
|
505
|
+
}
|
|
506
|
+
return total;
|
|
507
|
+
}
|
|
508
|
+
return String(value).length;
|
|
509
|
+
}
|
|
510
|
+
function updateFnv1a32(hash, text) {
|
|
511
|
+
let next = hash;
|
|
512
|
+
for (let index = 0;index < text.length; index += 1) {
|
|
513
|
+
next ^= text.charCodeAt(index);
|
|
514
|
+
next = Math.imul(next, FNV1A_32_PRIME) >>> 0;
|
|
515
|
+
}
|
|
516
|
+
return next;
|
|
517
|
+
}
|
|
518
|
+
function contentStringsHash(fields) {
|
|
519
|
+
let hash = FNV1A_32_OFFSET;
|
|
520
|
+
for (const field of fields) {
|
|
521
|
+
hash = updateFnv1a32(hash, `${field.length}:`);
|
|
522
|
+
hash = updateFnv1a32(hash, field);
|
|
523
|
+
hash = updateFnv1a32(hash, "\x00");
|
|
524
|
+
}
|
|
525
|
+
return hash.toString(16).padStart(8, "0");
|
|
526
|
+
}
|
|
527
|
+
function rawPartVersion(part) {
|
|
528
|
+
return part.__magicContextPartUpdatedAt ?? part.updated_at ?? part.updatedAt ?? part.version ?? part.revision ?? "";
|
|
529
|
+
}
|
|
530
|
+
function callIdFromPart(part) {
|
|
531
|
+
const direct = firstStringField(part, ["callID", "callId", "toolCallId", "tool_call_id", "id"]);
|
|
532
|
+
if (direct)
|
|
533
|
+
return direct;
|
|
534
|
+
const state = isRecord(part.state) ? part.state : null;
|
|
535
|
+
return state ? firstStringField(state, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
|
|
536
|
+
}
|
|
537
|
+
function toolSignalFromPart(part, withText = true) {
|
|
538
|
+
if (!isRecord(part))
|
|
539
|
+
return null;
|
|
540
|
+
const type = partType(part);
|
|
541
|
+
const state = isRecord(part.state) ? part.state : null;
|
|
542
|
+
const callId = callIdFromPart(part);
|
|
543
|
+
if (!callId && type !== "tool")
|
|
544
|
+
return null;
|
|
545
|
+
if (type === "tool") {
|
|
546
|
+
const hasInput = state !== null && hasOwn(state, "input");
|
|
547
|
+
const outputKey = state ? hasOwn(state, "output") ? "output" : hasOwn(state, "error") ? "error" : hasOwn(state, "result") ? "result" : null : null;
|
|
548
|
+
const hasOutput = outputKey !== null;
|
|
549
|
+
const outputValue = outputKey && state ? state[outputKey] : undefined;
|
|
550
|
+
const providerExecuted = part.providerExecuted === true;
|
|
551
|
+
const openInvocation = !providerExecuted && !hasOutput;
|
|
552
|
+
return {
|
|
553
|
+
callId,
|
|
554
|
+
hasInput: hasInput || openInvocation,
|
|
555
|
+
hasOutput,
|
|
556
|
+
inputText: withText && hasInput && state ? stringValue(state.input) : "",
|
|
557
|
+
outputText: withText && hasOutput ? stringValue(outputValue) : ""
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
if (type === "tool-invocation") {
|
|
561
|
+
const args = part.args ?? part.input;
|
|
562
|
+
return {
|
|
563
|
+
callId,
|
|
564
|
+
hasInput: args !== undefined,
|
|
565
|
+
hasOutput: false,
|
|
566
|
+
inputText: withText && args !== undefined ? stringValue(args) : "",
|
|
567
|
+
outputText: ""
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
if (type === "tool_use") {
|
|
571
|
+
const input = part.input;
|
|
572
|
+
return {
|
|
573
|
+
callId,
|
|
574
|
+
hasInput: input !== undefined,
|
|
575
|
+
hasOutput: false,
|
|
576
|
+
inputText: withText && input !== undefined ? stringValue(input) : "",
|
|
577
|
+
outputText: ""
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
if (type === "tool_result") {
|
|
581
|
+
const content = part.content ?? part.output ?? part.result;
|
|
582
|
+
return {
|
|
583
|
+
callId,
|
|
584
|
+
hasInput: false,
|
|
585
|
+
hasOutput: content !== undefined,
|
|
586
|
+
inputText: "",
|
|
587
|
+
outputText: withText && content !== undefined ? textFromToolResultContent(content) : ""
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
function partCheapFingerprint(part) {
|
|
593
|
+
if (!isRecord(part))
|
|
594
|
+
return `${typeof part}:${recursiveByteLength(part)}`;
|
|
595
|
+
const version = rawPartVersion(part);
|
|
596
|
+
const type = typeof part.type === "string" ? part.type : "";
|
|
597
|
+
return `${type}:${String(version)}:${recursiveByteLength(providerVisiblePart(part))}`;
|
|
598
|
+
}
|
|
599
|
+
function messageCacheKey(message, options) {
|
|
600
|
+
const namespace = "cacheNamespace" in options ? options.cacheNamespace : "estimate";
|
|
601
|
+
const cheapFingerprint = message.parts.map(partCheapFingerprint).join("|");
|
|
602
|
+
return [
|
|
603
|
+
namespace,
|
|
604
|
+
options.providerShapeVersion,
|
|
605
|
+
message.id || `ordinal:${message.ordinal}`,
|
|
606
|
+
message.role,
|
|
607
|
+
message.parts.length,
|
|
608
|
+
cheapFingerprint
|
|
609
|
+
].join("\x00");
|
|
610
|
+
}
|
|
611
|
+
function setCachedEstimate(key, breakdown) {
|
|
612
|
+
const keyEstimateBytes = key.length * 2 + 64;
|
|
613
|
+
const existing = messageEstimateCache.get(key);
|
|
614
|
+
if (existing)
|
|
615
|
+
messageEstimateCacheBytes -= existing.keyEstimateBytes;
|
|
616
|
+
else {
|
|
617
|
+
for (const field of new Set(key.split("\x00").slice(1, -1))) {
|
|
618
|
+
const keys = messageEstimateKeysByField.get(field) ?? new Set;
|
|
619
|
+
keys.add(key);
|
|
620
|
+
messageEstimateKeysByField.set(field, keys);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
messageEstimateCache.set(key, { breakdown, keyEstimateBytes });
|
|
624
|
+
messageEstimateCacheBytes += keyEstimateBytes;
|
|
625
|
+
while (messageEstimateCache.size > MAX_MESSAGE_CACHE_ENTRIES || messageEstimateCacheBytes > MAX_MESSAGE_CACHE_KEY_BYTES) {
|
|
626
|
+
const first = messageEstimateCache.keys().next().value;
|
|
627
|
+
if (typeof first !== "string")
|
|
628
|
+
break;
|
|
629
|
+
deleteCachedEstimate(first);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
function deleteCachedEstimate(key) {
|
|
633
|
+
const removed = messageEstimateCache.get(key);
|
|
634
|
+
if (!removed)
|
|
635
|
+
return;
|
|
636
|
+
messageEstimateCacheBytes -= removed.keyEstimateBytes;
|
|
637
|
+
messageEstimateCache.delete(key);
|
|
638
|
+
for (const field of new Set(key.split("\x00").slice(1, -1))) {
|
|
639
|
+
const keys = messageEstimateKeysByField.get(field);
|
|
640
|
+
keys?.delete(key);
|
|
641
|
+
if (keys?.size === 0)
|
|
642
|
+
messageEstimateKeysByField.delete(field);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function cloneBreakdown(value) {
|
|
646
|
+
return { ...value };
|
|
647
|
+
}
|
|
648
|
+
function estimateNonToolPart(part, options, breakdown) {
|
|
649
|
+
if (!isRecord(part)) {
|
|
650
|
+
if (part !== null && part !== undefined)
|
|
651
|
+
addBreakdown(breakdown, "other", estimateStructured(part));
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
const type = partType(part);
|
|
655
|
+
if (type === "step-start" || type === "step-finish" || type === "meta" && Object.keys(part).length <= 1) {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
if (type === "text") {
|
|
659
|
+
const text = firstStringField(part, ["text", "content"]);
|
|
660
|
+
if (text)
|
|
661
|
+
addBreakdown(breakdown, "text", estimateTokens(text));
|
|
662
|
+
return true;
|
|
663
|
+
}
|
|
664
|
+
if (type === "reasoning" || type === "thinking" || type === "redacted_thinking") {
|
|
665
|
+
const text = firstStringField(part, ["thinking", "text", "content", "reasoning"]);
|
|
666
|
+
if (text) {
|
|
667
|
+
addBreakdown(breakdown, "reasoning", estimateTokens(text));
|
|
668
|
+
} else {
|
|
669
|
+
addBreakdown(breakdown, "other", estimateStructured(part));
|
|
670
|
+
}
|
|
671
|
+
return true;
|
|
672
|
+
}
|
|
673
|
+
const reasoningText = firstStringField(part, ["thinking", "reasoning"]);
|
|
674
|
+
if (reasoningText && type.length === 0) {
|
|
675
|
+
addBreakdown(breakdown, "reasoning", estimateTokens(reasoningText));
|
|
676
|
+
return true;
|
|
677
|
+
}
|
|
678
|
+
if (looksImageLike(part)) {
|
|
679
|
+
addBreakdown(breakdown, "image", options.imageTokenHeuristic?.(part) ?? defaultImageTokenHeuristic(part));
|
|
680
|
+
const altText = firstStringField(part, ["alt", "text", "description"]);
|
|
681
|
+
if (altText)
|
|
682
|
+
addBreakdown(breakdown, "text", estimateTokens(altText));
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
if (type.includes("file") || type === "source") {
|
|
686
|
+
const content = firstStringField(part, ["content", "text", "source"]);
|
|
687
|
+
if (content)
|
|
688
|
+
addBreakdown(breakdown, "text", estimateTokens(content));
|
|
689
|
+
else
|
|
690
|
+
addBreakdown(breakdown, "other", estimateStructured(part));
|
|
691
|
+
return true;
|
|
692
|
+
}
|
|
693
|
+
return false;
|
|
694
|
+
}
|
|
695
|
+
function estimateTrueRawMessageTokens(message, options) {
|
|
696
|
+
const breakdown = cloneBreakdown(EMPTY_BREAKDOWN);
|
|
697
|
+
const countedInput = new Set;
|
|
698
|
+
const countedOutput = new Set;
|
|
699
|
+
let ordinalToolIndex = 0;
|
|
700
|
+
for (const part of message.parts) {
|
|
701
|
+
const signal = toolSignalFromPart(part);
|
|
702
|
+
if (signal) {
|
|
703
|
+
const localKey = `${signal.callId || "tool"}:${message.ordinal}:${ordinalToolIndex}`;
|
|
704
|
+
ordinalToolIndex += 1;
|
|
705
|
+
if (signal.hasInput) {
|
|
706
|
+
const key = `${signal.callId}:input:${message.ordinal}`;
|
|
707
|
+
if (!countedInput.has(key)) {
|
|
708
|
+
countedInput.add(key);
|
|
709
|
+
addBreakdown(breakdown, "toolInput", estimateTokens(signal.inputText));
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if (signal.hasOutput) {
|
|
713
|
+
const key = `${signal.callId}:output:${message.ordinal}:${localKey}`;
|
|
714
|
+
if (!countedOutput.has(key)) {
|
|
715
|
+
countedOutput.add(key);
|
|
716
|
+
addBreakdown(breakdown, "toolOutput", estimateTokens(signal.outputText));
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
if (!estimateNonToolPart(part, options, breakdown)) {
|
|
722
|
+
addBreakdown(breakdown, "other", estimateStructured(part));
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return breakdown;
|
|
726
|
+
}
|
|
727
|
+
function buildToolArcs(messages) {
|
|
728
|
+
const openQueues = new Map;
|
|
729
|
+
const arcs = [];
|
|
730
|
+
for (const message of messages) {
|
|
731
|
+
for (const part of message.parts) {
|
|
732
|
+
const signal = toolSignalFromPart(part, false);
|
|
733
|
+
if (!signal || signal.callId.length === 0)
|
|
734
|
+
continue;
|
|
735
|
+
if (signal.hasInput && signal.hasOutput) {
|
|
736
|
+
arcs.push({
|
|
737
|
+
callId: signal.callId,
|
|
738
|
+
invOrdinal: message.ordinal,
|
|
739
|
+
resOrdinal: message.ordinal
|
|
740
|
+
});
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
if (signal.hasInput) {
|
|
744
|
+
const queue = openQueues.get(signal.callId) ?? [];
|
|
745
|
+
queue.push(message.ordinal);
|
|
746
|
+
openQueues.set(signal.callId, queue);
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
if (signal.hasOutput) {
|
|
750
|
+
const queue = openQueues.get(signal.callId) ?? [];
|
|
751
|
+
const invOrdinal = queue.shift();
|
|
752
|
+
if (queue.length === 0)
|
|
753
|
+
openQueues.delete(signal.callId);
|
|
754
|
+
else
|
|
755
|
+
openQueues.set(signal.callId, queue);
|
|
756
|
+
if (invOrdinal !== undefined) {
|
|
757
|
+
arcs.push({ callId: signal.callId, invOrdinal, resOrdinal: message.ordinal });
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
for (const [callId, queue] of openQueues) {
|
|
763
|
+
for (const invOrdinal of queue) {
|
|
764
|
+
arcs.push({ callId, invOrdinal, resOrdinal: null });
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return arcs.sort((a, b) => a.invOrdinal - b.invOrdinal || (a.resOrdinal ?? Number.MAX_SAFE_INTEGER) - (b.resOrdinal ?? Number.MAX_SAFE_INTEGER));
|
|
768
|
+
}
|
|
769
|
+
function fenceBoundaryForCompletedToolArcs(candidate, arcs, publicationFloorOrdinal, observeComponent) {
|
|
770
|
+
const completed = arcs.filter((arc) => arc.resOrdinal !== null).map((arc) => ({ invocation: arc.invOrdinal, result: arc.resOrdinal }));
|
|
771
|
+
const component = completed.filter((arc) => completedToolArcCrossesBoundary(arc.invocation, arc.result, candidate));
|
|
772
|
+
if (component.length === 0)
|
|
773
|
+
return candidate;
|
|
774
|
+
for (let pass = 0;pass <= completed.length; pass += 1) {
|
|
775
|
+
const minInvocation = Math.min(...component.map((arc) => arc.invocation));
|
|
776
|
+
const maxResult = Math.max(...component.map((arc) => arc.result));
|
|
777
|
+
const before = component.length;
|
|
778
|
+
for (const arc of completed) {
|
|
779
|
+
if (arc.invocation <= maxResult && arc.result >= minInvocation && !component.includes(arc)) {
|
|
780
|
+
component.push(arc);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (component.length === before)
|
|
784
|
+
break;
|
|
785
|
+
}
|
|
786
|
+
const minInvocation = Math.min(...component.map((arc) => arc.invocation));
|
|
787
|
+
const maxResult = Math.max(...component.map((arc) => arc.result));
|
|
788
|
+
observeComponent?.(component);
|
|
789
|
+
return minInvocation < publicationFloorOrdinal ? maxResult + 1 : minInvocation;
|
|
790
|
+
}
|
|
791
|
+
function fenceBoundaryForToolArcs(candidate, arcs, lastCompartmentEndOrdinal, recentOpenArcCutoff) {
|
|
792
|
+
let boundary = fenceBoundaryForCompletedToolArcs(candidate, arcs, lastCompartmentEndOrdinal + 1);
|
|
793
|
+
for (const arc of arcs) {
|
|
794
|
+
if (arc.resOrdinal !== null)
|
|
795
|
+
continue;
|
|
796
|
+
if (arc.invOrdinal < recentOpenArcCutoff)
|
|
797
|
+
continue;
|
|
798
|
+
if (arc.invOrdinal >= lastCompartmentEndOrdinal + 1 && arc.invOrdinal < boundary) {
|
|
799
|
+
boundary = arc.invOrdinal;
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
if (arc.invOrdinal >= boundary) {
|
|
803
|
+
boundary = arc.invOrdinal;
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
return fenceBoundaryForCompletedToolArcs(boundary, arcs, 1);
|
|
808
|
+
}
|
|
809
|
+
function tokenForMessage(message, options) {
|
|
810
|
+
const key = messageCacheKey(message, options);
|
|
811
|
+
const cached = messageEstimateCache.get(key);
|
|
812
|
+
if (cached)
|
|
813
|
+
return cloneBreakdown(cached.breakdown);
|
|
814
|
+
const breakdown = estimateTrueRawMessageTokens(message, options);
|
|
815
|
+
setCachedEstimate(key, breakdown);
|
|
816
|
+
return cloneBreakdown(breakdown);
|
|
817
|
+
}
|
|
818
|
+
function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
819
|
+
const ordered = [...messages].sort((a, b) => a.ordinal - b.ordinal);
|
|
820
|
+
const sliceCount = ordered.length;
|
|
821
|
+
const firstOrdinal = ordered.length > 0 ? ordered[0].ordinal : 1;
|
|
822
|
+
const terminalOrdinal = ordered.length > 0 ? ordered[ordered.length - 1].ordinal : 0;
|
|
823
|
+
const rawMessageCount = Math.max(sliceCount, terminalOrdinal, options.absoluteMessageCount ?? sliceCount);
|
|
824
|
+
const ordinalSpan = terminalOrdinal >= firstOrdinal ? terminalOrdinal - firstOrdinal + 1 : 0;
|
|
825
|
+
const tokensByOrdinal = new Map;
|
|
826
|
+
const idsByOrdinal = new Map;
|
|
827
|
+
const prefix = new Array(ordinalSpan + 1).fill(0);
|
|
828
|
+
for (const message of ordered) {
|
|
829
|
+
const stored = options.storedTotalForMessage?.(message);
|
|
830
|
+
let total;
|
|
831
|
+
if (stored !== undefined && stored !== null) {
|
|
832
|
+
total = stored;
|
|
833
|
+
} else {
|
|
834
|
+
const raw = tokenForMessage(message, options);
|
|
835
|
+
const seed = options.calibration;
|
|
836
|
+
total = seed ? (raw.toolInput + raw.toolOutput) * seed.toolsRatio + (raw.text + raw.reasoning + raw.other) * seed.proseRatio + raw.image : raw.total;
|
|
837
|
+
}
|
|
838
|
+
tokensByOrdinal.set(message.ordinal, total);
|
|
839
|
+
idsByOrdinal.set(message.ordinal, message.id);
|
|
840
|
+
const relative = message.ordinal - firstOrdinal + 1;
|
|
841
|
+
if (relative >= 1 && relative <= ordinalSpan) {
|
|
842
|
+
prefix[relative] = total;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
for (let k = 1;k <= ordinalSpan; k += 1) {
|
|
846
|
+
prefix[k] += prefix[k - 1];
|
|
847
|
+
}
|
|
848
|
+
const ordinalToIndex = (ordinal) => Math.max(0, Math.min(ordinalSpan, ordinal - firstOrdinal));
|
|
849
|
+
return {
|
|
850
|
+
sessionId,
|
|
851
|
+
providerShapeVersion: options.providerShapeVersion,
|
|
852
|
+
rawMessageCount,
|
|
853
|
+
tokenForOrdinal(ordinal) {
|
|
854
|
+
return tokensByOrdinal.get(ordinal) ?? 0;
|
|
855
|
+
},
|
|
856
|
+
messageIdAtOrdinal(ordinal) {
|
|
857
|
+
return idsByOrdinal.get(ordinal) ?? null;
|
|
858
|
+
},
|
|
859
|
+
suffixTokensFromOrdinal(ordinal) {
|
|
860
|
+
if (ordinal <= firstOrdinal)
|
|
861
|
+
return prefix[ordinalSpan];
|
|
862
|
+
if (ordinal > terminalOrdinal)
|
|
863
|
+
return 0;
|
|
864
|
+
return prefix[ordinalSpan] - prefix[ordinalToIndex(ordinal)];
|
|
865
|
+
},
|
|
866
|
+
rangeTokens(startInclusive, endExclusive) {
|
|
867
|
+
const start = Math.max(firstOrdinal, startInclusive);
|
|
868
|
+
const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
|
|
869
|
+
return prefix[end - firstOrdinal] - prefix[start - firstOrdinal];
|
|
870
|
+
},
|
|
871
|
+
findSuffixStartForTokens(tokens) {
|
|
872
|
+
if (!Number.isFinite(tokens) || tokens <= 0)
|
|
873
|
+
return terminalOrdinal + 1;
|
|
874
|
+
const target = Math.max(0, Math.floor(tokens));
|
|
875
|
+
const total = prefix[ordinalSpan];
|
|
876
|
+
if (total < target)
|
|
877
|
+
return firstOrdinal;
|
|
878
|
+
const cut = total - target;
|
|
879
|
+
let lo = 0;
|
|
880
|
+
let hi = ordinalSpan;
|
|
881
|
+
let best = 0;
|
|
882
|
+
while (lo <= hi) {
|
|
883
|
+
const mid = lo + hi >> 1;
|
|
884
|
+
if (prefix[mid] <= cut) {
|
|
885
|
+
best = mid;
|
|
886
|
+
lo = mid + 1;
|
|
887
|
+
} else {
|
|
888
|
+
hi = mid - 1;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
return firstOrdinal + best;
|
|
892
|
+
},
|
|
893
|
+
findHeadEndForCap(startInclusive, endExclusive, capTokens) {
|
|
894
|
+
const start = Math.max(firstOrdinal, Math.min(terminalOrdinal + 1, startInclusive));
|
|
895
|
+
const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
|
|
896
|
+
if (!Number.isFinite(capTokens) || capTokens <= 0)
|
|
897
|
+
return start;
|
|
898
|
+
const startIndex = start - firstOrdinal;
|
|
899
|
+
const endIndex = end - firstOrdinal;
|
|
900
|
+
const cut = prefix[startIndex] + Math.floor(capTokens);
|
|
901
|
+
let lo = startIndex + 1;
|
|
902
|
+
let hi = endIndex;
|
|
903
|
+
let bestEndIndex = startIndex;
|
|
904
|
+
while (lo <= hi) {
|
|
905
|
+
const mid = lo + hi >> 1;
|
|
906
|
+
if (prefix[mid] <= cut) {
|
|
907
|
+
bestEndIndex = mid;
|
|
908
|
+
lo = mid + 1;
|
|
909
|
+
} else {
|
|
910
|
+
hi = mid - 1;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
let bestEnd = firstOrdinal + bestEndIndex;
|
|
914
|
+
if (bestEnd === start && start < end)
|
|
915
|
+
bestEnd = start + 1;
|
|
916
|
+
return Math.min(bestEnd, end);
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
function partContentFingerprint(part) {
|
|
921
|
+
if (!isRecord(part))
|
|
922
|
+
return `${typeof part}:${recursiveByteLength(part)}`;
|
|
923
|
+
const tool = toolSignalFromPart(part);
|
|
924
|
+
if (tool) {
|
|
925
|
+
return contentStringsHash([tool.inputText, tool.outputText]);
|
|
926
|
+
}
|
|
927
|
+
const text = firstStringField(part, ["text", "thinking", "reasoning", "content", "url"]) ?? "";
|
|
928
|
+
return contentStringsHash([text]);
|
|
929
|
+
}
|
|
930
|
+
function computeRawRangeFingerprint(messages, startInclusive, endExclusive) {
|
|
931
|
+
const pieces = [];
|
|
932
|
+
for (const message of messages) {
|
|
933
|
+
if (message.ordinal < startInclusive || message.ordinal >= endExclusive)
|
|
934
|
+
continue;
|
|
935
|
+
const partFingerprint = message.parts.map(partContentFingerprint).join(",");
|
|
936
|
+
pieces.push(`${message.ordinal}:${message.id}:${message.parts.length}:${partFingerprint}`);
|
|
937
|
+
}
|
|
938
|
+
return pieces.join("|");
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// src/hooks/magic-context/system-injection-stripper.ts
|
|
942
|
+
var SYSTEM_INJECTION_MARKERS = [
|
|
943
|
+
"<!-- OMO_INTERNAL_INITIATOR -->",
|
|
944
|
+
"[SYSTEM DIRECTIVE: MAGIC-CONTEXT",
|
|
945
|
+
"[SYSTEM DIRECTIVE: OH-MY-OPENCODE",
|
|
946
|
+
"[Category+Skill Reminder]",
|
|
947
|
+
"[EDIT ERROR - IMMEDIATE ACTION REQUIRED]",
|
|
948
|
+
"[task CALL FAILED - IMMEDIATE RETRY REQUIRED]",
|
|
949
|
+
"[EMERGENCY CONTEXT WINDOW WARNING]",
|
|
950
|
+
"Unstable background agent appears idle",
|
|
951
|
+
"**THE SUBAGENT JUST CLAIMED THIS TASK IS DONE."
|
|
952
|
+
];
|
|
953
|
+
var SYSTEM_REMINDER_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
954
|
+
var OMO_MARKER_REGEX = /<!-- OMO_INTERNAL_INITIATOR -->/g;
|
|
955
|
+
var STEERING_WRAPPER_REGEX = /<system-reminder>\nThe user sent the following message:\n[\s\S]*?\n\nPlease address this message and continue with your tasks\.\n<\/system-reminder>/g;
|
|
956
|
+
function stripSystemInjection(text) {
|
|
957
|
+
STEERING_WRAPPER_REGEX.lastIndex = 0;
|
|
958
|
+
if (!STEERING_WRAPPER_REGEX.test(text))
|
|
959
|
+
return stripInjectedRegions(text);
|
|
960
|
+
STEERING_WRAPPER_REGEX.lastIndex = 0;
|
|
961
|
+
let result = "";
|
|
962
|
+
let changed = false;
|
|
963
|
+
let cursor = 0;
|
|
964
|
+
const keepOrStrip = (segment) => {
|
|
965
|
+
const stripped = stripInjectedRegions(segment);
|
|
966
|
+
if (stripped === null) {
|
|
967
|
+
result += segment;
|
|
968
|
+
} else {
|
|
969
|
+
result += stripped;
|
|
970
|
+
changed = true;
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
for (const match of text.matchAll(STEERING_WRAPPER_REGEX)) {
|
|
974
|
+
keepOrStrip(text.slice(cursor, match.index));
|
|
975
|
+
result += match[0];
|
|
976
|
+
cursor = match.index + match[0].length;
|
|
977
|
+
}
|
|
978
|
+
keepOrStrip(text.slice(cursor));
|
|
979
|
+
return changed ? result.trim() : null;
|
|
980
|
+
}
|
|
981
|
+
function stripOutsideSteeringWrappers(text, strip) {
|
|
982
|
+
STEERING_WRAPPER_REGEX.lastIndex = 0;
|
|
983
|
+
let result = "";
|
|
984
|
+
let cursor = 0;
|
|
985
|
+
for (const match of text.matchAll(STEERING_WRAPPER_REGEX)) {
|
|
986
|
+
result += strip(text.slice(cursor, match.index));
|
|
987
|
+
result += match[0];
|
|
988
|
+
cursor = match.index + match[0].length;
|
|
989
|
+
}
|
|
990
|
+
return result + strip(text.slice(cursor));
|
|
991
|
+
}
|
|
992
|
+
function stripInjectedRegions(text) {
|
|
993
|
+
let hasInjection = false;
|
|
994
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
995
|
+
if (text.includes(marker)) {
|
|
996
|
+
hasInjection = true;
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
if (SYSTEM_REMINDER_REGEX.test(text))
|
|
1001
|
+
hasInjection = true;
|
|
1002
|
+
SYSTEM_REMINDER_REGEX.lastIndex = 0;
|
|
1003
|
+
if (!hasInjection)
|
|
1004
|
+
return null;
|
|
1005
|
+
let cleaned = text;
|
|
1006
|
+
cleaned = cleaned.replace(SYSTEM_REMINDER_REGEX, "");
|
|
1007
|
+
cleaned = cleaned.replace(OMO_MARKER_REGEX, "");
|
|
1008
|
+
cleaned = cleaned.replace(/\[SYSTEM DIRECTIVE: OH-MY-(?:OPENCODE|CLAUDE)[^\]]*\][\s\S]*?(?=\n\n(?!\s*[-*])|$)/g, "");
|
|
1009
|
+
for (const marker of SYSTEM_INJECTION_MARKERS) {
|
|
1010
|
+
if (marker.startsWith("<!-- ") || marker.startsWith("[SYSTEM DIRECTIVE"))
|
|
1011
|
+
continue;
|
|
1012
|
+
const idx = cleaned.indexOf(marker);
|
|
1013
|
+
if (idx === -1)
|
|
1014
|
+
continue;
|
|
1015
|
+
const blockEnd = cleaned.indexOf(`
|
|
1016
|
+
|
|
1017
|
+
`, idx + marker.length);
|
|
1018
|
+
cleaned = blockEnd !== -1 ? cleaned.slice(0, idx) + cleaned.slice(blockEnd) : cleaned.slice(0, idx);
|
|
1019
|
+
}
|
|
1020
|
+
return cleaned.trim();
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// src/hooks/magic-context/tag-part-guards.ts
|
|
1024
|
+
function isTextPart(part) {
|
|
1025
|
+
if (part === null || typeof part !== "object")
|
|
1026
|
+
return false;
|
|
1027
|
+
const p = part;
|
|
1028
|
+
return p.type === "text" && typeof p.text === "string";
|
|
1029
|
+
}
|
|
1030
|
+
function isToolPartWithOutput(part) {
|
|
1031
|
+
if (part === null || typeof part !== "object")
|
|
1032
|
+
return false;
|
|
1033
|
+
const p = part;
|
|
1034
|
+
if (p.type !== "tool" || typeof p.callID !== "string")
|
|
1035
|
+
return false;
|
|
1036
|
+
if (p.state === null || typeof p.state !== "object")
|
|
1037
|
+
return false;
|
|
1038
|
+
return typeof p.state.output === "string";
|
|
1039
|
+
}
|
|
1040
|
+
function isFilePart(part) {
|
|
1041
|
+
if (part === null || typeof part !== "object")
|
|
1042
|
+
return false;
|
|
1043
|
+
const p = part;
|
|
1044
|
+
return p.type === "file" && typeof p.url === "string";
|
|
1045
|
+
}
|
|
1046
|
+
function buildFileSourceContent(parts) {
|
|
1047
|
+
const content = parts.filter(isTextPart).map((part) => stripTagPrefix(part.text)).join(`
|
|
1048
|
+
`).trim();
|
|
1049
|
+
return content.length > 0 ? content : null;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// src/shared/user-answer.ts
|
|
1053
|
+
function hasUserAnswerMetadata(value) {
|
|
1054
|
+
if (!isRecord(value))
|
|
1055
|
+
return false;
|
|
1056
|
+
if (value.userAnswer === true)
|
|
1057
|
+
return true;
|
|
1058
|
+
if (Array.isArray(value.answers))
|
|
1059
|
+
return true;
|
|
1060
|
+
if (typeof value.answer === "string")
|
|
1061
|
+
return true;
|
|
1062
|
+
if (Array.isArray(value.selectedOptions) || typeof value.customInput === "string")
|
|
1063
|
+
return true;
|
|
1064
|
+
return Array.isArray(value.results) && value.results.some(hasUserAnswerMetadata);
|
|
1065
|
+
}
|
|
1066
|
+
function toolPartHasUserAnswer(part) {
|
|
1067
|
+
if (!isRecord(part))
|
|
1068
|
+
return false;
|
|
1069
|
+
const state = isRecord(part.state) ? part.state : undefined;
|
|
1070
|
+
return hasUserAnswerMetadata(state?.metadata) || hasUserAnswerMetadata(part.details);
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
// src/features/magic-context/dreamer/token-budget.ts
|
|
1074
|
+
class DreamTokenBudgetExceeded extends Error {
|
|
1075
|
+
sessionId;
|
|
1076
|
+
spent;
|
|
1077
|
+
constructor(sessionId, spent) {
|
|
1078
|
+
super(`Dreamer child ${sessionId} spent ${spent} prompt tokens (token_budget)`);
|
|
1079
|
+
this.sessionId = sessionId;
|
|
1080
|
+
this.spent = spent;
|
|
1081
|
+
this.name = "DreamTokenBudgetExceeded";
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
var TOKEN_BUDGET_FINALIZE_MESSAGE = "You're out of token budget. Stop investigating: make no more tool calls and output your result now, covering only what you've already checked; leave the rest out.";
|
|
1085
|
+
var TOKEN_BUDGET_TOOL_REFUSAL = "Out of token budget: no more tool calls. Output your result now.";
|
|
1086
|
+
var finalizingChildren = new Map;
|
|
1087
|
+
function registerBudgetFinalizeChild(sessionId, guard) {
|
|
1088
|
+
finalizingChildren.set(sessionId, guard);
|
|
1089
|
+
}
|
|
1090
|
+
function releaseBudgetFinalizeChild(sessionId) {
|
|
1091
|
+
finalizingChildren.delete(sessionId);
|
|
1092
|
+
}
|
|
1093
|
+
function createDreamTokenBudget(budget) {
|
|
1094
|
+
if (!Number.isSafeInteger(budget) || budget <= 0)
|
|
1095
|
+
throw new Error("Invalid token budget");
|
|
1096
|
+
let spent = 0;
|
|
1097
|
+
let finalizeFired = false;
|
|
1098
|
+
let refusedCalls = 0;
|
|
1099
|
+
let forcedStop = false;
|
|
1100
|
+
const snapshot = () => ({
|
|
1101
|
+
budget,
|
|
1102
|
+
spent,
|
|
1103
|
+
finalizeFired,
|
|
1104
|
+
refusedCalls,
|
|
1105
|
+
hardStopped: forcedStop || spent >= budget || refusedCalls >= 2
|
|
1106
|
+
});
|
|
1107
|
+
return {
|
|
1108
|
+
snapshot,
|
|
1109
|
+
finalize() {
|
|
1110
|
+
if (finalizeFired)
|
|
1111
|
+
return "continue";
|
|
1112
|
+
finalizeFired = true;
|
|
1113
|
+
return "finalize";
|
|
1114
|
+
},
|
|
1115
|
+
charge(input, cacheRead, cacheWrite, completed = false, canFinalize = true) {
|
|
1116
|
+
for (const value of [input, cacheRead, cacheWrite]) {
|
|
1117
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
1118
|
+
throw new Error("Invalid prompt usage");
|
|
1119
|
+
}
|
|
1120
|
+
spent += input + cacheRead + cacheWrite;
|
|
1121
|
+
if (completed)
|
|
1122
|
+
return "continue";
|
|
1123
|
+
if (spent >= budget)
|
|
1124
|
+
return "stop";
|
|
1125
|
+
if (!completed && !finalizeFired && spent >= budget * 0.8) {
|
|
1126
|
+
if (!canFinalize) {
|
|
1127
|
+
forcedStop = true;
|
|
1128
|
+
return "stop";
|
|
1129
|
+
}
|
|
1130
|
+
finalizeFired = true;
|
|
1131
|
+
return "finalize";
|
|
1132
|
+
}
|
|
1133
|
+
return "continue";
|
|
1134
|
+
},
|
|
1135
|
+
refuseTool() {
|
|
1136
|
+
if (!finalizeFired && !snapshot().hardStopped)
|
|
1137
|
+
return null;
|
|
1138
|
+
refusedCalls += 1;
|
|
1139
|
+
return { message: TOKEN_BUDGET_TOOL_REFUSAL, hardStopped: snapshot().hardStopped };
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
// src/hooks/magic-context/dropped-input-guard.ts
|
|
1145
|
+
var LEGACY_TRUNCATED_VALUE = /^[\s\S]{0,5}\.\.\.\[truncated\]$/;
|
|
1146
|
+
var MAX_QUOTED_ARGUMENTS = 160;
|
|
1147
|
+
var MAX_LISTED_PARAMETERS = 12;
|
|
1148
|
+
var MAX_TRACKED_SESSIONS = 1000;
|
|
1149
|
+
function isDroppedPlaceholderString(value) {
|
|
1150
|
+
return value.startsWith("[dropped §") && value.endsWith("§]") || LEGACY_TRUNCATED_VALUE.test(value) || value === "[object]" || /^\[\d+ items\]$/.test(value);
|
|
1151
|
+
}
|
|
1152
|
+
function droppedInputMarker(tagId) {
|
|
1153
|
+
return { dropped: `[dropped §${tagId}§]` };
|
|
1154
|
+
}
|
|
1155
|
+
function containsDroppedInputPlaceholder(value) {
|
|
1156
|
+
const seen = new WeakSet;
|
|
1157
|
+
const visit = (candidate) => {
|
|
1158
|
+
if (typeof candidate === "string")
|
|
1159
|
+
return isDroppedPlaceholderString(candidate);
|
|
1160
|
+
if (candidate === null || typeof candidate !== "object")
|
|
1161
|
+
return false;
|
|
1162
|
+
if (seen.has(candidate))
|
|
1163
|
+
return false;
|
|
1164
|
+
seen.add(candidate);
|
|
1165
|
+
if (Array.isArray(candidate))
|
|
1166
|
+
return candidate.some(visit);
|
|
1167
|
+
return Object.values(candidate).some(visit);
|
|
1168
|
+
};
|
|
1169
|
+
return visit(value);
|
|
1170
|
+
}
|
|
1171
|
+
function isRecord2(value) {
|
|
1172
|
+
return value !== null && typeof value === "object";
|
|
1173
|
+
}
|
|
1174
|
+
function isOptionalZodField(field) {
|
|
1175
|
+
if (!isRecord2(field))
|
|
1176
|
+
return false;
|
|
1177
|
+
const isOptional = field.isOptional;
|
|
1178
|
+
if (typeof isOptional === "function") {
|
|
1179
|
+
try {
|
|
1180
|
+
return isOptional.call(field) === true;
|
|
1181
|
+
} catch {}
|
|
1182
|
+
}
|
|
1183
|
+
const internals = field._zod;
|
|
1184
|
+
return internals?.optin === "optional";
|
|
1185
|
+
}
|
|
1186
|
+
function toolParameterNames(schema) {
|
|
1187
|
+
if (!isRecord2(schema))
|
|
1188
|
+
return;
|
|
1189
|
+
const properties = schema.properties;
|
|
1190
|
+
if (isRecord2(properties) && !Array.isArray(properties)) {
|
|
1191
|
+
const names = Object.keys(properties);
|
|
1192
|
+
const requiredList = Array.isArray(schema.required) ? schema.required : [];
|
|
1193
|
+
const required = new Set(requiredList.filter((name) => typeof name === "string"));
|
|
1194
|
+
return {
|
|
1195
|
+
required: names.filter((name) => required.has(name)),
|
|
1196
|
+
optional: names.filter((name) => !required.has(name))
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
let shape;
|
|
1200
|
+
try {
|
|
1201
|
+
shape = schema.shape;
|
|
1202
|
+
} catch {
|
|
1203
|
+
shape = undefined;
|
|
1204
|
+
}
|
|
1205
|
+
if (isRecord2(shape) && !Array.isArray(shape)) {
|
|
1206
|
+
const result = { required: [], optional: [] };
|
|
1207
|
+
for (const [name, field] of Object.entries(shape)) {
|
|
1208
|
+
(isOptionalZodField(field) ? result.optional : result.required).push(name);
|
|
1209
|
+
}
|
|
1210
|
+
return result;
|
|
1211
|
+
}
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
var recordedToolParameters = new Map;
|
|
1215
|
+
function recordToolParameters(toolName, schema) {
|
|
1216
|
+
const names = toolParameterNames(schema);
|
|
1217
|
+
if (names)
|
|
1218
|
+
recordedToolParameters.set(toolName, names);
|
|
1219
|
+
else
|
|
1220
|
+
recordedToolParameters.delete(toolName);
|
|
1221
|
+
}
|
|
1222
|
+
function quoteArguments(input) {
|
|
1223
|
+
let text;
|
|
1224
|
+
try {
|
|
1225
|
+
text = JSON.stringify(input) ?? String(input);
|
|
1226
|
+
} catch {
|
|
1227
|
+
text = String(input);
|
|
1228
|
+
}
|
|
1229
|
+
return text.length > MAX_QUOTED_ARGUMENTS ? `${text.slice(0, MAX_QUOTED_ARGUMENTS - 1)}…` : text;
|
|
1230
|
+
}
|
|
1231
|
+
function ordinal(value) {
|
|
1232
|
+
const lastTwo = value % 100;
|
|
1233
|
+
if (lastTwo >= 11 && lastTwo <= 13)
|
|
1234
|
+
return `${value}th`;
|
|
1235
|
+
switch (value % 10) {
|
|
1236
|
+
case 1:
|
|
1237
|
+
return `${value}st`;
|
|
1238
|
+
case 2:
|
|
1239
|
+
return `${value}nd`;
|
|
1240
|
+
case 3:
|
|
1241
|
+
return `${value}rd`;
|
|
1242
|
+
default:
|
|
1243
|
+
return `${value}th`;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
function describeParameters(names) {
|
|
1247
|
+
if (!names || names.required.length + names.optional.length === 0) {
|
|
1248
|
+
return "the tool's own parameters";
|
|
1249
|
+
}
|
|
1250
|
+
const listed = [...names.required.map((name) => `${name} (required)`), ...names.optional];
|
|
1251
|
+
const shown = listed.slice(0, MAX_LISTED_PARAMETERS);
|
|
1252
|
+
const more = listed.length > shown.length ? ", …" : "";
|
|
1253
|
+
return `its parameters: ${shown.join(", ")}${more}`;
|
|
1254
|
+
}
|
|
1255
|
+
function droppedInputRefusalMessage(refusal) {
|
|
1256
|
+
const tool = refusal.toolName ? `\`${refusal.toolName}\`` : undefined;
|
|
1257
|
+
const names = toolParameterNames(refusal.parameters) ?? (refusal.toolName ? recordedToolParameters.get(refusal.toolName) : undefined);
|
|
1258
|
+
const lines = [];
|
|
1259
|
+
if (refusal.consecutive >= 2) {
|
|
1260
|
+
lines.push(`This is the ${ordinal(refusal.consecutive)} call in a row with placeholder arguments.`);
|
|
1261
|
+
}
|
|
1262
|
+
lines.push(`Not executed: your arguments${tool ? ` to ${tool}` : ""} were ${quoteArguments(refusal.input)}. That is the placeholder Magic Context shows in place of an earlier call's arguments, not a value to send. Nothing is wrong with the session or the tool.`, `Call ${tool ?? "the tool"} again with real values for ${describeParameters(names)}.`, "Only if you need the original arguments of an earlier dropped call, recover them with ctx_expand first.");
|
|
1263
|
+
return lines.join(`
|
|
1264
|
+
`);
|
|
1265
|
+
}
|
|
1266
|
+
function createDroppedInputGuard(options = {}) {
|
|
1267
|
+
const consecutiveBySession = new Map;
|
|
1268
|
+
return {
|
|
1269
|
+
check(call) {
|
|
1270
|
+
const session = call.sessionID ?? "";
|
|
1271
|
+
if (!containsDroppedInputPlaceholder(call.input)) {
|
|
1272
|
+
consecutiveBySession.delete(session);
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
const consecutive = (consecutiveBySession.get(session) ?? 0) + 1;
|
|
1276
|
+
consecutiveBySession.delete(session);
|
|
1277
|
+
consecutiveBySession.set(session, consecutive);
|
|
1278
|
+
if (consecutiveBySession.size > MAX_TRACKED_SESSIONS) {
|
|
1279
|
+
const oldest = consecutiveBySession.keys().next().value;
|
|
1280
|
+
if (oldest !== undefined)
|
|
1281
|
+
consecutiveBySession.delete(oldest);
|
|
1282
|
+
}
|
|
1283
|
+
let parameters;
|
|
1284
|
+
if (call.toolName && options.parametersFor) {
|
|
1285
|
+
try {
|
|
1286
|
+
parameters = options.parametersFor(call.toolName);
|
|
1287
|
+
} catch {
|
|
1288
|
+
parameters = undefined;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
return droppedInputRefusalMessage({
|
|
1292
|
+
toolName: call.toolName,
|
|
1293
|
+
input: call.input,
|
|
1294
|
+
parameters,
|
|
1295
|
+
consecutive
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
function assertExecutableToolInput(guard, call) {
|
|
1301
|
+
const refusal = guard.check(call);
|
|
1302
|
+
if (refusal !== undefined)
|
|
1303
|
+
throw new Error(refusal);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// src/hooks/magic-context/edit-marker.ts
|
|
1307
|
+
var TRUNCATION_SENTINEL = "...[truncated]";
|
|
1308
|
+
var EDIT_REGION_HINT_LEN = 40;
|
|
1309
|
+
var PATH_KEYS = new Set(["filePath", "file_path", "path"]);
|
|
1310
|
+
var DIFF_KEYS = new Set(["oldString", "newString", "content", "old_string", "new_string"]);
|
|
1311
|
+
function safeSlice(str, maxLen) {
|
|
1312
|
+
if (str.length <= maxLen)
|
|
1313
|
+
return str;
|
|
1314
|
+
const lastCharCode = str.charCodeAt(maxLen - 1);
|
|
1315
|
+
if (lastCharCode >= 55296 && lastCharCode <= 56319) {
|
|
1316
|
+
return str.slice(0, maxLen - 1);
|
|
1317
|
+
}
|
|
1318
|
+
return str.slice(0, maxLen);
|
|
1319
|
+
}
|
|
1320
|
+
function isEditTool(name) {
|
|
1321
|
+
return name === "edit" || name === "write";
|
|
1322
|
+
}
|
|
1323
|
+
function applyEditMarkerToInput(input) {
|
|
1324
|
+
for (const key of Object.keys(input)) {
|
|
1325
|
+
if (PATH_KEYS.has(key))
|
|
1326
|
+
continue;
|
|
1327
|
+
const value = input[key];
|
|
1328
|
+
if (typeof value !== "string" || !DIFF_KEYS.has(key))
|
|
1329
|
+
continue;
|
|
1330
|
+
if (value.endsWith(TRUNCATION_SENTINEL))
|
|
1331
|
+
continue;
|
|
1332
|
+
input[key] = value.length > EDIT_REGION_HINT_LEN ? `${safeSlice(value, EDIT_REGION_HINT_LEN)}${TRUNCATION_SENTINEL}` : value;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
// src/hooks/magic-context/final-wire-token-estimate.ts
|
|
1337
|
+
function compactWireLabel(value, fallback) {
|
|
1338
|
+
if (typeof value !== "string" || value.length === 0)
|
|
1339
|
+
return fallback;
|
|
1340
|
+
return value.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 32) || fallback;
|
|
1341
|
+
}
|
|
1342
|
+
function wirePartKind(part, role) {
|
|
1343
|
+
const rawType = part !== null && typeof part === "object" && typeof part.type === "string" ? part.type : "unknown";
|
|
1344
|
+
if (rawType === "tool_result" || rawType === "tool-result")
|
|
1345
|
+
return "toolresult";
|
|
1346
|
+
if (rawType === "tool_use" || rawType === "tool-use" || rawType === "tool-invocation") {
|
|
1347
|
+
return "tool";
|
|
1348
|
+
}
|
|
1349
|
+
if (role === "user" && rawType === "tool")
|
|
1350
|
+
return "toolresult";
|
|
1351
|
+
return compactWireLabel(rawType, "unknown");
|
|
1352
|
+
}
|
|
1353
|
+
function describeFinalWireTail(messages) {
|
|
1354
|
+
return `[${messages.slice(-3).map((message) => {
|
|
1355
|
+
const role = compactWireLabel(message.info.role, "unknown");
|
|
1356
|
+
const kinds = message.parts.map((part) => wirePartKind(part, role)).join("+") || "none";
|
|
1357
|
+
return `${role}:${kinds}`;
|
|
1358
|
+
}).join(", ")}]`;
|
|
1359
|
+
}
|
|
1360
|
+
function serializedText(value) {
|
|
1361
|
+
if (value === undefined)
|
|
1362
|
+
return "";
|
|
1363
|
+
return (typeof value === "string" ? value : JSON.stringify(value)) ?? "";
|
|
1364
|
+
}
|
|
1365
|
+
var wireTextTokens = createTokenCountMemo(1e5, 128 * 1024 * 1024);
|
|
1366
|
+
function serializedTokens(value, bounded = false) {
|
|
1367
|
+
const serialized = serializedText(value);
|
|
1368
|
+
if (bounded && tokenCountUsesByteBound(serialized))
|
|
1369
|
+
return Buffer.byteLength(serialized);
|
|
1370
|
+
return serialized ? wireTextTokens(serialized) : 0;
|
|
1371
|
+
}
|
|
1372
|
+
function visitWireContent(message, visit) {
|
|
1373
|
+
for (const part of message.parts) {
|
|
1374
|
+
if (!part || typeof part !== "object")
|
|
1375
|
+
continue;
|
|
1376
|
+
const p = part;
|
|
1377
|
+
if (p.ignored)
|
|
1378
|
+
continue;
|
|
1379
|
+
const text = (value) => {
|
|
1380
|
+
if (typeof value === "string")
|
|
1381
|
+
visit.text("conversation", value);
|
|
1382
|
+
};
|
|
1383
|
+
const tool = (value) => visit.text("toolCall", value);
|
|
1384
|
+
switch (p.type) {
|
|
1385
|
+
case "text":
|
|
1386
|
+
text(p.text);
|
|
1387
|
+
break;
|
|
1388
|
+
case "reasoning":
|
|
1389
|
+
text(p.text);
|
|
1390
|
+
text(p.metadata?.anthropic?.signature);
|
|
1391
|
+
break;
|
|
1392
|
+
case "thinking":
|
|
1393
|
+
text(p.thinking);
|
|
1394
|
+
text(p.signature);
|
|
1395
|
+
break;
|
|
1396
|
+
case "redacted_thinking":
|
|
1397
|
+
text(p.data);
|
|
1398
|
+
break;
|
|
1399
|
+
case "file":
|
|
1400
|
+
if (typeof p.mime === "string" && p.mime.startsWith("image/")) {
|
|
1401
|
+
visit.image("conversation", typeof p.url === "string" && p.url.startsWith("data:") ? estimateImageTokensFromDataUrl(p.url) : 1200);
|
|
1402
|
+
}
|
|
1403
|
+
break;
|
|
1404
|
+
case "tool":
|
|
1405
|
+
tool(p.state?.input ?? p.input ?? p.args);
|
|
1406
|
+
tool(p.state?.output ?? p.state?.content ?? p.output ?? p.result ?? p.content);
|
|
1407
|
+
tool(p.state?.error);
|
|
1408
|
+
visit.image("toolCall", estimateToolAttachmentImageTokens(p.state));
|
|
1409
|
+
break;
|
|
1410
|
+
case "tool-call":
|
|
1411
|
+
tool(p.input ?? p.args);
|
|
1412
|
+
break;
|
|
1413
|
+
case "tool-invocation":
|
|
1414
|
+
tool(p.args ?? p.input);
|
|
1415
|
+
tool(p.result ?? p.output ?? p.state?.output);
|
|
1416
|
+
tool(p.state?.error);
|
|
1417
|
+
break;
|
|
1418
|
+
case "tool-result":
|
|
1419
|
+
tool(p.result ?? p.content ?? p.output);
|
|
1420
|
+
break;
|
|
1421
|
+
case "tool_use":
|
|
1422
|
+
tool(p.input ?? p.args);
|
|
1423
|
+
break;
|
|
1424
|
+
case "tool_result":
|
|
1425
|
+
tool(p.content ?? p.result ?? p.output);
|
|
1426
|
+
break;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
function estimateMessageTokens(message, bounded = false) {
|
|
1431
|
+
const total = { conversation: 0, toolCall: 0 };
|
|
1432
|
+
visitWireContent(message, {
|
|
1433
|
+
text: (bucket, value) => {
|
|
1434
|
+
total[bucket] += serializedTokens(value, bounded);
|
|
1435
|
+
},
|
|
1436
|
+
image: (bucket, tokens) => {
|
|
1437
|
+
total[bucket] += tokens;
|
|
1438
|
+
}
|
|
1439
|
+
});
|
|
1440
|
+
return total;
|
|
1441
|
+
}
|
|
1442
|
+
function wireContentBytes(messages, abortAboveBytes, bytesPerToken) {
|
|
1443
|
+
let bytes = 0;
|
|
1444
|
+
try {
|
|
1445
|
+
for (const message of messages) {
|
|
1446
|
+
visitWireContent(message, {
|
|
1447
|
+
text: (_bucket, value) => {
|
|
1448
|
+
bytes += Buffer.byteLength(serializedText(value));
|
|
1449
|
+
},
|
|
1450
|
+
image: (_bucket, tokens) => {
|
|
1451
|
+
bytes += tokens * bytesPerToken;
|
|
1452
|
+
}
|
|
1453
|
+
});
|
|
1454
|
+
if (bytes > abortAboveBytes)
|
|
1455
|
+
return { bytes, aborted: true };
|
|
1456
|
+
}
|
|
1457
|
+
} catch {
|
|
1458
|
+
return null;
|
|
1459
|
+
}
|
|
1460
|
+
return { bytes, aborted: false };
|
|
1461
|
+
}
|
|
1462
|
+
function createFinalWireUsageTracker() {
|
|
1463
|
+
const served = new Map;
|
|
1464
|
+
const wireRows = (input) => input.messages.filter((message) => message.parts.some((part) => !part || typeof part !== "object" || !["step-start", "step-finish"].includes(String(part.type))));
|
|
1465
|
+
const rowBytes = (message) => JSON.stringify({ id: message.info.id, role: message.info.role, parts: message.parts });
|
|
1466
|
+
const envelopeFor = (input) => {
|
|
1467
|
+
if (!input.providerID || !input.modelID || !input.systemPromptHash)
|
|
1468
|
+
return;
|
|
1469
|
+
const tools = getToolDefinitionMeasurementSignature(input.providerID, input.modelID, input.agentName);
|
|
1470
|
+
if (!tools)
|
|
1471
|
+
return;
|
|
1472
|
+
return JSON.stringify([
|
|
1473
|
+
input.providerID,
|
|
1474
|
+
input.modelID,
|
|
1475
|
+
input.agentName,
|
|
1476
|
+
input.systemPromptHash,
|
|
1477
|
+
input.systemPromptTokens,
|
|
1478
|
+
tools
|
|
1479
|
+
]);
|
|
1480
|
+
};
|
|
1481
|
+
return {
|
|
1482
|
+
estimate(sessionId, input, limit) {
|
|
1483
|
+
let measuredPrefix;
|
|
1484
|
+
try {
|
|
1485
|
+
const previous = served.get(sessionId);
|
|
1486
|
+
const rows = wireRows(input);
|
|
1487
|
+
if (previous && previous.envelope === envelopeFor(input) && rows.length > previous.prefix.length && previous.prefix.every((bytes, i) => rowBytes(rows[i]) === bytes)) {
|
|
1488
|
+
const reply = rows[previous.prefix.length]?.info;
|
|
1489
|
+
const tokens = reply.tokens;
|
|
1490
|
+
const time = reply.time;
|
|
1491
|
+
const counts = [tokens?.input, tokens?.cache?.read, tokens?.cache?.write];
|
|
1492
|
+
if (reply.role === "assistant" && reply.parentID === previous.parent && reply.providerID === input.providerID && reply.modelID === input.modelID && ["stop", "tool-calls", "length"].includes(String(reply.finish)) && !reply.error && typeof time?.completed === "number" && time.completed >= previous.at && counts.every((n) => typeof n === "number" && Number.isSafeInteger(n) && n >= 0)) {
|
|
1493
|
+
const inputTokens = counts.reduce((sum, n) => sum + (n ?? 0), 0);
|
|
1494
|
+
if (inputTokens > 0)
|
|
1495
|
+
measuredPrefix = {
|
|
1496
|
+
inputTokens,
|
|
1497
|
+
appendedMessages: rows.slice(previous.prefix.length)
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
} catch {}
|
|
1502
|
+
return estimateOutgoingWireForRefusal({ ...input, measuredPrefix }, limit);
|
|
1503
|
+
},
|
|
1504
|
+
capture(sessionId, input) {
|
|
1505
|
+
served.delete(sessionId);
|
|
1506
|
+
try {
|
|
1507
|
+
const envelope = envelopeFor(input);
|
|
1508
|
+
const rows = wireRows(input);
|
|
1509
|
+
const parent = [...rows].reverse().find((row) => row.info.role === "user")?.info.id;
|
|
1510
|
+
if (!envelope || typeof parent !== "string" || !rows.every(hasCountableParts))
|
|
1511
|
+
return;
|
|
1512
|
+
const prefix = rows.map(rowBytes);
|
|
1513
|
+
if (prefix.reduce((sum, text) => sum + text.length, 0) > 4 * 1024 * 1024)
|
|
1514
|
+
return;
|
|
1515
|
+
if (served.size >= 16)
|
|
1516
|
+
served.delete(served.keys().next().value);
|
|
1517
|
+
served.set(sessionId, { envelope, prefix, parent, at: Date.now() });
|
|
1518
|
+
} catch {}
|
|
1519
|
+
}
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
function estimateOutgoingWireForRefusal(input, limit) {
|
|
1523
|
+
if (typeof limit === "number" && Number.isFinite(limit) && limit > 0) {
|
|
1524
|
+
const measured = input.measuredPrefix;
|
|
1525
|
+
const baseline = measured?.inputTokens ?? 0;
|
|
1526
|
+
const pricedMessages = measured?.appendedMessages ?? input.messages;
|
|
1527
|
+
const bytes = wireContentBytes(pricedMessages, Math.max(0, limit - baseline) * 4, 4);
|
|
1528
|
+
if (bytes) {
|
|
1529
|
+
const lower = baseline + Math.ceil(bytes.bytes / 4);
|
|
1530
|
+
const calibration = resolveDecisionCalibration(input.providerID, input.modelID);
|
|
1531
|
+
const tools = input.providerID && input.modelID ? getMeasuredToolDefinitionTokens(input.providerID, input.modelID, input.agentName) : undefined;
|
|
1532
|
+
const envelope = measured ? baseline : tools !== undefined && Number.isFinite(input.systemPromptTokens) && input.systemPromptTokens > 0 ? providerMass({ system: input.systemPromptTokens, tools }, calibration, true) : undefined;
|
|
1533
|
+
const upper = envelope === undefined ? undefined : envelope + Math.ceil(bytes.bytes * Math.max(UNKNOWN_FIT_RATIO, calibration.toolsRatio, calibration.proseRatio));
|
|
1534
|
+
if (bytes.aborted || lower > limit || upper !== undefined && upper <= limit) {
|
|
1535
|
+
const over = bytes.aborted || lower > limit;
|
|
1536
|
+
return {
|
|
1537
|
+
tokens: over ? lower : upper,
|
|
1538
|
+
trusted: !over,
|
|
1539
|
+
refusalGrade: over && envelope !== undefined,
|
|
1540
|
+
refusalTokens: over ? lower : undefined,
|
|
1541
|
+
refusalBasis: "byte-bound",
|
|
1542
|
+
messageTokens: { conversation: 0, toolCall: 0 },
|
|
1543
|
+
systemTokens: input.systemPromptTokens,
|
|
1544
|
+
toolDefinitionTokens: tools,
|
|
1545
|
+
toolDefinitionsMeasured: tools !== undefined
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
return estimateFinalWireInputTokens({ ...input, boundedTokenization: true });
|
|
1551
|
+
}
|
|
1552
|
+
function estimateFinalWireInputTokens(input) {
|
|
1553
|
+
const messageTokens = input.messages.reduce((total, message) => {
|
|
1554
|
+
const next = estimateMessageTokens(message, input.boundedTokenization);
|
|
1555
|
+
total.conversation += next.conversation;
|
|
1556
|
+
total.toolCall += next.toolCall;
|
|
1557
|
+
return total;
|
|
1558
|
+
}, { conversation: 0, toolCall: 0 });
|
|
1559
|
+
const measuredToolDefinitions = input.toolDefinitionTokens ?? (input.providerID && input.modelID ? getMeasuredToolDefinitionTokens(input.providerID, input.modelID, input.agentName) : undefined);
|
|
1560
|
+
const calibration = resolveDecisionCalibration(input.providerID, input.modelID);
|
|
1561
|
+
const largestToolDefinitions = measuredToolDefinitions === undefined ? getLargestMeasuredToolDefinitionTokens() : undefined;
|
|
1562
|
+
const toolDefinitions = measuredToolDefinitions ?? (largestToolDefinitions === undefined ? undefined : Math.ceil(largestToolDefinitions * UNKNOWN_FIT_RATIO / (calibration.seeded ? calibration.toolsRatio : UNKNOWN_FIT_RATIO)));
|
|
1563
|
+
const rawComponents = {
|
|
1564
|
+
system: input.systemPromptTokens,
|
|
1565
|
+
tools: (toolDefinitions ?? 0) + messageTokens.toolCall,
|
|
1566
|
+
prose: messageTokens.conversation
|
|
1567
|
+
};
|
|
1568
|
+
const tokens = providerMass(rawComponents, calibration, true);
|
|
1569
|
+
const complete = Number.isFinite(tokens) && tokens > 0 && Number.isFinite(input.systemPromptTokens) && input.systemPromptTokens > 0 && toolDefinitions !== undefined && input.messages.every(hasCountableParts);
|
|
1570
|
+
const refusalGrade = complete && hasTokenizerForFit() && measuredToolDefinitions !== undefined && hasMeasuredDecisionCalibration(calibration) && input.messages.every(hasRefusalCountableParts);
|
|
1571
|
+
const measured = input.measuredPrefix;
|
|
1572
|
+
const useMeasured = refusalGrade && measured && Number.isSafeInteger(measured.inputTokens) && measured.inputTokens > 0 && measured.appendedMessages.every(hasCountableParts);
|
|
1573
|
+
const tail = useMeasured ? measured.appendedMessages.reduce((sum, message) => {
|
|
1574
|
+
const next = estimateMessageTokens(message, input.boundedTokenization);
|
|
1575
|
+
return {
|
|
1576
|
+
conversation: sum.conversation + next.conversation,
|
|
1577
|
+
toolCall: sum.toolCall + next.toolCall
|
|
1578
|
+
};
|
|
1579
|
+
}, { conversation: 0, toolCall: 0 }) : undefined;
|
|
1580
|
+
const refusalTokens = refusalGrade ? tail && measured ? measured.inputTokens + providerMass({ tools: tail.toolCall, prose: tail.conversation }, calibration) : providerMass(rawComponents, calibration) : undefined;
|
|
1581
|
+
const systemTokens = Math.round(Math.max(0, input.systemPromptTokens) * calibration.systemRatio);
|
|
1582
|
+
const toolDefinitionTokens = toolDefinitions === undefined ? undefined : Math.round(toolDefinitions * (calibration.seeded ? calibration.toolsRatio : UNKNOWN_FIT_RATIO));
|
|
1583
|
+
return {
|
|
1584
|
+
tokens,
|
|
1585
|
+
trusted: complete,
|
|
1586
|
+
refusalGrade,
|
|
1587
|
+
refusalTokens,
|
|
1588
|
+
refusalBasis: refusalGrade ? useMeasured ? "provider-prefix" : "calibrated" : undefined,
|
|
1589
|
+
rawTokens: rawComponents.system + rawComponents.tools + rawComponents.prose,
|
|
1590
|
+
rawComponents,
|
|
1591
|
+
completeness: complete ? "complete" : "partial",
|
|
1592
|
+
componentsComplete: toolDefinitions !== undefined && input.messages.every(hasCountableParts),
|
|
1593
|
+
messageTokens,
|
|
1594
|
+
systemTokens,
|
|
1595
|
+
toolDefinitionTokens,
|
|
1596
|
+
toolDefinitionsMeasured: measuredToolDefinitions !== undefined
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
function hasRefusalCountableParts(message) {
|
|
1600
|
+
let exact = true;
|
|
1601
|
+
visitWireContent(message, {
|
|
1602
|
+
text: (_bucket, value) => {
|
|
1603
|
+
if (tokenCountUsesByteBound(serializedText(value)))
|
|
1604
|
+
exact = false;
|
|
1605
|
+
},
|
|
1606
|
+
image: () => {}
|
|
1607
|
+
});
|
|
1608
|
+
return exact;
|
|
1609
|
+
}
|
|
1610
|
+
function estimateAppendedWireTokens(input) {
|
|
1611
|
+
const messageTokens = input.messages.reduce((total, message) => {
|
|
1612
|
+
const next = estimateMessageTokens(message);
|
|
1613
|
+
total.conversation += next.conversation;
|
|
1614
|
+
total.toolCall += next.toolCall;
|
|
1615
|
+
return total;
|
|
1616
|
+
}, { conversation: 0, toolCall: 0 });
|
|
1617
|
+
const tokens = providerMass({ prose: messageTokens.conversation, tools: messageTokens.toolCall }, resolveDecisionCalibration(input.providerID, input.modelID), true);
|
|
1618
|
+
return {
|
|
1619
|
+
tokens,
|
|
1620
|
+
trusted: hasTokenizerForFit() && Number.isFinite(tokens) && tokens >= 0 && input.messages.every(hasCountableParts),
|
|
1621
|
+
messageTokens,
|
|
1622
|
+
systemTokens: 0,
|
|
1623
|
+
toolDefinitionTokens: 0
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
function hasCountableParts(message) {
|
|
1627
|
+
return message.parts.every((part) => {
|
|
1628
|
+
if (!part || typeof part !== "object")
|
|
1629
|
+
return false;
|
|
1630
|
+
const p = part;
|
|
1631
|
+
if (p.ignored === true)
|
|
1632
|
+
return true;
|
|
1633
|
+
switch (p.type) {
|
|
1634
|
+
case "text":
|
|
1635
|
+
case "reasoning":
|
|
1636
|
+
return typeof p.text === "string";
|
|
1637
|
+
case "thinking":
|
|
1638
|
+
return typeof p.thinking === "string";
|
|
1639
|
+
case "redacted_thinking":
|
|
1640
|
+
return typeof p.data === "string";
|
|
1641
|
+
case "tool": {
|
|
1642
|
+
const state = p.state !== null && typeof p.state === "object" ? p.state : undefined;
|
|
1643
|
+
const hasInput = state?.input !== undefined || p.input !== undefined || p.args !== undefined;
|
|
1644
|
+
const hasResult = state?.output !== undefined || state?.content !== undefined || state?.error !== undefined || p.output !== undefined || p.result !== undefined || p.content !== undefined;
|
|
1645
|
+
return hasInput && hasResult;
|
|
1646
|
+
}
|
|
1647
|
+
case "tool-call":
|
|
1648
|
+
return p.input !== undefined || p.args !== undefined;
|
|
1649
|
+
case "tool-invocation":
|
|
1650
|
+
return (p.args !== undefined || p.input !== undefined) && (p.result !== undefined || p.output !== undefined || p.state !== null && typeof p.state === "object");
|
|
1651
|
+
case "tool-result":
|
|
1652
|
+
return p.result !== undefined || p.content !== undefined || p.output !== undefined;
|
|
1653
|
+
case "tool_use":
|
|
1654
|
+
return p.input !== undefined || p.args !== undefined;
|
|
1655
|
+
case "tool_result":
|
|
1656
|
+
return p.content !== undefined || p.result !== undefined || p.output !== undefined;
|
|
1657
|
+
case "step-start":
|
|
1658
|
+
case "step-finish":
|
|
1659
|
+
return true;
|
|
1660
|
+
case "file":
|
|
1661
|
+
return typeof p.url === "string" && p.url.startsWith("data:image/");
|
|
1662
|
+
default:
|
|
1663
|
+
return false;
|
|
1664
|
+
}
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
// src/hooks/magic-context/sentinel.ts
|
|
1669
|
+
var WHOLE_MESSAGE_PLACEHOLDER_TEXT = "[dropped]";
|
|
1670
|
+
function modelAcceptsEmptyContent(providerID) {
|
|
1671
|
+
return providerID === "anthropic";
|
|
1672
|
+
}
|
|
1673
|
+
function isAnthropicFamilyRoute(providerID, modelID) {
|
|
1674
|
+
const provider = (providerID ?? "").toLowerCase();
|
|
1675
|
+
const model = (modelID ?? "").toLowerCase();
|
|
1676
|
+
return provider.includes("anthropic") || model.includes("claude") || model.includes("anthropic");
|
|
1677
|
+
}
|
|
1678
|
+
var REMOVED_REASONING_MARK = Symbol.for("magic-context.removed-reasoning");
|
|
1679
|
+
var NEUTRALIZED_ORIGINALS = new WeakMap;
|
|
1680
|
+
function neutralizeDroppedReasoningPart(part) {
|
|
1681
|
+
if (!isRecord(part))
|
|
1682
|
+
return;
|
|
1683
|
+
if (part.thinking === undefined && part.text === undefined)
|
|
1684
|
+
return;
|
|
1685
|
+
if (part.type === "text")
|
|
1686
|
+
return;
|
|
1687
|
+
NEUTRALIZED_ORIGINALS.set(part, { ...part });
|
|
1688
|
+
const cacheControl = part.cache_control;
|
|
1689
|
+
const cacheControlCamel = part.cacheControl;
|
|
1690
|
+
for (const key of Object.keys(part))
|
|
1691
|
+
delete part[key];
|
|
1692
|
+
part.type = "text";
|
|
1693
|
+
part.text = "";
|
|
1694
|
+
if (cacheControl !== undefined)
|
|
1695
|
+
part.cache_control = cacheControl;
|
|
1696
|
+
if (cacheControlCamel !== undefined)
|
|
1697
|
+
part.cacheControl = cacheControlCamel;
|
|
1698
|
+
Object.defineProperty(part, REMOVED_REASONING_MARK, {
|
|
1699
|
+
value: true,
|
|
1700
|
+
enumerable: false,
|
|
1701
|
+
configurable: true
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
function restoreNeutralizedReasoningPart(part, legacyCleared) {
|
|
1705
|
+
if (!isRecord(part))
|
|
1706
|
+
return false;
|
|
1707
|
+
const original = NEUTRALIZED_ORIGINALS.get(part);
|
|
1708
|
+
if (!original)
|
|
1709
|
+
return false;
|
|
1710
|
+
for (const key of Object.keys(part))
|
|
1711
|
+
delete part[key];
|
|
1712
|
+
Object.assign(part, original);
|
|
1713
|
+
if (legacyCleared) {
|
|
1714
|
+
if (part.thinking !== undefined)
|
|
1715
|
+
part.thinking = "[cleared]";
|
|
1716
|
+
if (part.text !== undefined)
|
|
1717
|
+
part.text = "[cleared]";
|
|
1718
|
+
}
|
|
1719
|
+
NEUTRALIZED_ORIGINALS.delete(part);
|
|
1720
|
+
delete part[REMOVED_REASONING_MARK];
|
|
1721
|
+
return true;
|
|
1722
|
+
}
|
|
1723
|
+
function isNeutralizedReasoningPart(part) {
|
|
1724
|
+
return isRecord(part) && part[REMOVED_REASONING_MARK] === true;
|
|
1725
|
+
}
|
|
1726
|
+
function neutralizedReasoningSource(part) {
|
|
1727
|
+
return isRecord(part) ? NEUTRALIZED_ORIGINALS.get(part) ?? part : part;
|
|
1728
|
+
}
|
|
1729
|
+
var VARIANT_CACHE_PRESERVING_MODELS = {
|
|
1730
|
+
"anthropic/claude-fable-5-1": "2026-09-02",
|
|
1731
|
+
"openai/gpt-6-astra": "2026-09-05",
|
|
1732
|
+
"anthropic/claude-opus-5-5": "2026-09-23"
|
|
1733
|
+
};
|
|
1734
|
+
function canonicalVariantModelIdentity(providerID, modelID) {
|
|
1735
|
+
const normalizedProviderID = providerID.toLowerCase();
|
|
1736
|
+
const isAnthropicFamily = normalizedProviderID === "anthropic" || normalizedProviderID === "google-vertex-anthropic" || normalizedProviderID.includes("bedrock");
|
|
1737
|
+
if (isAnthropicFamily && isFable51ThinkingBindingModel("anthropic", modelID)) {
|
|
1738
|
+
return "anthropic/claude-fable-5-1";
|
|
1739
|
+
}
|
|
1740
|
+
return canonicalModelIdentity(`${providerID}/${modelID}`).toLowerCase();
|
|
1741
|
+
}
|
|
1742
|
+
function variantChangeBustsProviderCache(providerID, modelID) {
|
|
1743
|
+
if (!providerID || !modelID)
|
|
1744
|
+
return false;
|
|
1745
|
+
const identity = canonicalVariantModelIdentity(providerID, modelID);
|
|
1746
|
+
if (Object.hasOwn(VARIANT_CACHE_PRESERVING_MODELS, identity))
|
|
1747
|
+
return false;
|
|
1748
|
+
const normalizedProviderID = providerID.toLowerCase();
|
|
1749
|
+
return normalizedProviderID === "anthropic" || normalizedProviderID === "google-vertex-anthropic" || normalizedProviderID.includes("bedrock");
|
|
1750
|
+
}
|
|
1751
|
+
function makeSentinel(originalPart) {
|
|
1752
|
+
const sentinel = {
|
|
1753
|
+
type: "text",
|
|
1754
|
+
text: ""
|
|
1755
|
+
};
|
|
1756
|
+
if (isRecord(originalPart)) {
|
|
1757
|
+
if (originalPart.cache_control !== undefined) {
|
|
1758
|
+
sentinel.cache_control = originalPart.cache_control;
|
|
1759
|
+
}
|
|
1760
|
+
if (originalPart.cacheControl !== undefined) {
|
|
1761
|
+
sentinel.cacheControl = originalPart.cacheControl;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
return sentinel;
|
|
1765
|
+
}
|
|
1766
|
+
function makeWholeMessageSentinel(providerID) {
|
|
1767
|
+
return {
|
|
1768
|
+
type: "text",
|
|
1769
|
+
text: modelAcceptsEmptyContent(providerID) ? "" : WHOLE_MESSAGE_PLACEHOLDER_TEXT
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
function wholeMessageNeutralizationRemoves(message, providerID) {
|
|
1773
|
+
return message.info.role === "system" && modelAcceptsEmptyContent(providerID);
|
|
1774
|
+
}
|
|
1775
|
+
function neutralizeWholeMessage(message, providerID) {
|
|
1776
|
+
message.parts.length = 0;
|
|
1777
|
+
if (!wholeMessageNeutralizationRemoves(message, providerID)) {
|
|
1778
|
+
message.parts.push(makeWholeMessageSentinel(providerID));
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
function isSentinel(part) {
|
|
1782
|
+
if (!isRecord(part))
|
|
1783
|
+
return false;
|
|
1784
|
+
if (part.type !== "text")
|
|
1785
|
+
return false;
|
|
1786
|
+
if (typeof part.text !== "string")
|
|
1787
|
+
return false;
|
|
1788
|
+
return part.text === "" || part.text === WHOLE_MESSAGE_PLACEHOLDER_TEXT;
|
|
1789
|
+
}
|
|
1790
|
+
function replaySentinelByMessageIds(messages, ids, providerID, hiddenSeamIds = new Set) {
|
|
1791
|
+
if (ids.size === 0)
|
|
1792
|
+
return { replayed: 0, missingIds: [] };
|
|
1793
|
+
const seen = new Set;
|
|
1794
|
+
let replayed = 0;
|
|
1795
|
+
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
1796
|
+
const msg = messages[index];
|
|
1797
|
+
const id = msg.info.id;
|
|
1798
|
+
if (!id || !ids.has(id))
|
|
1799
|
+
continue;
|
|
1800
|
+
seen.add(id);
|
|
1801
|
+
if (!modelAcceptsEmptyContent(providerID) && hiddenSeamIds.has(id)) {
|
|
1802
|
+
messages.splice(index, 1);
|
|
1803
|
+
replayed += 1;
|
|
1804
|
+
continue;
|
|
1805
|
+
}
|
|
1806
|
+
if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
|
|
1807
|
+
continue;
|
|
1808
|
+
if (wholeMessageNeutralizationRemoves(msg, providerID) && msg.parts.length === 0)
|
|
1809
|
+
continue;
|
|
1810
|
+
neutralizeWholeMessage(msg, providerID);
|
|
1811
|
+
replayed += 1;
|
|
1812
|
+
}
|
|
1813
|
+
const missingIds = [];
|
|
1814
|
+
for (const id of ids)
|
|
1815
|
+
if (!seen.has(id))
|
|
1816
|
+
missingIds.push(id);
|
|
1817
|
+
return { replayed, missingIds };
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
// src/hooks/magic-context/tool-input-size.ts
|
|
1821
|
+
var SKELETON_REAL_INPUT_MAX_BYTES = 1024;
|
|
1822
|
+
var encoder = new TextEncoder;
|
|
1823
|
+
function toolInputStringBytes(value) {
|
|
1824
|
+
const seen = new WeakSet;
|
|
1825
|
+
const visit = (candidate) => {
|
|
1826
|
+
if (typeof candidate === "string")
|
|
1827
|
+
return encoder.encode(candidate).length;
|
|
1828
|
+
if (candidate === null || typeof candidate !== "object")
|
|
1829
|
+
return 0;
|
|
1830
|
+
if (seen.has(candidate))
|
|
1831
|
+
return 0;
|
|
1832
|
+
seen.add(candidate);
|
|
1833
|
+
let total = 0;
|
|
1834
|
+
const values = Array.isArray(candidate) ? candidate : Object.values(candidate);
|
|
1835
|
+
for (const item of values)
|
|
1836
|
+
total += visit(item);
|
|
1837
|
+
return total;
|
|
1838
|
+
};
|
|
1839
|
+
return visit(value);
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
// src/hooks/magic-context/tool-drop-target.ts
|
|
1843
|
+
var DROP_PREFIX = "[dropped";
|
|
1844
|
+
var IGNORE_PART_TYPES = new Set([
|
|
1845
|
+
"thinking",
|
|
1846
|
+
"reasoning",
|
|
1847
|
+
"redacted_thinking",
|
|
1848
|
+
"meta",
|
|
1849
|
+
"step-start",
|
|
1850
|
+
"step-finish"
|
|
1851
|
+
]);
|
|
1852
|
+
function isToolCallId(value) {
|
|
1853
|
+
return typeof value === "string" && value.length > 0;
|
|
1854
|
+
}
|
|
1855
|
+
function getToolContent(part) {
|
|
1856
|
+
if (!isRecord(part))
|
|
1857
|
+
return;
|
|
1858
|
+
if (part.type === "tool" && isRecord(part.state)) {
|
|
1859
|
+
return typeof part.state.output === "string" ? part.state.output : undefined;
|
|
1860
|
+
}
|
|
1861
|
+
if (part.type === "tool_result") {
|
|
1862
|
+
return typeof part.content === "string" ? part.content : undefined;
|
|
1863
|
+
}
|
|
1864
|
+
return;
|
|
1865
|
+
}
|
|
1866
|
+
function setToolContent(part, content) {
|
|
1867
|
+
if (!isRecord(part))
|
|
1868
|
+
return;
|
|
1869
|
+
if (part.type === "tool" && isRecord(part.state)) {
|
|
1870
|
+
part.state.output = content;
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
if (part.type === "tool_result") {
|
|
1874
|
+
part.content = content;
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
function clonePart(part) {
|
|
1878
|
+
if (part === null || typeof part !== "object")
|
|
1879
|
+
return part;
|
|
1880
|
+
try {
|
|
1881
|
+
return structuredClone(part);
|
|
1882
|
+
} catch {
|
|
1883
|
+
try {
|
|
1884
|
+
return JSON.parse(JSON.stringify(part));
|
|
1885
|
+
} catch {
|
|
1886
|
+
return part;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
function clampCloneInPlace(occurrence, clamp) {
|
|
1891
|
+
const clone = clonePart(occurrence.part);
|
|
1892
|
+
clamp(clone);
|
|
1893
|
+
const parts = occurrence.message.parts;
|
|
1894
|
+
const index = parts.indexOf(servedPart(occurrence));
|
|
1895
|
+
if (index >= 0) {
|
|
1896
|
+
parts[index] = clone;
|
|
1897
|
+
occurrence.served = clone;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
function servedPart(occurrence) {
|
|
1901
|
+
return occurrence.served ?? occurrence.part;
|
|
1902
|
+
}
|
|
1903
|
+
function skeletonRealToolPart(part, tagId, stripAttachments = false) {
|
|
1904
|
+
if (!isRecord(part))
|
|
1905
|
+
return;
|
|
1906
|
+
const sentinel = `[dropped §${tagId}§]`;
|
|
1907
|
+
if (part.type === "tool" && isRecord(part.state)) {
|
|
1908
|
+
part.state.output = sentinel;
|
|
1909
|
+
if (stripAttachments)
|
|
1910
|
+
part.state.attachments = [];
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
if (part.type === "tool_result") {
|
|
1914
|
+
part.content = sentinel;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
function readToolPartRawInput(part) {
|
|
1918
|
+
if (!isRecord(part))
|
|
1919
|
+
return;
|
|
1920
|
+
if (part.type === "tool" && isRecord(part.state))
|
|
1921
|
+
return part.state.input;
|
|
1922
|
+
if (part.type === "tool-invocation")
|
|
1923
|
+
return part.args;
|
|
1924
|
+
if (part.type === "tool_use")
|
|
1925
|
+
return part.input;
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
function truncateToolPart(part, tagId) {
|
|
1929
|
+
if (!isRecord(part))
|
|
1930
|
+
return;
|
|
1931
|
+
const sentinel = `[dropped §${tagId}§]`;
|
|
1932
|
+
if (part.type === "tool" && isRecord(part.state)) {
|
|
1933
|
+
const state = part.state;
|
|
1934
|
+
state.output = sentinel;
|
|
1935
|
+
state.input = droppedInputMarker(tagId);
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
if (part.type === "tool_result") {
|
|
1939
|
+
part.content = sentinel;
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
if (part.type === "tool-invocation") {
|
|
1943
|
+
part.args = droppedInputMarker(tagId);
|
|
1944
|
+
return;
|
|
1945
|
+
}
|
|
1946
|
+
if (part.type === "tool_use") {
|
|
1947
|
+
part.input = droppedInputMarker(tagId);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
function editMarkerToolPart(part, tagId, stripAttachments = false) {
|
|
1951
|
+
if (!isRecord(part))
|
|
1952
|
+
return;
|
|
1953
|
+
const sentinel = `[dropped §${tagId}§]`;
|
|
1954
|
+
if (part.type === "tool" && isRecord(part.state)) {
|
|
1955
|
+
part.state.output = sentinel;
|
|
1956
|
+
if (stripAttachments)
|
|
1957
|
+
part.state.attachments = [];
|
|
1958
|
+
if (isRecord(part.state.input))
|
|
1959
|
+
applyEditMarkerToInput(part.state.input);
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
if (part.type === "tool_result") {
|
|
1963
|
+
part.content = sentinel;
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
if (part.type === "tool-invocation" && isRecord(part.args)) {
|
|
1967
|
+
applyEditMarkerToInput(part.args);
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
if (part.type === "tool_use" && isRecord(part.input)) {
|
|
1971
|
+
applyEditMarkerToInput(part.input);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
function readToolPartInput(part) {
|
|
1975
|
+
if (!isRecord(part))
|
|
1976
|
+
return null;
|
|
1977
|
+
if (part.type === "tool" && isRecord(part.state) && isRecord(part.state.input)) {
|
|
1978
|
+
return part.state.input;
|
|
1979
|
+
}
|
|
1980
|
+
if (part.type === "tool-invocation" && isRecord(part.args))
|
|
1981
|
+
return part.args;
|
|
1982
|
+
if (part.type === "tool_use" && isRecord(part.input))
|
|
1983
|
+
return part.input;
|
|
1984
|
+
return null;
|
|
1985
|
+
}
|
|
1986
|
+
function hasMeaningfulPart(part) {
|
|
1987
|
+
if (!isRecord(part))
|
|
1988
|
+
return false;
|
|
1989
|
+
const type = part.type;
|
|
1990
|
+
if (type === "text") {
|
|
1991
|
+
if (typeof part.text !== "string")
|
|
1992
|
+
return false;
|
|
1993
|
+
return stripTagPrefix(part.text).trim().length > 0;
|
|
1994
|
+
}
|
|
1995
|
+
if (typeof type !== "string")
|
|
1996
|
+
return false;
|
|
1997
|
+
if (IGNORE_PART_TYPES.has(type))
|
|
1998
|
+
return false;
|
|
1999
|
+
return true;
|
|
2000
|
+
}
|
|
2001
|
+
function clearThinkingParts(thinkingParts) {
|
|
2002
|
+
for (const part of thinkingParts)
|
|
2003
|
+
neutralizeDroppedReasoningPart(part);
|
|
2004
|
+
}
|
|
2005
|
+
function messageHasNativeReasoning(message) {
|
|
2006
|
+
return message.parts.some((part) => {
|
|
2007
|
+
if (!isRecord(part))
|
|
2008
|
+
return false;
|
|
2009
|
+
return ["thinking", "reasoning", "redacted_thinking"].includes(String(part.type));
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
function partHasCompletedResult(part) {
|
|
2013
|
+
if (!isRecord(part))
|
|
2014
|
+
return false;
|
|
2015
|
+
if (part.type === "tool") {
|
|
2016
|
+
if (!isRecord(part.state))
|
|
2017
|
+
return false;
|
|
2018
|
+
return typeof part.state.output === "string" || part.state.status === "error";
|
|
2019
|
+
}
|
|
2020
|
+
return part.type === "tool_result";
|
|
2021
|
+
}
|
|
2022
|
+
function extractToolCallObservation(part) {
|
|
2023
|
+
if (!isRecord(part))
|
|
2024
|
+
return null;
|
|
2025
|
+
if (part.type === "tool" && isToolCallId(part.callID)) {
|
|
2026
|
+
return { callId: part.callID, kind: "result" };
|
|
2027
|
+
}
|
|
2028
|
+
if (part.type === "tool-invocation" && isToolCallId(part.callID)) {
|
|
2029
|
+
return { callId: part.callID, kind: "invocation" };
|
|
2030
|
+
}
|
|
2031
|
+
if (part.type === "tool_use" && isToolCallId(part.id)) {
|
|
2032
|
+
return { callId: part.id, kind: "invocation" };
|
|
2033
|
+
}
|
|
2034
|
+
if (part.type === "tool_result" && isToolCallId(part.tool_use_id)) {
|
|
2035
|
+
return { callId: part.tool_use_id, kind: "result" };
|
|
2036
|
+
}
|
|
2037
|
+
return null;
|
|
2038
|
+
}
|
|
2039
|
+
function isDropContent(content) {
|
|
2040
|
+
return content.startsWith(DROP_PREFIX);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
class ToolMutationBatch {
|
|
2044
|
+
scopedSweep;
|
|
2045
|
+
servedMessages;
|
|
2046
|
+
partsToRemove = new Set;
|
|
2047
|
+
affectedMessages = new Set;
|
|
2048
|
+
messages;
|
|
2049
|
+
resolvedScopedSweep;
|
|
2050
|
+
constructor(messages, scopedSweep = false, servedMessages) {
|
|
2051
|
+
this.scopedSweep = scopedSweep;
|
|
2052
|
+
this.servedMessages = servedMessages;
|
|
2053
|
+
this.messages = messages;
|
|
2054
|
+
}
|
|
2055
|
+
markForRemoval(occurrence) {
|
|
2056
|
+
this.partsToRemove.add(servedPart(occurrence));
|
|
2057
|
+
this.affectedMessages.add(occurrence.message);
|
|
2058
|
+
}
|
|
2059
|
+
wouldStrandConversationEnd(occurrences) {
|
|
2060
|
+
const served = this.servedMessages ?? this.messages;
|
|
2061
|
+
let end;
|
|
2062
|
+
for (let i = served.length - 1;i >= 0 && end === undefined; i -= 1) {
|
|
2063
|
+
if (served[i].parts.some(hasMeaningfulPart))
|
|
2064
|
+
end = served[i];
|
|
2065
|
+
}
|
|
2066
|
+
if (!end || !occurrences.some((occurrence) => occurrence.message === end))
|
|
2067
|
+
return false;
|
|
2068
|
+
const leaving = new Set(occurrences.map(servedPart));
|
|
2069
|
+
const survives = (part) => !leaving.has(part) && !this.partsToRemove.has(part);
|
|
2070
|
+
return end.info.role === "assistant" ? !end.parts.some((part) => partHasCompletedResult(part) && survives(part)) : !end.parts.some((part) => hasMeaningfulPart(part) && survives(part));
|
|
2071
|
+
}
|
|
2072
|
+
finalize() {
|
|
2073
|
+
if (this.partsToRemove.size === 0)
|
|
2074
|
+
return;
|
|
2075
|
+
for (const message of this.affectedMessages) {
|
|
2076
|
+
message.parts = message.parts.filter((p) => !this.partsToRemove.has(p));
|
|
2077
|
+
}
|
|
2078
|
+
const scopedSweep = this.resolveScopedSweep();
|
|
2079
|
+
const removed = new Set;
|
|
2080
|
+
let writeIndex = 0;
|
|
2081
|
+
for (let i = 0;i < this.messages.length; i += 1) {
|
|
2082
|
+
if ((!scopedSweep || this.affectedMessages.has(this.messages[i])) && !this.messages[i].parts.some(hasMeaningfulPart)) {
|
|
2083
|
+
removed.add(this.messages[i]);
|
|
2084
|
+
} else {
|
|
2085
|
+
this.messages[writeIndex++] = this.messages[i];
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
this.messages.length = writeIndex;
|
|
2089
|
+
this.pruneServedRows(removed);
|
|
2090
|
+
this.partsToRemove.clear();
|
|
2091
|
+
this.affectedMessages.clear();
|
|
2092
|
+
}
|
|
2093
|
+
resolveScopedSweep() {
|
|
2094
|
+
if (typeof this.scopedSweep !== "function")
|
|
2095
|
+
return this.scopedSweep;
|
|
2096
|
+
if (this.resolvedScopedSweep === undefined) {
|
|
2097
|
+
this.resolvedScopedSweep = this.scopedSweep({
|
|
2098
|
+
legacy: this.messages.filter((message) => message.parts.some(hasMeaningfulPart)),
|
|
2099
|
+
scoped: this.messages.filter((message) => !this.affectedMessages.has(message) || message.parts.some(hasMeaningfulPart))
|
|
2100
|
+
});
|
|
2101
|
+
}
|
|
2102
|
+
return this.resolvedScopedSweep;
|
|
2103
|
+
}
|
|
2104
|
+
pruneServedRows(removed) {
|
|
2105
|
+
const served = this.servedMessages;
|
|
2106
|
+
if (!served || served === this.messages || removed.size === 0)
|
|
2107
|
+
return;
|
|
2108
|
+
for (let i = served.length - 1;i >= 0; i -= 1) {
|
|
2109
|
+
if (removed.has(served[i]))
|
|
2110
|
+
served.splice(i, 1);
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
function createToolDropTarget(compositeKey, thinkingParts, index, batch, tagId) {
|
|
2115
|
+
const drop = () => {
|
|
2116
|
+
const entry = index.get(compositeKey);
|
|
2117
|
+
if (!entry || entry.occurrences.length === 0)
|
|
2118
|
+
return "absent";
|
|
2119
|
+
if (!entry.hasResult)
|
|
2120
|
+
return "incomplete";
|
|
2121
|
+
if (batch.wouldStrandConversationEnd(entry.occurrences))
|
|
2122
|
+
return skeletonReal();
|
|
2123
|
+
for (const occurrence of entry.occurrences) {
|
|
2124
|
+
batch.markForRemoval(occurrence);
|
|
2125
|
+
}
|
|
2126
|
+
clearThinkingParts(thinkingParts);
|
|
2127
|
+
index.delete(compositeKey);
|
|
2128
|
+
return "removed";
|
|
2129
|
+
};
|
|
2130
|
+
const truncate = () => {
|
|
2131
|
+
const entry = index.get(compositeKey);
|
|
2132
|
+
if (!entry || entry.occurrences.length === 0)
|
|
2133
|
+
return "absent";
|
|
2134
|
+
if (!entry.hasResult)
|
|
2135
|
+
return "incomplete";
|
|
2136
|
+
for (const occurrence of entry.occurrences) {
|
|
2137
|
+
clampCloneInPlace(occurrence, (part) => truncateToolPart(part, tagId));
|
|
2138
|
+
}
|
|
2139
|
+
clearThinkingParts(thinkingParts);
|
|
2140
|
+
return "truncated";
|
|
2141
|
+
};
|
|
2142
|
+
const skeletonReal = () => {
|
|
2143
|
+
const entry = index.get(compositeKey);
|
|
2144
|
+
if (!entry || entry.occurrences.length === 0)
|
|
2145
|
+
return "absent";
|
|
2146
|
+
if (!entry.hasResult)
|
|
2147
|
+
return "incomplete";
|
|
2148
|
+
for (const occurrence of entry.occurrences) {
|
|
2149
|
+
clampCloneInPlace(occurrence, (part) => skeletonRealToolPart(part, tagId));
|
|
2150
|
+
}
|
|
2151
|
+
clearThinkingParts(thinkingParts);
|
|
2152
|
+
return "truncated";
|
|
2153
|
+
};
|
|
2154
|
+
const skeletonStripped = () => {
|
|
2155
|
+
const entry = index.get(compositeKey);
|
|
2156
|
+
if (!entry || entry.occurrences.length === 0)
|
|
2157
|
+
return "absent";
|
|
2158
|
+
if (!entry.hasResult)
|
|
2159
|
+
return "incomplete";
|
|
2160
|
+
for (const occurrence of entry.occurrences) {
|
|
2161
|
+
clampCloneInPlace(occurrence, (part) => skeletonRealToolPart(part, tagId, true));
|
|
2162
|
+
}
|
|
2163
|
+
clearThinkingParts(thinkingParts);
|
|
2164
|
+
return "truncated";
|
|
2165
|
+
};
|
|
2166
|
+
const hasAttachments = () => index.get(compositeKey)?.occurrences.some(({ part }) => isRecord(part) && isRecord(part.state) && Array.isArray(part.state.attachments) && part.state.attachments.length > 0) ?? false;
|
|
2167
|
+
const readRawInput = () => {
|
|
2168
|
+
const entry = index.get(compositeKey);
|
|
2169
|
+
if (!entry)
|
|
2170
|
+
return;
|
|
2171
|
+
for (const occurrence of entry.occurrences) {
|
|
2172
|
+
const input = readToolPartRawInput(occurrence.part);
|
|
2173
|
+
if (input !== undefined)
|
|
2174
|
+
return input;
|
|
2175
|
+
}
|
|
2176
|
+
return;
|
|
2177
|
+
};
|
|
2178
|
+
const applyEditMarker = (stripAttachments) => {
|
|
2179
|
+
const entry = index.get(compositeKey);
|
|
2180
|
+
if (!entry || entry.occurrences.length === 0)
|
|
2181
|
+
return "absent";
|
|
2182
|
+
if (!entry.hasResult)
|
|
2183
|
+
return "incomplete";
|
|
2184
|
+
for (const occurrence of entry.occurrences) {
|
|
2185
|
+
clampCloneInPlace(occurrence, (part) => editMarkerToolPart(part, tagId, stripAttachments));
|
|
2186
|
+
}
|
|
2187
|
+
clearThinkingParts(thinkingParts);
|
|
2188
|
+
return "truncated";
|
|
2189
|
+
};
|
|
2190
|
+
return {
|
|
2191
|
+
dropReasoningParts: thinkingParts,
|
|
2192
|
+
mutationParts: index.get(compositeKey)?.occurrences.map(({ message, part }) => ({ message, part })) ?? [],
|
|
2193
|
+
measureReclaim: (skeleton) => {
|
|
2194
|
+
const entry = index.get(compositeKey);
|
|
2195
|
+
const parts = entry?.occurrences.map((occ) => occ.part) ?? [];
|
|
2196
|
+
const count = (parts) => estimateMessageTokens({
|
|
2197
|
+
info: { id: "reclaim", role: "assistant" },
|
|
2198
|
+
parts
|
|
2199
|
+
});
|
|
2200
|
+
const before = count(parts);
|
|
2201
|
+
const retained = skeleton ? structuredClone(parts) : [];
|
|
2202
|
+
for (const part of retained)
|
|
2203
|
+
skeletonRealToolPart(part, tagId);
|
|
2204
|
+
const after = count(retained);
|
|
2205
|
+
return {
|
|
2206
|
+
beforeTools: before.toolCall,
|
|
2207
|
+
afterTools: after.toolCall,
|
|
2208
|
+
beforeProse: 0,
|
|
2209
|
+
afterProse: 0
|
|
2210
|
+
};
|
|
2211
|
+
},
|
|
2212
|
+
setContent: (content) => {
|
|
2213
|
+
if (isDropContent(content)) {
|
|
2214
|
+
drop();
|
|
2215
|
+
return true;
|
|
2216
|
+
}
|
|
2217
|
+
const entry = index.get(compositeKey);
|
|
2218
|
+
if (!entry)
|
|
2219
|
+
return false;
|
|
2220
|
+
let changed = false;
|
|
2221
|
+
for (const occurrence of entry.occurrences) {
|
|
2222
|
+
if (occurrence.kind !== "result")
|
|
2223
|
+
continue;
|
|
2224
|
+
const prevContent = getToolContent(occurrence.part);
|
|
2225
|
+
if (prevContent !== content) {
|
|
2226
|
+
setToolContent(occurrence.part, content);
|
|
2227
|
+
changed = true;
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
return changed;
|
|
2231
|
+
},
|
|
2232
|
+
drop,
|
|
2233
|
+
truncate,
|
|
2234
|
+
skeletonReal,
|
|
2235
|
+
skeletonStripped,
|
|
2236
|
+
hasAttachments,
|
|
2237
|
+
editMarker: () => applyEditMarker(false),
|
|
2238
|
+
editMarkerStripped: () => applyEditMarker(true),
|
|
2239
|
+
inputStringBytes: () => {
|
|
2240
|
+
const entry = index.get(compositeKey);
|
|
2241
|
+
if (!entry || entry.occurrences.length === 0)
|
|
2242
|
+
return null;
|
|
2243
|
+
return toolInputStringBytes(readRawInput());
|
|
2244
|
+
},
|
|
2245
|
+
wouldStrandConversationEnd: () => {
|
|
2246
|
+
const entry = index.get(compositeKey);
|
|
2247
|
+
if (!entry || entry.occurrences.length === 0)
|
|
2248
|
+
return false;
|
|
2249
|
+
return batch.wouldStrandConversationEnd(entry.occurrences);
|
|
2250
|
+
},
|
|
2251
|
+
canDrop: () => {
|
|
2252
|
+
const entry = index.get(compositeKey);
|
|
2253
|
+
return !!entry && entry.occurrences.length > 0 && entry.hasResult && !entry.occurrences.some((occurrence) => toolPartHasUserAnswer(occurrence.part));
|
|
2254
|
+
},
|
|
2255
|
+
requiresToolArcSkeleton: thinkingParts.length > 0 || (index.get(compositeKey)?.occurrences.some((occurrence) => messageHasNativeReasoning(occurrence.message)) ?? false),
|
|
2256
|
+
readInput: () => {
|
|
2257
|
+
const entry = index.get(compositeKey);
|
|
2258
|
+
if (!entry)
|
|
2259
|
+
return null;
|
|
2260
|
+
for (const occurrence of entry.occurrences) {
|
|
2261
|
+
if (occurrence.kind !== "invocation")
|
|
2262
|
+
continue;
|
|
2263
|
+
const input = readToolPartInput(occurrence.part);
|
|
2264
|
+
if (input)
|
|
2265
|
+
return input;
|
|
2266
|
+
}
|
|
2267
|
+
for (const occurrence of entry.occurrences) {
|
|
2268
|
+
const input = readToolPartInput(occurrence.part);
|
|
2269
|
+
if (input)
|
|
2270
|
+
return input;
|
|
2271
|
+
}
|
|
2272
|
+
return null;
|
|
2273
|
+
}
|
|
2274
|
+
};
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
// src/hooks/magic-context/read-session-chunk.ts
|
|
2278
|
+
var BLOCK_TOKEN_MEMO_MAX = 2048;
|
|
2279
|
+
var blockTokenMemo = new Map;
|
|
2280
|
+
function estimateBlockTokens(blockText) {
|
|
2281
|
+
const cached = blockTokenMemo.get(blockText);
|
|
2282
|
+
if (cached !== undefined) {
|
|
2283
|
+
blockTokenMemo.delete(blockText);
|
|
2284
|
+
blockTokenMemo.set(blockText, cached);
|
|
2285
|
+
return cached;
|
|
2286
|
+
}
|
|
2287
|
+
const count = estimateTokens(blockText);
|
|
2288
|
+
if (blockTokenMemo.size >= BLOCK_TOKEN_MEMO_MAX) {
|
|
2289
|
+
const oldest = blockTokenMemo.keys().next().value;
|
|
2290
|
+
if (oldest !== undefined)
|
|
2291
|
+
blockTokenMemo.delete(oldest);
|
|
2292
|
+
}
|
|
2293
|
+
blockTokenMemo.set(blockText, count);
|
|
2294
|
+
return count;
|
|
2295
|
+
}
|
|
2296
|
+
var activeRawMessageCache = null;
|
|
2297
|
+
var activeAbsoluteCountCache = null;
|
|
2298
|
+
var sessionProviders = new Map;
|
|
2299
|
+
function resolveHostServedBoundaryId2(sessionId, messageId) {
|
|
2300
|
+
if (messageId.length === 0)
|
|
2301
|
+
return messageId;
|
|
2302
|
+
return sessionProviders.get(sessionId)?.provider.readServedBoundaryId?.(messageId) ?? messageId;
|
|
2303
|
+
}
|
|
2304
|
+
function hasRawMessageProvider2(sessionId) {
|
|
2305
|
+
return sessionProviders.has(sessionId);
|
|
2306
|
+
}
|
|
2307
|
+
function setRawMessageProvider2(sessionId, provider) {
|
|
2308
|
+
const current = sessionProviders.get(sessionId);
|
|
2309
|
+
const registration = current?.provider === provider ? current : { provider, scopes: 0 };
|
|
2310
|
+
registration.scopes += 1;
|
|
2311
|
+
sessionProviders.set(sessionId, registration);
|
|
2312
|
+
let active = true;
|
|
2313
|
+
return () => {
|
|
2314
|
+
if (!active)
|
|
2315
|
+
return;
|
|
2316
|
+
active = false;
|
|
2317
|
+
registration.scopes -= 1;
|
|
2318
|
+
if (registration.scopes === 0 && sessionProviders.get(sessionId) === registration) {
|
|
2319
|
+
sessionProviders.delete(sessionId);
|
|
2320
|
+
}
|
|
2321
|
+
};
|
|
2322
|
+
}
|
|
2323
|
+
var boundedProviderWrappers = new WeakMap;
|
|
2324
|
+
function setBoundedRawMessageProvider2(sessionId, provider) {
|
|
2325
|
+
let wrapper = boundedProviderWrappers.get(provider);
|
|
2326
|
+
if (!wrapper) {
|
|
2327
|
+
wrapper = {
|
|
2328
|
+
...provider,
|
|
2329
|
+
readMessages: () => {
|
|
2330
|
+
throw new Error("Bounded raw-message providers cannot read complete history; full reads are reserved for store-generation conversion");
|
|
2331
|
+
}
|
|
2332
|
+
};
|
|
2333
|
+
boundedProviderWrappers.set(provider, wrapper);
|
|
2334
|
+
}
|
|
2335
|
+
return setRawMessageProvider2(sessionId, wrapper);
|
|
2336
|
+
}
|
|
2337
|
+
function withRawMessageProvider2(sessionId, provider, fn) {
|
|
2338
|
+
const cleanup = setRawMessageProvider2(sessionId, provider);
|
|
2339
|
+
let result;
|
|
2340
|
+
try {
|
|
2341
|
+
result = fn();
|
|
2342
|
+
} catch (error) {
|
|
2343
|
+
cleanup();
|
|
2344
|
+
throw error;
|
|
2345
|
+
}
|
|
2346
|
+
if (result !== null && typeof result === "object" && typeof result.then === "function") {
|
|
2347
|
+
return result.finally(cleanup);
|
|
2348
|
+
}
|
|
2349
|
+
cleanup();
|
|
2350
|
+
return result;
|
|
2351
|
+
}
|
|
2352
|
+
var SYSTEM_REMINDER_BLOCK_REGEX = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
2353
|
+
function cleanUserText2(text) {
|
|
2354
|
+
return stripOutsideSteeringWrappers(text, (segment) => segment.replace(SYSTEM_REMINDER_BLOCK_REGEX, "").replace(OMO_INTERNAL_INITIATOR_MARKER, "")).trim();
|
|
2355
|
+
}
|
|
2356
|
+
function hasMeaningfulChunkUserText(parts) {
|
|
2357
|
+
for (const part of parts) {
|
|
2358
|
+
if (part === null || typeof part !== "object")
|
|
2359
|
+
continue;
|
|
2360
|
+
const candidate = part;
|
|
2361
|
+
if (candidate.type !== "text" || typeof candidate.text !== "string")
|
|
2362
|
+
continue;
|
|
2363
|
+
if (candidate.ignored === true)
|
|
2364
|
+
continue;
|
|
2365
|
+
const cleaned = cleanUserText2(candidate.text);
|
|
2366
|
+
if (!cleaned)
|
|
2367
|
+
continue;
|
|
2368
|
+
if (isSystemDirective(cleaned))
|
|
2369
|
+
continue;
|
|
2370
|
+
return true;
|
|
2371
|
+
}
|
|
2372
|
+
return false;
|
|
2373
|
+
}
|
|
2374
|
+
function withRawSessionMessageCache2(fn) {
|
|
2375
|
+
const outerCache = activeRawMessageCache;
|
|
2376
|
+
if (!outerCache) {
|
|
2377
|
+
activeRawMessageCache = new Map;
|
|
2378
|
+
activeAbsoluteCountCache = new Map;
|
|
2379
|
+
}
|
|
2380
|
+
try {
|
|
2381
|
+
return fn();
|
|
2382
|
+
} finally {
|
|
2383
|
+
if (!outerCache) {
|
|
2384
|
+
activeRawMessageCache = null;
|
|
2385
|
+
activeAbsoluteCountCache = null;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
function readRawSessionMessages2(sessionId) {
|
|
2390
|
+
if (activeRawMessageCache) {
|
|
2391
|
+
const cached = activeRawMessageCache.get(sessionId);
|
|
2392
|
+
if (cached?.coveredFromOrdinal === 1 && cached.coveredToOrdinal === null) {
|
|
2393
|
+
return cached.messages;
|
|
2394
|
+
}
|
|
2395
|
+
const messages = readRawSessionMessagesFromSource(sessionId);
|
|
2396
|
+
if (!cached) {
|
|
2397
|
+
activeRawMessageCache.set(sessionId, {
|
|
2398
|
+
messages,
|
|
2399
|
+
coveredFromOrdinal: 1,
|
|
2400
|
+
coveredToOrdinal: null
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
return messages;
|
|
2404
|
+
}
|
|
2405
|
+
return readRawSessionMessagesFromSource(sessionId);
|
|
2406
|
+
}
|
|
2407
|
+
function readRawSessionMessagePage2(sessionId, afterOrdinal, limit, finalWatermark, after) {
|
|
2408
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2409
|
+
if (provider?.readMessagePage) {
|
|
2410
|
+
return provider.readMessagePage(afterOrdinal, limit, finalWatermark, after);
|
|
2411
|
+
}
|
|
2412
|
+
if (provider) {
|
|
2413
|
+
return provider.readMessages().filter((message) => message.ordinal > afterOrdinal && message.ordinal <= finalWatermark).slice(0, limit);
|
|
2414
|
+
}
|
|
2415
|
+
if (!openCodeDbExists())
|
|
2416
|
+
return [];
|
|
2417
|
+
return withReadOnlySessionDb((db) => readRawSessionMessagePageFromDb2(db, sessionId, afterOrdinal, limit, finalWatermark, after));
|
|
2418
|
+
}
|
|
2419
|
+
function getRawSessionMessageOrdinalCount2(sessionId) {
|
|
2420
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2421
|
+
if (provider) {
|
|
2422
|
+
if (provider.getMessageCount)
|
|
2423
|
+
return provider.getMessageCount();
|
|
2424
|
+
const messages = provider.readMessages();
|
|
2425
|
+
return messages.reduce((maximum, message) => Math.max(maximum, message.ordinal), messages.length);
|
|
2426
|
+
}
|
|
2427
|
+
if (!openCodeDbExists())
|
|
2428
|
+
return 0;
|
|
2429
|
+
return withReadOnlySessionDb((db) => countRawSessionMessageOrdinalsFromDb2(db, sessionId));
|
|
2430
|
+
}
|
|
2431
|
+
var RAW_MESSAGE_RANGE_PAGE_SIZE = 100;
|
|
2432
|
+
function readRawSessionMessageRangeFromSource(sessionId, fromOrdinal, toOrdinal) {
|
|
2433
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2434
|
+
if (provider?.iterateMessageRange)
|
|
2435
|
+
return [...provider.iterateMessageRange(fromOrdinal, toOrdinal)];
|
|
2436
|
+
if (provider && !provider.readMessagePage) {
|
|
2437
|
+
return provider.readMessages().filter((message) => message.ordinal >= fromOrdinal && message.ordinal <= toOrdinal);
|
|
2438
|
+
}
|
|
2439
|
+
if (!provider && !openCodeDbExists())
|
|
2440
|
+
return [];
|
|
2441
|
+
const messages = [];
|
|
2442
|
+
let afterOrdinal = fromOrdinal - 1;
|
|
2443
|
+
let after;
|
|
2444
|
+
while (afterOrdinal < toOrdinal) {
|
|
2445
|
+
const limit = Math.min(RAW_MESSAGE_RANGE_PAGE_SIZE, toOrdinal - afterOrdinal);
|
|
2446
|
+
const page = provider?.readMessagePage ? provider.readMessagePage(afterOrdinal, limit, toOrdinal, after) : withReadOnlySessionDb((db) => readRawSessionMessagePageFromDb2(db, sessionId, afterOrdinal, limit, toOrdinal, after));
|
|
2447
|
+
if (page.length === 0)
|
|
2448
|
+
break;
|
|
2449
|
+
let nextOrdinal = afterOrdinal;
|
|
2450
|
+
for (const message of page) {
|
|
2451
|
+
if (message.ordinal < fromOrdinal || message.ordinal > toOrdinal)
|
|
2452
|
+
continue;
|
|
2453
|
+
messages.push(message);
|
|
2454
|
+
nextOrdinal = Math.max(nextOrdinal, message.ordinal);
|
|
2455
|
+
}
|
|
2456
|
+
if (nextOrdinal <= afterOrdinal)
|
|
2457
|
+
break;
|
|
2458
|
+
afterOrdinal = nextOrdinal;
|
|
2459
|
+
const last = page.at(-1);
|
|
2460
|
+
after = last ? { timeCreated: last.createdAt ?? 0, id: last.id } : undefined;
|
|
2461
|
+
}
|
|
2462
|
+
return messages;
|
|
2463
|
+
}
|
|
2464
|
+
var RAW_MESSAGE_VISIT_PAGE_SIZE2 = 50;
|
|
2465
|
+
function visitRawSessionMessages2(sessionId, fromOrdinal, toOrdinal, visit, options = {}) {
|
|
2466
|
+
const from = Math.max(1, Math.floor(fromOrdinal));
|
|
2467
|
+
const to = Math.floor(toOrdinal);
|
|
2468
|
+
if (to < from)
|
|
2469
|
+
return;
|
|
2470
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2471
|
+
if (provider?.iterateMessageRange) {
|
|
2472
|
+
for (const message of provider.iterateMessageRange(from, to)) {
|
|
2473
|
+
if (!visit(message))
|
|
2474
|
+
return;
|
|
2475
|
+
}
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
if (provider && !provider.readMessagePage) {
|
|
2479
|
+
for (const message of provider.readMessages()) {
|
|
2480
|
+
if (message.ordinal < from || message.ordinal > to)
|
|
2481
|
+
continue;
|
|
2482
|
+
if (!visit(message))
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
return;
|
|
2486
|
+
}
|
|
2487
|
+
if (!provider && !openCodeDbExists())
|
|
2488
|
+
return;
|
|
2489
|
+
const pageSize = Math.max(1, Math.floor(options.pageSize ?? RAW_MESSAGE_VISIT_PAGE_SIZE2));
|
|
2490
|
+
let afterOrdinal = from - 1;
|
|
2491
|
+
let after;
|
|
2492
|
+
while (afterOrdinal < to) {
|
|
2493
|
+
const limit = Math.min(pageSize, to - afterOrdinal);
|
|
2494
|
+
const cursor = afterOrdinal;
|
|
2495
|
+
const page = provider?.readMessagePage ? provider.readMessagePage(cursor, limit, to, after) : withReadOnlySessionDb((db) => options.summary ? readRawSessionMessageSummaryPageFromDb2(db, sessionId, cursor, limit, to, after) : readRawSessionMessagePageFromDb2(db, sessionId, cursor, limit, to, after));
|
|
2496
|
+
if (page.length === 0)
|
|
2497
|
+
return;
|
|
2498
|
+
let nextOrdinal = afterOrdinal;
|
|
2499
|
+
for (const message of page) {
|
|
2500
|
+
if (message.ordinal < from || message.ordinal > to)
|
|
2501
|
+
continue;
|
|
2502
|
+
if (!visit(message))
|
|
2503
|
+
return;
|
|
2504
|
+
nextOrdinal = Math.max(nextOrdinal, message.ordinal);
|
|
2505
|
+
}
|
|
2506
|
+
if (nextOrdinal <= afterOrdinal)
|
|
2507
|
+
return;
|
|
2508
|
+
afterOrdinal = nextOrdinal;
|
|
2509
|
+
const last = page.at(-1);
|
|
2510
|
+
after = last ? { timeCreated: last.createdAt ?? 0, id: last.id } : undefined;
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
function readRawSessionMessageRange2(sessionId, fromOrdinal, toOrdinal) {
|
|
2514
|
+
const from = Math.max(1, Math.floor(fromOrdinal));
|
|
2515
|
+
const to = Math.floor(toOrdinal);
|
|
2516
|
+
if (to < from)
|
|
2517
|
+
return [];
|
|
2518
|
+
const cached = activeRawMessageCache?.get(sessionId);
|
|
2519
|
+
if (!cached)
|
|
2520
|
+
return readRawSessionMessageRangeFromSource(sessionId, from, to);
|
|
2521
|
+
const coveredTo = cached.coveredToOrdinal ?? Number.POSITIVE_INFINITY;
|
|
2522
|
+
const overlapFrom = Math.max(from, cached.coveredFromOrdinal);
|
|
2523
|
+
const overlapTo = Math.min(to, coveredTo);
|
|
2524
|
+
if (overlapTo < overlapFrom) {
|
|
2525
|
+
return readRawSessionMessageRangeFromSource(sessionId, from, to);
|
|
2526
|
+
}
|
|
2527
|
+
const messages = [];
|
|
2528
|
+
if (from < overlapFrom) {
|
|
2529
|
+
messages.push(...readRawSessionMessageRangeFromSource(sessionId, from, overlapFrom - 1));
|
|
2530
|
+
}
|
|
2531
|
+
messages.push(...cached.messages.filter((message) => message.ordinal >= overlapFrom && message.ordinal <= overlapTo));
|
|
2532
|
+
if (overlapTo < to) {
|
|
2533
|
+
messages.push(...readRawSessionMessageRangeFromSource(sessionId, overlapTo + 1, to));
|
|
2534
|
+
}
|
|
2535
|
+
return messages;
|
|
2536
|
+
}
|
|
2537
|
+
readRawSessionMessages2.readPage = readRawSessionMessagePage2;
|
|
2538
|
+
readRawSessionMessages2.getCount = getRawSessionMessageOrdinalCount2;
|
|
2539
|
+
readRawSessionMessages2.prepare = prepareRawSessionOrdinals2;
|
|
2540
|
+
async function prepareRawSessionOrdinals2(sessionId) {
|
|
2541
|
+
if (sessionProviders.get(sessionId)?.provider)
|
|
2542
|
+
return true;
|
|
2543
|
+
if (!openCodeDbExists())
|
|
2544
|
+
return true;
|
|
2545
|
+
const db = withReadOnlySessionDb((connection) => connection);
|
|
2546
|
+
let timer;
|
|
2547
|
+
const deadline = Date.now() + 250;
|
|
2548
|
+
const prepare = async () => {
|
|
2549
|
+
for (let attempt = 0;attempt < 3 && Date.now() < deadline; attempt++) {
|
|
2550
|
+
if (await prewarmRawSessionOrdinalsForDb(db, sessionId) === "warm")
|
|
2551
|
+
return true;
|
|
2552
|
+
}
|
|
2553
|
+
return false;
|
|
2554
|
+
};
|
|
2555
|
+
try {
|
|
2556
|
+
const ready = await Promise.race([
|
|
2557
|
+
prepare(),
|
|
2558
|
+
new Promise((resolve) => {
|
|
2559
|
+
timer = setTimeout(() => resolve(false), 250);
|
|
2560
|
+
})
|
|
2561
|
+
]);
|
|
2562
|
+
if (!ready) {
|
|
2563
|
+
sessionLog2(sessionId, "WARN canonical ordinal preparation unavailable within 250ms; exact reads must defer or retry");
|
|
2564
|
+
}
|
|
2565
|
+
return ready;
|
|
2566
|
+
} finally {
|
|
2567
|
+
clearTimeout(timer);
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
function primeTailRawMessageCache2(args) {
|
|
2571
|
+
const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
|
|
2572
|
+
if (!activeRawMessageCache)
|
|
2573
|
+
return false;
|
|
2574
|
+
if (activeRawMessageCache.has(sessionId))
|
|
2575
|
+
return false;
|
|
2576
|
+
if (lastCompartmentEnd < 1 || !anchorMessageId)
|
|
2577
|
+
return false;
|
|
2578
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2579
|
+
if (provider) {
|
|
2580
|
+
if (!provider.readMessagePage || !provider.getMessageCount)
|
|
2581
|
+
return false;
|
|
2582
|
+
const absoluteMessageCount = provider.getMessageCount();
|
|
2583
|
+
const messages = readRawSessionMessageRange2(sessionId, lastCompartmentEnd, absoluteMessageCount);
|
|
2584
|
+
if (messages.find((message) => message.ordinal === lastCompartmentEnd)?.id !== anchorMessageId)
|
|
2585
|
+
return false;
|
|
2586
|
+
activeRawMessageCache.set(sessionId, {
|
|
2587
|
+
messages,
|
|
2588
|
+
coveredFromOrdinal: lastCompartmentEnd,
|
|
2589
|
+
coveredToOrdinal: lastCompartmentEnd === 1 ? null : absoluteMessageCount
|
|
2590
|
+
});
|
|
2591
|
+
activeAbsoluteCountCache?.set(sessionId, absoluteMessageCount);
|
|
2592
|
+
return true;
|
|
2593
|
+
}
|
|
2594
|
+
if (!openCodeDbExists())
|
|
2595
|
+
return false;
|
|
2596
|
+
const result = withReadOnlySessionDb((db) => readRawSessionTailFromDb2(db, sessionId, lastCompartmentEnd, anchorMessageId));
|
|
2597
|
+
if (!result)
|
|
2598
|
+
return false;
|
|
2599
|
+
activeRawMessageCache.set(sessionId, {
|
|
2600
|
+
messages: result.messages,
|
|
2601
|
+
coveredFromOrdinal: lastCompartmentEnd,
|
|
2602
|
+
coveredToOrdinal: lastCompartmentEnd === 1 ? null : result.absoluteMessageCount
|
|
2603
|
+
});
|
|
2604
|
+
activeAbsoluteCountCache?.set(sessionId, result.absoluteMessageCount);
|
|
2605
|
+
return true;
|
|
2606
|
+
}
|
|
2607
|
+
function getCachedAbsoluteMessageCount2(sessionId) {
|
|
2608
|
+
return activeAbsoluteCountCache?.get(sessionId) ?? null;
|
|
2609
|
+
}
|
|
2610
|
+
function primeInMemoryTailRawMessageCache2(args) {
|
|
2611
|
+
const { sessionId, messages, absoluteMessageCount } = args;
|
|
2612
|
+
if (!activeRawMessageCache)
|
|
2613
|
+
return false;
|
|
2614
|
+
if (activeRawMessageCache.has(sessionId))
|
|
2615
|
+
return false;
|
|
2616
|
+
const coveredFromOrdinal = messages[0]?.ordinal ?? absoluteMessageCount + 1;
|
|
2617
|
+
activeRawMessageCache.set(sessionId, {
|
|
2618
|
+
messages,
|
|
2619
|
+
coveredFromOrdinal,
|
|
2620
|
+
coveredToOrdinal: coveredFromOrdinal === 1 ? null : absoluteMessageCount
|
|
2621
|
+
});
|
|
2622
|
+
activeAbsoluteCountCache?.set(sessionId, absoluteMessageCount);
|
|
2623
|
+
return true;
|
|
2624
|
+
}
|
|
2625
|
+
function readRawSessionMessageOrdinalPage2(sessionId, after, limit) {
|
|
2626
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2627
|
+
if (provider?.readMessageOrdinalPage)
|
|
2628
|
+
return provider.readMessageOrdinalPage(after, limit);
|
|
2629
|
+
if (provider) {
|
|
2630
|
+
const rows = provider.readMessages().map((message) => ({
|
|
2631
|
+
id: message.id,
|
|
2632
|
+
timeCreated: message.createdAt ?? message.ordinal,
|
|
2633
|
+
contributesOrdinal: true,
|
|
2634
|
+
hasValidInfo: true
|
|
2635
|
+
})).filter((row) => !after || row.timeCreated > after.timeCreated || row.timeCreated === after.timeCreated && row.id > after.id).sort((left, right) => left.timeCreated - right.timeCreated || left.id.localeCompare(right.id));
|
|
2636
|
+
return rows.slice(0, Math.max(1, Math.floor(limit)));
|
|
2637
|
+
}
|
|
2638
|
+
if (!openCodeDbExists())
|
|
2639
|
+
return [];
|
|
2640
|
+
return withReadOnlySessionDb((db) => readRawSessionMessageOrdinalPageFromDb2(db, sessionId, after, limit));
|
|
2641
|
+
}
|
|
2642
|
+
function getRawSessionStoredMessageCount2(sessionId) {
|
|
2643
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2644
|
+
if (provider?.getStoredMessageCount)
|
|
2645
|
+
return provider.getStoredMessageCount();
|
|
2646
|
+
if (provider)
|
|
2647
|
+
return provider.readMessages().length;
|
|
2648
|
+
if (!openCodeDbExists())
|
|
2649
|
+
return 0;
|
|
2650
|
+
return withReadOnlySessionDb((db) => countStoredRawSessionMessagesFromDb2(db, sessionId));
|
|
2651
|
+
}
|
|
2652
|
+
function readRawSessionMessageIdOrdinalsForRange2(sessionId, fromOrdinal, toOrdinal) {
|
|
2653
|
+
const from = Math.max(1, Math.floor(fromOrdinal));
|
|
2654
|
+
const to = Math.floor(toOrdinal);
|
|
2655
|
+
if (to < from)
|
|
2656
|
+
return new Map;
|
|
2657
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2658
|
+
if (provider?.readMessageIdOrdinalsForRange) {
|
|
2659
|
+
return provider.readMessageIdOrdinalsForRange(from, to);
|
|
2660
|
+
}
|
|
2661
|
+
if (!provider) {
|
|
2662
|
+
return !openCodeDbExists() ? new Map : withReadOnlySessionDb((db) => readRawSessionMessageIdOrdinalsForRangeFromDb2(db, sessionId, from, to));
|
|
2663
|
+
}
|
|
2664
|
+
const all = provider?.readMessageIdOrdinals ? provider.readMessageIdOrdinals() : new Map(provider.readMessages().map((message) => [message.id, message.ordinal]));
|
|
2665
|
+
return new Map([...all].filter(([, ordinal]) => ordinal >= from && ordinal <= to));
|
|
2666
|
+
}
|
|
2667
|
+
function readRawSessionMessageIdOrdinals2(sessionId) {
|
|
2668
|
+
const count = getRawSessionMessageOrdinalCount2(sessionId);
|
|
2669
|
+
return readRawSessionMessageIdOrdinalsForRange2(sessionId, 1, count);
|
|
2670
|
+
}
|
|
2671
|
+
function readRawSessionMessagePartsById2(sessionId, messageId, onQuery) {
|
|
2672
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2673
|
+
if (provider?.readMessagePartsById)
|
|
2674
|
+
return provider.readMessagePartsById(messageId);
|
|
2675
|
+
if (provider?.readMessageById)
|
|
2676
|
+
return provider.readMessageById(messageId);
|
|
2677
|
+
if (provider) {
|
|
2678
|
+
return provider.readMessages().find((message) => message.id === messageId) ?? null;
|
|
2679
|
+
}
|
|
2680
|
+
if (!openCodeDbExists())
|
|
2681
|
+
return null;
|
|
2682
|
+
return withReadOnlySessionDb((db) => readRawSessionMessagePartsByIdFromDb2(db, sessionId, messageId, onQuery));
|
|
2683
|
+
}
|
|
2684
|
+
function readRawSessionBoundaryEndpoints2(sessionId, ids, blockIds) {
|
|
2685
|
+
if (sessionProviders.get(sessionId)?.provider)
|
|
2686
|
+
return null;
|
|
2687
|
+
if (!openCodeDbExists())
|
|
2688
|
+
return new Map(ids.map((id) => [id, null]));
|
|
2689
|
+
return withReadOnlySessionDb((db) => readRawSessionBoundaryEndpointsFromDb2(db, sessionId, ids, blockIds));
|
|
2690
|
+
}
|
|
2691
|
+
function hasRawSessionMessageById2(sessionId, messageId) {
|
|
2692
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2693
|
+
if (provider?.hasMessageById)
|
|
2694
|
+
return provider.hasMessageById(messageId);
|
|
2695
|
+
if (!provider)
|
|
2696
|
+
return openCodeDbExists() && withReadOnlySessionDb((db) => hasRawSessionMessageByIdFromDb2(db, sessionId, messageId));
|
|
2697
|
+
return readRawSessionMessageById2(sessionId, messageId) !== null;
|
|
2698
|
+
}
|
|
2699
|
+
function readRawSessionMessageOrdinalById2(sessionId, messageId) {
|
|
2700
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2701
|
+
if (provider?.readMessageOrdinalById) {
|
|
2702
|
+
return provider.readMessageOrdinalById(messageId);
|
|
2703
|
+
}
|
|
2704
|
+
if (provider?.readMessageIdOrdinals) {
|
|
2705
|
+
return provider.readMessageIdOrdinals().get(messageId) ?? null;
|
|
2706
|
+
}
|
|
2707
|
+
if (provider?.readMessageOrdinalPage) {
|
|
2708
|
+
let after = null;
|
|
2709
|
+
let ordinal = 0;
|
|
2710
|
+
while (true) {
|
|
2711
|
+
const page = provider.readMessageOrdinalPage(after, 500);
|
|
2712
|
+
if (page.length === 0)
|
|
2713
|
+
return null;
|
|
2714
|
+
for (const entry of page) {
|
|
2715
|
+
if (entry.contributesOrdinal)
|
|
2716
|
+
ordinal += 1;
|
|
2717
|
+
if (entry.id === messageId)
|
|
2718
|
+
return entry.contributesOrdinal ? ordinal : null;
|
|
2719
|
+
}
|
|
2720
|
+
const last = page.at(-1);
|
|
2721
|
+
if (!last || page.length < 500)
|
|
2722
|
+
return null;
|
|
2723
|
+
after = { timeCreated: last.timeCreated, id: last.id };
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
if (provider?.readMessageById) {
|
|
2727
|
+
return provider.readMessageById(messageId)?.ordinal ?? null;
|
|
2728
|
+
}
|
|
2729
|
+
if (provider) {
|
|
2730
|
+
return provider.readMessages().find((message) => message.id === messageId)?.ordinal ?? null;
|
|
2731
|
+
}
|
|
2732
|
+
if (!openCodeDbExists())
|
|
2733
|
+
return null;
|
|
2734
|
+
return withReadOnlySessionDb((db) => readRawSessionMessageOrdinalByIdFromDb2(db, sessionId, messageId));
|
|
2735
|
+
}
|
|
2736
|
+
function compareRawSessionMessageOrder2(sessionId, leftId, rightId) {
|
|
2737
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2738
|
+
if (provider) {
|
|
2739
|
+
if (!provider.readMessageOrdinalById)
|
|
2740
|
+
return null;
|
|
2741
|
+
const left = provider.readMessageOrdinalById(leftId);
|
|
2742
|
+
const right = provider.readMessageOrdinalById(rightId);
|
|
2743
|
+
return left === null || right === null ? null : left - right;
|
|
2744
|
+
}
|
|
2745
|
+
if (!openCodeDbExists())
|
|
2746
|
+
return null;
|
|
2747
|
+
return withReadOnlySessionDb((db) => {
|
|
2748
|
+
const lookup = db.prepare("SELECT time_created, id FROM message WHERE session_id = ? AND id = ? LIMIT 1");
|
|
2749
|
+
const left = lookup.get(sessionId, leftId);
|
|
2750
|
+
const right = lookup.get(sessionId, rightId);
|
|
2751
|
+
if (typeof left?.time_created !== "number" || typeof right?.time_created !== "number" || typeof left.id !== "string" || typeof right.id !== "string") {
|
|
2752
|
+
return null;
|
|
2753
|
+
}
|
|
2754
|
+
if (left.time_created !== right.time_created) {
|
|
2755
|
+
return left.time_created - right.time_created;
|
|
2756
|
+
}
|
|
2757
|
+
return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
function readRawSessionMessageById2(sessionId, messageId) {
|
|
2761
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2762
|
+
if (provider?.readMessageById) {
|
|
2763
|
+
return provider.readMessageById(messageId);
|
|
2764
|
+
}
|
|
2765
|
+
if (provider) {
|
|
2766
|
+
return provider.readMessages().find((message) => message.id === messageId) ?? null;
|
|
2767
|
+
}
|
|
2768
|
+
if (!openCodeDbExists())
|
|
2769
|
+
return null;
|
|
2770
|
+
return withReadOnlySessionDb((db) => readRawSessionMessageByIdFromDb2(db, sessionId, messageId));
|
|
2771
|
+
}
|
|
2772
|
+
readRawSessionMessageById2.prepare = prepareRawSessionOrdinals2;
|
|
2773
|
+
function readRawSessionMessagesFromSource(sessionId) {
|
|
2774
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2775
|
+
if (provider)
|
|
2776
|
+
return provider.readMessages();
|
|
2777
|
+
if (!openCodeDbExists())
|
|
2778
|
+
return [];
|
|
2779
|
+
return withReadOnlySessionDb((db) => readRawSessionMessagesFromDb2(db, sessionId));
|
|
2780
|
+
}
|
|
2781
|
+
function getRawSessionMessageCount2(sessionId) {
|
|
2782
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
2783
|
+
if (provider) {
|
|
2784
|
+
if (provider.getMessageCount)
|
|
2785
|
+
return provider.getMessageCount();
|
|
2786
|
+
const messages = provider.readMessages();
|
|
2787
|
+
return messages.reduce((maximum, message) => Math.max(maximum, message.ordinal), messages.length);
|
|
2788
|
+
}
|
|
2789
|
+
if (!openCodeDbExists())
|
|
2790
|
+
return 0;
|
|
2791
|
+
return withReadOnlySessionDb((db) => getRawSessionMessageCountFromDb(db, sessionId));
|
|
2792
|
+
}
|
|
2793
|
+
var RAW_SESSION_TAG_KEY_PAGE_SIZE2 = 32;
|
|
2794
|
+
function yieldRawSessionTagKeyPage() {
|
|
2795
|
+
return new Promise((resolve) => {
|
|
2796
|
+
const immediate = globalThis.setImmediate;
|
|
2797
|
+
if (typeof immediate === "function") {
|
|
2798
|
+
immediate(resolve);
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2801
|
+
setTimeout(resolve, 0);
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
async function getRawSessionTagKeysThrough2(sessionId, upToMessageIndex, options = {}) {
|
|
2805
|
+
const messageFileKeys = new Set;
|
|
2806
|
+
const toolObservations = new Map;
|
|
2807
|
+
const unpairedInvocations = new Map;
|
|
2808
|
+
const candidateOwnersByCallId = new Map;
|
|
2809
|
+
const messageTimesById = new Map;
|
|
2810
|
+
const finalWatermark = Number.isFinite(upToMessageIndex) ? Math.max(0, Math.floor(upToMessageIndex)) : getRawSessionMessageOrdinalCount2(sessionId);
|
|
2811
|
+
const pageSize = Number.isFinite(options.pageSize) ? Math.max(1, Math.floor(options.pageSize ?? RAW_SESSION_TAG_KEY_PAGE_SIZE2)) : RAW_SESSION_TAG_KEY_PAGE_SIZE2;
|
|
2812
|
+
const yieldToEventLoop = options.yieldToEventLoop ?? yieldRawSessionTagKeyPage;
|
|
2813
|
+
const nearestPersistedOwner = (callId, currentMessageId) => {
|
|
2814
|
+
if (!options.db)
|
|
2815
|
+
return null;
|
|
2816
|
+
let candidates = candidateOwnersByCallId.get(callId);
|
|
2817
|
+
if (!candidates) {
|
|
2818
|
+
candidates = getCandidateToolOwners2(options.db, sessionId, callId);
|
|
2819
|
+
candidateOwnersByCallId.set(callId, candidates);
|
|
2820
|
+
}
|
|
2821
|
+
if (candidates.length === 0)
|
|
2822
|
+
return null;
|
|
2823
|
+
const ids = [...candidates, currentMessageId];
|
|
2824
|
+
const unresolved = ids.filter((id) => !messageTimesById.has(id));
|
|
2825
|
+
if (unresolved.length > 0) {
|
|
2826
|
+
const resolved = getMessageTimesFromOpenCodeDb(sessionId, unresolved);
|
|
2827
|
+
for (const id of unresolved) {
|
|
2828
|
+
messageTimesById.set(id, resolved.get(id) ?? null);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
const times = new Map;
|
|
2832
|
+
for (const id of ids) {
|
|
2833
|
+
const time = messageTimesById.get(id);
|
|
2834
|
+
if (typeof time === "number")
|
|
2835
|
+
times.set(id, time);
|
|
2836
|
+
}
|
|
2837
|
+
return pickNearestPriorOwner2(candidates, currentMessageId, times);
|
|
2838
|
+
};
|
|
2839
|
+
const firstOrdinal = Number.isFinite(options.fromMessageIndex) ? Math.max(1, Math.floor(options.fromMessageIndex ?? 1)) : 1;
|
|
2840
|
+
let afterOrdinal = firstOrdinal - 1;
|
|
2841
|
+
let after;
|
|
2842
|
+
while (afterOrdinal < finalWatermark) {
|
|
2843
|
+
const messages = readRawSessionMessages2.readPage(sessionId, afterOrdinal, pageSize, finalWatermark, after);
|
|
2844
|
+
if (messages.length === 0)
|
|
2845
|
+
break;
|
|
2846
|
+
let nextOrdinal = afterOrdinal;
|
|
2847
|
+
for (const message of messages) {
|
|
2848
|
+
if (message.ordinal <= afterOrdinal || message.ordinal > finalWatermark)
|
|
2849
|
+
continue;
|
|
2850
|
+
nextOrdinal = Math.max(nextOrdinal, message.ordinal);
|
|
2851
|
+
messageTimesById.set(message.id, typeof message.createdAt === "number" ? message.createdAt : null);
|
|
2852
|
+
for (const [partIndex, part] of message.parts.entries()) {
|
|
2853
|
+
if (isTextPart(part)) {
|
|
2854
|
+
messageFileKeys.add(`${message.id}:p${partIndex}`);
|
|
2855
|
+
continue;
|
|
2856
|
+
}
|
|
2857
|
+
if (isFilePart(part)) {
|
|
2858
|
+
messageFileKeys.add(`${message.id}:file${partIndex}`);
|
|
2859
|
+
continue;
|
|
2860
|
+
}
|
|
2861
|
+
const observation = extractToolCallObservation(part);
|
|
2862
|
+
if (!observation)
|
|
2863
|
+
continue;
|
|
2864
|
+
let ownerMessageId;
|
|
2865
|
+
if (observation.kind === "invocation") {
|
|
2866
|
+
ownerMessageId = message.id;
|
|
2867
|
+
const queue = unpairedInvocations.get(observation.callId) ?? [];
|
|
2868
|
+
queue.push(message.id);
|
|
2869
|
+
unpairedInvocations.set(observation.callId, queue);
|
|
2870
|
+
} else {
|
|
2871
|
+
const queue = unpairedInvocations.get(observation.callId);
|
|
2872
|
+
const pairedOwner = queue?.shift();
|
|
2873
|
+
if (queue?.length === 0)
|
|
2874
|
+
unpairedInvocations.delete(observation.callId);
|
|
2875
|
+
ownerMessageId = pairedOwner ?? nearestPersistedOwner(observation.callId, message.id) ?? message.id;
|
|
2876
|
+
}
|
|
2877
|
+
const owners = toolObservations.get(observation.callId) ?? new Set;
|
|
2878
|
+
owners.add(ownerMessageId);
|
|
2879
|
+
toolObservations.set(observation.callId, owners);
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
if (nextOrdinal <= afterOrdinal)
|
|
2883
|
+
break;
|
|
2884
|
+
afterOrdinal = nextOrdinal;
|
|
2885
|
+
const last = messages.at(-1);
|
|
2886
|
+
after = last ? { timeCreated: last.createdAt ?? 0, id: last.id } : undefined;
|
|
2887
|
+
if (afterOrdinal < finalWatermark)
|
|
2888
|
+
await yieldToEventLoop();
|
|
2889
|
+
}
|
|
2890
|
+
return { messageFileKeys, toolObservations };
|
|
2891
|
+
}
|
|
2892
|
+
var PROTECTED_TAIL_USER_TURNS = 5;
|
|
2893
|
+
function getLegacyProtectedTailStartOrdinal2(sessionId) {
|
|
2894
|
+
const count = getRawSessionMessageOrdinalCount2(sessionId);
|
|
2895
|
+
const userOrdinals = [];
|
|
2896
|
+
let toOrdinal = count;
|
|
2897
|
+
while (toOrdinal >= 1 && userOrdinals.length < PROTECTED_TAIL_USER_TURNS) {
|
|
2898
|
+
const fromOrdinal = Math.max(1, toOrdinal - RAW_MESSAGE_RANGE_PAGE_SIZE + 1);
|
|
2899
|
+
const messages = readRawSessionMessageRange2(sessionId, fromOrdinal, toOrdinal);
|
|
2900
|
+
for (let index = messages.length - 1;index >= 0; index--) {
|
|
2901
|
+
const message = messages[index];
|
|
2902
|
+
if (message?.role === "user" && hasMeaningfulUserText2(message.parts)) {
|
|
2903
|
+
userOrdinals.push(message.ordinal);
|
|
2904
|
+
if (userOrdinals.length === PROTECTED_TAIL_USER_TURNS)
|
|
2905
|
+
break;
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
toOrdinal = fromOrdinal - 1;
|
|
2909
|
+
}
|
|
2910
|
+
return userOrdinals.length < PROTECTED_TAIL_USER_TURNS ? 1 : userOrdinals[PROTECTED_TAIL_USER_TURNS - 1] ?? 1;
|
|
2911
|
+
}
|
|
2912
|
+
function getProtectedTailStartOrdinal2(sessionId) {
|
|
2913
|
+
return getLegacyProtectedTailStartOrdinal2(sessionId);
|
|
2914
|
+
}
|
|
2915
|
+
function readSessionChunk2(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal, options = {}) {
|
|
2916
|
+
const totalMessageCount = getCachedAbsoluteMessageCount2(sessionId) ?? getRawSessionMessageOrdinalCount2(sessionId);
|
|
2917
|
+
const startOrdinal = Math.max(1, offset);
|
|
2918
|
+
const finalOrdinal = eligibleEndOrdinal === undefined ? totalMessageCount : Math.min(totalMessageCount, eligibleEndOrdinal - 1);
|
|
2919
|
+
const messages = readRawSessionMessageRange2(sessionId, Math.max(1, startOrdinal - 1), finalOrdinal);
|
|
2920
|
+
const expandedParts = new Map;
|
|
2921
|
+
const expandedResults = new Set;
|
|
2922
|
+
if (options.expand !== false) {
|
|
2923
|
+
const calls = new Map;
|
|
2924
|
+
for (const message of messages)
|
|
2925
|
+
for (const part of message.parts) {
|
|
2926
|
+
if (!part || typeof part !== "object")
|
|
2927
|
+
continue;
|
|
2928
|
+
const p = part;
|
|
2929
|
+
if (p.type !== "tool")
|
|
2930
|
+
continue;
|
|
2931
|
+
const state = p.state;
|
|
2932
|
+
if (state?.input !== undefined && typeof p.callID === "string")
|
|
2933
|
+
calls.set(p.callID, p);
|
|
2934
|
+
expandedParts.set(part, expandToolPart(part, options.expandTools));
|
|
2935
|
+
if (state?.input === undefined && state?.output !== undefined && typeof p.callID === "string") {
|
|
2936
|
+
const call = calls.get(p.callID);
|
|
2937
|
+
if (call) {
|
|
2938
|
+
const expansion = expandToolPart({ ...call, state: { ...call.state, output: state.output } }, options.expandTools);
|
|
2939
|
+
if (expansion !== null) {
|
|
2940
|
+
expandedParts.set(call, expansion);
|
|
2941
|
+
expandedResults.add(part);
|
|
2942
|
+
}
|
|
2943
|
+
calls.delete(p.callID);
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
const completedToolArcs = buildToolArcs(messages).flatMap((arc) => arc.resOrdinal === null ? [] : [{ start: arc.invOrdinal, end: arc.resOrdinal }]);
|
|
2949
|
+
const completedToolComponents = [];
|
|
2950
|
+
for (const arc of completedToolArcs) {
|
|
2951
|
+
const component = completedToolComponents[completedToolComponents.length - 1];
|
|
2952
|
+
if (component && arc.start <= component.end)
|
|
2953
|
+
component.end = Math.max(component.end, arc.end);
|
|
2954
|
+
else
|
|
2955
|
+
completedToolComponents.push({ ...arc });
|
|
2956
|
+
}
|
|
2957
|
+
const lines = [];
|
|
2958
|
+
const lineMeta = [];
|
|
2959
|
+
const flushedToolOnlyBlocks = [];
|
|
2960
|
+
let totalTokens = 0;
|
|
2961
|
+
let messagesProcessed = 0;
|
|
2962
|
+
let lastOrdinal = startOrdinal - 1;
|
|
2963
|
+
let highestScannedOrdinal = startOrdinal - 1;
|
|
2964
|
+
let lastMessageId = "";
|
|
2965
|
+
let firstMessageId = "";
|
|
2966
|
+
let currentBlock = null;
|
|
2967
|
+
let pendingNoiseMeta = [];
|
|
2968
|
+
let commitClusters = 0;
|
|
2969
|
+
let lastFlushedRole = "";
|
|
2970
|
+
let admittedOversizeComponentEnd = null;
|
|
2971
|
+
let currentBlockApproxTokens = 0;
|
|
2972
|
+
let formattedBudgetCrossed = false;
|
|
2973
|
+
let sourceCharacters = 0;
|
|
2974
|
+
const toolResultBoundaries = [];
|
|
2975
|
+
function pinComponentWhenFormattedBudgetCrosses(ordinal, appendedText) {
|
|
2976
|
+
if (admittedOversizeComponentEnd !== null || formattedBudgetCrossed || !currentBlock)
|
|
2977
|
+
return;
|
|
2978
|
+
currentBlockApproxTokens += estimateTokens(appendedText) + (currentBlock.parts.length > 1 ? 1 : 0);
|
|
2979
|
+
if (totalTokens + currentBlockApproxTokens + 64 <= tokenBudget)
|
|
2980
|
+
return;
|
|
2981
|
+
const previewTokens = totalTokens + estimateTokens(formatBlock(currentBlock));
|
|
2982
|
+
if (previewTokens <= tokenBudget)
|
|
2983
|
+
return;
|
|
2984
|
+
formattedBudgetCrossed = true;
|
|
2985
|
+
const component = completedToolComponents.find((candidate) => candidate.start <= ordinal && candidate.end >= ordinal);
|
|
2986
|
+
if (component)
|
|
2987
|
+
admittedOversizeComponentEnd = component.end;
|
|
2988
|
+
}
|
|
2989
|
+
function recordFilteredNoise(meta) {
|
|
2990
|
+
pendingNoiseMeta.push(meta);
|
|
2991
|
+
if (!currentBlock) {
|
|
2992
|
+
highestScannedOrdinal = Math.max(highestScannedOrdinal, meta.ordinal);
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
function flushCurrentBlock() {
|
|
2996
|
+
if (!currentBlock)
|
|
2997
|
+
return true;
|
|
2998
|
+
const blockText = formatBlock(currentBlock);
|
|
2999
|
+
const blockTokens = estimateBlockTokens(blockText);
|
|
3000
|
+
if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
|
|
3001
|
+
const splitsCompletedArc = completedToolArcs.some((arc) => arc.start <= lastOrdinal && arc.end > lastOrdinal);
|
|
3002
|
+
if (!splitsCompletedArc)
|
|
3003
|
+
return false;
|
|
3004
|
+
}
|
|
3005
|
+
if (currentBlock.role === "A" && currentBlock.commitHashes.length > 0 && lastFlushedRole !== "A") {
|
|
3006
|
+
commitClusters++;
|
|
3007
|
+
}
|
|
3008
|
+
lastFlushedRole = currentBlock.role;
|
|
3009
|
+
if (!firstMessageId)
|
|
3010
|
+
firstMessageId = currentBlock.meta[0]?.messageId ?? "";
|
|
3011
|
+
lastOrdinal = currentBlock.meta[currentBlock.meta.length - 1]?.ordinal ?? currentBlock.endOrdinal;
|
|
3012
|
+
highestScannedOrdinal = Math.max(highestScannedOrdinal, lastOrdinal);
|
|
3013
|
+
lastMessageId = currentBlock.meta[currentBlock.meta.length - 1]?.messageId ?? "";
|
|
3014
|
+
messagesProcessed += currentBlock.meta.length;
|
|
3015
|
+
const lineStart = sourceCharacters + (lines.length > 0 ? 1 : 0);
|
|
3016
|
+
const renderedParts = currentBlock.parts.join(" / ");
|
|
3017
|
+
let partOffset = lineStart + (blockText.length - renderedParts.length);
|
|
3018
|
+
for (let index = 0;index < currentBlock.parts.length; index++) {
|
|
3019
|
+
const part = currentBlock.parts[index] ?? "";
|
|
3020
|
+
const partMeta = currentBlock.partMeta[index];
|
|
3021
|
+
if (partMeta && partMeta.toolResultBodyTokens > 0) {
|
|
3022
|
+
toolResultBoundaries.push({
|
|
3023
|
+
ordinal: partMeta.ordinal,
|
|
3024
|
+
sourceOffset: partOffset,
|
|
3025
|
+
bodyTokens: partMeta.toolResultBodyTokens
|
|
3026
|
+
});
|
|
3027
|
+
}
|
|
3028
|
+
partOffset += part.length + (index + 1 < currentBlock.parts.length ? 3 : 0);
|
|
3029
|
+
}
|
|
3030
|
+
lines.push(blockText);
|
|
3031
|
+
sourceCharacters = lineStart + blockText.length;
|
|
3032
|
+
lineMeta.push(...currentBlock.meta);
|
|
3033
|
+
totalTokens += blockTokens;
|
|
3034
|
+
if (currentBlock.isToolOnly) {
|
|
3035
|
+
flushedToolOnlyBlocks.push({
|
|
3036
|
+
start: currentBlock.startOrdinal,
|
|
3037
|
+
end: currentBlock.endOrdinal
|
|
3038
|
+
});
|
|
3039
|
+
}
|
|
3040
|
+
currentBlock = null;
|
|
3041
|
+
currentBlockApproxTokens = 0;
|
|
3042
|
+
return true;
|
|
3043
|
+
}
|
|
3044
|
+
for (const msg of messages) {
|
|
3045
|
+
if (eligibleEndOrdinal !== undefined && msg.ordinal >= eligibleEndOrdinal)
|
|
3046
|
+
break;
|
|
3047
|
+
if (admittedOversizeComponentEnd !== null && msg.ordinal > admittedOversizeComponentEnd) {
|
|
3048
|
+
break;
|
|
3049
|
+
}
|
|
3050
|
+
if (msg.ordinal < startOrdinal)
|
|
3051
|
+
continue;
|
|
3052
|
+
const meta = { ordinal: msg.ordinal, messageId: msg.id };
|
|
3053
|
+
if (isHostUnservedRow(msg))
|
|
3054
|
+
markHostUnservedRow(meta);
|
|
3055
|
+
if (msg.role === "user" && !hasMeaningfulChunkUserText(msg.parts)) {
|
|
3056
|
+
const tcSummaries = msg.parts.flatMap((part) => {
|
|
3057
|
+
if (expandedResults.has(part))
|
|
3058
|
+
return [];
|
|
3059
|
+
const expansion = expandedParts.get(part) ?? null;
|
|
3060
|
+
return expansion === null ? extractToolCallSummaries([part]) : [`TC: ${expansion}`];
|
|
3061
|
+
});
|
|
3062
|
+
if (tcSummaries.length === 0) {
|
|
3063
|
+
recordFilteredNoise(meta);
|
|
3064
|
+
continue;
|
|
3065
|
+
}
|
|
3066
|
+
const tcText = tcSummaries.join(" / ");
|
|
3067
|
+
if (currentBlock && currentBlock.role === "A") {
|
|
3068
|
+
currentBlock.endOrdinal = msg.ordinal;
|
|
3069
|
+
currentBlock.parts.push(tcText);
|
|
3070
|
+
currentBlock.partMeta.push({
|
|
3071
|
+
ordinal: msg.ordinal,
|
|
3072
|
+
toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
|
|
3073
|
+
});
|
|
3074
|
+
currentBlock.meta.push(...pendingNoiseMeta, meta);
|
|
3075
|
+
pendingNoiseMeta = [];
|
|
3076
|
+
} else {
|
|
3077
|
+
if (!flushCurrentBlock())
|
|
3078
|
+
break;
|
|
3079
|
+
currentBlock = {
|
|
3080
|
+
role: "A",
|
|
3081
|
+
startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
|
|
3082
|
+
endOrdinal: msg.ordinal,
|
|
3083
|
+
parts: [tcText],
|
|
3084
|
+
partMeta: [
|
|
3085
|
+
{
|
|
3086
|
+
ordinal: msg.ordinal,
|
|
3087
|
+
toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
|
|
3088
|
+
}
|
|
3089
|
+
],
|
|
3090
|
+
meta: [...pendingNoiseMeta, meta],
|
|
3091
|
+
commitHashes: [],
|
|
3092
|
+
isToolOnly: true
|
|
3093
|
+
};
|
|
3094
|
+
pendingNoiseMeta = [];
|
|
3095
|
+
}
|
|
3096
|
+
pinComponentWhenFormattedBudgetCrosses(msg.ordinal, tcText);
|
|
3097
|
+
continue;
|
|
3098
|
+
}
|
|
3099
|
+
const role = compactRole(msg.role);
|
|
3100
|
+
const textParts = extractTexts2(msg.parts).map((t) => msg.role === "user" ? cleanUserText2(t) : t).map(normalizeText).filter((value) => value.length > 0);
|
|
3101
|
+
const allParts = options.expand === false ? [
|
|
3102
|
+
...textParts,
|
|
3103
|
+
...textParts.length === 0 ? extractToolCallSummaries(msg.parts) : []
|
|
3104
|
+
] : msg.parts.flatMap((part) => {
|
|
3105
|
+
if (expandedResults.has(part))
|
|
3106
|
+
return [];
|
|
3107
|
+
const expansion = expandedParts.get(part) ?? null;
|
|
3108
|
+
if (expansion !== null)
|
|
3109
|
+
return [`TC: ${expansion}`];
|
|
3110
|
+
const texts = extractTexts2([part]).map((t) => msg.role === "user" ? cleanUserText2(t) : t).map(normalizeText).filter(Boolean);
|
|
3111
|
+
return texts.length ? texts : textParts.length === 0 ? extractToolCallSummaries([part]) : [];
|
|
3112
|
+
});
|
|
3113
|
+
const compacted = compactTextForSummary(allParts.join(" / "), msg.role);
|
|
3114
|
+
const text = compacted.text;
|
|
3115
|
+
if (!text) {
|
|
3116
|
+
recordFilteredNoise(meta);
|
|
3117
|
+
continue;
|
|
3118
|
+
}
|
|
3119
|
+
const msgHasNarrative = textParts.length > 0;
|
|
3120
|
+
if (currentBlock && currentBlock.role === role) {
|
|
3121
|
+
currentBlock.endOrdinal = msg.ordinal;
|
|
3122
|
+
currentBlock.parts.push(text);
|
|
3123
|
+
currentBlock.partMeta.push({
|
|
3124
|
+
ordinal: msg.ordinal,
|
|
3125
|
+
toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
|
|
3126
|
+
});
|
|
3127
|
+
currentBlock.meta.push(...pendingNoiseMeta, meta);
|
|
3128
|
+
currentBlock.commitHashes = mergeCommitHashes(currentBlock.commitHashes, compacted.commitHashes);
|
|
3129
|
+
if (msgHasNarrative)
|
|
3130
|
+
currentBlock.isToolOnly = false;
|
|
3131
|
+
pendingNoiseMeta = [];
|
|
3132
|
+
pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
|
|
3133
|
+
continue;
|
|
3134
|
+
}
|
|
3135
|
+
if (!flushCurrentBlock())
|
|
3136
|
+
break;
|
|
3137
|
+
currentBlock = {
|
|
3138
|
+
role,
|
|
3139
|
+
startOrdinal: pendingNoiseMeta[0]?.ordinal ?? msg.ordinal,
|
|
3140
|
+
endOrdinal: msg.ordinal,
|
|
3141
|
+
parts: [text],
|
|
3142
|
+
partMeta: [
|
|
3143
|
+
{
|
|
3144
|
+
ordinal: msg.ordinal,
|
|
3145
|
+
toolResultBodyTokens: extractToolResultBodyTokens(msg.parts)
|
|
3146
|
+
}
|
|
3147
|
+
],
|
|
3148
|
+
meta: [...pendingNoiseMeta, meta],
|
|
3149
|
+
commitHashes: [...compacted.commitHashes],
|
|
3150
|
+
isToolOnly: !msgHasNarrative
|
|
3151
|
+
};
|
|
3152
|
+
pendingNoiseMeta = [];
|
|
3153
|
+
pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
|
|
3154
|
+
}
|
|
3155
|
+
if (flushCurrentBlock() && pendingNoiseMeta.length > 0) {
|
|
3156
|
+
highestScannedOrdinal = Math.max(highestScannedOrdinal, pendingNoiseMeta[pendingNoiseMeta.length - 1]?.ordinal ?? highestScannedOrdinal);
|
|
3157
|
+
}
|
|
3158
|
+
const toolOnlyRanges = [];
|
|
3159
|
+
for (const range of flushedToolOnlyBlocks) {
|
|
3160
|
+
const last = toolOnlyRanges[toolOnlyRanges.length - 1];
|
|
3161
|
+
if (last && range.start === last.end + 1) {
|
|
3162
|
+
last.end = range.end;
|
|
3163
|
+
} else {
|
|
3164
|
+
toolOnlyRanges.push({ start: range.start, end: range.end });
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
const text = lines.join(`
|
|
3168
|
+
`);
|
|
3169
|
+
const oversizeAtomicUnit = estimateBlockTokens(text) > tokenBudget && completedToolArcs.some((arc) => arc.start <= lastOrdinal && arc.end >= startOrdinal);
|
|
3170
|
+
return {
|
|
3171
|
+
startIndex: startOrdinal,
|
|
3172
|
+
endIndex: lastOrdinal,
|
|
3173
|
+
startMessageId: firstMessageId,
|
|
3174
|
+
endMessageId: lastMessageId,
|
|
3175
|
+
messageCount: messagesProcessed,
|
|
3176
|
+
tokenEstimate: totalTokens,
|
|
3177
|
+
...oversizeAtomicUnit ? { oversizeAtomicUnit: true } : {},
|
|
3178
|
+
hasMore: Math.max(lastOrdinal, highestScannedOrdinal) < (eligibleEndOrdinal !== undefined ? Math.min(eligibleEndOrdinal - 1, totalMessageCount) : totalMessageCount),
|
|
3179
|
+
text,
|
|
3180
|
+
lines: lineMeta,
|
|
3181
|
+
...messagesProcessed === 0 && text.length === 0 ? { filteredNoiseLines: pendingNoiseMeta } : {},
|
|
3182
|
+
commitClusterCount: commitClusters,
|
|
3183
|
+
toolOnlyRanges,
|
|
3184
|
+
completedToolArcs,
|
|
3185
|
+
toolResultBoundaries
|
|
3186
|
+
};
|
|
3187
|
+
}
|
|
3188
|
+
function getRawSessionMessageIdsThrough2(sessionId, endOrdinal) {
|
|
3189
|
+
if (endOrdinal < 1)
|
|
3190
|
+
return [];
|
|
3191
|
+
return [...readRawSessionMessageIdOrdinalsForRange2(sessionId, 1, endOrdinal).entries()].sort((left, right) => left[1] - right[1]).map(([id]) => id);
|
|
3192
|
+
}
|
|
3193
|
+
function readRawSessionSeedTail2(sessionId, boundaryId, onQuery) {
|
|
3194
|
+
const provider = sessionProviders.get(sessionId)?.provider;
|
|
3195
|
+
if (provider) {
|
|
3196
|
+
const boundaryOrdinal = boundaryId === null ? 1 : readRawSessionMessageOrdinalById2(sessionId, boundaryId);
|
|
3197
|
+
if (boundaryOrdinal === null)
|
|
3198
|
+
throw new Error("state_sync materialized boundary is missing from raw provider");
|
|
3199
|
+
const messages = readRawSessionMessageRange2(sessionId, boundaryOrdinal, getRawSessionMessageOrdinalCount2(sessionId));
|
|
3200
|
+
return new Map(messages.map((message) => [message.id, message]));
|
|
3201
|
+
}
|
|
3202
|
+
if (!openCodeDbExists()) {
|
|
3203
|
+
if (boundaryId !== null)
|
|
3204
|
+
throw new Error("state_sync raw storage is unavailable for materialized boundary");
|
|
3205
|
+
return new Map;
|
|
3206
|
+
}
|
|
3207
|
+
return withReadOnlySessionDb((db) => {
|
|
3208
|
+
onQuery?.();
|
|
3209
|
+
return readRawSeedTailFromDb2(db, sessionId, boundaryId);
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
export { detectLatestTurnThinkingMismatch, isPrefixBoundThinkingModel, detectOverflow, expandToolPart, markHostUnservedRow, retreatPastHostUnservedRows, snapTerminalCompartmentToServedRow, isHostRenderedSystemMessage, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, stripSystemInjection, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, toolPartHasUserAnswer, DreamTokenBudgetExceeded, TOKEN_BUDGET_FINALIZE_MESSAGE, registerBudgetFinalizeChild, releaseBudgetFinalizeChild, createDreamTokenBudget, recordToolParameters, createDroppedInputGuard, assertExecutableToolInput, isEditTool, describeFinalWireTail, estimateMessageTokens, wireContentBytes, createFinalWireUsageTracker, estimateFinalWireInputTokens, estimateAppendedWireTokens, modelAcceptsEmptyContent, isAnthropicFamilyRoute, neutralizeDroppedReasoningPart, restoreNeutralizedReasoningPart, isNeutralizedReasoningPart, neutralizedReasoningSource, variantChangeBustsProviderCache, makeSentinel, makeWholeMessageSentinel, neutralizeWholeMessage, isSentinel, replaySentinelByMessageIds, SKELETON_REAL_INPUT_MAX_BYTES, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, resolveHostServedBoundaryId2, hasRawMessageProvider2, setRawMessageProvider2, setBoundedRawMessageProvider2, withRawMessageProvider2, cleanUserText2, withRawSessionMessageCache2, readRawSessionMessages2, readRawSessionMessagePage2, getRawSessionMessageOrdinalCount2, RAW_MESSAGE_VISIT_PAGE_SIZE2, visitRawSessionMessages2, readRawSessionMessageRange2, prepareRawSessionOrdinals2, primeTailRawMessageCache2, getCachedAbsoluteMessageCount2, primeInMemoryTailRawMessageCache2, readRawSessionMessageOrdinalPage2, getRawSessionStoredMessageCount2, readRawSessionMessageIdOrdinalsForRange2, readRawSessionMessageIdOrdinals2, readRawSessionMessagePartsById2, readRawSessionBoundaryEndpoints2, hasRawSessionMessageById2, readRawSessionMessageOrdinalById2, compareRawSessionMessageOrder2, readRawSessionMessageById2, getRawSessionMessageCount2, RAW_SESSION_TAG_KEY_PAGE_SIZE2, getRawSessionTagKeysThrough2, getLegacyProtectedTailStartOrdinal2, getProtectedTailStartOrdinal2, readSessionChunk2, getRawSessionMessageIdsThrough2, readRawSessionSeedTail2 };
|