@retaw106/mmc-oc 2.2.1 → 2.4.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/cli.js +14 -3
- package/dist/config/deprecated-config.d.ts +4 -0
- package/dist/config/deprecated-config.d.ts.map +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +2 -2
- package/dist/config/schema/magic-context.d.ts +36 -3
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/config-init.js +14 -3
- package/dist/{context-mrvm92n8.js → context-c72brxe5.js} +2410 -1801
- package/dist/{derive-budgets-rjjz5f7y.js → derive-budgets-s1p37t2g.js} +2 -2
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/historian-failure-reason.d.ts +7 -0
- package/dist/features/magic-context/historian-failure-reason.d.ts.map +1 -0
- package/dist/features/magic-context/memory-maintainer/launcher.d.ts +13 -4
- package/dist/features/magic-context/memory-maintainer/launcher.d.ts.map +1 -1
- package/dist/features/magic-context/memory-maintainer/manual-commands.d.ts.map +1 -1
- package/dist/features/magic-context/memory-maintainer/model-chain.d.ts +47 -0
- package/dist/features/magic-context/memory-maintainer/model-chain.d.ts.map +1 -0
- package/dist/features/magic-context/memory-maintainer/oc2-adapter.d.ts +17 -4
- package/dist/features/magic-context/memory-maintainer/oc2-adapter.d.ts.map +1 -1
- package/dist/features/magic-context/memory-maintainer/pipeline.d.ts +6 -0
- package/dist/features/magic-context/memory-maintainer/pipeline.d.ts.map +1 -1
- package/dist/features/magic-context/message-index-async.d.ts +21 -3
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- 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/migrations.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.d.ts +29 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/storage-clone.d.ts +2 -0
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
- package/dist/features/magic-context/storage-compartment-history-version.d.ts +4 -0
- package/dist/features/magic-context/storage-compartment-history-version.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +23 -5
- 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-session-tables.d.ts +5 -1
- 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 +159 -5
- package/dist/features/magic-context/storage-tags.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 +60 -2
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/hooks/magic-context/__fixtures__/tail-hygiene-refresh.d.ts +34 -0
- package/dist/hooks/magic-context/__fixtures__/tail-hygiene-refresh.d.ts.map +1 -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/apply-operations.d.ts +10 -1
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts +2 -2
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-types.d.ts +2 -2
- package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner.d.ts +4 -0
- package/dist/hooks/magic-context/compartment-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-trigger-error.d.ts +11 -0
- package/dist/hooks/magic-context/compartment-trigger-error.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-trigger.d.ts +1 -1
- package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +1 -0
- package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
- package/dist/hooks/magic-context/degraded-pass-refusal.d.ts +2 -0
- package/dist/hooks/magic-context/degraded-pass-refusal.d.ts.map +1 -1
- package/dist/hooks/magic-context/edit-marker.d.ts +2 -0
- package/dist/hooks/magic-context/edit-marker.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +2 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/history-boundary-repair.d.ts +11 -2
- package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
- package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-persist.d.ts +10 -13
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
- package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
- package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-replay.d.ts +16 -9
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +141 -2
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
- package/dist/hooks/magic-context/opaque-thinking.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/pending-drop-eligibility.d.ts +14 -0
- package/dist/hooks/magic-context/pending-drop-eligibility.d.ts.map +1 -0
- package/dist/hooks/magic-context/pending-materialization.d.ts +10 -0
- package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
- package/dist/hooks/magic-context/postprocess-read-cache.d.ts.map +1 -1
- package/dist/hooks/magic-context/provider-visible-parts.d.ts +51 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +22 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
- 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 +123 -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/render-options.d.ts +19 -0
- package/dist/hooks/magic-context/render-options.d.ts.map +1 -0
- 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/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 +38 -24
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/supersession-reclaim.d.ts +5 -3
- package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
- package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
- package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
- package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +18 -5
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +19 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts +14 -0
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/tail-hygiene-output-count.d.ts +18 -0
- package/dist/hooks/magic-context/tail-hygiene-output-count.d.ts.map +1 -0
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +8 -4
- package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
- package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts +2 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/tool-reclaim.d.ts +5 -2
- package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +9 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +21 -11
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/unresolved-history-boundary.d.ts +5 -1
- package/dist/hooks/magic-context/unresolved-history-boundary.d.ts.map +1 -1
- package/dist/{index-g2z2k5m4.js → index-27ddyx39.js} +2 -2
- package/dist/{index-btp5tdc8.js → index-48e9znrc.js} +1248 -570
- package/dist/{index-5cep2r9n.js → index-5ty9rnbx.js} +60 -258
- package/dist/{index-z2g20msd.js → index-azbmnekv.js} +4 -4
- package/dist/{index-1j34a56j.js → index-dwh99z66.js} +293 -36
- package/dist/{index-qbkzdkk0.js → index-k59af64t.js} +6 -2
- package/dist/{index-5b7x80ec.js → index-kahkxcqw.js} +12532 -10348
- package/dist/{index-53g38ggt.js → index-kmbme1v1.js} +1 -1
- package/dist/{index-amycb7b1.js → index-r7s7d350.js} +3 -3
- package/dist/{index-33gprt9g.js → index-yjv8dpht.js} +1 -1
- package/dist/index-ykq24x1n.js +1477 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +114 -2
- package/dist/{message-time-backfill-phrwp2fz.js → message-time-backfill-j96x1sab.js} +3 -3
- package/dist/model-resolution-cvyrrcjw.js +8 -0
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{read-session-chunk-2xm4sc4y.js → read-session-chunk-t8bg6wkz.js} +6 -4
- package/dist/recomp-orchestrator-k760qy1n.js +21 -0
- package/dist/{safe-notification-target-ph3xd1ve.js → safe-notification-target-1jkf0m82.js} +2 -2
- package/dist/{send-session-notification-rnc4nrsr.js → send-session-notification-njjf3b4s.js} +5 -5
- package/dist/shared/auto-search-lifecycle.d.ts +14 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/model-suggestion-retry.d.ts +21 -0
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/models-dev-cache.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/processed-image-eligibility.d.ts +22 -0
- package/dist/shared/processed-image-eligibility.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/prompt-surface-runtime.d.ts +5 -0
- package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
- package/dist/shared/reclaim-distance.d.ts +33 -0
- package/dist/shared/reclaim-distance.d.ts.map +1 -0
- package/dist/shared/recovery-reasoning-prefix.d.ts +9 -0
- package/dist/shared/recovery-reasoning-prefix.d.ts.map +1 -0
- package/dist/shared/sqlite.d.ts +35 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts +7 -0
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/storage-file-mutex.d.ts +9 -0
- package/dist/shared/storage-file-mutex.d.ts.map +1 -0
- package/dist/shared/storage-permissions.d.ts +6 -0
- package/dist/shared/storage-permissions.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/tag-owner-id.d.ts +1 -0
- package/dist/shared/tag-owner-id.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts +9 -0
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/shared/tail-hygiene-json.d.ts +22 -0
- package/dist/shared/tail-hygiene-json.d.ts.map +1 -0
- package/dist/shared/user-facing-codes.d.ts +2 -2
- package/dist/shared/window-geometry.d.ts +9 -66
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/dist/standalone-plugin-marker.d.ts +8 -0
- package/dist/standalone-plugin-marker.d.ts.map +1 -0
- package/dist/tools/ctx-expand/search-archive.d.ts +4 -0
- package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/constants.d.ts +1 -2
- package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/v2/hidden-completion.d.ts +20 -1
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
- package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
- package/dist/v2/hooks/generate.d.ts +9 -2
- package/dist/v2/hooks/generate.d.ts.map +1 -1
- package/dist/v2/hooks/hidden-child.d.ts +22 -1
- package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
- package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
- package/dist/v2/server.d.ts.map +1 -1
- package/dist/v2/server.js +26593 -21940
- package/dist/v2/store-reader.d.ts +27 -1
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/web/main.js +401 -23
- package/dist/{wrapup-orchestrator-yknks3ad.js → wrapup-orchestrator-b2gswatj.js} +10 -10
- package/package.json +1 -1
- package/src/config/deprecated-config.ts +18 -0
- package/src/config/index.test.ts +13 -37
- package/src/config/index.ts +2 -2
- package/src/config/latch-permanence-guard.test.ts +4 -0
- package/src/config/project-security.test.ts +17 -0
- package/src/config/project-security.ts +3 -3
- package/src/config/schema/magic-context.test.ts +50 -0
- package/src/config/schema/magic-context.ts +44 -7
- package/src/shared/auto-search-lifecycle.ts +43 -0
- package/src/shared/logger.ts +10 -2
- package/src/shared/model-suggestion-retry.ts +5 -1
- package/src/shared/models-dev-cache.ts +1 -7
- package/src/shared/models-dev-temperature.ts +107 -0
- package/src/shared/processed-image-eligibility.test.ts +68 -0
- package/src/shared/processed-image-eligibility.ts +41 -0
- package/src/shared/processed-image-position-review.json +20 -0
- package/src/shared/processed-image-position-review.test.ts +19 -0
- package/src/shared/project-directory-key.ts +20 -0
- package/src/shared/prompt-surface-runtime.ts +12 -0
- package/src/shared/reclaim-distance.test.ts +111 -0
- package/src/shared/reclaim-distance.ts +91 -0
- package/src/shared/recovery-reasoning-prefix.test.ts +34 -0
- package/src/shared/recovery-reasoning-prefix.ts +35 -0
- package/src/shared/root-async-context.probe.mjs +36 -0
- package/src/shared/root-async-context.test.ts +49 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +4 -3
- package/src/shared/sqlite-busy-budget-review.test.ts +291 -0
- package/src/shared/sqlite-foreground-wait.test.ts +304 -0
- package/src/shared/sqlite-pass-scope.test.ts +4 -4
- package/src/shared/sqlite-writer-diagnostics.test.ts +52 -12
- package/src/shared/sqlite.ts +428 -46
- package/src/shared/stable-json.ts +79 -7
- package/src/shared/storage-file-mutex.test.ts +50 -0
- package/src/shared/storage-file-mutex.ts +130 -0
- package/src/shared/storage-permissions.ts +46 -0
- package/src/shared/subagent-temperature.ts +110 -0
- package/src/shared/tag-owner-id.ts +13 -0
- package/src/shared/tag-transcript.ts +118 -0
- package/src/shared/tail-hygiene-json.test.ts +117 -0
- package/src/shared/tail-hygiene-json.ts +217 -0
- package/src/shared/user-facing-codes.ts +2 -2
- package/src/shared/window-geometry.test.ts +102 -236
- package/src/shared/window-geometry.ts +23 -413
- package/dist/index-ramz5kkm.js +0 -514
- package/dist/model-resolution-wazv26n0.js +0 -6
- package/dist/recomp-orchestrator-frmwj9hz.js +0 -21
- package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
|
@@ -5,17 +5,30 @@ import {
|
|
|
5
5
|
hasMeasuredDecisionCalibration,
|
|
6
6
|
providerMass
|
|
7
7
|
} from "./index-x37vg474.js";
|
|
8
|
+
import {
|
|
9
|
+
getTagIdentityWriteGeneration
|
|
10
|
+
} from "./index-dwh99z66.js";
|
|
8
11
|
import {
|
|
9
12
|
getHarness,
|
|
10
13
|
sessionLog
|
|
11
|
-
} from "./index-
|
|
14
|
+
} from "./index-k59af64t.js";
|
|
12
15
|
import {
|
|
13
16
|
isKnownAutocommit,
|
|
17
|
+
readRawSessionMessagesFromDb,
|
|
18
|
+
readRawSessionMessagePageFromDb,
|
|
19
|
+
readRawSessionMessageSummaryPageFromDb,
|
|
20
|
+
countRawSessionMessageOrdinalsFromDb,
|
|
21
|
+
readRawSessionMessageIdOrdinalsForRangeFromDb,
|
|
22
|
+
readRawSessionTailFromDb,
|
|
23
|
+
warmRawSessionOrdinalsForDb,
|
|
24
|
+
readRawSessionMessageOrdinalByIdFromDb,
|
|
25
|
+
readRawSessionMessageByIdFromDb,
|
|
26
|
+
hasRawSessionMessageByIdFromDb,
|
|
14
27
|
openCodeDbExists,
|
|
15
28
|
withReadOnlySessionDb,
|
|
16
29
|
getRawSessionMessageCountFromDb,
|
|
17
30
|
getMessageTimesFromOpenCodeDb
|
|
18
|
-
} from "./index-
|
|
31
|
+
} from "./index-ykq24x1n.js";
|
|
19
32
|
|
|
20
33
|
// src/shared/protected-tools-policy.ts
|
|
21
34
|
var DEFAULT_PROTECTED_TOOLS = {
|
|
@@ -67,7 +80,7 @@ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
|
67
80
|
import { createRequire } from "node:module";
|
|
68
81
|
import { homedir } from "node:os";
|
|
69
82
|
import { dirname, join, resolve } from "node:path";
|
|
70
|
-
import { pathToFileURL } from "node:url";
|
|
83
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
71
84
|
|
|
72
85
|
// src/shared/commit-detection.ts
|
|
73
86
|
var HASH_HEX = "[0-9a-f]{7,12}";
|
|
@@ -92,6 +105,272 @@ function removeSystemReminders(text) {
|
|
|
92
105
|
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
|
|
93
106
|
}
|
|
94
107
|
|
|
108
|
+
// src/hooks/magic-context/token-count-exact.ts
|
|
109
|
+
var NO_RANK = 4294967295;
|
|
110
|
+
var LONG_PIECE_BYTES = 256;
|
|
111
|
+
var MERGE_CACHE_GENERATION = 50000;
|
|
112
|
+
function hasInternals(tokenizer) {
|
|
113
|
+
const value = tokenizer;
|
|
114
|
+
return !!value && value.patternRegex instanceof RegExp && value.patternRegex.global && typeof value.stringRankEncoder === "object" && value.stringRankEncoder !== null && Array.isArray(value.binaryFirstByteIndex);
|
|
115
|
+
}
|
|
116
|
+
var textEncoder = new TextEncoder;
|
|
117
|
+
var textDecoder = new TextDecoder("utf-8");
|
|
118
|
+
function isValidUtf8(bytes) {
|
|
119
|
+
let index = 0;
|
|
120
|
+
while (index < bytes.length) {
|
|
121
|
+
const first = bytes[index];
|
|
122
|
+
let size = 0;
|
|
123
|
+
let codePoint = 0;
|
|
124
|
+
if (first <= 127) {
|
|
125
|
+
size = 1;
|
|
126
|
+
codePoint = first;
|
|
127
|
+
} else if ((first & 224) === 192) {
|
|
128
|
+
size = 2;
|
|
129
|
+
codePoint = first & 31;
|
|
130
|
+
if (first <= 193)
|
|
131
|
+
return false;
|
|
132
|
+
} else if ((first & 240) === 224) {
|
|
133
|
+
size = 3;
|
|
134
|
+
codePoint = first & 15;
|
|
135
|
+
} else if ((first & 248) === 240) {
|
|
136
|
+
size = 4;
|
|
137
|
+
codePoint = first & 7;
|
|
138
|
+
if (first > 244)
|
|
139
|
+
return false;
|
|
140
|
+
} else
|
|
141
|
+
return false;
|
|
142
|
+
if (index + size > bytes.length)
|
|
143
|
+
return false;
|
|
144
|
+
for (let offset = 1;offset < size; offset += 1) {
|
|
145
|
+
const byte = bytes[index + offset];
|
|
146
|
+
if ((byte & 192) !== 128)
|
|
147
|
+
return false;
|
|
148
|
+
codePoint = codePoint << 6 | byte & 63;
|
|
149
|
+
}
|
|
150
|
+
if (size === 2 && codePoint < 128)
|
|
151
|
+
return false;
|
|
152
|
+
if (size === 3 && codePoint < 2048)
|
|
153
|
+
return false;
|
|
154
|
+
if (size === 4 && codePoint < 65536)
|
|
155
|
+
return false;
|
|
156
|
+
if (codePoint >= 55296 && codePoint <= 57343)
|
|
157
|
+
return false;
|
|
158
|
+
if (codePoint > 1114111)
|
|
159
|
+
return false;
|
|
160
|
+
index += size;
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
function binarySearchBytes(sorted, key) {
|
|
165
|
+
let low = 0;
|
|
166
|
+
let high = sorted.length - 1;
|
|
167
|
+
while (low <= high) {
|
|
168
|
+
const mid = low + high >>> 1;
|
|
169
|
+
const midKey = sorted[mid][0];
|
|
170
|
+
let compare = 0;
|
|
171
|
+
const shared = Math.min(midKey.length, key.length);
|
|
172
|
+
for (let index = 0;index < shared; index += 1) {
|
|
173
|
+
compare = midKey[index] - key[index];
|
|
174
|
+
if (compare !== 0)
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
if (compare === 0)
|
|
178
|
+
compare = midKey.length - key.length;
|
|
179
|
+
if (compare === 0)
|
|
180
|
+
return sorted[mid][1];
|
|
181
|
+
if (compare < 0)
|
|
182
|
+
low = mid + 1;
|
|
183
|
+
else
|
|
184
|
+
high = mid - 1;
|
|
185
|
+
}
|
|
186
|
+
return -1;
|
|
187
|
+
}
|
|
188
|
+
function rankOf(tokenizer, slice) {
|
|
189
|
+
if (isValidUtf8(slice)) {
|
|
190
|
+
const rank = tokenizer.stringRankEncoder[textDecoder.decode(slice)];
|
|
191
|
+
if (rank !== undefined)
|
|
192
|
+
return rank;
|
|
193
|
+
}
|
|
194
|
+
const bucket = tokenizer.binaryFirstByteIndex[slice[0]];
|
|
195
|
+
if (bucket !== null && bucket !== undefined) {
|
|
196
|
+
const rank = binarySearchBytes(bucket, slice);
|
|
197
|
+
if (rank !== -1)
|
|
198
|
+
return rank;
|
|
199
|
+
}
|
|
200
|
+
return NO_RANK;
|
|
201
|
+
}
|
|
202
|
+
function mergeByScanning(tokenizer, bytes) {
|
|
203
|
+
const starts = [];
|
|
204
|
+
const ranks = [];
|
|
205
|
+
const pairRank = (index) => {
|
|
206
|
+
const end = starts[index + 2];
|
|
207
|
+
return end === undefined ? NO_RANK : rankOf(tokenizer, bytes.subarray(starts[index], end));
|
|
208
|
+
};
|
|
209
|
+
for (let index = 0;index <= bytes.length; index += 1)
|
|
210
|
+
starts.push(index);
|
|
211
|
+
for (let index = 0;index < starts.length; index += 1)
|
|
212
|
+
ranks.push(pairRank(index));
|
|
213
|
+
while (starts.length > 1) {
|
|
214
|
+
let minRank = NO_RANK;
|
|
215
|
+
let minIndex = -1;
|
|
216
|
+
for (let index = 0;index < ranks.length - 1; index += 1) {
|
|
217
|
+
if (ranks[index] < minRank) {
|
|
218
|
+
minRank = ranks[index];
|
|
219
|
+
minIndex = index;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (minIndex === -1)
|
|
223
|
+
break;
|
|
224
|
+
starts.splice(minIndex + 1, 1);
|
|
225
|
+
ranks.splice(minIndex, 1);
|
|
226
|
+
ranks[minIndex] = pairRank(minIndex);
|
|
227
|
+
if (minIndex > 0)
|
|
228
|
+
ranks[minIndex - 1] = pairRank(minIndex - 1);
|
|
229
|
+
}
|
|
230
|
+
const tokens = [];
|
|
231
|
+
for (let index = 0;index < starts.length - 1; index += 1) {
|
|
232
|
+
const rank = rankOf(tokenizer, bytes.subarray(starts[index], starts[index + 1]));
|
|
233
|
+
if (rank !== NO_RANK)
|
|
234
|
+
tokens.push(rank);
|
|
235
|
+
}
|
|
236
|
+
return tokens;
|
|
237
|
+
}
|
|
238
|
+
function mergeWithHeap(tokenizer, bytes) {
|
|
239
|
+
const length = bytes.length;
|
|
240
|
+
const next = new Int32Array(length + 1);
|
|
241
|
+
const prev = new Int32Array(length + 1);
|
|
242
|
+
const alive = new Uint8Array(length + 1).fill(1);
|
|
243
|
+
const rank = new Float64Array(length + 1).fill(NO_RANK);
|
|
244
|
+
for (let index = 0;index <= length; index += 1) {
|
|
245
|
+
next[index] = index + 1;
|
|
246
|
+
prev[index] = index - 1;
|
|
247
|
+
}
|
|
248
|
+
const heapRank = [];
|
|
249
|
+
const heapAt = [];
|
|
250
|
+
const less = (a, b) => heapRank[a] < heapRank[b] || heapRank[a] === heapRank[b] && heapAt[a] < heapAt[b];
|
|
251
|
+
const swap = (a, b) => {
|
|
252
|
+
[heapRank[a], heapRank[b]] = [heapRank[b], heapRank[a]];
|
|
253
|
+
[heapAt[a], heapAt[b]] = [heapAt[b], heapAt[a]];
|
|
254
|
+
};
|
|
255
|
+
const push = (value, at) => {
|
|
256
|
+
heapRank.push(value);
|
|
257
|
+
heapAt.push(at);
|
|
258
|
+
let child = heapRank.length - 1;
|
|
259
|
+
while (child > 0) {
|
|
260
|
+
const parent = child - 1 >> 1;
|
|
261
|
+
if (!less(child, parent))
|
|
262
|
+
break;
|
|
263
|
+
swap(child, parent);
|
|
264
|
+
child = parent;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
const pop = () => {
|
|
268
|
+
const last = heapRank.length - 1;
|
|
269
|
+
swap(0, last);
|
|
270
|
+
heapRank.pop();
|
|
271
|
+
heapAt.pop();
|
|
272
|
+
let parent = 0;
|
|
273
|
+
for (;; ) {
|
|
274
|
+
const left = parent * 2 + 1;
|
|
275
|
+
const right = left + 1;
|
|
276
|
+
let smallest = parent;
|
|
277
|
+
if (left < heapRank.length && less(left, smallest))
|
|
278
|
+
smallest = left;
|
|
279
|
+
if (right < heapRank.length && less(right, smallest))
|
|
280
|
+
smallest = right;
|
|
281
|
+
if (smallest === parent)
|
|
282
|
+
break;
|
|
283
|
+
swap(parent, smallest);
|
|
284
|
+
parent = smallest;
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
const pairRank = (at) => {
|
|
288
|
+
const middle = next[at];
|
|
289
|
+
if (middle >= length)
|
|
290
|
+
return NO_RANK;
|
|
291
|
+
return rankOf(tokenizer, bytes.subarray(at, next[middle]));
|
|
292
|
+
};
|
|
293
|
+
const update = (at) => {
|
|
294
|
+
rank[at] = pairRank(at);
|
|
295
|
+
if (rank[at] !== NO_RANK)
|
|
296
|
+
push(rank[at], at);
|
|
297
|
+
};
|
|
298
|
+
for (let at = 0;at < length; at += 1)
|
|
299
|
+
update(at);
|
|
300
|
+
while (heapRank.length > 0) {
|
|
301
|
+
const value = heapRank[0];
|
|
302
|
+
const at = heapAt[0];
|
|
303
|
+
pop();
|
|
304
|
+
if (!alive[at] || rank[at] !== value)
|
|
305
|
+
continue;
|
|
306
|
+
const removed = next[at];
|
|
307
|
+
alive[removed] = 0;
|
|
308
|
+
next[at] = next[removed];
|
|
309
|
+
prev[next[removed]] = at;
|
|
310
|
+
update(at);
|
|
311
|
+
if (at > 0)
|
|
312
|
+
update(prev[at]);
|
|
313
|
+
}
|
|
314
|
+
const tokens = [];
|
|
315
|
+
for (let at = 0;at < length; at = next[at]) {
|
|
316
|
+
const value = rankOf(tokenizer, bytes.subarray(at, next[at]));
|
|
317
|
+
if (value !== NO_RANK)
|
|
318
|
+
tokens.push(value);
|
|
319
|
+
}
|
|
320
|
+
return tokens;
|
|
321
|
+
}
|
|
322
|
+
var mergeCaches = new WeakMap;
|
|
323
|
+
var mergedPieces = 0;
|
|
324
|
+
function mergePiece(tokenizer, piece) {
|
|
325
|
+
let cache = mergeCaches.get(tokenizer);
|
|
326
|
+
if (!cache) {
|
|
327
|
+
cache = { current: new Map, previous: new Map };
|
|
328
|
+
mergeCaches.set(tokenizer, cache);
|
|
329
|
+
}
|
|
330
|
+
let tokens = cache.current.get(piece);
|
|
331
|
+
if (tokens)
|
|
332
|
+
return tokens;
|
|
333
|
+
tokens = cache.previous.get(piece);
|
|
334
|
+
if (!tokens) {
|
|
335
|
+
const bytes = textEncoder.encode(piece);
|
|
336
|
+
mergedPieces += 1;
|
|
337
|
+
tokens = bytes.length > LONG_PIECE_BYTES ? mergeWithHeap(tokenizer, bytes) : mergeByScanning(tokenizer, bytes);
|
|
338
|
+
}
|
|
339
|
+
if (cache.current.size >= MERGE_CACHE_GENERATION) {
|
|
340
|
+
cache.previous = cache.current;
|
|
341
|
+
cache.current = new Map;
|
|
342
|
+
}
|
|
343
|
+
cache.current.set(piece, tokens);
|
|
344
|
+
return tokens;
|
|
345
|
+
}
|
|
346
|
+
function encodeTokensExactly(tokenizer, text) {
|
|
347
|
+
if (!hasInternals(tokenizer)) {
|
|
348
|
+
return tokenizer.encode(text, "all");
|
|
349
|
+
}
|
|
350
|
+
if (text.length < 10) {
|
|
351
|
+
const direct = tokenizer.stringRankEncoder[text];
|
|
352
|
+
if (direct !== undefined)
|
|
353
|
+
return [direct];
|
|
354
|
+
}
|
|
355
|
+
const tokens = [];
|
|
356
|
+
const regex = tokenizer.patternRegex;
|
|
357
|
+
regex.lastIndex = 0;
|
|
358
|
+
for (let match = regex.exec(text);match !== null; match = regex.exec(text)) {
|
|
359
|
+
const piece = match[0];
|
|
360
|
+
const direct = tokenizer.stringRankEncoder[piece];
|
|
361
|
+
if (direct !== undefined) {
|
|
362
|
+
tokens.push(direct);
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
for (const token of mergePiece(tokenizer, piece))
|
|
366
|
+
tokens.push(token);
|
|
367
|
+
}
|
|
368
|
+
return tokens;
|
|
369
|
+
}
|
|
370
|
+
function countTokensExactly(tokenizer, text) {
|
|
371
|
+
return encodeTokensExactly(tokenizer, text).length;
|
|
372
|
+
}
|
|
373
|
+
|
|
95
374
|
// src/hooks/magic-context/read-session-formatting.ts
|
|
96
375
|
var MAX_COMMITS_PER_BLOCK = 5;
|
|
97
376
|
function hasMeaningfulUserText2(parts) {
|
|
@@ -204,22 +483,30 @@ var tokenizerSerializedTableBytes;
|
|
|
204
483
|
function tokenizerPackageRoots() {
|
|
205
484
|
const cwd = process.cwd();
|
|
206
485
|
const openCodeCache = join(process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "opencode");
|
|
207
|
-
const roots = [cwd, openCodeCache];
|
|
208
486
|
const candidates = [];
|
|
209
|
-
|
|
487
|
+
const probeRoot = (root) => {
|
|
210
488
|
for (const packageDir of TOKENIZER_PACKAGE_DIRS) {
|
|
211
489
|
candidates.push(join(root, "node_modules", ...packageDir, "node_modules", "ai-tokenizer"));
|
|
212
490
|
}
|
|
213
491
|
candidates.push(join(root, "node_modules", "ai-tokenizer"));
|
|
492
|
+
};
|
|
493
|
+
for (const root of [cwd, openCodeCache]) {
|
|
494
|
+
probeRoot(root);
|
|
214
495
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
496
|
+
const pushAncestors = (startDir) => {
|
|
497
|
+
let ancestor = startDir;
|
|
498
|
+
while (true) {
|
|
499
|
+
candidates.push(join(ancestor, "node_modules", "ai-tokenizer"));
|
|
500
|
+
const parent = dirname(ancestor);
|
|
501
|
+
if (parent === ancestor)
|
|
502
|
+
break;
|
|
503
|
+
ancestor = parent;
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
pushAncestors(process.argv[1] ? dirname(resolve(process.argv[1])) : cwd);
|
|
507
|
+
const ownDir = dirname(fileURLToPath(new URL(import.meta.url)));
|
|
508
|
+
pushAncestors(ownDir);
|
|
509
|
+
probeRoot(join(homedir(), ".omp", "plugins"));
|
|
223
510
|
return [...new Set(candidates)];
|
|
224
511
|
}
|
|
225
512
|
function packageImportTarget(value) {
|
|
@@ -379,7 +666,7 @@ function estimateTokens(text) {
|
|
|
379
666
|
if (!activeTokenizer)
|
|
380
667
|
return estimateTokensHeuristically(text);
|
|
381
668
|
try {
|
|
382
|
-
return activeTokenizer
|
|
669
|
+
return countTokensExactly(activeTokenizer, text);
|
|
383
670
|
} catch (error) {
|
|
384
671
|
tokenizer = undefined;
|
|
385
672
|
tokenizerLoadAttempted = true;
|
|
@@ -500,10 +787,34 @@ function mergeCommitHashes(existing, next) {
|
|
|
500
787
|
var encoder = new TextEncoder;
|
|
501
788
|
var TAG_PREFIX_REGEX = /^(?:§\d+§\s*)+/;
|
|
502
789
|
var MALFORMED_TAG_PREFIX_REGEX = /^(?:§\d+">§(?:\d+§)?\s*)+/;
|
|
790
|
+
var DANGLING_TAG_GLOBAL_REGEX = /\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?/g;
|
|
503
791
|
var DANGLING_TAG_PREFIX_REGEX = /^(?:\u00a7\d+(?!\.\d)[^\s\u00a7\w.]?\s*)+/;
|
|
792
|
+
var COMPLETE_TAG_PAIR_GLOBAL_REGEX = /\u00a7\d+\u00a7/g;
|
|
793
|
+
var MALFORMED_TAG_GLOBAL_REGEX = /\u00a7\d+">(?:\u00a7(?:\d+\u00a7)?)?/g;
|
|
794
|
+
var STRAY_SECTION_CHAR_REGEX = /\u00a7/g;
|
|
504
795
|
function stripWellFormedLeadingTagPrefix(value) {
|
|
505
796
|
return value.replace(/^(\u00a7\d+\u00a7\s*)+/, "");
|
|
506
797
|
}
|
|
798
|
+
function stripCompleteTagPairsGlobally(value) {
|
|
799
|
+
return value.replace(COMPLETE_TAG_PAIR_GLOBAL_REGEX, "");
|
|
800
|
+
}
|
|
801
|
+
function stripMalformedTagNotationGlobally(value) {
|
|
802
|
+
return value.replace(MALFORMED_TAG_GLOBAL_REGEX, "");
|
|
803
|
+
}
|
|
804
|
+
function stripDanglingTagNotationGlobally(value) {
|
|
805
|
+
return value.replace(DANGLING_TAG_GLOBAL_REGEX, "");
|
|
806
|
+
}
|
|
807
|
+
function stripTagSectionCharacters(value) {
|
|
808
|
+
return value.replace(STRAY_SECTION_CHAR_REGEX, "");
|
|
809
|
+
}
|
|
810
|
+
function stripPersistedAssistantText(value) {
|
|
811
|
+
let text = stripWellFormedLeadingTagPrefix(value);
|
|
812
|
+
text = stripCompleteTagPairsGlobally(text);
|
|
813
|
+
text = stripMalformedTagNotationGlobally(text);
|
|
814
|
+
text = stripDanglingTagNotationGlobally(text);
|
|
815
|
+
text = stripTagSectionCharacters(text);
|
|
816
|
+
return text.trim();
|
|
817
|
+
}
|
|
507
818
|
function byteSize(value) {
|
|
508
819
|
return encoder.encode(value).length;
|
|
509
820
|
}
|
|
@@ -536,6 +847,21 @@ function isThinkingPart(part) {
|
|
|
536
847
|
return candidate.type === "thinking" || candidate.type === "reasoning";
|
|
537
848
|
}
|
|
538
849
|
|
|
850
|
+
// src/hooks/magic-context/tail-hygiene-output-count.ts
|
|
851
|
+
var CURRENT_OUTPUT_COUNT = Symbol.for("magic-context.current-reclaimable-tool-output-count");
|
|
852
|
+
function countReclaimableToolOutputs(parts) {
|
|
853
|
+
return parts.filter((part) => part.kind === "toolOutput" && part.uTokens > 0).length;
|
|
854
|
+
}
|
|
855
|
+
function rememberCurrentToolOutputCount(baseline, measurement) {
|
|
856
|
+
return Object.assign(baseline, {
|
|
857
|
+
[CURRENT_OUTPUT_COUNT]: countReclaimableToolOutputs(measurement.parts)
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
function currentReclaimableToolOutputCount(baseline) {
|
|
861
|
+
if (!baseline || !Object.hasOwn(baseline, CURRENT_OUTPUT_COUNT))
|
|
862
|
+
return 0;
|
|
863
|
+
return baseline[CURRENT_OUTPUT_COUNT];
|
|
864
|
+
}
|
|
539
865
|
// src/shared/record-type-guard.ts
|
|
540
866
|
function isRecord(value) {
|
|
541
867
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -543,15 +869,34 @@ function isRecord(value) {
|
|
|
543
869
|
|
|
544
870
|
// src/shared/stable-json.ts
|
|
545
871
|
function stableStringify(value, seen = new WeakSet) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
872
|
+
const pieces = [];
|
|
873
|
+
writeStable(value, seen, (piece) => pieces.push(piece));
|
|
874
|
+
return pieces.join("");
|
|
875
|
+
}
|
|
876
|
+
function writeStable(value, seen, write) {
|
|
877
|
+
if (value === undefined) {
|
|
878
|
+
write("undefined");
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
if (value === null || typeof value !== "object") {
|
|
882
|
+
write(JSON.stringify(value) ?? String(value));
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
if (seen.has(value)) {
|
|
886
|
+
write('"[Circular]"');
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
552
889
|
seen.add(value);
|
|
553
890
|
if (Array.isArray(value)) {
|
|
554
|
-
|
|
891
|
+
write("[");
|
|
892
|
+
for (let index = 0;index < value.length; index += 1) {
|
|
893
|
+
if (index > 0)
|
|
894
|
+
write(",");
|
|
895
|
+
if (index in value)
|
|
896
|
+
writeStable(value[index], seen, write);
|
|
897
|
+
}
|
|
898
|
+
write("]");
|
|
899
|
+
return;
|
|
555
900
|
}
|
|
556
901
|
const entries = Object.entries(value).sort(([a], [b]) => {
|
|
557
902
|
if (a < b)
|
|
@@ -560,10 +905,38 @@ function stableStringify(value, seen = new WeakSet) {
|
|
|
560
905
|
return 1;
|
|
561
906
|
return 0;
|
|
562
907
|
});
|
|
563
|
-
|
|
908
|
+
if (entries.length > 0 && entries.length <= 16 && entries.every(([key, child]) => key.length <= 4096 && !/^(0|[1-9]\d*)$/.test(key) && (child === null || typeof child === "number" || typeof child === "boolean" || typeof child === "string" && child.length <= 4096))) {
|
|
909
|
+
write(JSON.stringify(Object.fromEntries(entries)));
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
write("{");
|
|
913
|
+
entries.forEach(([key, child], index) => {
|
|
914
|
+
if (index > 0)
|
|
915
|
+
write(",");
|
|
916
|
+
write(JSON.stringify(key));
|
|
917
|
+
write(":");
|
|
918
|
+
writeStable(child, seen, write);
|
|
919
|
+
});
|
|
920
|
+
write("}");
|
|
921
|
+
}
|
|
922
|
+
function stableStringifyHash(value, prefix = "") {
|
|
923
|
+
const sink = jsonHashSink(prefix);
|
|
924
|
+
writeStable(value, new WeakSet, sink.write);
|
|
925
|
+
return sink.digest();
|
|
926
|
+
}
|
|
927
|
+
function jsonHashSink(prefix = "") {
|
|
928
|
+
let hash = 2166136261;
|
|
929
|
+
const write = (piece) => {
|
|
930
|
+
for (let index = 0;index < piece.length; index++) {
|
|
931
|
+
hash = Math.imul(hash ^ piece.charCodeAt(index), 16777619);
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
write(prefix);
|
|
935
|
+
return { write, digest: () => (hash >>> 0).toString(16).padStart(8, "0") };
|
|
564
936
|
}
|
|
565
937
|
|
|
566
938
|
// src/shared/tag-owner-id.ts
|
|
939
|
+
var PI_FALLBACK_PREFIXES_JSON = JSON.stringify([..."pi-msg-"].reduce((prefixes, char) => prefixes.flatMap((prefix) => /[a-z]/.test(char) ? [prefix + char, prefix + char.toUpperCase()] : [prefix + char]), [""]));
|
|
567
940
|
var POSITIONAL_CONTENT_SUFFIX = /:(?:p|file)\d+$/;
|
|
568
941
|
var CONTENT_DERIVED_TEXT_SUFFIX = /:mc-text-v1:[0-9a-f]+:[0-9a-f]+:o\d+$/;
|
|
569
942
|
function contentTagOwnerMessageId(contentId) {
|
|
@@ -576,6 +949,127 @@ function contentTagOwnerMessageId(contentId) {
|
|
|
576
949
|
return contentId;
|
|
577
950
|
}
|
|
578
951
|
|
|
952
|
+
// src/shared/tail-hygiene-json.ts
|
|
953
|
+
var MAX_MEMO_BYTES = 64 * 1024 * 1024;
|
|
954
|
+
var MAX_MEMO_ENTRIES = 1e4;
|
|
955
|
+
|
|
956
|
+
class TailHygieneJsonMemo {
|
|
957
|
+
entries = new Map;
|
|
958
|
+
bytes = 0;
|
|
959
|
+
passText = new WeakMap;
|
|
960
|
+
passHash = new WeakMap;
|
|
961
|
+
beginPass() {
|
|
962
|
+
this.passText = new WeakMap;
|
|
963
|
+
this.passHash = new WeakMap;
|
|
964
|
+
}
|
|
965
|
+
get(key, value, compute, fingerprint = false) {
|
|
966
|
+
const pass = fingerprint ? this.passHash : this.passText;
|
|
967
|
+
const object = value !== null && typeof value === "object" ? value : undefined;
|
|
968
|
+
const local = object ? pass.get(object) : undefined;
|
|
969
|
+
if (local !== undefined)
|
|
970
|
+
return local;
|
|
971
|
+
const previous = this.entries.get(key);
|
|
972
|
+
if (previous && sameJson(previous.snapshot, value)) {
|
|
973
|
+
if (object)
|
|
974
|
+
pass.set(object, previous.result);
|
|
975
|
+
return previous.result;
|
|
976
|
+
}
|
|
977
|
+
const result = compute();
|
|
978
|
+
if (previous) {
|
|
979
|
+
this.bytes -= previous.bytes;
|
|
980
|
+
this.entries.delete(key);
|
|
981
|
+
}
|
|
982
|
+
try {
|
|
983
|
+
const copy = copyJson(value);
|
|
984
|
+
const bytes = copy.bytes + (key.length + result.length) * 2;
|
|
985
|
+
if (bytes <= MAX_MEMO_BYTES) {
|
|
986
|
+
this.entries.set(key, { snapshot: copy.value, result, bytes });
|
|
987
|
+
this.bytes += bytes;
|
|
988
|
+
if (object)
|
|
989
|
+
pass.set(object, result);
|
|
990
|
+
}
|
|
991
|
+
} catch {}
|
|
992
|
+
while (this.bytes > MAX_MEMO_BYTES || this.entries.size > MAX_MEMO_ENTRIES) {
|
|
993
|
+
const oldest = this.entries.entries().next().value;
|
|
994
|
+
if (!oldest)
|
|
995
|
+
break;
|
|
996
|
+
this.bytes -= oldest[1].bytes;
|
|
997
|
+
this.entries.delete(oldest[0]);
|
|
998
|
+
}
|
|
999
|
+
return result;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
function copyJson(value) {
|
|
1003
|
+
const seen = new Map;
|
|
1004
|
+
let bytes = 0;
|
|
1005
|
+
const copy = (current) => {
|
|
1006
|
+
bytes += 16;
|
|
1007
|
+
if (typeof current === "string")
|
|
1008
|
+
bytes += current.length * 2;
|
|
1009
|
+
if (bytes > MAX_MEMO_BYTES)
|
|
1010
|
+
throw new Error("memo capacity");
|
|
1011
|
+
if (current === null || typeof current !== "object") {
|
|
1012
|
+
if (["function", "symbol", "bigint"].includes(typeof current))
|
|
1013
|
+
throw new Error("exotic");
|
|
1014
|
+
return current;
|
|
1015
|
+
}
|
|
1016
|
+
if (seen.has(current))
|
|
1017
|
+
return seen.get(current);
|
|
1018
|
+
const prototype = Object.getPrototypeOf(current);
|
|
1019
|
+
if (!Array.isArray(current) && prototype !== Object.prototype && prototype !== null)
|
|
1020
|
+
throw new Error("exotic");
|
|
1021
|
+
const result = Array.isArray(current) ? new Array(current.length) : Object.create(prototype);
|
|
1022
|
+
seen.set(current, result);
|
|
1023
|
+
for (const key of Object.keys(current)) {
|
|
1024
|
+
const descriptor = Object.getOwnPropertyDescriptor(current, key);
|
|
1025
|
+
if (!descriptor || !("value" in descriptor))
|
|
1026
|
+
throw new Error("accessor");
|
|
1027
|
+
bytes += key.length * 2 + 16;
|
|
1028
|
+
if (key === "__proto__") {
|
|
1029
|
+
Object.defineProperty(result, key, {
|
|
1030
|
+
value: copy(descriptor.value),
|
|
1031
|
+
enumerable: true,
|
|
1032
|
+
writable: true,
|
|
1033
|
+
configurable: true
|
|
1034
|
+
});
|
|
1035
|
+
} else
|
|
1036
|
+
result[key] = copy(descriptor.value);
|
|
1037
|
+
}
|
|
1038
|
+
return result;
|
|
1039
|
+
};
|
|
1040
|
+
return { value: copy(value), bytes };
|
|
1041
|
+
}
|
|
1042
|
+
function sameJson(before, after) {
|
|
1043
|
+
const forward = new Map;
|
|
1044
|
+
const reverse = new Set;
|
|
1045
|
+
const same = (left, right) => {
|
|
1046
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object")
|
|
1047
|
+
return Object.is(left, right);
|
|
1048
|
+
if (forward.has(left))
|
|
1049
|
+
return forward.get(left) === right;
|
|
1050
|
+
if (reverse.has(right) || Object.getPrototypeOf(left) !== Object.getPrototypeOf(right))
|
|
1051
|
+
return false;
|
|
1052
|
+
forward.set(left, right);
|
|
1053
|
+
reverse.add(right);
|
|
1054
|
+
if (Array.isArray(left) && (!Array.isArray(right) || left.length !== right.length))
|
|
1055
|
+
return false;
|
|
1056
|
+
const keys = Object.keys(left);
|
|
1057
|
+
const otherKeys = Object.keys(right);
|
|
1058
|
+
if (keys.length !== otherKeys.length)
|
|
1059
|
+
return false;
|
|
1060
|
+
for (let index = 0;index < keys.length; index++) {
|
|
1061
|
+
const key = keys[index];
|
|
1062
|
+
if (key !== otherKeys[index])
|
|
1063
|
+
return false;
|
|
1064
|
+
const descriptor = Object.getOwnPropertyDescriptor(right, key);
|
|
1065
|
+
if (!descriptor || !("value" in descriptor) || !same(left[key], descriptor.value))
|
|
1066
|
+
return false;
|
|
1067
|
+
}
|
|
1068
|
+
return true;
|
|
1069
|
+
};
|
|
1070
|
+
return same(before, after);
|
|
1071
|
+
}
|
|
1072
|
+
|
|
579
1073
|
// src/hooks/magic-context/image-token-estimate.ts
|
|
580
1074
|
var IMAGE_TOKEN_DIVISOR = 750;
|
|
581
1075
|
var IMAGE_FALLBACK_TOKENS = 1200;
|
|
@@ -768,6 +1262,151 @@ function readUint32BE(b, offset) {
|
|
|
768
1262
|
return (b[offset] << 24 | b[offset + 1] << 16 | b[offset + 2] << 8 | b[offset + 3]) >>> 0;
|
|
769
1263
|
}
|
|
770
1264
|
|
|
1265
|
+
// src/hooks/magic-context/provider-visible-parts.ts
|
|
1266
|
+
function isRecord2(value) {
|
|
1267
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1268
|
+
}
|
|
1269
|
+
var KEPT_TOOL_STATE_FIELDS = new Set([
|
|
1270
|
+
"status",
|
|
1271
|
+
"input",
|
|
1272
|
+
"output",
|
|
1273
|
+
"error",
|
|
1274
|
+
"attachments",
|
|
1275
|
+
"content"
|
|
1276
|
+
]);
|
|
1277
|
+
var KEPT_TOOL_STATE_TIME_FIELD = "compacted";
|
|
1278
|
+
function tailProviderVisibleToolState(state, openCode1) {
|
|
1279
|
+
const view = {};
|
|
1280
|
+
for (const key of Object.keys(state)) {
|
|
1281
|
+
if (tailToolStateFieldIsKept(key, openCode1)) {
|
|
1282
|
+
view[key] = state[key];
|
|
1283
|
+
} else if (key === "time" && openCode1) {
|
|
1284
|
+
const value = state.time;
|
|
1285
|
+
if (isRecord2(value)) {
|
|
1286
|
+
view.time = value[KEPT_TOOL_STATE_TIME_FIELD] === undefined ? {} : { [KEPT_TOOL_STATE_TIME_FIELD]: value[KEPT_TOOL_STATE_TIME_FIELD] };
|
|
1287
|
+
}
|
|
1288
|
+
} else if (key === "metadata" && openCode1 && state.status === "error") {
|
|
1289
|
+
const metadata = state.metadata;
|
|
1290
|
+
if (isRecord2(metadata) && metadata.interrupted === true) {
|
|
1291
|
+
const output = metadata.output;
|
|
1292
|
+
if (typeof output === "string")
|
|
1293
|
+
view.metadata = { interrupted: true, output };
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return view;
|
|
1298
|
+
}
|
|
1299
|
+
function tailToolStateFieldIsKept(key, openCode1) {
|
|
1300
|
+
return KEPT_TOOL_STATE_FIELDS.has(key) && (key !== "content" || !openCode1);
|
|
1301
|
+
}
|
|
1302
|
+
function tailToolStateIsReduced(state, openCode1) {
|
|
1303
|
+
for (const key of Object.keys(state)) {
|
|
1304
|
+
if (tailToolStateFieldIsKept(key, openCode1))
|
|
1305
|
+
continue;
|
|
1306
|
+
return false;
|
|
1307
|
+
}
|
|
1308
|
+
return true;
|
|
1309
|
+
}
|
|
1310
|
+
function providerVisiblePart(part) {
|
|
1311
|
+
if (!isRecord2(part) || part.type !== "tool" || !isRecord2(part.state))
|
|
1312
|
+
return part;
|
|
1313
|
+
if (toolStateIsReduced(part.state))
|
|
1314
|
+
return part;
|
|
1315
|
+
return { ...part, state: providerVisibleToolState(part.state) };
|
|
1316
|
+
}
|
|
1317
|
+
function providerVisiblePartForTailHygiene(part) {
|
|
1318
|
+
return providerVisiblePartForHost(part, true);
|
|
1319
|
+
}
|
|
1320
|
+
function providerVisiblePartForOpenCode2(part) {
|
|
1321
|
+
return providerVisiblePartForHost(part, false);
|
|
1322
|
+
}
|
|
1323
|
+
function providerVisiblePartForHost(part, openCode1) {
|
|
1324
|
+
if (!isRecord2(part))
|
|
1325
|
+
return part;
|
|
1326
|
+
if (part.type !== "tool") {
|
|
1327
|
+
if (!Object.hasOwn(part, "state"))
|
|
1328
|
+
return part;
|
|
1329
|
+
const view = {};
|
|
1330
|
+
for (const key of Object.keys(part)) {
|
|
1331
|
+
if (key !== "state")
|
|
1332
|
+
view[key] = part[key];
|
|
1333
|
+
}
|
|
1334
|
+
return view;
|
|
1335
|
+
}
|
|
1336
|
+
if (!isRecord2(part.state))
|
|
1337
|
+
return part;
|
|
1338
|
+
if (tailToolStateIsReduced(part.state, openCode1))
|
|
1339
|
+
return part;
|
|
1340
|
+
return { ...part, state: tailProviderVisibleToolState(part.state, openCode1) };
|
|
1341
|
+
}
|
|
1342
|
+
var KEPT_ERROR_METADATA_FIELDS = ["interrupted", "output"];
|
|
1343
|
+
function providerVisibleToolState(state) {
|
|
1344
|
+
const view = {};
|
|
1345
|
+
for (const key of Object.keys(state)) {
|
|
1346
|
+
const value = state[key];
|
|
1347
|
+
if (KEPT_TOOL_STATE_FIELDS.has(key)) {
|
|
1348
|
+
view[key] = value;
|
|
1349
|
+
} else if (key === "time" && isRecord2(value)) {
|
|
1350
|
+
view.time = value[KEPT_TOOL_STATE_TIME_FIELD] === undefined ? {} : { [KEPT_TOOL_STATE_TIME_FIELD]: value[KEPT_TOOL_STATE_TIME_FIELD] };
|
|
1351
|
+
} else if (key === "metadata" && state.status === "error" && isRecord2(value)) {
|
|
1352
|
+
const kept = {};
|
|
1353
|
+
for (const field of KEPT_ERROR_METADATA_FIELDS) {
|
|
1354
|
+
if (Object.hasOwn(value, field))
|
|
1355
|
+
kept[field] = value[field];
|
|
1356
|
+
}
|
|
1357
|
+
view.metadata = kept;
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
return view;
|
|
1361
|
+
}
|
|
1362
|
+
function toolStateIsReduced(state) {
|
|
1363
|
+
for (const key of Object.keys(state)) {
|
|
1364
|
+
if (KEPT_TOOL_STATE_FIELDS.has(key))
|
|
1365
|
+
continue;
|
|
1366
|
+
const value = state[key];
|
|
1367
|
+
if (key === "time" && isRecord2(value)) {
|
|
1368
|
+
const keys = Object.keys(value);
|
|
1369
|
+
if (keys.length === 0)
|
|
1370
|
+
continue;
|
|
1371
|
+
if (keys.length === 1 && keys[0] === KEPT_TOOL_STATE_TIME_FIELD)
|
|
1372
|
+
continue;
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
if (key === "metadata" && state.status === "error" && isRecord2(value)) {
|
|
1376
|
+
const extra = Object.keys(value).some((field) => !KEPT_ERROR_METADATA_FIELDS.includes(field));
|
|
1377
|
+
if (!extra)
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
return false;
|
|
1381
|
+
}
|
|
1382
|
+
return true;
|
|
1383
|
+
}
|
|
1384
|
+
function providerVisibleMessage(message) {
|
|
1385
|
+
return projectMessage(message, providerVisiblePart);
|
|
1386
|
+
}
|
|
1387
|
+
function providerVisibleMessageForTailHygiene(message) {
|
|
1388
|
+
return projectMessage(message, providerVisiblePartForTailHygiene);
|
|
1389
|
+
}
|
|
1390
|
+
function providerVisibleMessageForOpenCode2(message) {
|
|
1391
|
+
return projectMessage(message, providerVisiblePartForOpenCode2);
|
|
1392
|
+
}
|
|
1393
|
+
function projectMessage(message, projectPart) {
|
|
1394
|
+
if (!isRecord2(message) || !Array.isArray(message.parts))
|
|
1395
|
+
return message;
|
|
1396
|
+
let parts;
|
|
1397
|
+
for (let index = 0;index < message.parts.length; index += 1) {
|
|
1398
|
+
const part = message.parts[index];
|
|
1399
|
+
const view = projectPart(part);
|
|
1400
|
+
if (view !== part) {
|
|
1401
|
+
parts ??= message.parts.slice(0, index);
|
|
1402
|
+
parts.push(view);
|
|
1403
|
+
} else if (parts) {
|
|
1404
|
+
parts.push(part);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
return parts ? { ...message, parts } : message;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
771
1410
|
// src/hooks/magic-context/todo-view.ts
|
|
772
1411
|
import { createHash } from "node:crypto";
|
|
773
1412
|
var TODO_STATUS_PENDING = "pending";
|
|
@@ -885,7 +1524,7 @@ function isTodoItem(value) {
|
|
|
885
1524
|
|
|
886
1525
|
// src/hooks/magic-context/tail-hygiene-walk.ts
|
|
887
1526
|
var MAX_CONTENT_MEMO_ENTRIES = 1e5;
|
|
888
|
-
var MAX_CONTENT_MEMO_BYTES =
|
|
1527
|
+
var MAX_CONTENT_MEMO_BYTES = 256 * 1024 * 1024;
|
|
889
1528
|
var contentMemo = new Map;
|
|
890
1529
|
var contentMemoOrder = new Set;
|
|
891
1530
|
var contentMemoBytes = 0;
|
|
@@ -1069,41 +1708,46 @@ function stripChannel1ReminderSpans(output) {
|
|
|
1069
1708
|
return stripped;
|
|
1070
1709
|
}
|
|
1071
1710
|
function isDropSentinel(content) {
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1711
|
+
let stripped = content.trimStart();
|
|
1712
|
+
const tag = TAG_PREFIX.exec(stripped);
|
|
1713
|
+
if (tag)
|
|
1714
|
+
stripped = stripped.slice(tag[0].length).trimStart();
|
|
1715
|
+
return DROP_PREFIXES.some((prefix) => stripped.slice(0, prefix.length).toLowerCase() === prefix);
|
|
1716
|
+
}
|
|
1717
|
+
function toolOutputText(part, key) {
|
|
1718
|
+
const serialize = (value) => partJsonMemo.get(key, value, () => safeStableStringify(value));
|
|
1076
1719
|
if (part.type === "tool") {
|
|
1077
1720
|
const state = isRecord(part.state) ? part.state : null;
|
|
1078
1721
|
if (!state)
|
|
1079
1722
|
return null;
|
|
1080
1723
|
if (state.output !== undefined)
|
|
1081
|
-
return
|
|
1724
|
+
return serialize(state.output);
|
|
1082
1725
|
if (state.error !== undefined)
|
|
1083
|
-
return
|
|
1726
|
+
return serialize(state.error);
|
|
1084
1727
|
if (state.result !== undefined)
|
|
1085
|
-
return
|
|
1728
|
+
return serialize(state.result);
|
|
1086
1729
|
return null;
|
|
1087
1730
|
}
|
|
1088
1731
|
if (part.type === "tool_result") {
|
|
1089
1732
|
const value = part.content ?? part.output ?? part.result;
|
|
1090
|
-
return value === undefined ? null :
|
|
1733
|
+
return value === undefined ? null : serialize(value);
|
|
1091
1734
|
}
|
|
1092
1735
|
return null;
|
|
1093
1736
|
}
|
|
1094
|
-
function toolInputText(part) {
|
|
1737
|
+
function toolInputText(part, key) {
|
|
1738
|
+
const serialize = (value) => partJsonMemo.get(key, value, () => safeStableStringify(value));
|
|
1095
1739
|
if (part.type === "tool") {
|
|
1096
1740
|
const state = isRecord(part.state) ? part.state : null;
|
|
1097
1741
|
if (!state || state.input === undefined)
|
|
1098
1742
|
return null;
|
|
1099
|
-
return
|
|
1743
|
+
return serialize(state.input);
|
|
1100
1744
|
}
|
|
1101
1745
|
if (part.type === "tool-invocation") {
|
|
1102
1746
|
const value = part.args ?? part.input;
|
|
1103
|
-
return value === undefined ? null :
|
|
1747
|
+
return value === undefined ? null : serialize(value);
|
|
1104
1748
|
}
|
|
1105
1749
|
if (part.type === "tool_use") {
|
|
1106
|
-
return part.input === undefined ? null :
|
|
1750
|
+
return part.input === undefined ? null : serialize(part.input);
|
|
1107
1751
|
}
|
|
1108
1752
|
return null;
|
|
1109
1753
|
}
|
|
@@ -1114,8 +1758,8 @@ function messageIdForTag(tag) {
|
|
|
1114
1758
|
}
|
|
1115
1759
|
function resolveProtectedTagNumbers(tags, protectedTagNumbersInput, protectedToolTags) {
|
|
1116
1760
|
const protectedNumbers = new Set(protectedTagNumbersInput);
|
|
1117
|
-
const
|
|
1118
|
-
for (const tagNumber of
|
|
1761
|
+
const protectedCtxReduceTags = protectedToolTags ?? protectedToolTagNumbers(tags);
|
|
1762
|
+
for (const tagNumber of protectedCtxReduceTags)
|
|
1119
1763
|
protectedNumbers.add(tagNumber);
|
|
1120
1764
|
return protectedNumbers;
|
|
1121
1765
|
}
|
|
@@ -1230,17 +1874,28 @@ function snapshot(args) {
|
|
|
1230
1874
|
queuedForDrop
|
|
1231
1875
|
};
|
|
1232
1876
|
}
|
|
1877
|
+
var partJsonMemo = new TailHygieneJsonMemo;
|
|
1233
1878
|
function excludedSnapshot(key, part) {
|
|
1234
|
-
const
|
|
1235
|
-
|
|
1879
|
+
const contentHash = partJsonMemo.get(key, part, () => {
|
|
1880
|
+
if (part === null || part === undefined || typeof part === "string")
|
|
1881
|
+
return memoizedContent("excluded", safeStableStringify(part)).hash;
|
|
1882
|
+
try {
|
|
1883
|
+
return stableStringifyHash(part, "excluded\x00");
|
|
1884
|
+
} catch {
|
|
1885
|
+
return memoizedContent("excluded", String(part)).hash;
|
|
1886
|
+
}
|
|
1887
|
+
}, true);
|
|
1888
|
+
return {
|
|
1236
1889
|
key,
|
|
1890
|
+
contentHash,
|
|
1237
1891
|
kind: "excluded",
|
|
1238
|
-
content,
|
|
1239
1892
|
tokens: 0,
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1893
|
+
uTokens: 0,
|
|
1894
|
+
tagNumber: null,
|
|
1895
|
+
tagStatus: null,
|
|
1896
|
+
protected: false,
|
|
1897
|
+
queuedForDrop: false
|
|
1898
|
+
};
|
|
1244
1899
|
}
|
|
1245
1900
|
function fileContentAndTokens(part) {
|
|
1246
1901
|
const mime = typeof part.mime === "string" ? part.mime : "";
|
|
@@ -1280,12 +1935,12 @@ function structuralSize(value) {
|
|
|
1280
1935
|
}
|
|
1281
1936
|
return 0;
|
|
1282
1937
|
}
|
|
1283
|
-
function tailHygieneStructuralSignature(messages) {
|
|
1938
|
+
function tailHygieneStructuralSignature(messages, opencode2 = false) {
|
|
1284
1939
|
const partCounts = [];
|
|
1285
1940
|
let totalBytes = 0;
|
|
1286
1941
|
for (const message of messages) {
|
|
1287
1942
|
partCounts.push(message.parts.length);
|
|
1288
|
-
totalBytes += structuralSize(message);
|
|
1943
|
+
totalBytes += structuralSize(opencode2 ? providerVisibleMessageForOpenCode2(message) : providerVisibleMessageForTailHygiene(message));
|
|
1289
1944
|
}
|
|
1290
1945
|
return { messageCount: messages.length, partCounts, totalBytes };
|
|
1291
1946
|
}
|
|
@@ -1299,10 +1954,22 @@ function measureTailHygiene(input) {
|
|
|
1299
1954
|
return measureWithReplay(input);
|
|
1300
1955
|
}
|
|
1301
1956
|
function measureWithReplay(input, replay) {
|
|
1957
|
+
partJsonMemo.beginPass();
|
|
1958
|
+
const projectPart = input.opencode2 ? providerVisiblePartForOpenCode2 : providerVisiblePartForTailHygiene;
|
|
1959
|
+
const views = new WeakMap;
|
|
1960
|
+
const excluded = (key, part) => {
|
|
1961
|
+
let view = part !== null && typeof part === "object" ? views.get(part) : undefined;
|
|
1962
|
+
if (view === undefined) {
|
|
1963
|
+
view = projectPart(part);
|
|
1964
|
+
if (part !== null && typeof part === "object")
|
|
1965
|
+
views.set(part, view);
|
|
1966
|
+
}
|
|
1967
|
+
return excludedSnapshot(key, view);
|
|
1968
|
+
};
|
|
1302
1969
|
const pendingDropTagNumbers = input.pendingDropTagNumbers ?? new Set;
|
|
1303
1970
|
const unchanged = input.messages.map((message, index) => {
|
|
1304
1971
|
const previous = replay?.messages[index];
|
|
1305
|
-
return previous !== undefined && sameReplayMessage(previous, message);
|
|
1972
|
+
return previous !== undefined && sameReplayMessage(previous, message, projectPart);
|
|
1306
1973
|
});
|
|
1307
1974
|
const toolIdentities = collectToolPartIdentities(input.messages);
|
|
1308
1975
|
const attribution = buildTagAttribution({
|
|
@@ -1312,7 +1979,7 @@ function measureWithReplay(input, replay) {
|
|
|
1312
1979
|
protectedTagNumbers: input.protectedTagNumbers,
|
|
1313
1980
|
protectedToolTags: input.protectedToolTags
|
|
1314
1981
|
});
|
|
1315
|
-
const toolOutputs = input.messages.map((message, index) => message.parts.map((part, partIndex) => unchanged[index] ? replay?.measured.toolOutputs[index][partIndex] ?? null : isRecord(part) ? toolOutputText(part) : null));
|
|
1982
|
+
const toolOutputs = input.messages.map((message, index) => message.parts.map((part, partIndex) => unchanged[index] ? replay?.measured.toolOutputs[index][partIndex] ?? null : isRecord(part) ? toolOutputText(part, `${messageIdentity(message, index)}\x00${partIndex}\x00output`) : null));
|
|
1316
1983
|
const outputByPart = new Map;
|
|
1317
1984
|
input.messages.forEach((message, index) => {
|
|
1318
1985
|
message.parts.forEach((part, partIndex) => {
|
|
@@ -1378,19 +2045,19 @@ function measureWithReplay(input, replay) {
|
|
|
1378
2045
|
const part = message.parts[partIndex];
|
|
1379
2046
|
const key = `${messageKey}\x00${partIndex}`;
|
|
1380
2047
|
if (messageSynthetic || isSyntheticPart(part) || !isRecord(part)) {
|
|
1381
|
-
parts.push(
|
|
2048
|
+
parts.push(excluded(`${key}\x00excluded`, part));
|
|
1382
2049
|
continue;
|
|
1383
2050
|
}
|
|
1384
2051
|
const type = typeof part.type === "string" ? part.type : "";
|
|
1385
2052
|
if (type === "reasoning" || type === "thinking" || type === "redacted_thinking" || type === "signature") {
|
|
1386
|
-
parts.push(
|
|
2053
|
+
parts.push(excluded(`${key}\x00excluded`, part));
|
|
1387
2054
|
continue;
|
|
1388
2055
|
}
|
|
1389
2056
|
if (type === "text") {
|
|
1390
2057
|
const rawContent = firstString(part, ["text", "content"]);
|
|
1391
2058
|
const content = rawContent === null ? null : stripChannel1ReminderSpans(rawContent);
|
|
1392
2059
|
if (!content || isDropSentinel(content)) {
|
|
1393
|
-
parts.push(
|
|
2060
|
+
parts.push(excluded(`${key}\x00excluded`, part));
|
|
1394
2061
|
continue;
|
|
1395
2062
|
}
|
|
1396
2063
|
const tokens = memoizedTokens("text", content);
|
|
@@ -1412,7 +2079,7 @@ function measureWithReplay(input, replay) {
|
|
|
1412
2079
|
if (type === "file" || type.includes("image") || type === "source") {
|
|
1413
2080
|
const file = fileContentAndTokens(part);
|
|
1414
2081
|
if (!file.content || isDropSentinel(file.content)) {
|
|
1415
|
-
parts.push(
|
|
2082
|
+
parts.push(excluded(`${key}\x00excluded`, part));
|
|
1416
2083
|
continue;
|
|
1417
2084
|
}
|
|
1418
2085
|
const tag = attribution.messageTags.get(`${message.info.id}:file${partIndex}`);
|
|
@@ -1434,11 +2101,11 @@ function measureWithReplay(input, replay) {
|
|
|
1434
2101
|
if (toolIdentity) {
|
|
1435
2102
|
const ownerKey = `${toolIdentity.ownerMessageId}\x00${toolIdentity.callId}`;
|
|
1436
2103
|
if (droppedToolOwners.has(ownerKey)) {
|
|
1437
|
-
parts.push(
|
|
2104
|
+
parts.push(excluded(`${key}\x00excluded`, part));
|
|
1438
2105
|
continue;
|
|
1439
2106
|
}
|
|
1440
2107
|
const tag = attribution.toolTagsByPart.get(part);
|
|
1441
|
-
const inputText = toolInputText(part);
|
|
2108
|
+
const inputText = toolInputText(part, `${key}\x00input`);
|
|
1442
2109
|
if (inputText !== null) {
|
|
1443
2110
|
const tokens = memoizedTokens("toolInput", inputText);
|
|
1444
2111
|
const measured = snapshot({
|
|
@@ -1458,7 +2125,7 @@ function measureWithReplay(input, replay) {
|
|
|
1458
2125
|
if (rawOutput !== null) {
|
|
1459
2126
|
const output = stripChannel1ReminderSpans(rawOutput);
|
|
1460
2127
|
if (isDropSentinel(output)) {
|
|
1461
|
-
parts.push(
|
|
2128
|
+
parts.push(excluded(`${key}\x00excludedOutput`, output));
|
|
1462
2129
|
} else {
|
|
1463
2130
|
const tokens = memoizedTokens("toolOutput", output) + (part.type === "tool" ? estimateToolAttachmentImageTokens(part.state) : 0);
|
|
1464
2131
|
const measured = snapshot({
|
|
@@ -1476,11 +2143,11 @@ function measureWithReplay(input, replay) {
|
|
|
1476
2143
|
}
|
|
1477
2144
|
}
|
|
1478
2145
|
if (inputText === null && rawOutput === null) {
|
|
1479
|
-
parts.push(
|
|
2146
|
+
parts.push(excluded(`${key}\x00excluded`, part));
|
|
1480
2147
|
}
|
|
1481
2148
|
continue;
|
|
1482
2149
|
}
|
|
1483
|
-
parts.push(
|
|
2150
|
+
parts.push(excluded(`${key}\x00excluded`, part));
|
|
1484
2151
|
}
|
|
1485
2152
|
}
|
|
1486
2153
|
return {
|
|
@@ -1621,16 +2288,19 @@ function sameNumbers(before, after) {
|
|
|
1621
2288
|
return false;
|
|
1622
2289
|
return true;
|
|
1623
2290
|
}
|
|
1624
|
-
function sameReplayMessage(left, right) {
|
|
1625
|
-
return left.info.id === right.info.id && left.info.role === right.info.role && left.info.summary === right.info.summary && sameReplayValue(left.parts, right.parts);
|
|
2291
|
+
function sameReplayMessage(left, right, projectPart = providerVisiblePartForTailHygiene) {
|
|
2292
|
+
return left.info.id === right.info.id && left.info.role === right.info.role && left.info.summary === right.info.summary && sameReplayValue(left.parts, right.parts.map(projectPart));
|
|
1626
2293
|
}
|
|
1627
|
-
function
|
|
2294
|
+
function replaySnapshotParts(parts, projectPart = providerVisiblePartForTailHygiene) {
|
|
2295
|
+
return copyReplayValue(parts.map(projectPart));
|
|
2296
|
+
}
|
|
2297
|
+
function sameReplayMessages(before, after, projectPart = providerVisiblePartForTailHygiene) {
|
|
1628
2298
|
if (before.length !== after.length)
|
|
1629
2299
|
return false;
|
|
1630
2300
|
for (let index = 0;index < before.length; index += 1) {
|
|
1631
2301
|
const left = before[index];
|
|
1632
2302
|
const right = after[index];
|
|
1633
|
-
if (!sameReplayMessage(left, right))
|
|
2303
|
+
if (!sameReplayMessage(left, right, projectPart))
|
|
1634
2304
|
return false;
|
|
1635
2305
|
}
|
|
1636
2306
|
return true;
|
|
@@ -1689,8 +2359,10 @@ function refreshTailHygieneBaseline(input) {
|
|
|
1689
2359
|
protectedTagNumbers: new Set([...input.protectedTagNumbers, ...protectedToolTags])
|
|
1690
2360
|
};
|
|
1691
2361
|
const pendingDropTagNumbers = input.pendingDropTagNumbers ?? new Set;
|
|
1692
|
-
const
|
|
1693
|
-
const
|
|
2362
|
+
const priorMemo = input.previous ? baselineMeasurementMemo.get(input.previous.baselineParts) : undefined;
|
|
2363
|
+
const cached = priorMemo?.opencode2 === !!input.opencode2 ? priorMemo : undefined;
|
|
2364
|
+
const projectPart = input.opencode2 ? providerVisiblePartForOpenCode2 : providerVisiblePartForTailHygiene;
|
|
2365
|
+
const hit = !input.cacheBusting && cached && sameReplayMessages(cached.messages, input.messages, projectPart) && sameReplayValue(cached.tags, input.tags) && sameNumbers(cached.protectedTagNumbers, input.protectedTagNumbers) && sameNumbers(cached.pendingDropTagNumbers, pendingDropTagNumbers);
|
|
1694
2366
|
const rawMeasured = hit ? cached.measured : measureWithReplay(input, cached);
|
|
1695
2367
|
const frozenCalibration = !input.cacheBusting && input.previous ? {
|
|
1696
2368
|
toolsRatio: input.previous.toolsRatio,
|
|
@@ -1710,19 +2382,20 @@ function refreshTailHygieneBaseline(input) {
|
|
|
1710
2382
|
})
|
|
1711
2383
|
};
|
|
1712
2384
|
const memo = hit ? cached : {
|
|
1713
|
-
|
|
2385
|
+
opencode2: !!input.opencode2,
|
|
2386
|
+
messages: input.messages.map((message, index) => cached?.messages[index] && sameReplayMessage(cached.messages[index], message, projectPart) ? cached.messages[index] : {
|
|
1714
2387
|
info: {
|
|
1715
2388
|
id: message.info.id,
|
|
1716
2389
|
role: message.info.role,
|
|
1717
2390
|
summary: message.info.summary
|
|
1718
2391
|
},
|
|
1719
|
-
parts:
|
|
2392
|
+
parts: replaySnapshotParts(message.parts, projectPart)
|
|
1720
2393
|
}),
|
|
1721
2394
|
tags: structuredClone(input.tags),
|
|
1722
2395
|
protectedTagNumbers: new Set(input.protectedTagNumbers),
|
|
1723
2396
|
pendingDropTagNumbers: new Set(pendingDropTagNumbers),
|
|
1724
2397
|
measured: rawMeasured,
|
|
1725
|
-
size: 2 * structuralSize(input.messages) + 512 * input.tags.length
|
|
2398
|
+
size: 2 * structuralSize(input.messages.map(input.opencode2 ? providerVisibleMessageForOpenCode2 : providerVisibleMessageForTailHygiene)) + 512 * input.tags.length
|
|
1726
2399
|
};
|
|
1727
2400
|
if (!hit) {
|
|
1728
2401
|
const owners = new Map;
|
|
@@ -1739,8 +2412,9 @@ function refreshTailHygieneBaseline(input) {
|
|
|
1739
2412
|
const refrozen = (mismatch) => {
|
|
1740
2413
|
const frozen = freezeTailHygieneMeasurement(measured);
|
|
1741
2414
|
retainBaselineMeasurement(frozen.baselineParts, memo);
|
|
1742
|
-
return {
|
|
2415
|
+
return rememberCurrentToolOutputCount({
|
|
1743
2416
|
...frozen,
|
|
2417
|
+
protectedToolsPolicy,
|
|
1744
2418
|
hygieneUnitsVersion: frozenCalibration.hygieneUnitsVersion,
|
|
1745
2419
|
toolsRatio: frozenCalibration.toolsRatio,
|
|
1746
2420
|
proseRatio: frozenCalibration.proseRatio,
|
|
@@ -1750,9 +2424,8 @@ function refreshTailHygieneBaseline(input) {
|
|
|
1750
2424
|
generationInvalidated: false,
|
|
1751
2425
|
contentSignature: measured.contentSignature,
|
|
1752
2426
|
channel1PostReduceGrace: input.previous?.channel1PostReduceGrace,
|
|
1753
|
-
lastPrefixMismatch: mismatch
|
|
1754
|
-
|
|
1755
|
-
};
|
|
2427
|
+
lastPrefixMismatch: mismatch
|
|
2428
|
+
}, measured);
|
|
1756
2429
|
};
|
|
1757
2430
|
if (input.cacheBusting || !input.previous)
|
|
1758
2431
|
return refrozen();
|
|
@@ -1768,7 +2441,7 @@ function refreshTailHygieneBaseline(input) {
|
|
|
1768
2441
|
if (part.kind !== "toolOutput" || !part.protected)
|
|
1769
2442
|
turnDeltaU += part.uTokens;
|
|
1770
2443
|
}
|
|
1771
|
-
return {
|
|
2444
|
+
return rememberCurrentToolOutputCount({
|
|
1772
2445
|
...input.previous,
|
|
1773
2446
|
protectedToolsPolicy,
|
|
1774
2447
|
turnDeltaU,
|
|
@@ -1777,7 +2450,7 @@ function refreshTailHygieneBaseline(input) {
|
|
|
1777
2450
|
generationInvalidated: false,
|
|
1778
2451
|
contentSignature: measured.contentSignature,
|
|
1779
2452
|
lastPrefixMismatch: undefined
|
|
1780
|
-
};
|
|
2453
|
+
}, measured);
|
|
1781
2454
|
}
|
|
1782
2455
|
function effectiveTailHygiene(baseline) {
|
|
1783
2456
|
const t = Math.ceil(Math.max(0, baseline.baselineT + baseline.turnDeltaT));
|
|
@@ -2049,7 +2722,7 @@ function formatOldestReclaimableHint(hint) {
|
|
|
2049
2722
|
oldest reclaimable: ${rendered}.` : "";
|
|
2050
2723
|
}
|
|
2051
2724
|
function reclaimableToolOutputCount(parts) {
|
|
2052
|
-
return parts
|
|
2725
|
+
return countReclaimableToolOutputs(parts);
|
|
2053
2726
|
}
|
|
2054
2727
|
function formatReclaimableOutputSummary(count, tokens) {
|
|
2055
2728
|
const outputCount = Math.max(0, Math.floor(count));
|
|
@@ -2392,6 +3065,117 @@ function removePendingOp(db, sessionId, tagId) {
|
|
|
2392
3065
|
getRemovePendingOpStatement(db).run(sessionId, tagId);
|
|
2393
3066
|
}
|
|
2394
3067
|
|
|
3068
|
+
// src/features/magic-context/storage-tag-identity-revision.ts
|
|
3069
|
+
var TAG_IDENTITY_REVISION_PREFIX = "tag_identity_revision:";
|
|
3070
|
+
var TAG_REVISION_PREFIX = "tag_revision:";
|
|
3071
|
+
var TAG_TOMBSTONE_OWNER_PREFIX = "tag_revision_owner:";
|
|
3072
|
+
var TAG_REVISION_INCARNATION_KEY = "tag_revision_incarnation";
|
|
3073
|
+
var tagRevisionIncarnationSql = (value) => `CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, 1, INSTR(${value}, ':') - 1) ELSE '0' END`;
|
|
3074
|
+
var tagRevisionCountSql = (value) => `CAST(CASE WHEN INSTR(${value}, ':') > 0 THEN SUBSTR(${value}, INSTR(${value}, ':') + 1) ELSE ${value} END AS INTEGER)`;
|
|
3075
|
+
var ADVANCE = (delta = "1") => `CASE
|
|
3076
|
+
WHEN ${tagRevisionCountSql("value")} <= 9223372036854775807 - ${delta}
|
|
3077
|
+
THEN (${tagRevisionIncarnationSql("value")}) || ':' || CAST(${tagRevisionCountSql("value")} + ${delta} AS TEXT)
|
|
3078
|
+
ELSE NULL END`;
|
|
3079
|
+
function tagTombstoneOwnerRange(sessionId) {
|
|
3080
|
+
const stem = `${TAG_TOMBSTONE_OWNER_PREFIX}${JSON.stringify(sessionId)}`;
|
|
3081
|
+
return [`${stem}:`, `${stem};`];
|
|
3082
|
+
}
|
|
3083
|
+
function tagTombstoneOwnerKey(sessionId, harness) {
|
|
3084
|
+
return `${tagTombstoneOwnerRange(sessionId)[0]}${harness}`;
|
|
3085
|
+
}
|
|
3086
|
+
function tagRevisionKey(sessionId) {
|
|
3087
|
+
return `${TAG_REVISION_PREFIX}${sessionId}`;
|
|
3088
|
+
}
|
|
3089
|
+
function tagIdentityRevisionKey(sessionId) {
|
|
3090
|
+
return `${TAG_IDENTITY_REVISION_PREFIX}${sessionId}`;
|
|
3091
|
+
}
|
|
3092
|
+
var BUMP = (session, prefix = TAG_IDENTITY_REVISION_PREFIX) => `INSERT INTO schema_migrations_meta (key, value)
|
|
3093
|
+
VALUES ('${prefix}' || ${session}, '1')
|
|
3094
|
+
ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()}`;
|
|
3095
|
+
var TAG_INSERT_CONFLICT_ROWS = `SELECT id, session_id, tag_number FROM tags WHERE id = NEW.id
|
|
3096
|
+
UNION SELECT id, session_id, tag_number FROM tags WHERE session_id = NEW.session_id AND tag_number = NEW.tag_number
|
|
3097
|
+
UNION SELECT id, session_id, tag_number FROM tags
|
|
3098
|
+
WHERE NEW.type = 'tool' AND NEW.tool_owner_message_id IS NOT NULL
|
|
3099
|
+
AND type = 'tool' AND tool_owner_message_id IS NOT NULL
|
|
3100
|
+
AND session_id = NEW.session_id AND message_id = NEW.message_id
|
|
3101
|
+
AND tool_owner_message_id = NEW.tool_owner_message_id`;
|
|
3102
|
+
var BUMP_INSERT_CONFLICTS = (prefix) => `INSERT INTO schema_migrations_meta (key, value)
|
|
3103
|
+
SELECT '${prefix}' || session_id, CAST(COUNT(*) AS TEXT)
|
|
3104
|
+
FROM (${TAG_INSERT_CONFLICT_ROWS}) GROUP BY session_id
|
|
3105
|
+
ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE("CAST(excluded.value AS INTEGER)")}`;
|
|
3106
|
+
var TRIGGER_SQL = `CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_identity_revision_au
|
|
3107
|
+
AFTER UPDATE OF id, session_id, message_id, tag_number, type, tool_owner_message_id, reasoning_token_count
|
|
3108
|
+
ON main.tags
|
|
3109
|
+
BEGIN
|
|
3110
|
+
${BUMP("OLD.session_id")};
|
|
3111
|
+
INSERT INTO schema_migrations_meta (key, value)
|
|
3112
|
+
SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || NEW.session_id, '1'
|
|
3113
|
+
WHERE NEW.session_id IS NOT OLD.session_id
|
|
3114
|
+
ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
|
|
3115
|
+
END`;
|
|
3116
|
+
function installTagIdentityRevisionTrigger(db) {
|
|
3117
|
+
db.exec(`DROP TRIGGER IF EXISTS temp.mc_tag_identity_revision_au;
|
|
3118
|
+
DROP TRIGGER IF EXISTS temp.mc_tag_revision_bi;
|
|
3119
|
+
DROP TRIGGER IF EXISTS temp.mc_tag_revision_ai;
|
|
3120
|
+
DROP TRIGGER IF EXISTS temp.mc_tag_revision_au;
|
|
3121
|
+
DROP TRIGGER IF EXISTS temp.mc_tag_revision_ad;
|
|
3122
|
+
DROP TRIGGER IF EXISTS temp.mc_tag_revision_seed_ai;`);
|
|
3123
|
+
db.exec(`CREATE TEMP TRIGGER mc_tag_revision_seed_ai AFTER INSERT ON main.schema_migrations_meta
|
|
3124
|
+
WHEN INSTR(NEW.value, ':') = 0 AND (
|
|
3125
|
+
SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
|
|
3126
|
+
OR SUBSTR(NEW.key, 1, ${TAG_IDENTITY_REVISION_PREFIX.length}) = '${TAG_IDENTITY_REVISION_PREFIX}')
|
|
3127
|
+
BEGIN
|
|
3128
|
+
INSERT INTO schema_migrations_meta (key, value) VALUES ('${TAG_REVISION_INCARNATION_KEY}', '1')
|
|
3129
|
+
ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
|
|
3130
|
+
WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
|
|
3131
|
+
ELSE NULL END AS TEXT);
|
|
3132
|
+
UPDATE schema_migrations_meta SET value =
|
|
3133
|
+
(SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}')
|
|
3134
|
+
|| ':' || CAST(NEW.value AS TEXT) WHERE key = NEW.key;
|
|
3135
|
+
INSERT INTO schema_migrations_meta (key, value)
|
|
3136
|
+
SELECT '${TAG_REVISION_INCARNATION_KEY}', '1'
|
|
3137
|
+
WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
|
|
3138
|
+
AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
|
|
3139
|
+
WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}))
|
|
3140
|
+
ON CONFLICT(key) DO UPDATE SET value = CAST(CASE
|
|
3141
|
+
WHEN CAST(value AS INTEGER) < 9223372036854775807 THEN CAST(value AS INTEGER) + 1
|
|
3142
|
+
ELSE NULL END AS TEXT);
|
|
3143
|
+
INSERT INTO schema_migrations_meta (key, value)
|
|
3144
|
+
SELECT '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}),
|
|
3145
|
+
(SELECT value FROM schema_migrations_meta WHERE key = '${TAG_REVISION_INCARNATION_KEY}') || ':0'
|
|
3146
|
+
WHERE SUBSTR(NEW.key, 1, ${TAG_REVISION_PREFIX.length}) = '${TAG_REVISION_PREFIX}'
|
|
3147
|
+
AND NOT EXISTS (SELECT 1 FROM schema_migrations_meta
|
|
3148
|
+
WHERE key = '${TAG_IDENTITY_REVISION_PREFIX}' || SUBSTR(NEW.key, ${TAG_REVISION_PREFIX.length + 1}));
|
|
3149
|
+
END;`);
|
|
3150
|
+
db.exec(TRIGGER_SQL);
|
|
3151
|
+
db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_bi BEFORE INSERT ON main.tags BEGIN
|
|
3152
|
+
${BUMP_INSERT_CONFLICTS(TAG_REVISION_PREFIX)};
|
|
3153
|
+
${BUMP_INSERT_CONFLICTS(TAG_IDENTITY_REVISION_PREFIX)};
|
|
3154
|
+
UPDATE session_meta SET tags_version = tags_version + 1
|
|
3155
|
+
WHERE session_id IN (SELECT session_id FROM (${TAG_INSERT_CONFLICT_ROWS}));
|
|
3156
|
+
END;`);
|
|
3157
|
+
db.exec(`CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ai AFTER INSERT ON main.tags BEGIN
|
|
3158
|
+
${BUMP("NEW.session_id", TAG_REVISION_PREFIX)};
|
|
3159
|
+
END;
|
|
3160
|
+
CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_au AFTER UPDATE ON main.tags BEGIN
|
|
3161
|
+
${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
|
|
3162
|
+
INSERT INTO schema_migrations_meta (key, value)
|
|
3163
|
+
SELECT '${TAG_REVISION_PREFIX}' || NEW.session_id, '1'
|
|
3164
|
+
WHERE NEW.session_id IS NOT OLD.session_id
|
|
3165
|
+
ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()};
|
|
3166
|
+
END;
|
|
3167
|
+
CREATE TEMP TRIGGER IF NOT EXISTS mc_tag_revision_ad AFTER DELETE ON main.tags BEGIN
|
|
3168
|
+
${BUMP("OLD.session_id", TAG_REVISION_PREFIX)};
|
|
3169
|
+
END;`);
|
|
3170
|
+
}
|
|
3171
|
+
function deleteTagIdentityRevisions(db, sessionIds) {
|
|
3172
|
+
const statement = db.prepare(`INSERT INTO schema_migrations_meta (key, value) VALUES (?, '1')
|
|
3173
|
+
ON CONFLICT(key) DO UPDATE SET value = ${ADVANCE()}`);
|
|
3174
|
+
for (const sessionId of sessionIds) {
|
|
3175
|
+
statement.run(tagIdentityRevisionKey(sessionId));
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
|
|
2395
3179
|
// src/features/magic-context/storage-tags.ts
|
|
2396
3180
|
var insertTagStatements = new WeakMap;
|
|
2397
3181
|
var updateTagStatusStatements = new WeakMap;
|
|
@@ -2610,8 +3394,41 @@ function getActiveTagTokenTotalsByMessage(db, sessionId, messageIds) {
|
|
|
2610
3394
|
}
|
|
2611
3395
|
var updateTagTokenCountStatements = new WeakMap;
|
|
2612
3396
|
var updateTagInputTokenCountStatements = new WeakMap;
|
|
2613
|
-
function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration = { proseRatio: 1, toolsRatio: 1 }, options) {
|
|
2614
|
-
const
|
|
3397
|
+
function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration = { proseRatio: 1, toolsRatio: 1 }, options, ownerMessageIds) {
|
|
3398
|
+
const columns = "type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count";
|
|
3399
|
+
const owners = ownerMessageIds ? new Set(ownerMessageIds) : undefined;
|
|
3400
|
+
let scanOrder = "id";
|
|
3401
|
+
if (owners) {
|
|
3402
|
+
const planStatement = db.prepare(`EXPLAIN QUERY PLAN SELECT ${columns} FROM tags WHERE session_id = ?${floor > 0 ? " AND tag_number >= ?" : ""}`);
|
|
3403
|
+
let plan;
|
|
3404
|
+
try {
|
|
3405
|
+
plan = planStatement.all(sessionId, ...floor > 0 ? [floor] : []);
|
|
3406
|
+
} finally {
|
|
3407
|
+
planStatement.finalize?.();
|
|
3408
|
+
}
|
|
3409
|
+
const index = plan.map((row) => /USING (?:COVERING )?INDEX (\S+)/.exec(row.detail)?.[1]).find(Boolean);
|
|
3410
|
+
if (index) {
|
|
3411
|
+
const keyStatement = db.prepare("SELECT name, coll, desc FROM pragma_index_xinfo(?) WHERE key = 1 ORDER BY seqno");
|
|
3412
|
+
let keys;
|
|
3413
|
+
try {
|
|
3414
|
+
keys = keyStatement.all(index);
|
|
3415
|
+
} finally {
|
|
3416
|
+
keyStatement.finalize?.();
|
|
3417
|
+
}
|
|
3418
|
+
scanOrder = [
|
|
3419
|
+
...keys.map((key) => `"${(key.name ?? "id").replaceAll('"', '""')}" COLLATE "${key.coll.replaceAll('"', '""')}"${key.desc ? " DESC" : ""}`),
|
|
3420
|
+
"id"
|
|
3421
|
+
].join(", ");
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
const rows = owners ? db.prepare(`SELECT ${columns} FROM tags WHERE id IN (
|
|
3425
|
+
SELECT t.id FROM json_each(?) o CROSS JOIN tags t INDEXED BY idx_tags_session_message_id
|
|
3426
|
+
ON t.session_id = ? AND t.message_id >= o.value AND t.message_id < o.value || ';'
|
|
3427
|
+
UNION
|
|
3428
|
+
SELECT t.id FROM json_each(?) o CROSS JOIN tags t INDEXED BY idx_tags_pi_fallback_tool_owner
|
|
3429
|
+
ON t.session_id = ? AND t.tool_owner_message_id = o.value
|
|
3430
|
+
WHERE t.type = 'tool'
|
|
3431
|
+
) AND tag_number >= ? ORDER BY ${scanOrder}`).all(JSON.stringify([...owners]), sessionId, JSON.stringify([...owners]), sessionId, floor) : floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
2615
3432
|
FROM tags
|
|
2616
3433
|
WHERE session_id = ? AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
2617
3434
|
FROM tags
|
|
@@ -2624,6 +3441,8 @@ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration =
|
|
|
2624
3441
|
if (options?.excludeToolTags === true && row.type === "tool")
|
|
2625
3442
|
continue;
|
|
2626
3443
|
const owner = ownerMessageIdForTagRow(row);
|
|
3444
|
+
if (owners && !owners.has(owner))
|
|
3445
|
+
continue;
|
|
2627
3446
|
if (row.token_count === null) {
|
|
2628
3447
|
nullMessageIds.add(owner);
|
|
2629
3448
|
totals.delete(owner);
|
|
@@ -2638,15 +3457,199 @@ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0, calibration =
|
|
|
2638
3457
|
return { totals, nullMessageIds };
|
|
2639
3458
|
}
|
|
2640
3459
|
function getReasoningTokenEstimatesByMessage(db, sessionId, proseRatio) {
|
|
2641
|
-
const
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
3460
|
+
const summary = readTagOwnerSummary(db, sessionId, proseRatio);
|
|
3461
|
+
return summary.reasoningEstimatesByRatio.get(proseRatio) ?? new Map;
|
|
3462
|
+
}
|
|
3463
|
+
function tryGetReasoningTokenEstimatesByMessage(db, sessionId, ratio) {
|
|
3464
|
+
try {
|
|
3465
|
+
return getReasoningTokenEstimatesByMessage(db, sessionId, ratio);
|
|
3466
|
+
} catch (error) {
|
|
3467
|
+
if (error instanceof TagOwnerSummaryNotReady)
|
|
3468
|
+
return;
|
|
3469
|
+
throw error;
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
function getMaxTagNumberByOwnerMessage(db, sessionId) {
|
|
3473
|
+
return readTagOwnerSummary(db, sessionId).maxTagByOwner;
|
|
3474
|
+
}
|
|
3475
|
+
var tagOwnerSummaries = new WeakMap;
|
|
3476
|
+
var MAX_CACHED_PROSE_RATIOS = 4;
|
|
3477
|
+
var TAG_OWNER_PAGE_LIMIT = 512;
|
|
3478
|
+
|
|
3479
|
+
class TagOwnerSummaryNotReady extends Error {
|
|
3480
|
+
constructor() {
|
|
3481
|
+
super("tag owner summary needs off-thread preparation");
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
function scanTagOwnerSummary(db, sessionId, ratio, ratios = []) {
|
|
3485
|
+
db.exec("BEGIN");
|
|
3486
|
+
try {
|
|
3487
|
+
return readTagOwnerSummary(db, sessionId, ratio, ratios);
|
|
3488
|
+
} finally {
|
|
3489
|
+
db.exec("ROLLBACK");
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
function isTagOwnerSummaryReady(db, sessionId, ratio) {
|
|
3493
|
+
try {
|
|
3494
|
+
readTagOwnerSummary(db, sessionId, ratio);
|
|
3495
|
+
return true;
|
|
3496
|
+
} catch (error) {
|
|
3497
|
+
if (error instanceof TagOwnerSummaryNotReady)
|
|
3498
|
+
return false;
|
|
3499
|
+
throw error;
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
var tagOwnerRowsRead = 0;
|
|
3503
|
+
var tagOwnerShapeChecks = 0;
|
|
3504
|
+
function foldTagOwnerRow(summary, row, newRow = true) {
|
|
3505
|
+
summary.lastRowId = Math.max(summary.lastRowId, row.id);
|
|
3506
|
+
if (newRow)
|
|
3507
|
+
summary.rowCount += 1;
|
|
3508
|
+
if (row.type === "tool" && typeof row.tool_owner_message_id !== "string")
|
|
3509
|
+
summary.unownedToolRows.add(row.id);
|
|
3510
|
+
else
|
|
3511
|
+
summary.unownedToolRows.delete(row.id);
|
|
3512
|
+
const owner = row.type === "tool" ? typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null : typeof row.message_id === "string" ? contentTagOwnerMessageId(row.message_id) : null;
|
|
3513
|
+
if (owner) {
|
|
3514
|
+
summary.maxTagByOwner.set(owner, Math.max(summary.maxTagByOwner.get(owner) ?? 0, row.tag_number));
|
|
3515
|
+
}
|
|
3516
|
+
if (row.type !== "message" || row.reasoning_token_count === null)
|
|
3517
|
+
return;
|
|
3518
|
+
const reasoningOwner = ownerMessageIdForTagRow({
|
|
3519
|
+
type: row.type,
|
|
3520
|
+
message_id: row.message_id,
|
|
3521
|
+
tool_owner_message_id: row.tool_owner_message_id
|
|
3522
|
+
});
|
|
3523
|
+
for (const [ratio, estimates] of summary.reasoningEstimatesByRatio) {
|
|
3524
|
+
estimates.set(reasoningOwner, Math.max(estimates.get(reasoningOwner) ?? 0, row.reasoning_token_count * ratio));
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3527
|
+
var TAG_OWNER_COLUMNS = "id, type, message_id, tool_owner_message_id, tag_number, reasoning_token_count";
|
|
3528
|
+
function connectionInTransaction(db) {
|
|
3529
|
+
try {
|
|
3530
|
+
const state = db;
|
|
3531
|
+
return state.inTransaction !== false && state.isTransaction !== false;
|
|
3532
|
+
} catch {
|
|
3533
|
+
return true;
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
var TAG_OWNER_APPENDED_WITH_SHAPE_SQL = `SELECT ${TAG_OWNER_COLUMNS}, 0 AS shape, NULL AS tag_count, NULL AS max_id, NULL AS revision
|
|
3537
|
+
FROM tags WHERE id > ? AND +session_id = ?
|
|
3538
|
+
UNION ALL
|
|
3539
|
+
SELECT NULL, NULL, NULL, NULL, NULL, NULL, 1, COUNT(*), MAX(id), (SELECT value FROM schema_migrations_meta WHERE key = ?)
|
|
3540
|
+
FROM tags WHERE session_id = ?`;
|
|
3541
|
+
function readTagIdentityRevision(db, sessionId) {
|
|
3542
|
+
const row = db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(tagIdentityRevisionKey(sessionId));
|
|
3543
|
+
return typeof row?.value === "string" ? row.value : null;
|
|
3544
|
+
}
|
|
3545
|
+
function captureInitialTagOwnerRevision(db, sessionId, cached, appendedRows) {
|
|
3546
|
+
if (cached.identityRevision !== null || appendedRows === 0)
|
|
3547
|
+
return true;
|
|
3548
|
+
const revision = readTagIdentityRevision(db, sessionId);
|
|
3549
|
+
if (revision !== null && !/^[1-9]\d*:0$/.test(revision))
|
|
3550
|
+
return false;
|
|
3551
|
+
cached.identityRevision = revision;
|
|
3552
|
+
return true;
|
|
3553
|
+
}
|
|
3554
|
+
function appendedSinceForeignCommit(db, sessionId, cached) {
|
|
3555
|
+
tagOwnerShapeChecks += 1;
|
|
3556
|
+
const rows = db.prepare(TAG_OWNER_APPENDED_WITH_SHAPE_SQL).all(cached.globalLastRowId, sessionId, tagIdentityRevisionKey(sessionId), sessionId);
|
|
3557
|
+
const shape = rows.find((row) => row.shape === 1);
|
|
3558
|
+
const appended = rows.filter((row) => row.shape === 0);
|
|
3559
|
+
const highest = appended.reduce((max, row) => Math.max(max, row.id), cached.lastRowId);
|
|
3560
|
+
if (!shape || (shape.revision ?? null) !== cached.identityRevision || shape.tag_count !== cached.rowCount + appended.length || (shape.max_id ?? 0) !== highest)
|
|
3561
|
+
return null;
|
|
3562
|
+
return appended;
|
|
3563
|
+
}
|
|
3564
|
+
function adoptedSinceForeignCommit(db, cached) {
|
|
3565
|
+
if (cached.unownedToolRows.size === 0)
|
|
3566
|
+
return [];
|
|
3567
|
+
return db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags
|
|
3568
|
+
WHERE id IN (SELECT value FROM json_each(?)) AND tool_owner_message_id IS NOT NULL LIMIT ${TAG_OWNER_PAGE_LIMIT + 1}`).all(JSON.stringify([...cached.unownedToolRows]));
|
|
3569
|
+
}
|
|
3570
|
+
function readTagOwnerSummary(db, sessionId, proseRatio, extraRatios = []) {
|
|
3571
|
+
const inTransaction = connectionInTransaction(db);
|
|
3572
|
+
const versions = inTransaction ? null : db.prepare("SELECT data_version AS dataVersion, (SELECT schema_version FROM pragma_schema_version) AS schemaVersion FROM pragma_data_version").get();
|
|
3573
|
+
const dataVersion = versions?.dataVersion ?? -1;
|
|
3574
|
+
const schemaVersion = versions?.schemaVersion ?? -1;
|
|
3575
|
+
const generation = getTagIdentityWriteGeneration();
|
|
3576
|
+
const sessions = tagOwnerSummaries.get(db) ?? new Map;
|
|
3577
|
+
const cached = inTransaction ? undefined : sessions.get(sessionId);
|
|
3578
|
+
if (cached && (cached.generation === generation || cached.identityRevision === readTagIdentityRevision(db, sessionId)) && cached.schemaVersion === schemaVersion && (proseRatio === undefined || cached.reasoningEstimatesByRatio.has(proseRatio))) {
|
|
3579
|
+
let rows;
|
|
3580
|
+
let globalLastRowId = db.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM tags").get().id;
|
|
3581
|
+
if (cached.dataVersion === dataVersion && cached.generation === generation) {
|
|
3582
|
+
const statement = db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags WHERE id > ? AND +session_id = ? ORDER BY id LIMIT ${TAG_OWNER_PAGE_LIMIT + 1}`);
|
|
3583
|
+
rows = statement.all(cached.globalLastRowId, sessionId);
|
|
3584
|
+
let page = rows;
|
|
3585
|
+
while (page.length === TAG_OWNER_PAGE_LIMIT + 1) {
|
|
3586
|
+
page = statement.all(page[page.length - 1].id, sessionId);
|
|
3587
|
+
rows.push(...page);
|
|
3588
|
+
}
|
|
3589
|
+
if (!captureInitialTagOwnerRevision(db, sessionId, cached, rows.length)) {
|
|
3590
|
+
rows = null;
|
|
3591
|
+
}
|
|
3592
|
+
} else {
|
|
3593
|
+
try {
|
|
3594
|
+
globalLastRowId = db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM tags").get().id;
|
|
3595
|
+
rows = appendedSinceForeignCommit(db, sessionId, cached);
|
|
3596
|
+
const adopted = rows ? adoptedSinceForeignCommit(db, cached) : [];
|
|
3597
|
+
if (!rows || rows.length > TAG_OWNER_PAGE_LIMIT || adopted.length > TAG_OWNER_PAGE_LIMIT) {
|
|
3598
|
+
rows = null;
|
|
3599
|
+
} else {
|
|
3600
|
+
tagOwnerRowsRead += rows.length + adopted.length;
|
|
3601
|
+
for (const row of rows)
|
|
3602
|
+
foldTagOwnerRow(cached, row);
|
|
3603
|
+
for (const row of adopted)
|
|
3604
|
+
foldTagOwnerRow(cached, row, false);
|
|
3605
|
+
cached.dataVersion = dataVersion;
|
|
3606
|
+
cached.generation = generation;
|
|
3607
|
+
cached.globalLastRowId = globalLastRowId;
|
|
3608
|
+
return cached;
|
|
3609
|
+
}
|
|
3610
|
+
} catch {
|
|
3611
|
+
rows = null;
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
if (rows) {
|
|
3615
|
+
const adopted = cached.dataVersion === dataVersion ? [] : adoptedSinceForeignCommit(db, cached);
|
|
3616
|
+
tagOwnerRowsRead += rows.length + adopted.length;
|
|
3617
|
+
for (const row of rows)
|
|
3618
|
+
foldTagOwnerRow(cached, row);
|
|
3619
|
+
for (const row of adopted)
|
|
3620
|
+
foldTagOwnerRow(cached, row, false);
|
|
3621
|
+
cached.dataVersion = dataVersion;
|
|
3622
|
+
cached.generation = generation;
|
|
3623
|
+
cached.globalLastRowId = globalLastRowId;
|
|
3624
|
+
return cached;
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
const ratios = [
|
|
3628
|
+
...new Set([...cached?.reasoningEstimatesByRatio.keys() ?? [], ...extraRatios])
|
|
3629
|
+
];
|
|
3630
|
+
if (proseRatio !== undefined && !ratios.includes(proseRatio))
|
|
3631
|
+
ratios.push(proseRatio);
|
|
3632
|
+
const summary = {
|
|
3633
|
+
dataVersion,
|
|
3634
|
+
schemaVersion,
|
|
3635
|
+
generation,
|
|
3636
|
+
lastRowId: 0,
|
|
3637
|
+
globalLastRowId: db.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM tags").get().id,
|
|
3638
|
+
rowCount: 0,
|
|
3639
|
+
unownedToolRows: new Set,
|
|
3640
|
+
identityRevision: readTagIdentityRevision(db, sessionId),
|
|
3641
|
+
maxTagByOwner: new Map,
|
|
3642
|
+
reasoningEstimatesByRatio: new Map(ratios.slice(-MAX_CACHED_PROSE_RATIOS).map((ratio) => [ratio, new Map]))
|
|
3643
|
+
};
|
|
3644
|
+
const rows = db.prepare(`SELECT ${TAG_OWNER_COLUMNS} FROM tags WHERE session_id = ? ORDER BY id`).all(sessionId);
|
|
3645
|
+
tagOwnerRowsRead += rows.length;
|
|
3646
|
+
for (const row of rows)
|
|
3647
|
+
foldTagOwnerRow(summary, row);
|
|
3648
|
+
if (!inTransaction) {
|
|
3649
|
+
sessions.set(sessionId, summary);
|
|
3650
|
+
tagOwnerSummaries.set(db, sessions);
|
|
2648
3651
|
}
|
|
2649
|
-
return
|
|
3652
|
+
return summary;
|
|
2650
3653
|
}
|
|
2651
3654
|
function tagTokenCountIsNull(db, sessionId, tagNumber) {
|
|
2652
3655
|
const row = db.prepare("SELECT token_count FROM tags WHERE session_id = ? AND tag_number = ?").get(sessionId, tagNumber);
|
|
@@ -2689,7 +3692,7 @@ function getTagNumberByMessageIdStatement(db) {
|
|
|
2689
3692
|
function getAssignableTagNumberByMessageIdStatement(db) {
|
|
2690
3693
|
let stmt = getAssignableTagNumberByMessageIdStatements.get(db);
|
|
2691
3694
|
if (!stmt) {
|
|
2692
|
-
stmt = db.prepare(`SELECT tag_number FROM tags
|
|
3695
|
+
stmt = db.prepare(`SELECT tag_number FROM tags INDEXED BY idx_tags_session_message_id
|
|
2693
3696
|
WHERE session_id = ?
|
|
2694
3697
|
AND message_id = ?
|
|
2695
3698
|
AND NOT (
|
|
@@ -2750,6 +3753,19 @@ function insertTag(db, sessionId, messageId, type, byteSize, tagNumber, reasonin
|
|
|
2750
3753
|
function updateTagStatus(db, sessionId, tagId, status) {
|
|
2751
3754
|
getUpdateTagStatusStatement(db).run(status, sessionId, tagId);
|
|
2752
3755
|
}
|
|
3756
|
+
var droppedTagStatements = new WeakMap;
|
|
3757
|
+
function markTagDropped(db, sessionId, tagId, mode) {
|
|
3758
|
+
if (!mode) {
|
|
3759
|
+
updateTagStatus(db, sessionId, tagId, "dropped");
|
|
3760
|
+
return;
|
|
3761
|
+
}
|
|
3762
|
+
let statement = droppedTagStatements.get(db);
|
|
3763
|
+
if (!statement) {
|
|
3764
|
+
statement = db.prepare("UPDATE tags SET status = ?, drop_mode = ? WHERE session_id = ? AND tag_number = ?");
|
|
3765
|
+
droppedTagStatements.set(db, statement);
|
|
3766
|
+
}
|
|
3767
|
+
statement.run("dropped", mode, sessionId, tagId);
|
|
3768
|
+
}
|
|
2753
3769
|
var inertWhitespaceStatements = new WeakMap;
|
|
2754
3770
|
function markWhitespaceAssistantTagInert(db, sessionId, tagNumber, contentId) {
|
|
2755
3771
|
db.prepare(`UPDATE tags
|
|
@@ -2787,6 +3803,28 @@ function getInertWhitespaceAssistantTags(db, sessionId, messageIds) {
|
|
|
2787
3803
|
return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
|
|
2788
3804
|
});
|
|
2789
3805
|
}
|
|
3806
|
+
var inertWhitespaceByNumberStatements = new WeakMap;
|
|
3807
|
+
function getInertWhitespaceAssistantTagsByNumbers(db, sessionId, tagNumbers) {
|
|
3808
|
+
if (tagNumbers.length === 0)
|
|
3809
|
+
return [];
|
|
3810
|
+
let statement = inertWhitespaceByNumberStatements.get(db);
|
|
3811
|
+
if (!statement) {
|
|
3812
|
+
statement = db.prepare(`SELECT tags.tag_number AS tagNumber, tags.entry_fingerprint AS entryFingerprint
|
|
3813
|
+
FROM json_each(?) AS wanted CROSS JOIN tags
|
|
3814
|
+
WHERE tags.session_id = ?
|
|
3815
|
+
AND tags.tag_number = wanted.value
|
|
3816
|
+
AND tags.type = 'message'
|
|
3817
|
+
AND tags.status = 'compacted'
|
|
3818
|
+
AND tags.entry_fingerprint LIKE ?
|
|
3819
|
+
ORDER BY tags.tag_number, tags.id`);
|
|
3820
|
+
inertWhitespaceByNumberStatements.set(db, statement);
|
|
3821
|
+
}
|
|
3822
|
+
const rows = statement.all(JSON.stringify([...new Set(tagNumbers)]), sessionId, `${WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX}%`);
|
|
3823
|
+
return rows.flatMap((row) => {
|
|
3824
|
+
const contentId = row.entryFingerprint.slice(WHITESPACE_ASSISTANT_INERT_FINGERPRINT_PREFIX.length);
|
|
3825
|
+
return contentId.length > 0 ? [{ tagNumber: row.tagNumber, contentId }] : [];
|
|
3826
|
+
});
|
|
3827
|
+
}
|
|
2790
3828
|
function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
|
|
2791
3829
|
getUpdateTagDropModeStatement(db).run(dropMode, sessionId, tagNumber);
|
|
2792
3830
|
}
|
|
@@ -3013,7 +4051,8 @@ function markTagsCompactedByMessageIds(db, sessionId, messageIds, eligibleTagNum
|
|
|
3013
4051
|
SELECT value AS source_id, lower(value) AS folded_id FROM json_each(?)
|
|
3014
4052
|
)
|
|
3015
4053
|
SELECT id, tag_number, message_id, tool_owner_message_id FROM tags INDEXED BY ${tagOrderConstraintIndex(db)}
|
|
3016
|
-
WHERE session_id = ? AND
|
|
4054
|
+
WHERE session_id = ? ${eligibleTagNumbers ? "AND tag_number IN (SELECT value FROM json_each(?))" : ""}
|
|
4055
|
+
AND status IN ('active', 'dropped') AND (
|
|
3017
4056
|
message_id IN (SELECT source_id FROM ids)
|
|
3018
4057
|
OR tool_owner_message_id IN (SELECT source_id FROM ids)
|
|
3019
4058
|
OR (instr(lower(message_id), ':p') > 0 AND
|
|
@@ -3022,8 +4061,8 @@ function markTagsCompactedByMessageIds(db, sessionId, messageIds, eligibleTagNum
|
|
|
3022
4061
|
lower(substr(message_id, 1, instr(lower(message_id), ':file') - 1)) IN (SELECT folded_id FROM ids))
|
|
3023
4062
|
OR (? AND instr(message_id, ':') > 0)
|
|
3024
4063
|
OR ?
|
|
3025
|
-
)`).all(JSON.stringify(Array.from(ids)), sessionId, Array.from(ids).some((id) => id.includes(":")) ? 1 : 0, nulPrefixes.size > 0 ? 1 : 0);
|
|
3026
|
-
const candidates = rows.filter((row) =>
|
|
4064
|
+
)`).all(JSON.stringify(Array.from(ids)), sessionId, ...eligibleTagNumbers ? [JSON.stringify([...eligibleTagNumbers])] : [], Array.from(ids).some((id) => id.includes(":")) ? 1 : 0, nulPrefixes.size > 0 ? 1 : 0);
|
|
4065
|
+
const candidates = rows.filter((row) => matches(row.message_id, row.tool_owner_message_id));
|
|
3027
4066
|
if (candidates.length === 0)
|
|
3028
4067
|
return 0;
|
|
3029
4068
|
const update = db.prepare(`UPDATE tags SET status = 'compacted'
|
|
@@ -3177,7 +4216,7 @@ function getNewestToolTagNumbers(db, sessionId, limit) {
|
|
|
3177
4216
|
let statement = newestToolTagNumberStatements.get(db);
|
|
3178
4217
|
if (!statement) {
|
|
3179
4218
|
statement = db.prepare(`SELECT tag_number FROM tags
|
|
3180
|
-
WHERE session_id = ? AND type = 'tool'
|
|
4219
|
+
WHERE session_id = ? AND +type = 'tool'
|
|
3181
4220
|
AND typeof(message_id) = 'text'
|
|
3182
4221
|
AND typeof(status) = 'text'
|
|
3183
4222
|
AND typeof(byte_size) IN ('integer', 'real')
|
|
@@ -3685,423 +4724,6 @@ function isHostRenderedSystemMessage(message) {
|
|
|
3685
4724
|
return (typeof id !== "string" || id.length === 0) && message.info.role === "system";
|
|
3686
4725
|
}
|
|
3687
4726
|
|
|
3688
|
-
// src/hooks/magic-context/read-session-raw.ts
|
|
3689
|
-
function isStrictGapHealingMessage(message) {
|
|
3690
|
-
if (message.storeType === "synthetic")
|
|
3691
|
-
return true;
|
|
3692
|
-
let sawTool = false;
|
|
3693
|
-
for (const part of message.parts) {
|
|
3694
|
-
if (!part || typeof part !== "object" || Array.isArray(part))
|
|
3695
|
-
return false;
|
|
3696
|
-
const record = part;
|
|
3697
|
-
const type = typeof record.type === "string" ? record.type : "";
|
|
3698
|
-
if (type === "tool" || type === "tool_use" || type === "tool_result") {
|
|
3699
|
-
sawTool = true;
|
|
3700
|
-
continue;
|
|
3701
|
-
}
|
|
3702
|
-
const text = typeof record.text === "string" ? record.text : typeof record.content === "string" ? record.content : "";
|
|
3703
|
-
if (text.trim().length > 0 || type.length > 0)
|
|
3704
|
-
return false;
|
|
3705
|
-
}
|
|
3706
|
-
return sawTool;
|
|
3707
|
-
}
|
|
3708
|
-
var RAW_MESSAGE_PARTS_BY_ID_SQL = "SELECT message_id, data, time_updated FROM part WHERE +session_id = ? AND likelihood(message_id = ?, 0.000001) ORDER BY time_created ASC, id ASC";
|
|
3709
|
-
function isRawMessageRow(row) {
|
|
3710
|
-
if (row === null || typeof row !== "object")
|
|
3711
|
-
return false;
|
|
3712
|
-
const candidate = row;
|
|
3713
|
-
return typeof candidate.id === "string" && typeof candidate.data === "string";
|
|
3714
|
-
}
|
|
3715
|
-
function isRawPartRow(row) {
|
|
3716
|
-
if (row === null || typeof row !== "object")
|
|
3717
|
-
return false;
|
|
3718
|
-
const candidate = row;
|
|
3719
|
-
return typeof candidate.message_id === "string" && typeof candidate.data === "string";
|
|
3720
|
-
}
|
|
3721
|
-
function parseJsonRecord(value) {
|
|
3722
|
-
try {
|
|
3723
|
-
const parsed = JSON.parse(value);
|
|
3724
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3725
|
-
return null;
|
|
3726
|
-
}
|
|
3727
|
-
return parsed;
|
|
3728
|
-
} catch {
|
|
3729
|
-
return null;
|
|
3730
|
-
}
|
|
3731
|
-
}
|
|
3732
|
-
function isRawCompactionSummaryInfo(info) {
|
|
3733
|
-
if (info === null || typeof info !== "object" || Array.isArray(info))
|
|
3734
|
-
return false;
|
|
3735
|
-
const candidate = info;
|
|
3736
|
-
return candidate.summary === true && candidate.finish === "stop";
|
|
3737
|
-
}
|
|
3738
|
-
function parseJsonUnknown(value) {
|
|
3739
|
-
try {
|
|
3740
|
-
return JSON.parse(value);
|
|
3741
|
-
} catch {
|
|
3742
|
-
return null;
|
|
3743
|
-
}
|
|
3744
|
-
}
|
|
3745
|
-
function attachRawPartVersion(value, timeUpdated) {
|
|
3746
|
-
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
3747
|
-
return value;
|
|
3748
|
-
if (typeof timeUpdated !== "number")
|
|
3749
|
-
return value;
|
|
3750
|
-
try {
|
|
3751
|
-
Object.defineProperty(value, "__magicContextPartUpdatedAt", {
|
|
3752
|
-
value: timeUpdated,
|
|
3753
|
-
enumerable: false,
|
|
3754
|
-
configurable: true
|
|
3755
|
-
});
|
|
3756
|
-
} catch {}
|
|
3757
|
-
return value;
|
|
3758
|
-
}
|
|
3759
|
-
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
3760
|
-
const messageRows = db.prepare("SELECT id, data, time_created, time_updated FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
3761
|
-
const partsByMessageId = new Map;
|
|
3762
|
-
const partMessageBatchSize = 128;
|
|
3763
|
-
for (let offset = 0;offset < messageRows.length; offset += partMessageBatchSize) {
|
|
3764
|
-
const messageIds = messageRows.slice(offset, offset + partMessageBatchSize).map((row) => row.id);
|
|
3765
|
-
if (messageIds.length === 0)
|
|
3766
|
-
continue;
|
|
3767
|
-
const placeholders = messageIds.map(() => "?").join(", ");
|
|
3768
|
-
const partRows = db.prepare(`SELECT message_id, data, time_updated
|
|
3769
|
-
FROM part
|
|
3770
|
-
WHERE +session_id = ?
|
|
3771
|
-
AND likelihood(message_id IN (${placeholders}), 0.000001)
|
|
3772
|
-
ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageIds).filter(isRawPartRow);
|
|
3773
|
-
for (const part of partRows) {
|
|
3774
|
-
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
3775
|
-
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
3776
|
-
partsByMessageId.set(part.message_id, list);
|
|
3777
|
-
}
|
|
3778
|
-
}
|
|
3779
|
-
const filtered = messageRows.filter((row) => !isRawCompactionSummaryInfo(parseJsonRecord(row.data)));
|
|
3780
|
-
return filtered.flatMap((row, index) => {
|
|
3781
|
-
const info = parseJsonRecord(row.data);
|
|
3782
|
-
if (!info)
|
|
3783
|
-
return [];
|
|
3784
|
-
const role = typeof info.role === "string" ? info.role : "unknown";
|
|
3785
|
-
return {
|
|
3786
|
-
ordinal: index + 1,
|
|
3787
|
-
id: row.id,
|
|
3788
|
-
role,
|
|
3789
|
-
parts: partsByMessageId.get(row.id) ?? [],
|
|
3790
|
-
createdAt: row.time_created ?? null,
|
|
3791
|
-
version: row.time_updated ?? null
|
|
3792
|
-
};
|
|
3793
|
-
});
|
|
3794
|
-
}
|
|
3795
|
-
function readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER, after) {
|
|
3796
|
-
const messageRows = readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark, after);
|
|
3797
|
-
if (messageRows.length === 0)
|
|
3798
|
-
return [];
|
|
3799
|
-
const placeholders = messageRows.map(() => "?").join(", ");
|
|
3800
|
-
const partRows = db.prepare(`SELECT message_id, data, time_updated
|
|
3801
|
-
FROM part
|
|
3802
|
-
WHERE +session_id = ?
|
|
3803
|
-
AND likelihood(message_id IN (${placeholders}), 0.000001)
|
|
3804
|
-
ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
|
|
3805
|
-
return assembleRawMessagePage(messageRows, partRows);
|
|
3806
|
-
}
|
|
3807
|
-
function readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark, after) {
|
|
3808
|
-
const remaining = Math.max(0, Math.floor(finalWatermark) - Math.floor(afterOrdinal));
|
|
3809
|
-
const pageSize = Math.min(Math.max(1, Math.floor(limit)), remaining);
|
|
3810
|
-
if (pageSize === 0)
|
|
3811
|
-
return [];
|
|
3812
|
-
const parameters = [sessionId];
|
|
3813
|
-
if (after)
|
|
3814
|
-
parameters.push(after.timeCreated, after.timeCreated, after.timeCreated, after.id);
|
|
3815
|
-
parameters.push(pageSize);
|
|
3816
|
-
if (!after)
|
|
3817
|
-
parameters.push(Math.max(0, Math.floor(afterOrdinal)));
|
|
3818
|
-
return db.prepare(`SELECT id, data, time_created, time_updated
|
|
3819
|
-
FROM message
|
|
3820
|
-
WHERE session_id = ?
|
|
3821
|
-
${after ? "AND time_created >= ? AND (time_created > ? OR (time_created = ? AND id > ?))" : ""}
|
|
3822
|
-
AND NOT (
|
|
3823
|
-
CASE WHEN json_valid(data) = 1
|
|
3824
|
-
THEN COALESCE(json_extract(data, '$.summary'), 0)
|
|
3825
|
-
ELSE 0 END = 1
|
|
3826
|
-
AND CASE WHEN json_valid(data) = 1
|
|
3827
|
-
THEN COALESCE(json_extract(data, '$.finish'), '')
|
|
3828
|
-
ELSE '' END = 'stop'
|
|
3829
|
-
)
|
|
3830
|
-
ORDER BY time_created ASC, id ASC
|
|
3831
|
-
LIMIT ? ${after ? "" : "OFFSET ?"}`).all(...parameters).filter(isRawMessageRow).map((row, index) => ({
|
|
3832
|
-
...row,
|
|
3833
|
-
ordinal: Math.floor(afterOrdinal) + index + 1
|
|
3834
|
-
}));
|
|
3835
|
-
}
|
|
3836
|
-
function assembleRawMessagePage(messageRows, partRows) {
|
|
3837
|
-
const partsByMessageId = new Map;
|
|
3838
|
-
for (const part of partRows) {
|
|
3839
|
-
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
3840
|
-
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
3841
|
-
partsByMessageId.set(part.message_id, list);
|
|
3842
|
-
}
|
|
3843
|
-
return messageRows.map((row) => {
|
|
3844
|
-
const info = parseJsonRecord(row.data);
|
|
3845
|
-
return {
|
|
3846
|
-
ordinal: row.ordinal,
|
|
3847
|
-
id: row.id,
|
|
3848
|
-
role: typeof info?.role === "string" ? info.role : "unknown",
|
|
3849
|
-
parts: partsByMessageId.get(row.id) ?? [],
|
|
3850
|
-
createdAt: row.time_created ?? null,
|
|
3851
|
-
version: row.time_updated ?? null
|
|
3852
|
-
};
|
|
3853
|
-
});
|
|
3854
|
-
}
|
|
3855
|
-
var RAW_SUMMARY_TEXT_MAX_CHARS = 8192;
|
|
3856
|
-
var RAW_SUMMARY_ARG_MAX_CHARS = 512;
|
|
3857
|
-
var RAW_SUMMARY_TOOL_INPUT_KEYS = [
|
|
3858
|
-
"description",
|
|
3859
|
-
"filePath",
|
|
3860
|
-
"path",
|
|
3861
|
-
"pattern",
|
|
3862
|
-
"query",
|
|
3863
|
-
"symbol",
|
|
3864
|
-
"module",
|
|
3865
|
-
"action"
|
|
3866
|
-
];
|
|
3867
|
-
function summaryStringField(jsonPath) {
|
|
3868
|
-
return `CASE WHEN json_type(data, '${jsonPath}') = 'text' THEN substr(json_extract(data, '${jsonPath}'), 1, ${RAW_SUMMARY_ARG_MAX_CHARS}) END`;
|
|
3869
|
-
}
|
|
3870
|
-
var RAW_SUMMARY_PART_DATA_SQL = `CASE
|
|
3871
|
-
WHEN json_extract(data, '$.type') = 'text'
|
|
3872
|
-
THEN json_set(data, '$.text', substr(json_extract(data, '$.text'), 1, ${RAW_SUMMARY_TEXT_MAX_CHARS}))
|
|
3873
|
-
ELSE json_object(
|
|
3874
|
-
'type', 'tool',
|
|
3875
|
-
'tool', ${summaryStringField("$.tool")},
|
|
3876
|
-
'callID', ${summaryStringField("$.callID")},
|
|
3877
|
-
'state', json_object(
|
|
3878
|
-
'status', ${summaryStringField("$.state.status")},
|
|
3879
|
-
'input', json_object(${RAW_SUMMARY_TOOL_INPUT_KEYS.map((key) => `'${key}', ${summaryStringField(`$.state.input.${key}`)}`).join(", ")}),
|
|
3880
|
-
'metadata', json_object('description', ${summaryStringField("$.state.metadata.description")})
|
|
3881
|
-
)
|
|
3882
|
-
)
|
|
3883
|
-
END`;
|
|
3884
|
-
function readRawSessionMessageSummaryPageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER, after) {
|
|
3885
|
-
const messageRows = readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark, after);
|
|
3886
|
-
if (messageRows.length === 0)
|
|
3887
|
-
return [];
|
|
3888
|
-
const placeholders = messageRows.map(() => "?").join(", ");
|
|
3889
|
-
const partRows = db.prepare(`SELECT message_id, ${RAW_SUMMARY_PART_DATA_SQL} AS data, time_updated
|
|
3890
|
-
FROM part
|
|
3891
|
-
WHERE +session_id = ?
|
|
3892
|
-
AND likelihood(message_id IN (${placeholders}), 0.000001)
|
|
3893
|
-
AND json_valid(data) = 1
|
|
3894
|
-
AND json_extract(data, '$.type') IN ('text', 'tool')
|
|
3895
|
-
ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
|
|
3896
|
-
return assembleRawMessagePage(messageRows, partRows);
|
|
3897
|
-
}
|
|
3898
|
-
function countRawSessionMessageOrdinalsFromDb(db, sessionId) {
|
|
3899
|
-
const row = db.prepare(`SELECT COUNT(*) AS count
|
|
3900
|
-
FROM message
|
|
3901
|
-
WHERE session_id = ?
|
|
3902
|
-
AND NOT (
|
|
3903
|
-
CASE WHEN json_valid(data) = 1
|
|
3904
|
-
THEN COALESCE(json_extract(data, '$.summary'), 0)
|
|
3905
|
-
ELSE 0 END = 1
|
|
3906
|
-
AND CASE WHEN json_valid(data) = 1
|
|
3907
|
-
THEN COALESCE(json_extract(data, '$.finish'), '')
|
|
3908
|
-
ELSE '' END = 'stop'
|
|
3909
|
-
)`).get(sessionId);
|
|
3910
|
-
return typeof row?.count === "number" ? row.count : 0;
|
|
3911
|
-
}
|
|
3912
|
-
function readRawSessionMessageIdOrdinalsForRangeFromDb(db, sessionId, fromOrdinal, toOrdinal) {
|
|
3913
|
-
const from = Math.max(1, Math.floor(fromOrdinal));
|
|
3914
|
-
const to = Math.floor(toOrdinal);
|
|
3915
|
-
if (to < from)
|
|
3916
|
-
return new Map;
|
|
3917
|
-
const rows = db.prepare(`
|
|
3918
|
-
SELECT id, data FROM message WHERE session_id = ?
|
|
3919
|
-
AND CASE WHEN json_valid(data) THEN NOT (
|
|
3920
|
-
COALESCE(json_type(data, '$.summary'), '') = 'true'
|
|
3921
|
-
AND COALESCE(json_extract(data, '$.finish'), '') = 'stop'
|
|
3922
|
-
) ELSE 1 END
|
|
3923
|
-
ORDER BY time_created, id LIMIT ? OFFSET ?
|
|
3924
|
-
`).all(sessionId, to - from + 1, from - 1).filter(isRawMessageRow);
|
|
3925
|
-
const result = new Map;
|
|
3926
|
-
for (const [index, row] of rows.entries()) {
|
|
3927
|
-
if (parseJsonRecord(row.data))
|
|
3928
|
-
result.set(row.id, from + index);
|
|
3929
|
-
}
|
|
3930
|
-
return result;
|
|
3931
|
-
}
|
|
3932
|
-
function isAnchorRow(row) {
|
|
3933
|
-
return row !== null && typeof row === "object" && typeof row.time_created === "number" && typeof row.id === "string";
|
|
3934
|
-
}
|
|
3935
|
-
function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
3936
|
-
const anchorRow = db.prepare("SELECT time_created, id, data FROM message WHERE id = ? AND session_id = ?").get(anchorMessageId, sessionId);
|
|
3937
|
-
if (!isAnchorRow(anchorRow))
|
|
3938
|
-
return null;
|
|
3939
|
-
const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
|
|
3940
|
-
if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
|
|
3941
|
-
return null;
|
|
3942
|
-
const messageRows = db.prepare(`SELECT id, data, time_created, time_updated FROM message
|
|
3943
|
-
WHERE session_id = ?
|
|
3944
|
-
AND (time_created > ? OR (time_created = ? AND id >= ?))
|
|
3945
|
-
ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
|
|
3946
|
-
const filtered = messageRows.filter((row) => {
|
|
3947
|
-
const info = parseJsonRecord(row.data);
|
|
3948
|
-
return !(info?.summary === true && info?.finish === "stop");
|
|
3949
|
-
});
|
|
3950
|
-
const ids = filtered.map((row) => row.id);
|
|
3951
|
-
const partsByMessageId = new Map;
|
|
3952
|
-
if (ids.length > 0) {
|
|
3953
|
-
const CHUNK = 800;
|
|
3954
|
-
for (let i = 0;i < ids.length; i += CHUNK) {
|
|
3955
|
-
const slice = ids.slice(i, i + CHUNK);
|
|
3956
|
-
const placeholders = slice.map(() => "?").join(",");
|
|
3957
|
-
const partRows = db.prepare(`SELECT message_id, data, time_updated FROM part WHERE +session_id = ? AND likelihood(message_id IN (${placeholders}), 0.000001) ORDER BY time_created ASC, id ASC`).all(sessionId, ...slice).filter(isRawPartRow);
|
|
3958
|
-
for (const part of partRows) {
|
|
3959
|
-
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
3960
|
-
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
3961
|
-
partsByMessageId.set(part.message_id, list);
|
|
3962
|
-
}
|
|
3963
|
-
}
|
|
3964
|
-
}
|
|
3965
|
-
const messages = [];
|
|
3966
|
-
let ord = baseOrdinal;
|
|
3967
|
-
for (const row of filtered) {
|
|
3968
|
-
const info = parseJsonRecord(row.data);
|
|
3969
|
-
if (!info) {
|
|
3970
|
-
ord += 1;
|
|
3971
|
-
continue;
|
|
3972
|
-
}
|
|
3973
|
-
messages.push({
|
|
3974
|
-
ordinal: ord,
|
|
3975
|
-
id: row.id,
|
|
3976
|
-
role: typeof info.role === "string" ? info.role : "unknown",
|
|
3977
|
-
parts: partsByMessageId.get(row.id) ?? [],
|
|
3978
|
-
createdAt: row.time_created ?? null,
|
|
3979
|
-
version: row.time_updated ?? null
|
|
3980
|
-
});
|
|
3981
|
-
ord += 1;
|
|
3982
|
-
}
|
|
3983
|
-
return { messages, absoluteMessageCount: Math.max(0, ord - 1) };
|
|
3984
|
-
}
|
|
3985
|
-
function extractInMemoryMessageViews(messages) {
|
|
3986
|
-
return messages.map((m) => {
|
|
3987
|
-
const info = m.info ?? {};
|
|
3988
|
-
return {
|
|
3989
|
-
id: typeof info.id === "string" ? info.id : "",
|
|
3990
|
-
role: typeof info.role === "string" ? info.role : "unknown",
|
|
3991
|
-
parts: Array.isArray(m.parts) ? m.parts : [],
|
|
3992
|
-
summary: info.summary === true ? true : undefined,
|
|
3993
|
-
finish: typeof info.finish === "string" ? info.finish : undefined
|
|
3994
|
-
};
|
|
3995
|
-
});
|
|
3996
|
-
}
|
|
3997
|
-
function buildInMemoryTailRawMessages(args) {
|
|
3998
|
-
const { messages, lastCompartmentEnd, anchorMessageId } = args;
|
|
3999
|
-
const filtered = messages.filter((m) => !(m.summary === true && m.finish === "stop"));
|
|
4000
|
-
if (filtered.length === 0)
|
|
4001
|
-
return null;
|
|
4002
|
-
let startIndex = 0;
|
|
4003
|
-
let baseOrdinal;
|
|
4004
|
-
let anchorFound = false;
|
|
4005
|
-
if (anchorMessageId) {
|
|
4006
|
-
const anchorIndex = filtered.findIndex((m) => m.id === anchorMessageId);
|
|
4007
|
-
if (anchorIndex >= 0) {
|
|
4008
|
-
anchorFound = true;
|
|
4009
|
-
startIndex = anchorIndex;
|
|
4010
|
-
baseOrdinal = lastCompartmentEnd;
|
|
4011
|
-
} else {
|
|
4012
|
-
baseOrdinal = Math.max(1, lastCompartmentEnd + 1);
|
|
4013
|
-
}
|
|
4014
|
-
} else {
|
|
4015
|
-
baseOrdinal = Math.max(1, lastCompartmentEnd + 1);
|
|
4016
|
-
}
|
|
4017
|
-
const out = [];
|
|
4018
|
-
let ord = baseOrdinal;
|
|
4019
|
-
for (let i = startIndex;i < filtered.length; i += 1) {
|
|
4020
|
-
const m = filtered[i];
|
|
4021
|
-
if (!m.id || typeof m.id !== "string") {
|
|
4022
|
-
ord += 1;
|
|
4023
|
-
continue;
|
|
4024
|
-
}
|
|
4025
|
-
out.push({
|
|
4026
|
-
ordinal: ord,
|
|
4027
|
-
id: m.id,
|
|
4028
|
-
role: typeof m.role === "string" ? m.role : "unknown",
|
|
4029
|
-
parts: m.parts ?? [],
|
|
4030
|
-
version: null
|
|
4031
|
-
});
|
|
4032
|
-
ord += 1;
|
|
4033
|
-
}
|
|
4034
|
-
return { messages: out, absoluteMessageCount: Math.max(0, ord - 1), anchorFound };
|
|
4035
|
-
}
|
|
4036
|
-
function readRawSessionMessageOrdinalByIdFromDb(db, sessionId, messageId) {
|
|
4037
|
-
const row = db.prepare(`SELECT COUNT(candidate.id) AS ordinal
|
|
4038
|
-
FROM message AS target
|
|
4039
|
-
JOIN message AS candidate
|
|
4040
|
-
ON candidate.session_id = target.session_id
|
|
4041
|
-
AND NOT (
|
|
4042
|
-
CASE WHEN json_valid(candidate.data) = 1
|
|
4043
|
-
THEN COALESCE(json_extract(candidate.data, '$.summary'), 0)
|
|
4044
|
-
ELSE 0 END = 1
|
|
4045
|
-
AND CASE WHEN json_valid(candidate.data) = 1
|
|
4046
|
-
THEN COALESCE(json_extract(candidate.data, '$.finish'), '')
|
|
4047
|
-
ELSE '' END = 'stop'
|
|
4048
|
-
)
|
|
4049
|
-
AND (candidate.time_created < target.time_created
|
|
4050
|
-
OR (candidate.time_created = target.time_created AND candidate.id <= target.id))
|
|
4051
|
-
WHERE target.session_id = ?
|
|
4052
|
-
AND target.id = ?
|
|
4053
|
-
AND NOT (
|
|
4054
|
-
CASE WHEN json_valid(target.data) = 1
|
|
4055
|
-
THEN COALESCE(json_extract(target.data, '$.summary'), 0)
|
|
4056
|
-
ELSE 0 END = 1
|
|
4057
|
-
AND CASE WHEN json_valid(target.data) = 1
|
|
4058
|
-
THEN COALESCE(json_extract(target.data, '$.finish'), '')
|
|
4059
|
-
ELSE '' END = 'stop'
|
|
4060
|
-
)`).get(sessionId, messageId);
|
|
4061
|
-
const ordinal = row?.ordinal;
|
|
4062
|
-
return typeof ordinal === "number" && ordinal > 0 ? ordinal : null;
|
|
4063
|
-
}
|
|
4064
|
-
function readRawSessionMessageByIdFromDb(db, sessionId, messageId) {
|
|
4065
|
-
const row = db.prepare("SELECT id, data, time_created, time_updated FROM message WHERE session_id = ? AND id = ?").get(sessionId, messageId);
|
|
4066
|
-
if (!row || !isRawMessageRow(row) || typeof row.time_created !== "number") {
|
|
4067
|
-
return null;
|
|
4068
|
-
}
|
|
4069
|
-
const info = parseJsonRecord(row.data);
|
|
4070
|
-
if (!info || isRawCompactionSummaryInfo(info)) {
|
|
4071
|
-
return null;
|
|
4072
|
-
}
|
|
4073
|
-
const ordinalRow = db.prepare(`SELECT COUNT(*) AS ordinal FROM message
|
|
4074
|
-
WHERE session_id = ?
|
|
4075
|
-
AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
|
|
4076
|
-
AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
|
|
4077
|
-
AND (time_created < ? OR (time_created = ? AND id <= ?))`).get(sessionId, row.time_created, row.time_created, messageId);
|
|
4078
|
-
const ordinal = typeof ordinalRow?.ordinal === "number" ? ordinalRow.ordinal : 0;
|
|
4079
|
-
if (ordinal <= 0) {
|
|
4080
|
-
return null;
|
|
4081
|
-
}
|
|
4082
|
-
const partRows = db.prepare(RAW_MESSAGE_PARTS_BY_ID_SQL).all(sessionId, messageId).filter(isRawPartRow);
|
|
4083
|
-
const role = typeof info.role === "string" ? info.role : "unknown";
|
|
4084
|
-
return {
|
|
4085
|
-
ordinal,
|
|
4086
|
-
id: row.id,
|
|
4087
|
-
role,
|
|
4088
|
-
parts: partRows.map((part) => attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated)),
|
|
4089
|
-
createdAt: row.time_created,
|
|
4090
|
-
version: row.time_updated ?? null
|
|
4091
|
-
};
|
|
4092
|
-
}
|
|
4093
|
-
function hasRawSessionMessageByIdFromDb(db, sessionId, messageId) {
|
|
4094
|
-
const row = db.prepare("SELECT id, data, time_created FROM message WHERE session_id = ? AND id = ?").get(sessionId, messageId);
|
|
4095
|
-
if (!row || !isRawMessageRow(row) || typeof row.time_created !== "number")
|
|
4096
|
-
return false;
|
|
4097
|
-
const info = parseJsonRecord(row.data);
|
|
4098
|
-
if (!info || isRawCompactionSummaryInfo(info))
|
|
4099
|
-
return false;
|
|
4100
|
-
if (info.summary === 1 && info.finish === "stop")
|
|
4101
|
-
return readRawSessionMessageByIdFromDb(db, sessionId, messageId) !== null;
|
|
4102
|
-
return true;
|
|
4103
|
-
}
|
|
4104
|
-
|
|
4105
4727
|
// src/hooks/magic-context/read-session-true-raw-tokens.ts
|
|
4106
4728
|
function completedToolArcCrossesBoundary(invOrdinal, resOrdinal, boundary) {
|
|
4107
4729
|
return invOrdinal < boundary && boundary <= resOrdinal;
|
|
@@ -4239,7 +4861,7 @@ function callIdFromPart2(part) {
|
|
|
4239
4861
|
const state = isRecord(part.state) ? part.state : null;
|
|
4240
4862
|
return state ? firstStringField(state, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
|
|
4241
4863
|
}
|
|
4242
|
-
function toolSignalFromPart(part) {
|
|
4864
|
+
function toolSignalFromPart(part, withText = true) {
|
|
4243
4865
|
if (!isRecord(part))
|
|
4244
4866
|
return null;
|
|
4245
4867
|
const type = partType(part);
|
|
@@ -4258,8 +4880,8 @@ function toolSignalFromPart(part) {
|
|
|
4258
4880
|
callId,
|
|
4259
4881
|
hasInput: hasInput || openInvocation,
|
|
4260
4882
|
hasOutput,
|
|
4261
|
-
inputText: hasInput && state ? stringValue(state.input) : "",
|
|
4262
|
-
outputText: hasOutput ? stringValue(outputValue) : ""
|
|
4883
|
+
inputText: withText && hasInput && state ? stringValue(state.input) : "",
|
|
4884
|
+
outputText: withText && hasOutput ? stringValue(outputValue) : ""
|
|
4263
4885
|
};
|
|
4264
4886
|
}
|
|
4265
4887
|
if (type === "tool-invocation") {
|
|
@@ -4268,7 +4890,7 @@ function toolSignalFromPart(part) {
|
|
|
4268
4890
|
callId,
|
|
4269
4891
|
hasInput: args !== undefined,
|
|
4270
4892
|
hasOutput: false,
|
|
4271
|
-
inputText: args !== undefined ? stringValue(args) : "",
|
|
4893
|
+
inputText: withText && args !== undefined ? stringValue(args) : "",
|
|
4272
4894
|
outputText: ""
|
|
4273
4895
|
};
|
|
4274
4896
|
}
|
|
@@ -4278,7 +4900,7 @@ function toolSignalFromPart(part) {
|
|
|
4278
4900
|
callId,
|
|
4279
4901
|
hasInput: input !== undefined,
|
|
4280
4902
|
hasOutput: false,
|
|
4281
|
-
inputText: input !== undefined ? stringValue(input) : "",
|
|
4903
|
+
inputText: withText && input !== undefined ? stringValue(input) : "",
|
|
4282
4904
|
outputText: ""
|
|
4283
4905
|
};
|
|
4284
4906
|
}
|
|
@@ -4289,7 +4911,7 @@ function toolSignalFromPart(part) {
|
|
|
4289
4911
|
hasInput: false,
|
|
4290
4912
|
hasOutput: content !== undefined,
|
|
4291
4913
|
inputText: "",
|
|
4292
|
-
outputText: content !== undefined ? textFromToolResultContent(content) : ""
|
|
4914
|
+
outputText: withText && content !== undefined ? textFromToolResultContent(content) : ""
|
|
4293
4915
|
};
|
|
4294
4916
|
}
|
|
4295
4917
|
return null;
|
|
@@ -4299,7 +4921,7 @@ function partCheapFingerprint(part) {
|
|
|
4299
4921
|
return `${typeof part}:${recursiveByteLength(part)}`;
|
|
4300
4922
|
const version = rawPartVersion(part);
|
|
4301
4923
|
const type = typeof part.type === "string" ? part.type : "";
|
|
4302
|
-
return `${type}:${String(version)}:${recursiveByteLength(part)}`;
|
|
4924
|
+
return `${type}:${String(version)}:${recursiveByteLength(providerVisiblePart(part))}`;
|
|
4303
4925
|
}
|
|
4304
4926
|
function messageCacheKey(message, options) {
|
|
4305
4927
|
const namespace = "cacheNamespace" in options ? options.cacheNamespace : "estimate";
|
|
@@ -4419,7 +5041,7 @@ function buildToolArcs(messages) {
|
|
|
4419
5041
|
const arcs = [];
|
|
4420
5042
|
for (const message of messages) {
|
|
4421
5043
|
for (const part of message.parts) {
|
|
4422
|
-
const signal = toolSignalFromPart(part);
|
|
5044
|
+
const signal = toolSignalFromPart(part, false);
|
|
4423
5045
|
if (!signal || signal.callId.length === 0)
|
|
4424
5046
|
continue;
|
|
4425
5047
|
if (signal.hasInput && signal.hasOutput) {
|
|
@@ -4787,11 +5409,11 @@ function containsDroppedInputPlaceholder(value) {
|
|
|
4787
5409
|
};
|
|
4788
5410
|
return visit(value);
|
|
4789
5411
|
}
|
|
4790
|
-
function
|
|
5412
|
+
function isRecord3(value) {
|
|
4791
5413
|
return value !== null && typeof value === "object";
|
|
4792
5414
|
}
|
|
4793
5415
|
function isOptionalZodField(field) {
|
|
4794
|
-
if (!
|
|
5416
|
+
if (!isRecord3(field))
|
|
4795
5417
|
return false;
|
|
4796
5418
|
const isOptional = field.isOptional;
|
|
4797
5419
|
if (typeof isOptional === "function") {
|
|
@@ -4803,10 +5425,10 @@ function isOptionalZodField(field) {
|
|
|
4803
5425
|
return internals?.optin === "optional";
|
|
4804
5426
|
}
|
|
4805
5427
|
function toolParameterNames(schema) {
|
|
4806
|
-
if (!
|
|
5428
|
+
if (!isRecord3(schema))
|
|
4807
5429
|
return;
|
|
4808
5430
|
const properties = schema.properties;
|
|
4809
|
-
if (
|
|
5431
|
+
if (isRecord3(properties) && !Array.isArray(properties)) {
|
|
4810
5432
|
const names = Object.keys(properties);
|
|
4811
5433
|
const requiredList = Array.isArray(schema.required) ? schema.required : [];
|
|
4812
5434
|
const required = new Set(requiredList.filter((name) => typeof name === "string"));
|
|
@@ -4821,7 +5443,7 @@ function toolParameterNames(schema) {
|
|
|
4821
5443
|
} catch {
|
|
4822
5444
|
shape = undefined;
|
|
4823
5445
|
}
|
|
4824
|
-
if (
|
|
5446
|
+
if (isRecord3(shape) && !Array.isArray(shape)) {
|
|
4825
5447
|
const result = { required: [], optional: [] };
|
|
4826
5448
|
for (const [name, field] of Object.entries(shape)) {
|
|
4827
5449
|
(isOptionalZodField(field) ? result.optional : result.required).push(name);
|
|
@@ -4939,6 +5561,12 @@ function safeSlice(str, maxLen) {
|
|
|
4939
5561
|
function isEditTool(name) {
|
|
4940
5562
|
return name === "edit" || name === "write";
|
|
4941
5563
|
}
|
|
5564
|
+
function needsEditMarker(input) {
|
|
5565
|
+
return Object.keys(input).some((key) => {
|
|
5566
|
+
const value = input[key];
|
|
5567
|
+
return DIFF_KEYS.has(key) && typeof value === "string" && value.length > EDIT_REGION_HINT_LEN && !value.endsWith(TRUNCATION_SENTINEL);
|
|
5568
|
+
});
|
|
5569
|
+
}
|
|
4942
5570
|
function applyEditMarkerToInput(input) {
|
|
4943
5571
|
for (const key of Object.keys(input)) {
|
|
4944
5572
|
if (PATH_KEYS.has(key))
|
|
@@ -5100,6 +5728,17 @@ function serializedTokens(value, bounded = false) {
|
|
|
5100
5728
|
return Buffer.byteLength(serialized);
|
|
5101
5729
|
return serialized ? wireTextTokens(serialized) : 0;
|
|
5102
5730
|
}
|
|
5731
|
+
function estimatePartImageTokens(raw) {
|
|
5732
|
+
if (!raw || typeof raw !== "object")
|
|
5733
|
+
return 0;
|
|
5734
|
+
const part = raw;
|
|
5735
|
+
if (part.ignored)
|
|
5736
|
+
return 0;
|
|
5737
|
+
if (part.type === "file" && part.mime?.startsWith("image/")) {
|
|
5738
|
+
return typeof part.url === "string" && part.url.startsWith("data:") ? estimateImageTokensFromDataUrl(part.url) : 1200;
|
|
5739
|
+
}
|
|
5740
|
+
return part.type === "tool" ? estimateToolAttachmentImageTokens(part.state) : 0;
|
|
5741
|
+
}
|
|
5103
5742
|
function visitWireContent(message, visit) {
|
|
5104
5743
|
for (const part of message.parts) {
|
|
5105
5744
|
if (!part || typeof part !== "object")
|
|
@@ -5128,15 +5767,13 @@ function visitWireContent(message, visit) {
|
|
|
5128
5767
|
text(p.data);
|
|
5129
5768
|
break;
|
|
5130
5769
|
case "file":
|
|
5131
|
-
|
|
5132
|
-
visit.image("conversation", typeof p.url === "string" && p.url.startsWith("data:") ? estimateImageTokensFromDataUrl(p.url) : 1200);
|
|
5133
|
-
}
|
|
5770
|
+
visit.image("conversation", estimatePartImageTokens(part));
|
|
5134
5771
|
break;
|
|
5135
5772
|
case "tool":
|
|
5136
5773
|
tool(p.state?.input ?? p.input ?? p.args);
|
|
5137
5774
|
tool(p.state?.output ?? p.state?.content ?? p.output ?? p.result ?? p.content);
|
|
5138
5775
|
tool(p.state?.error);
|
|
5139
|
-
visit.image("toolCall",
|
|
5776
|
+
visit.image("toolCall", estimatePartImageTokens(part));
|
|
5140
5777
|
break;
|
|
5141
5778
|
case "tool-call":
|
|
5142
5779
|
tool(p.input ?? p.args);
|
|
@@ -5680,6 +6317,15 @@ function makeWholeMessageSentinel(providerID) {
|
|
|
5680
6317
|
text: modelAcceptsEmptyContent(providerID) ? "" : WHOLE_MESSAGE_PLACEHOLDER_TEXT
|
|
5681
6318
|
};
|
|
5682
6319
|
}
|
|
6320
|
+
function wholeMessageNeutralizationRemoves(message, providerID) {
|
|
6321
|
+
return message.info.role === "system" && modelAcceptsEmptyContent(providerID);
|
|
6322
|
+
}
|
|
6323
|
+
function neutralizeWholeMessage(message, providerID) {
|
|
6324
|
+
message.parts.length = 0;
|
|
6325
|
+
if (!wholeMessageNeutralizationRemoves(message, providerID)) {
|
|
6326
|
+
message.parts.push(makeWholeMessageSentinel(providerID));
|
|
6327
|
+
}
|
|
6328
|
+
}
|
|
5683
6329
|
function isSentinel(part) {
|
|
5684
6330
|
if (!isRecord(part))
|
|
5685
6331
|
return false;
|
|
@@ -5707,8 +6353,9 @@ function replaySentinelByMessageIds(messages, ids, providerID, hiddenSeamIds = n
|
|
|
5707
6353
|
}
|
|
5708
6354
|
if (msg.parts.length === 1 && isSentinel(msg.parts[0]))
|
|
5709
6355
|
continue;
|
|
5710
|
-
msg.parts.length
|
|
5711
|
-
|
|
6356
|
+
if (wholeMessageNeutralizationRemoves(msg, providerID) && msg.parts.length === 0)
|
|
6357
|
+
continue;
|
|
6358
|
+
neutralizeWholeMessage(msg, providerID);
|
|
5712
6359
|
replayed += 1;
|
|
5713
6360
|
}
|
|
5714
6361
|
const missingIds = [];
|
|
@@ -5776,24 +6423,18 @@ function setToolContent(part, content) {
|
|
|
5776
6423
|
}
|
|
5777
6424
|
}
|
|
5778
6425
|
function clonePart(part) {
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
} catch {
|
|
5784
|
-
try {
|
|
5785
|
-
return JSON.parse(JSON.stringify(part));
|
|
5786
|
-
} catch {
|
|
5787
|
-
return part;
|
|
5788
|
-
}
|
|
5789
|
-
}
|
|
6426
|
+
return {
|
|
6427
|
+
...part,
|
|
6428
|
+
...isRecord(part.state) ? { state: { ...part.state } } : {}
|
|
6429
|
+
};
|
|
5790
6430
|
}
|
|
5791
6431
|
function clampCloneInPlace(occurrence, clamp) {
|
|
5792
|
-
const clone = clonePart(occurrence.part);
|
|
5793
|
-
clamp(clone);
|
|
5794
6432
|
const parts = occurrence.message.parts;
|
|
5795
6433
|
const index = parts.indexOf(servedPart(occurrence));
|
|
5796
6434
|
if (index >= 0) {
|
|
6435
|
+
const clone = clamp(occurrence.part);
|
|
6436
|
+
if (clone === servedPart(occurrence))
|
|
6437
|
+
return;
|
|
5797
6438
|
parts[index] = clone;
|
|
5798
6439
|
occurrence.served = clone;
|
|
5799
6440
|
}
|
|
@@ -5803,17 +6444,24 @@ function servedPart(occurrence) {
|
|
|
5803
6444
|
}
|
|
5804
6445
|
function skeletonRealToolPart(part, tagId, stripAttachments = false) {
|
|
5805
6446
|
if (!isRecord(part))
|
|
5806
|
-
return;
|
|
6447
|
+
return part;
|
|
5807
6448
|
const sentinel = `[dropped §${tagId}§]`;
|
|
5808
6449
|
if (part.type === "tool" && isRecord(part.state)) {
|
|
5809
|
-
part.state.output
|
|
6450
|
+
if (part.state.output === sentinel && !needsAttachmentStrip(part.state, stripAttachments))
|
|
6451
|
+
return part;
|
|
6452
|
+
const clone = clonePart(part);
|
|
6453
|
+
const state = clone.state;
|
|
6454
|
+
state.output = sentinel;
|
|
5810
6455
|
if (stripAttachments)
|
|
5811
|
-
|
|
5812
|
-
return;
|
|
5813
|
-
}
|
|
5814
|
-
if (part.type === "tool_result") {
|
|
5815
|
-
part.content = sentinel;
|
|
6456
|
+
state.attachments = [];
|
|
6457
|
+
return clone;
|
|
5816
6458
|
}
|
|
6459
|
+
if (part.type === "tool_result" && part.content !== sentinel)
|
|
6460
|
+
return { ...part, content: sentinel };
|
|
6461
|
+
return part;
|
|
6462
|
+
}
|
|
6463
|
+
function needsAttachmentStrip(state, strip) {
|
|
6464
|
+
return strip && (!Array.isArray(state.attachments) || state.attachments.length !== 0);
|
|
5817
6465
|
}
|
|
5818
6466
|
function readToolPartRawInput(part) {
|
|
5819
6467
|
if (!isRecord(part))
|
|
@@ -5826,51 +6474,62 @@ function readToolPartRawInput(part) {
|
|
|
5826
6474
|
return part.input;
|
|
5827
6475
|
return;
|
|
5828
6476
|
}
|
|
6477
|
+
function isDroppedInput(input, sentinel) {
|
|
6478
|
+
return isRecord(input) && Object.keys(input).length === 1 && Object.hasOwn(input, "dropped") && input.dropped === sentinel;
|
|
6479
|
+
}
|
|
5829
6480
|
function truncateToolPart(part, tagId) {
|
|
5830
6481
|
if (!isRecord(part))
|
|
5831
|
-
return;
|
|
6482
|
+
return part;
|
|
5832
6483
|
const sentinel = `[dropped §${tagId}§]`;
|
|
5833
6484
|
if (part.type === "tool" && isRecord(part.state)) {
|
|
5834
|
-
|
|
6485
|
+
if (part.state.output === sentinel && isDroppedInput(part.state.input, sentinel))
|
|
6486
|
+
return part;
|
|
6487
|
+
const clone = clonePart(part);
|
|
6488
|
+
const state = clone.state;
|
|
5835
6489
|
state.output = sentinel;
|
|
5836
6490
|
state.input = droppedInputMarker(tagId);
|
|
5837
|
-
return;
|
|
6491
|
+
return clone;
|
|
5838
6492
|
}
|
|
5839
6493
|
if (part.type === "tool_result") {
|
|
5840
|
-
part.content
|
|
5841
|
-
return;
|
|
6494
|
+
return part.content === sentinel ? part : { ...part, content: sentinel };
|
|
5842
6495
|
}
|
|
5843
6496
|
if (part.type === "tool-invocation") {
|
|
5844
|
-
part.args
|
|
5845
|
-
return;
|
|
6497
|
+
return isDroppedInput(part.args, sentinel) ? part : { ...part, args: droppedInputMarker(tagId) };
|
|
5846
6498
|
}
|
|
5847
6499
|
if (part.type === "tool_use") {
|
|
5848
|
-
part.input
|
|
6500
|
+
return isDroppedInput(part.input, sentinel) ? part : { ...part, input: droppedInputMarker(tagId) };
|
|
5849
6501
|
}
|
|
6502
|
+
return part;
|
|
5850
6503
|
}
|
|
5851
6504
|
function editMarkerToolPart(part, tagId, stripAttachments = false) {
|
|
5852
6505
|
if (!isRecord(part))
|
|
5853
|
-
return;
|
|
6506
|
+
return part;
|
|
5854
6507
|
const sentinel = `[dropped §${tagId}§]`;
|
|
6508
|
+
const input = readToolPartInput(part);
|
|
6509
|
+
const rewriteInput = input !== null && needsEditMarker(input);
|
|
5855
6510
|
if (part.type === "tool" && isRecord(part.state)) {
|
|
5856
|
-
part.state.output
|
|
6511
|
+
if (part.state.output === sentinel && !rewriteInput && !needsAttachmentStrip(part.state, stripAttachments))
|
|
6512
|
+
return part;
|
|
6513
|
+
const clone = clonePart(part);
|
|
6514
|
+
const state = clone.state;
|
|
6515
|
+
state.output = sentinel;
|
|
5857
6516
|
if (stripAttachments)
|
|
5858
|
-
|
|
5859
|
-
if (
|
|
5860
|
-
|
|
5861
|
-
|
|
6517
|
+
state.attachments = [];
|
|
6518
|
+
if (rewriteInput) {
|
|
6519
|
+
state.input = { ...input };
|
|
6520
|
+
applyEditMarkerToInput(state.input);
|
|
6521
|
+
}
|
|
6522
|
+
return clone;
|
|
5862
6523
|
}
|
|
5863
6524
|
if (part.type === "tool_result") {
|
|
5864
|
-
part.content
|
|
5865
|
-
return;
|
|
5866
|
-
}
|
|
5867
|
-
if (part.type === "tool-invocation" && isRecord(part.args)) {
|
|
5868
|
-
applyEditMarkerToInput(part.args);
|
|
5869
|
-
return;
|
|
6525
|
+
return part.content === sentinel ? part : { ...part, content: sentinel };
|
|
5870
6526
|
}
|
|
5871
|
-
if (
|
|
5872
|
-
|
|
6527
|
+
if (rewriteInput) {
|
|
6528
|
+
const markedInput = { ...input };
|
|
6529
|
+
applyEditMarkerToInput(markedInput);
|
|
6530
|
+
return { ...part, [part.type === "tool-invocation" ? "args" : "input"]: markedInput };
|
|
5873
6531
|
}
|
|
6532
|
+
return part;
|
|
5874
6533
|
}
|
|
5875
6534
|
function readToolPartInput(part) {
|
|
5876
6535
|
if (!isRecord(part))
|
|
@@ -6099,9 +6758,7 @@ function createToolDropTarget(compositeKey, thinkingParts, index, batch, tagId)
|
|
|
6099
6758
|
parts
|
|
6100
6759
|
});
|
|
6101
6760
|
const before = count(parts);
|
|
6102
|
-
const retained = skeleton ?
|
|
6103
|
-
for (const part of retained)
|
|
6104
|
-
skeletonRealToolPart(part, tagId);
|
|
6761
|
+
const retained = skeleton ? parts.map((part) => skeletonRealToolPart(part, tagId)) : [];
|
|
6105
6762
|
const after = count(retained);
|
|
6106
6763
|
return {
|
|
6107
6764
|
beforeTools: before.toolCall,
|
|
@@ -6149,6 +6806,10 @@ function createToolDropTarget(compositeKey, thinkingParts, index, batch, tagId)
|
|
|
6149
6806
|
return false;
|
|
6150
6807
|
return batch.wouldStrandConversationEnd(entry.occurrences);
|
|
6151
6808
|
},
|
|
6809
|
+
prepareDrop: () => {
|
|
6810
|
+
const entry = index.get(compositeKey);
|
|
6811
|
+
return !!entry && entry.occurrences.length > 0 && entry.hasResult;
|
|
6812
|
+
},
|
|
6152
6813
|
canDrop: () => {
|
|
6153
6814
|
const entry = index.get(compositeKey);
|
|
6154
6815
|
return !!entry && entry.occurrences.length > 0 && entry.hasResult && !entry.occurrences.some((occurrence) => toolPartHasUserAnswer(occurrence.part));
|
|
@@ -6422,6 +7083,14 @@ function readRawSessionMessageRange2(sessionId, fromOrdinal, toOrdinal) {
|
|
|
6422
7083
|
}
|
|
6423
7084
|
readRawSessionMessages2.readPage = readRawSessionMessagePage2;
|
|
6424
7085
|
readRawSessionMessages2.getCount = getRawSessionMessageOrdinalCount2;
|
|
7086
|
+
readRawSessionMessages2.prepare = prepareRawSessionOrdinals2;
|
|
7087
|
+
async function prepareRawSessionOrdinals2(sessionId) {
|
|
7088
|
+
if (sessionProviders.get(sessionId)?.provider)
|
|
7089
|
+
return true;
|
|
7090
|
+
if (!openCodeDbExists())
|
|
7091
|
+
return true;
|
|
7092
|
+
return withReadOnlySessionDb((db) => warmRawSessionOrdinalsForDb(db, sessionId));
|
|
7093
|
+
}
|
|
6425
7094
|
function primeTailRawMessageCache2(args) {
|
|
6426
7095
|
const { sessionId, lastCompartmentEnd, anchorMessageId } = args;
|
|
6427
7096
|
if (!activeRawMessageCache)
|
|
@@ -6573,6 +7242,7 @@ function readRawSessionMessageById2(sessionId, messageId) {
|
|
|
6573
7242
|
return null;
|
|
6574
7243
|
return withReadOnlySessionDb((db) => readRawSessionMessageByIdFromDb(db, sessionId, messageId));
|
|
6575
7244
|
}
|
|
7245
|
+
readRawSessionMessageById2.prepare = prepareRawSessionOrdinals2;
|
|
6576
7246
|
function readRawSessionMessagesFromSource(sessionId) {
|
|
6577
7247
|
const provider = sessionProviders.get(sessionId)?.provider;
|
|
6578
7248
|
if (provider)
|
|
@@ -6953,6 +7623,14 @@ function readSessionChunk2(sessionId, tokenBudget, offset = 1, eligibleEndOrdina
|
|
|
6953
7623
|
pinComponentWhenFormattedBudgetCrosses(msg.ordinal, text);
|
|
6954
7624
|
}
|
|
6955
7625
|
if (flushCurrentBlock() && pendingNoiseMeta.length > 0) {
|
|
7626
|
+
const lastNoise = pendingNoiseMeta[pendingNoiseMeta.length - 1];
|
|
7627
|
+
if (messagesProcessed > 0 && lastNoise) {
|
|
7628
|
+
lineMeta.push(...pendingNoiseMeta);
|
|
7629
|
+
messagesProcessed += pendingNoiseMeta.length;
|
|
7630
|
+
lastOrdinal = lastNoise.ordinal;
|
|
7631
|
+
lastMessageId = lastNoise.messageId;
|
|
7632
|
+
pendingNoiseMeta = [];
|
|
7633
|
+
}
|
|
6956
7634
|
highestScannedOrdinal = Math.max(highestScannedOrdinal, pendingNoiseMeta[pendingNoiseMeta.length - 1]?.ordinal ?? highestScannedOrdinal);
|
|
6957
7635
|
}
|
|
6958
7636
|
const toolOnlyRanges = [];
|
|
@@ -6990,4 +7668,4 @@ function readSessionChunk2(sessionId, tokenBudget, offset = 1, eligibleEndOrdina
|
|
|
6990
7668
|
toolResultBoundaries
|
|
6991
7669
|
};
|
|
6992
7670
|
}
|
|
6993
|
-
export { toolTemplateError, DEFAULT_PROTECTED_TOOLS, normalizeProtectedToolName, mergeProtectedTools,
|
|
7671
|
+
export { toolTemplateError, DEFAULT_PROTECTED_TOOLS, normalizeProtectedToolName, mergeProtectedTools, detectLatestTurnThinkingMismatch, isPrefixBoundThinkingModel, detectOverflow, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isThinkingPart, isRecord, protectedToolTagNumbers, protectedToolTokenCount, textMentionsRecentCommit, removeSystemReminders, hasMeaningfulUserText2, extractTexts2, getTokenizerNativeMemoryStats, preloadTokenizer, estimateTokens, estimateFixedPromptTokens, currentReclaimableToolOutputCount, stableStringify, contentTagOwnerMessageId, estimateImageTokensFromDataUrl, estimateToolAttachmentImageTokens, providerVisibleMessage, normalizeTodoStateJson, buildSyntheticTodoPart, isSyntheticTodoPart, countRealUserMessages, tailHygieneStructuralSignature, sameTailHygieneStructuralSignature, formatTailHygienePrefixMismatch, refreshTailHygieneBaseline, effectiveTailHygiene, assertTailHygieneContentUnchangedIfEnabled, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, isDroppedToolOutput, toolOutputTokens, decideChannel1, evaluateChannel2, formatChannel1Evaluation, formatChannel2Evaluation, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, estimateEmergencyDropReclaimTokens, planEmergencyDrop, measureEmergencyTag, installV3PerfSchema, queuePendingOp, queuePendingDropForUnchangedTag, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, tagTombstoneOwnerRange, tagTombstoneOwnerKey, tagRevisionKey, tagIdentityRevisionKey, installTagIdentityRevisionTrigger, deleteTagIdentityRevisions, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, getActiveTagTokenTotalsByMessage, getAllStatusTagTokenTotalsFlat, getReasoningTokenEstimatesByMessage, tryGetReasoningTokenEstimatesByMessage, getMaxTagNumberByOwnerMessage, scanTagOwnerSummary, isTagOwnerSummaryReady, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, markTagDropped, markWhitespaceAssistantTagInert, getInertWhitespaceAssistantTags, getInertWhitespaceAssistantTagsByNumbers, updateTagDropMode, updateCavemanDepth, updateTagMessageId, foldShrunkPartTags, markTagsCompactedByMessageIds, getMaxTagNumberBySession, getTagNumberByMessageId, getAssignableTagNumberByMessageId, deriveTagLoadFloor, TAG_SELECT_COLUMNS, getTagsBySession, getActiveTagsBySession, getTailHygieneTags, getTagsByNumbers, getNewestToolTagNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getTagById, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, getCandidateToolOwners, pickNearestPriorOwner, expandToolPart, markHostUnservedRow, retreatPastHostUnservedRows, snapTerminalCompartmentToServedRow, isHostRenderedSystemMessage, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, stripSystemInjection, isTextPart, isToolPartWithOutput, isFilePart, buildFileSourceContent, toolPartHasUserAnswer, recordToolParameters, createDroppedInputGuard, assertExecutableToolInput, isEditTool, getCurrentToolSetHash, setDatabase, loadToolDefinitionMeasurements, recordToolDefinition, getMeasuredToolDefinitionTokens, describeFinalWireTail, estimatePartImageTokens, estimateMessageTokens, wireContentBytes, createFinalWireUsageTracker, estimateFinalWireInputTokens, modelAcceptsEmptyContent, isAnthropicFamilyRoute, neutralizeDroppedReasoningPart, restoreNeutralizedReasoningPart, isNeutralizedReasoningPart, neutralizedReasoningSource, variantChangeBustsProviderCache, makeSentinel, makeWholeMessageSentinel, neutralizeWholeMessage, isSentinel, replaySentinelByMessageIds, SKELETON_REAL_INPUT_MAX_BYTES, partHasCompletedResult, extractToolCallObservation, ToolMutationBatch, createToolDropTarget, resolveHostServedBoundaryId2, hasRawMessageProvider2, setBoundedRawMessageProvider2, cleanUserText2, withRawSessionMessageCache2, readRawSessionMessages2, readRawSessionMessagePage2, getRawSessionMessageOrdinalCount2, visitRawSessionMessages2, readRawSessionMessageRange2, prepareRawSessionOrdinals2, primeTailRawMessageCache2, getCachedAbsoluteMessageCount2, primeInMemoryTailRawMessageCache2, readRawSessionMessageIdOrdinalsForRange2, hasRawSessionMessageById2, readRawSessionMessageOrdinalById2, compareRawSessionMessageOrder2, readRawSessionMessageById2, getRawSessionMessageCount2, getRawSessionTagKeysThrough2, getLegacyProtectedTailStartOrdinal2, readSessionChunk2 };
|