pi-background-tasks 2.5.0 → 2.6.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.
Files changed (203) hide show
  1. package/BACKGROUND-TASKS-INSTRUCTIONS.md +1 -1
  2. package/README.md +70 -25
  3. package/TESTING.md +42 -2
  4. package/TEST_PLAN.md +7 -4
  5. package/dist/extensions/anthropic-attribution-child.js +4 -0
  6. package/dist/extensions/anthropic-attribution-child.js.map +1 -0
  7. package/dist/extensions/anthropic-attribution.js +107 -0
  8. package/dist/extensions/anthropic-attribution.js.map +1 -0
  9. package/dist/extensions/background-tasks.js +2 -0
  10. package/dist/extensions/background-tasks.js.map +1 -0
  11. package/dist/extensions/delegate-child.js +2 -0
  12. package/dist/extensions/delegate-child.js.map +1 -0
  13. package/dist/extensions/fusion-child.js +2 -0
  14. package/dist/extensions/fusion-child.js.map +1 -0
  15. package/dist/package.json +5 -0
  16. package/dist/src/core/anthropic-attribution-path.js +24 -0
  17. package/dist/src/core/anthropic-attribution-path.js.map +1 -0
  18. package/dist/src/core/anthropic-attribution.js +2247 -0
  19. package/dist/src/core/anthropic-attribution.js.map +1 -0
  20. package/dist/src/core/attested-pi-contract.js +5 -0
  21. package/dist/src/core/attested-pi-contract.js.map +1 -0
  22. package/dist/src/core/attested-pi-run.js +749 -0
  23. package/dist/src/core/attested-pi-run.js.map +1 -0
  24. package/dist/src/core/canonical-json.js +19 -0
  25. package/dist/src/core/canonical-json.js.map +1 -0
  26. package/dist/src/core/common.js +787 -0
  27. package/dist/src/core/common.js.map +1 -0
  28. package/dist/src/core/config.js +78 -0
  29. package/dist/src/core/config.js.map +1 -0
  30. package/dist/src/core/context/parent-snapshot.js +75 -0
  31. package/dist/src/core/context/parent-snapshot.js.map +1 -0
  32. package/dist/src/core/context/token-budget.js +631 -0
  33. package/dist/src/core/context/token-budget.js.map +1 -0
  34. package/dist/src/core/context/visible-conversation-v2.js +390 -0
  35. package/dist/src/core/context/visible-conversation-v2.js.map +1 -0
  36. package/dist/src/core/delegate/artifacts.js +357 -0
  37. package/dist/src/core/delegate/artifacts.js.map +1 -0
  38. package/dist/src/core/delegate/budget.js +266 -0
  39. package/dist/src/core/delegate/budget.js.map +1 -0
  40. package/dist/src/core/delegate/facade-contract.js +7 -0
  41. package/dist/src/core/delegate/facade-contract.js.map +1 -0
  42. package/dist/src/core/delegate/hook-contract-evidence.json +18 -0
  43. package/dist/src/core/delegate/hook-contract.js +124 -0
  44. package/dist/src/core/delegate/hook-contract.js.map +1 -0
  45. package/dist/src/core/delegate/launch.js +366 -0
  46. package/dist/src/core/delegate/launch.js.map +1 -0
  47. package/dist/src/core/delegate/result-package.js +293 -0
  48. package/dist/src/core/delegate/result-package.js.map +1 -0
  49. package/dist/src/core/delegate/runner.js +398 -0
  50. package/dist/src/core/delegate/runner.js.map +1 -0
  51. package/dist/src/core/delegate/seed.js +334 -0
  52. package/dist/src/core/delegate/seed.js.map +1 -0
  53. package/dist/src/core/delegate/types.js +103 -0
  54. package/dist/src/core/delegate/types.js.map +1 -0
  55. package/dist/src/core/durable-fs.js +372 -0
  56. package/dist/src/core/durable-fs.js.map +1 -0
  57. package/dist/src/core/extension-api.js +382 -0
  58. package/dist/src/core/extension-api.js.map +1 -0
  59. package/dist/src/core/fusion/artifacts.js +654 -0
  60. package/dist/src/core/fusion/artifacts.js.map +1 -0
  61. package/dist/src/core/fusion/budget.js +949 -0
  62. package/dist/src/core/fusion/budget.js.map +1 -0
  63. package/dist/src/core/fusion/child-protocol.js +176 -0
  64. package/dist/src/core/fusion/child-protocol.js.map +1 -0
  65. package/dist/src/core/fusion/claude-cache.js +156 -0
  66. package/dist/src/core/fusion/claude-cache.js.map +1 -0
  67. package/dist/src/core/fusion/clean-context.js +64 -0
  68. package/dist/src/core/fusion/clean-context.js.map +1 -0
  69. package/dist/src/core/fusion/config.js +349 -0
  70. package/dist/src/core/fusion/config.js.map +1 -0
  71. package/dist/src/core/fusion/context.js +184 -0
  72. package/dist/src/core/fusion/context.js.map +1 -0
  73. package/dist/src/core/fusion/evaluation.js +696 -0
  74. package/dist/src/core/fusion/evaluation.js.map +1 -0
  75. package/dist/src/core/fusion/facade-contract.js +3 -0
  76. package/dist/src/core/fusion/facade-contract.js.map +1 -0
  77. package/dist/src/core/fusion/orchestrator.js +867 -0
  78. package/dist/src/core/fusion/orchestrator.js.map +1 -0
  79. package/dist/src/core/fusion/output-contract.js +27 -0
  80. package/dist/src/core/fusion/output-contract.js.map +1 -0
  81. package/dist/src/core/fusion/pi-child.js +1741 -0
  82. package/dist/src/core/fusion/pi-child.js.map +1 -0
  83. package/dist/src/core/fusion/prompts.js +260 -0
  84. package/dist/src/core/fusion/prompts.js.map +1 -0
  85. package/dist/src/core/fusion/result-package.js +857 -0
  86. package/dist/src/core/fusion/result-package.js.map +1 -0
  87. package/dist/src/core/fusion/source-policy.js +259 -0
  88. package/dist/src/core/fusion/source-policy.js.map +1 -0
  89. package/dist/src/core/fusion/types.js +207 -0
  90. package/dist/src/core/fusion/types.js.map +1 -0
  91. package/dist/src/core/fusion/web-fetch.js +777 -0
  92. package/dist/src/core/fusion/web-fetch.js.map +1 -0
  93. package/dist/src/core/fusion/workflows.js +126 -0
  94. package/dist/src/core/fusion/workflows.js.map +1 -0
  95. package/dist/src/core/lazy-module.js +181 -0
  96. package/dist/src/core/lazy-module.js.map +1 -0
  97. package/dist/src/core/pi-launch.js +431 -0
  98. package/dist/src/core/pi-launch.js.map +1 -0
  99. package/dist/src/core/registry.js +3331 -0
  100. package/dist/src/core/registry.js.map +1 -0
  101. package/dist/src/core/reload-shell-owner.js +1396 -0
  102. package/dist/src/core/reload-shell-owner.js.map +1 -0
  103. package/dist/src/core/shell-policy.js +80 -0
  104. package/dist/src/core/shell-policy.js.map +1 -0
  105. package/dist/src/core/task-durable.js +51 -0
  106. package/dist/src/core/task-durable.js.map +1 -0
  107. package/dist/src/core/update-check.js +92 -0
  108. package/dist/src/core/update-check.js.map +1 -0
  109. package/dist/src/core/windows-taskkill.js +185 -0
  110. package/dist/src/core/windows-taskkill.js.map +1 -0
  111. package/dist/src/delegate-child-extension.js +776 -0
  112. package/dist/src/delegate-child-extension.js.map +1 -0
  113. package/dist/src/delegate-extension.js +746 -0
  114. package/dist/src/delegate-extension.js.map +1 -0
  115. package/dist/src/extension.js +953 -0
  116. package/dist/src/extension.js.map +1 -0
  117. package/dist/src/fusion-child-extension.js +760 -0
  118. package/dist/src/fusion-child-extension.js.map +1 -0
  119. package/dist/src/fusion-extension.js +1030 -0
  120. package/dist/src/fusion-extension.js.map +1 -0
  121. package/dist/src/ui/background-tasks-manager.js +689 -0
  122. package/dist/src/ui/background-tasks-manager.js.map +1 -0
  123. package/dist/src/ui/fusion-model-selector.js +277 -0
  124. package/dist/src/ui/fusion-model-selector.js.map +1 -0
  125. package/docs/INDEX.md +35 -33
  126. package/docs/api/eventbus-v1.md +21 -5
  127. package/docs/choose-a-workflow.md +2 -0
  128. package/docs/commands/bg-clear.md +3 -3
  129. package/docs/commands/bg-update.md +3 -3
  130. package/docs/commands/bg.md +18 -6
  131. package/docs/commands/claude-cache.md +4 -4
  132. package/docs/commands/fusion-models.md +49 -4
  133. package/docs/commands/fusion.md +3 -3
  134. package/docs/commands/jobs.md +3 -3
  135. package/docs/commands/kill.md +3 -3
  136. package/docs/commands/logs.md +3 -3
  137. package/docs/commands/task-manager.md +5 -5
  138. package/docs/concepts/completion-delivery.md +6 -2
  139. package/docs/getting-started.md +7 -1
  140. package/docs/manifest.json +228 -42
  141. package/docs/operations/configuration.md +58 -5
  142. package/docs/operations/releasing.md +4 -2
  143. package/docs/operations/testing.md +22 -0
  144. package/docs/operations/troubleshooting.md +6 -2
  145. package/docs/read-before-edit.md +44 -31
  146. package/docs/reference/runtime-contracts.md +87 -51
  147. package/docs/reference/shortcuts-and-dock.md +28 -14
  148. package/docs/subsystems/anthropic-attribution.md +23 -11
  149. package/docs/subsystems/attested-pi-runs.md +12 -7
  150. package/docs/subsystems/background-task-runtime.md +53 -11
  151. package/docs/subsystems/child-launch-durability-and-safety.md +28 -9
  152. package/docs/subsystems/delegation.md +16 -3
  153. package/docs/subsystems/docs-freshness-gate.md +14 -7
  154. package/docs/subsystems/fusion.md +36 -11
  155. package/docs/subsystems/host-ui-and-telemetry.md +22 -9
  156. package/docs/tools/bg_delegate.md +3 -1
  157. package/docs/tools/bg_kill.md +3 -1
  158. package/docs/tools/bg_logs.md +3 -1
  159. package/docs/tools/bg_result.md +5 -3
  160. package/docs/tools/bg_run.md +31 -5
  161. package/docs/tools/bg_run_pi_attested.md +3 -1
  162. package/docs/tools/bg_status.md +3 -1
  163. package/docs/tools/fusion_investigate.md +3 -1
  164. package/docs/tools/fusion_reason.md +3 -1
  165. package/docs/tools/fusion_research.md +3 -1
  166. package/docs/tools/fusion_validate.md +3 -1
  167. package/extensions/anthropic-attribution-child.ts +3 -0
  168. package/extensions/anthropic-attribution.ts +166 -1
  169. package/package.json +12 -10
  170. package/src/core/anthropic-attribution-path.ts +5 -4
  171. package/src/core/anthropic-attribution.ts +293 -113
  172. package/src/core/attested-pi-contract.ts +4 -0
  173. package/src/core/attested-pi-run.ts +468 -81
  174. package/src/core/canonical-json.ts +21 -0
  175. package/src/core/common.ts +450 -40
  176. package/src/core/config.ts +121 -0
  177. package/src/core/context/visible-conversation-v2.ts +3 -6
  178. package/src/core/delegate/artifacts.ts +13 -9
  179. package/src/core/delegate/budget.ts +13 -6
  180. package/src/core/delegate/facade-contract.ts +6 -0
  181. package/src/core/delegate/result-package.ts +32 -14
  182. package/src/core/delegate/runner.ts +129 -58
  183. package/src/core/delegate/seed.ts +5 -7
  184. package/src/core/durable-fs.ts +178 -30
  185. package/src/core/extension-api.ts +36 -8
  186. package/src/core/fusion/artifacts.ts +17 -16
  187. package/src/core/fusion/clean-context.ts +8 -5
  188. package/src/core/fusion/config.ts +2 -1
  189. package/src/core/fusion/context.ts +2 -6
  190. package/src/core/fusion/facade-contract.ts +2 -0
  191. package/src/core/fusion/orchestrator.ts +3 -3
  192. package/src/core/fusion/prompts.ts +1 -1
  193. package/src/core/fusion/result-package.ts +259 -72
  194. package/src/core/fusion/source-policy.ts +43 -17
  195. package/src/core/lazy-module.ts +215 -0
  196. package/src/core/pi-launch.ts +390 -65
  197. package/src/core/registry.ts +2010 -381
  198. package/src/core/reload-shell-owner.ts +1662 -0
  199. package/src/core/shell-policy.ts +134 -0
  200. package/src/core/task-durable.ts +67 -0
  201. package/src/delegate-extension.ts +404 -144
  202. package/src/extension.ts +387 -114
  203. package/src/fusion-extension.ts +202 -96
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-budget.js","sourceRoot":"","sources":["../../../../src/core/context/token-budget.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared, dependency-free size arithmetic for prompt budgeting.\n *\n * Fusion and delegate both use the same pure estimator, but they pass distinct\n * scope profiles. Fusion may use a calibrated family rate only for measured\n * large prompts that remain in the calibration domain. Delegate uses a stricter\n * byte-ceiling profile because its 8,192-token floor is too small for relaxed\n * rates.\n *\n * Calibration basis: 882 real large Fusion prompts. The observed floors are\n * 2.047 B/tok for Anthropic and 3.400 B/tok for Codex. The shipped rates apply\n * a 15% haircut and add a provisional 512-token affine intercept. The\n * low-whitespace gate below is a corpus-derived heuristic proxy for dense ASCII\n * token density; it is not a tokenizer bound or guarantee.\n */\n\nexport const TOKEN_BUDGET_CALIBRATION_VERSION =\n 'pi-background-tasks.input-token-calibration.v1' as const;\nexport const TOKEN_BUDGET_RATE_SCALE = 100;\nexport const TOKEN_BUDGET_PROVENANCE_SCALE = 1000;\nexport const TOKEN_BUDGET_HAIRCUT_BASIS_POINTS = 1500;\nexport const TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES = 50 * 1024;\nexport const TOKEN_BUDGET_CONSERVATIVE_RATE_X100 = 200;\nexport const TOKEN_BUDGET_PROVABLE_RATE_X100 = 100;\nexport const TOKEN_BUDGET_DELEGATE_CONSERVATIVE_RATE_X100 = TOKEN_BUDGET_PROVABLE_RATE_X100;\nexport const TOKEN_BUDGET_MULTIBYTE_FATAL_RATE_X100 = TOKEN_BUDGET_CONSERVATIVE_RATE_X100;\nexport const TOKEN_BUDGET_AFFINE_F_TOKENS = 512;\nexport const TOKEN_BUDGET_WHITESPACE_FRACTION_SCALE = 10_000;\n/**\n * Floor of the observed large-prompt calibration corpus, scaled by\n * TOKEN_BUDGET_WHITESPACE_FRACTION_SCALE and rounded down. The gate threshold is\n * deliberately below this value; it catches near-zero-whitespace OOD payloads\n * without claiming to bound tokenizer density.\n */\nexport const TOKEN_BUDGET_CALIBRATION_CORPUS_MIN_WHITESPACE_FRACTION_X10000 = 18;\nexport const TOKEN_BUDGET_DENSE_ASCII_WHITESPACE_THRESHOLD_X10000 = 10;\n\nexport const TOKEN_BUDGET_FAMILIES = ['anthropic', 'openai-codex', 'unknown'] as const;\nexport type TokenBudgetFamily = (typeof TOKEN_BUDGET_FAMILIES)[number];\n\nexport const TOKEN_BUDGET_SEGMENT_KINDS = [\n 'known_text',\n 'known_json',\n 'unknown_output_contract',\n] as const;\nexport type TokenBudgetSegmentKind = (typeof TOKEN_BUDGET_SEGMENT_KINDS)[number];\n\nexport type TokenBudgetEstimatorScope =\n | 'fusion'\n | 'delegate_launch'\n | 'delegate'\n | 'conservative';\nexport type TokenBudgetDominantByteClass =\n | 'normal'\n | 'dense_ascii'\n | 'multibyte'\n | 'unknown_output_contract';\n\nexport interface TokenBudgetCalibrationProvenance {\n n: number;\n observed_min_bpt_x1000: number | null;\n median_bpt_x1000: number | null;\n max_bpt_x1000: number | null;\n corpus_sha256: string | null;\n corpus_date: string;\n haircut_basis_points: number;\n backed: boolean;\n byte_level_bpe: boolean;\n}\n\nexport interface TokenBudgetFamilyCalibration {\n family: TokenBudgetFamily;\n rate_bytes_per_token_x100: number;\n affine_f_tokens: number;\n provenance: TokenBudgetCalibrationProvenance;\n}\n\nconst ANTHROPIC_PROVENANCE: TokenBudgetCalibrationProvenance = Object.freeze({\n n: 85,\n observed_min_bpt_x1000: 2047,\n median_bpt_x1000: 2217,\n max_bpt_x1000: 2481,\n corpus_sha256: 'sha256:large-fusion-prompts-2026-08-02',\n corpus_date: '2026-08-02',\n haircut_basis_points: TOKEN_BUDGET_HAIRCUT_BASIS_POINTS,\n backed: true,\n byte_level_bpe: true,\n});\n\nconst OPENAI_CODEX_PROVENANCE: TokenBudgetCalibrationProvenance = Object.freeze({\n n: 797,\n observed_min_bpt_x1000: 3400,\n median_bpt_x1000: 3721,\n max_bpt_x1000: 4526,\n corpus_sha256: 'sha256:large-fusion-prompts-2026-08-02',\n corpus_date: '2026-08-02',\n haircut_basis_points: TOKEN_BUDGET_HAIRCUT_BASIS_POINTS,\n backed: true,\n byte_level_bpe: true,\n});\n\nconst UNKNOWN_PROVENANCE: TokenBudgetCalibrationProvenance = Object.freeze({\n n: 0,\n observed_min_bpt_x1000: null,\n median_bpt_x1000: null,\n max_bpt_x1000: null,\n corpus_sha256: null,\n corpus_date: 'unbacked',\n haircut_basis_points: TOKEN_BUDGET_HAIRCUT_BASIS_POINTS,\n backed: false,\n byte_level_bpe: true,\n});\n\nexport const TOKEN_BUDGET_FAMILY_CALIBRATIONS: Readonly<\n Record<TokenBudgetFamily, TokenBudgetFamilyCalibration>\n> = Object.freeze({\n anthropic: Object.freeze({\n family: 'anthropic',\n rate_bytes_per_token_x100: 173,\n affine_f_tokens: TOKEN_BUDGET_AFFINE_F_TOKENS,\n provenance: ANTHROPIC_PROVENANCE,\n }),\n 'openai-codex': Object.freeze({\n family: 'openai-codex',\n rate_bytes_per_token_x100: 289,\n affine_f_tokens: TOKEN_BUDGET_AFFINE_F_TOKENS,\n provenance: OPENAI_CODEX_PROVENANCE,\n }),\n unknown: Object.freeze({\n family: 'unknown',\n rate_bytes_per_token_x100: 100,\n affine_f_tokens: TOKEN_BUDGET_AFFINE_F_TOKENS,\n provenance: UNKNOWN_PROVENANCE,\n }),\n});\n\nconst MODEL_OVERRIDES: Readonly<Record<string, TokenBudgetFamily>> = Object.freeze({\n 'anthropic/claude-opus-5': 'anthropic',\n 'anthropic/claude-fable-5': 'anthropic',\n 'openai-codex/gpt-5.6-sol': 'openai-codex',\n 'openai-codex/gpt-5.6-terra': 'openai-codex',\n 'openai-codex/gpt-5.5': 'openai-codex',\n 'openai-codex/gpt-5.4-mini': 'openai-codex',\n});\nconst PROVIDER_DEFAULTS: Readonly<Record<string, TokenBudgetFamily>> = Object.freeze({\n anthropic: 'anthropic',\n 'openai-codex': 'openai-codex',\n});\n\nexport interface TokenBudgetRouteLike {\n provider: string;\n model: string;\n}\n\nexport interface ResolvedTokenBudgetFamily {\n family: TokenBudgetFamily;\n provider: string;\n model: string;\n qualified_id: string;\n backed: boolean;\n resolution: 'model_override' | 'known_provider_unbacked_model' | 'unknown_provider_floor';\n}\n\nexport function resolveTokenBudgetFamily(route: TokenBudgetRouteLike): ResolvedTokenBudgetFamily {\n const qualified = `${route.provider}/${route.model}`;\n const overridden = MODEL_OVERRIDES[qualified];\n if (overridden !== undefined) {\n return {\n family: overridden,\n provider: route.provider,\n model: route.model,\n qualified_id: qualified,\n backed: true,\n resolution: 'model_override',\n };\n }\n const providerDefault = PROVIDER_DEFAULTS[route.provider];\n if (providerDefault !== undefined) {\n return {\n family: providerDefault,\n provider: route.provider,\n model: route.model,\n qualified_id: qualified,\n backed: false,\n resolution: 'known_provider_unbacked_model',\n };\n }\n return {\n family: 'unknown',\n provider: route.provider,\n model: route.model,\n qualified_id: qualified,\n backed: false,\n resolution: 'unknown_provider_floor',\n };\n}\n\nexport interface TokenBudgetSegment {\n kind: TokenBudgetSegmentKind;\n bytes: number;\n multibyteBytes?: number | undefined;\n denseBytes?: number | undefined;\n asciiWhitespaceBytes?: number | undefined;\n}\n\nexport interface TokenBudgetByteClassBreakdown {\n total_bytes: number;\n normal_bytes: number;\n multibyte_bytes: number;\n dense_bytes: number;\n unknown_output_contract_bytes: number;\n}\n\nexport interface TokenBudgetPromptProfile extends TokenBudgetByteClassBreakdown {\n concrete_known_bytes: number;\n ascii_whitespace_bytes: number;\n whitespace_fraction_x10000: number | null;\n whitespace_fraction_scale: typeof TOKEN_BUDGET_WHITESPACE_FRACTION_SCALE;\n whitespace_fraction_available: boolean;\n dominant_byte_class: TokenBudgetDominantByteClass;\n}\n\nexport interface TokenBudgetDenseAsciiGate {\n heuristic: 'low_whitespace_fraction_proxy_not_tokenizer_bound';\n corpus_min_whitespace_fraction_x10000: number;\n threshold_whitespace_fraction_x10000: number;\n measured_whitespace_fraction_x10000: number | null;\n evaluated: boolean;\n out_of_distribution: boolean;\n decision: 'not_evaluated' | 'calibrated_allowed' | 'conservative_fallback';\n reason: 'prompt_below_large_prompt_floor' | 'multibyte_or_non_ascii_dominant' | 'whitespace_fraction_unavailable' | 'below_threshold' | 'at_or_above_threshold' | null;\n}\n\nexport interface TokenBudgetRateBucketEstimate {\n rate_bytes_per_token_x100: number;\n bytes: number;\n tokens: number;\n byte_classes: readonly TokenBudgetDominantByteClass[];\n}\n\nexport interface TokenBudgetAdvisoryEstimate {\n multibyte_provable_rate_bytes_per_token_x100: typeof TOKEN_BUDGET_PROVABLE_RATE_X100;\n multibyte_provable_tokens: number;\n input_tokens_if_multibyte_used_provable_ceiling: number;\n rate_buckets: readonly TokenBudgetRateBucketEstimate[];\n}\n\nexport interface TokenBudgetPerSegmentEstimate extends TokenBudgetByteClassBreakdown {\n kind: TokenBudgetSegmentKind;\n ascii_whitespace_bytes: number;\n normal_rate_bytes_per_token_x100: number;\n normal_tokens: number;\n multibyte_rate_bytes_per_token_x100: typeof TOKEN_BUDGET_MULTIBYTE_FATAL_RATE_X100;\n multibyte_tokens: number;\n multibyte_provable_tokens: number;\n dense_tokens: number;\n unknown_output_contract_tokens: number;\n tokens: number;\n}\n\nexport interface TokenBudgetRateSource {\n calibration_version: typeof TOKEN_BUDGET_CALIBRATION_VERSION;\n family: TokenBudgetFamily;\n configured_rate_bytes_per_token_x100: number;\n effective_rate_bytes_per_token_x100: number;\n conservative_rate_bytes_per_token_x100: number;\n delegate_conservative_rate_bytes_per_token_x100: typeof TOKEN_BUDGET_DELEGATE_CONSERVATIVE_RATE_X100;\n affine_f_tokens: number;\n scope: TokenBudgetEstimatorScope;\n source:\n | 'calibrated_large_window'\n | 'conservative_small_prompt'\n | 'conservative_capacity_guard'\n | 'conservative_dense_ascii_whitespace_gate'\n | 'delegate_conservative'\n | 'explicit_conservative'\n | 'unknown_provider_floor'\n | 'unbacked_model_floor';\n backed: boolean;\n provenance: TokenBudgetCalibrationProvenance;\n model_resolution: ResolvedTokenBudgetFamily['resolution'] | 'family_direct';\n scope_guard_min_bytes: typeof TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES;\n calibration_applied: boolean;\n prompt_profile: TokenBudgetPromptProfile;\n dense_ascii_gate: TokenBudgetDenseAsciiGate;\n dominant_byte_class: TokenBudgetDominantByteClass;\n warning: string | null;\n}\n\nexport interface EstimateInputTokensInput {\n family: TokenBudgetFamily;\n segments: readonly TokenBudgetSegment[];\n allowedInputTokens?: number | undefined;\n scope?: TokenBudgetEstimatorScope | undefined;\n calibrationBacked?: boolean | undefined;\n familyResolution?: ResolvedTokenBudgetFamily['resolution'] | 'family_direct' | undefined;\n}\n\nexport interface EstimateInputTokensResult {\n tokens: number;\n fixed_tokens: number;\n perSegment: readonly TokenBudgetPerSegmentEstimate[];\n byte_class_breakdown: TokenBudgetByteClassBreakdown;\n rate_buckets: readonly TokenBudgetRateBucketEstimate[];\n advisory: TokenBudgetAdvisoryEstimate;\n rateSource: TokenBudgetRateSource;\n}\n\nfunction assertSafeNonNegativeInteger(value: number, label: string): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new TypeError(`${label} must be a non-negative safe integer`);\n }\n}\n\nfunction assertPositiveInteger(value: number, label: string): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new TypeError(`${label} must be a positive safe integer`);\n }\n}\n\nfunction calibrationFor(family: TokenBudgetFamily): TokenBudgetFamilyCalibration {\n return TOKEN_BUDGET_FAMILY_CALIBRATIONS[family];\n}\n\nfunction ceilDiv(numerator: number, denominator: number): number {\n assertSafeNonNegativeInteger(numerator, 'division numerator');\n assertPositiveInteger(denominator, 'division denominator');\n if (numerator === 0) return 0;\n return Math.floor((numerator - 1) / denominator) + 1;\n}\n\nfunction tokensAtRate(bytes: number, rateBytesPerTokenX100: number): number {\n assertSafeNonNegativeInteger(bytes, 'bytes');\n assertPositiveInteger(rateBytesPerTokenX100, 'rateBytesPerTokenX100');\n return ceilDiv(bytes * TOKEN_BUDGET_RATE_SCALE, rateBytesPerTokenX100);\n}\n\nfunction conservativeFusionRate(configured: number): number {\n return Math.min(configured, TOKEN_BUDGET_CONSERVATIVE_RATE_X100);\n}\n\ninterface NormalizedTokenBudgetSegment {\n kind: TokenBudgetSegmentKind;\n bytes: number;\n multibyteBytes: number;\n denseBytes: number;\n asciiWhitespaceBytes: number;\n whitespaceKnown: boolean;\n}\n\nfunction normalizeSegment(\n segment: TokenBudgetSegment,\n index: number,\n): NormalizedTokenBudgetSegment {\n assertSafeNonNegativeInteger(segment.bytes, `segments[${String(index)}].bytes`);\n const denseBytes = segment.denseBytes ?? 0;\n assertSafeNonNegativeInteger(denseBytes, `segments[${String(index)}].denseBytes`);\n if (segment.kind === 'unknown_output_contract') {\n if (segment.multibyteBytes !== undefined) {\n throw new TypeError(\n `segments[${String(index)}].multibyteBytes must not be set for unknown_output_contract`,\n );\n }\n if (segment.asciiWhitespaceBytes !== undefined) {\n throw new TypeError(\n `segments[${String(index)}].asciiWhitespaceBytes must not be set for unknown_output_contract`,\n );\n }\n if (denseBytes !== 0) {\n throw new TypeError(\n `segments[${String(index)}].denseBytes must be zero for unknown_output_contract`,\n );\n }\n return {\n kind: segment.kind,\n bytes: segment.bytes,\n multibyteBytes: 0,\n denseBytes,\n asciiWhitespaceBytes: 0,\n whitespaceKnown: true,\n };\n }\n if (segment.kind !== 'known_text' && segment.kind !== 'known_json') {\n throw new TypeError(`segments[${String(index)}].kind is not supported`);\n }\n if (segment.multibyteBytes === undefined) {\n throw new TypeError(`segments[${String(index)}].multibyteBytes is required`);\n }\n assertSafeNonNegativeInteger(segment.multibyteBytes, `segments[${String(index)}].multibyteBytes`);\n if (segment.multibyteBytes + denseBytes > segment.bytes) {\n throw new TypeError(\n `segments[${String(index)}] byte classes exceed segment byte length`,\n );\n }\n const whitespaceKnown = segment.asciiWhitespaceBytes !== undefined;\n const asciiWhitespaceBytes = segment.asciiWhitespaceBytes ?? 0;\n assertSafeNonNegativeInteger(\n asciiWhitespaceBytes,\n `segments[${String(index)}].asciiWhitespaceBytes`,\n );\n if (asciiWhitespaceBytes > segment.bytes - segment.multibyteBytes) {\n throw new TypeError(\n `segments[${String(index)}].asciiWhitespaceBytes exceeds ASCII byte length`,\n );\n }\n return {\n kind: segment.kind,\n bytes: segment.bytes,\n multibyteBytes: segment.multibyteBytes,\n denseBytes,\n asciiWhitespaceBytes,\n whitespaceKnown,\n };\n}\n\nfunction addBreakdown(\n target: TokenBudgetByteClassBreakdown,\n delta: TokenBudgetByteClassBreakdown,\n): void {\n target.total_bytes += delta.total_bytes;\n target.normal_bytes += delta.normal_bytes;\n target.multibyte_bytes += delta.multibyte_bytes;\n target.dense_bytes += delta.dense_bytes;\n target.unknown_output_contract_bytes += delta.unknown_output_contract_bytes;\n}\n\nfunction dominantByteClass(breakdown: TokenBudgetByteClassBreakdown): TokenBudgetDominantByteClass {\n const entries: Array<{ byteClass: TokenBudgetDominantByteClass; bytes: number; order: number }> = [\n { byteClass: 'dense_ascii', bytes: breakdown.dense_bytes, order: 0 },\n { byteClass: 'multibyte', bytes: breakdown.multibyte_bytes, order: 1 },\n { byteClass: 'unknown_output_contract', bytes: breakdown.unknown_output_contract_bytes, order: 2 },\n { byteClass: 'normal', bytes: breakdown.normal_bytes, order: 3 },\n ];\n entries.sort((left, right) => right.bytes - left.bytes || left.order - right.order);\n return entries[0]?.byteClass ?? 'normal';\n}\n\nfunction profileForSegments(\n segments: readonly NormalizedTokenBudgetSegment[],\n breakdown: TokenBudgetByteClassBreakdown,\n): TokenBudgetPromptProfile {\n let asciiWhitespaceBytes = 0;\n let whitespaceKnown = true;\n for (const segment of segments) {\n if (segment.kind === 'unknown_output_contract') continue;\n asciiWhitespaceBytes += segment.asciiWhitespaceBytes;\n if (!segment.whitespaceKnown) whitespaceKnown = false;\n }\n const concreteKnownBytes = breakdown.total_bytes - breakdown.unknown_output_contract_bytes;\n const whitespaceFraction =\n whitespaceKnown && concreteKnownBytes > 0\n ? Math.floor((asciiWhitespaceBytes * TOKEN_BUDGET_WHITESPACE_FRACTION_SCALE) / concreteKnownBytes)\n : null;\n return {\n ...breakdown,\n concrete_known_bytes: concreteKnownBytes,\n ascii_whitespace_bytes: asciiWhitespaceBytes,\n whitespace_fraction_x10000: whitespaceFraction,\n whitespace_fraction_scale: TOKEN_BUDGET_WHITESPACE_FRACTION_SCALE,\n whitespace_fraction_available: whitespaceKnown,\n dominant_byte_class: dominantByteClass(breakdown),\n };\n}\n\nfunction denseAsciiGate(profile: TokenBudgetPromptProfile): TokenBudgetDenseAsciiGate {\n const base = {\n heuristic: 'low_whitespace_fraction_proxy_not_tokenizer_bound' as const,\n corpus_min_whitespace_fraction_x10000:\n TOKEN_BUDGET_CALIBRATION_CORPUS_MIN_WHITESPACE_FRACTION_X10000,\n threshold_whitespace_fraction_x10000:\n TOKEN_BUDGET_DENSE_ASCII_WHITESPACE_THRESHOLD_X10000,\n measured_whitespace_fraction_x10000: profile.whitespace_fraction_x10000,\n };\n if (profile.concrete_known_bytes < TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES) {\n return {\n ...base,\n evaluated: false,\n out_of_distribution: false,\n decision: 'not_evaluated',\n reason: 'prompt_below_large_prompt_floor',\n };\n }\n if (profile.normal_bytes === 0 || profile.multibyte_bytes > profile.normal_bytes) {\n return {\n ...base,\n evaluated: false,\n out_of_distribution: false,\n decision: 'not_evaluated',\n reason: 'multibyte_or_non_ascii_dominant',\n };\n }\n if (!profile.whitespace_fraction_available || profile.whitespace_fraction_x10000 === null) {\n return {\n ...base,\n evaluated: true,\n out_of_distribution: true,\n decision: 'conservative_fallback',\n reason: 'whitespace_fraction_unavailable',\n };\n }\n if (profile.whitespace_fraction_x10000 < TOKEN_BUDGET_DENSE_ASCII_WHITESPACE_THRESHOLD_X10000) {\n return {\n ...base,\n evaluated: true,\n out_of_distribution: true,\n decision: 'conservative_fallback',\n reason: 'below_threshold',\n };\n }\n return {\n ...base,\n evaluated: true,\n out_of_distribution: false,\n decision: 'calibrated_allowed',\n reason: 'at_or_above_threshold',\n };\n}\n\nfunction rateSourceWarning(input: {\n source: TokenBudgetRateSource['source'];\n family: TokenBudgetFamily;\n profile: TokenBudgetPromptProfile;\n gate: TokenBudgetDenseAsciiGate;\n scope: TokenBudgetEstimatorScope;\n}): string | null {\n if (input.source === 'unknown_provider_floor') {\n return `unknown provider family uses the provable 1.00 B/tok floor; no calibration backs ${input.family}`;\n }\n if (input.source === 'unbacked_model_floor') {\n return `model is not in the exact calibration backing set for family ${input.family}; using the provable 1.00 B/tok floor`;\n }\n if (input.source === 'delegate_conservative') {\n return 'delegate launch/runtime uses the provable 1.00 B/tok profile when the prompt or route is below the backed large-prompt calibration domain';\n }\n if (input.source === 'explicit_conservative') {\n return 'explicit conservative scope uses the provable 1.00 B/tok profile';\n }\n if (input.source === 'conservative_small_prompt') {\n return `calibrated rate withheld because measured prompt bytes ${String(input.profile.concrete_known_bytes)} are below the ${String(TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES)}-byte calibration floor; using conservative profile`;\n }\n if (input.source === 'conservative_capacity_guard') {\n return `calibrated rate withheld because route capacity evaluated at the conservative rate cannot hold the ${String(TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES)}-byte calibration floor`;\n }\n if (input.source === 'conservative_dense_ascii_whitespace_gate') {\n if (input.gate.reason === 'whitespace_fraction_unavailable') {\n return 'calibrated rate withheld because known-text whitespace bytes were not supplied; provide asciiWhitespaceBytes from a one-pass UTF-8 measurement to use calibrated rates';\n }\n return `calibrated rate withheld because whitespace fraction ${String(input.gate.measured_whitespace_fraction_x10000 ?? 0)}/${String(TOKEN_BUDGET_WHITESPACE_FRACTION_SCALE)} is below the dense-ASCII gate ${String(TOKEN_BUDGET_DENSE_ASCII_WHITESPACE_THRESHOLD_X10000)}/${String(TOKEN_BUDGET_WHITESPACE_FRACTION_SCALE)}; this is a heuristic token-density proxy, not a bound`;\n }\n return null;\n}\n\nfunction effectiveRateSource(input: {\n family: TokenBudgetFamily;\n allowedInputTokens: number | undefined;\n scope: TokenBudgetEstimatorScope;\n profile: TokenBudgetPromptProfile;\n calibrationBacked: boolean;\n familyResolution: ResolvedTokenBudgetFamily['resolution'] | 'family_direct';\n}): TokenBudgetRateSource {\n const calibration = calibrationFor(input.family);\n const configured = calibration.rate_bytes_per_token_x100;\n const familyBacked = calibration.provenance.backed;\n const backed = familyBacked && input.calibrationBacked;\n const conservativeRate = conservativeFusionRate(configured);\n const gate = denseAsciiGate(input.profile);\n let source: TokenBudgetRateSource['source'];\n let effective: number;\n let calibrationApplied = false;\n\n if (!backed) {\n source = input.familyResolution === 'known_provider_unbacked_model'\n ? 'unbacked_model_floor'\n : 'unknown_provider_floor';\n effective = TOKEN_BUDGET_PROVABLE_RATE_X100;\n } else if (\n input.scope === 'delegate' ||\n (input.scope === 'delegate_launch' &&\n (input.profile.concrete_known_bytes < TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES ||\n (input.allowedInputTokens !== undefined &&\n Math.floor(\n (input.allowedInputTokens * TOKEN_BUDGET_DELEGATE_CONSERVATIVE_RATE_X100) /\n TOKEN_BUDGET_RATE_SCALE,\n ) < TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES)))\n ) {\n source = 'delegate_conservative';\n effective = Math.min(configured, TOKEN_BUDGET_DELEGATE_CONSERVATIVE_RATE_X100);\n } else if (input.scope === 'conservative') {\n source = 'explicit_conservative';\n effective = Math.min(configured, TOKEN_BUDGET_PROVABLE_RATE_X100);\n } else if (input.profile.concrete_known_bytes < TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES) {\n source = 'conservative_small_prompt';\n effective = conservativeRate;\n } else if (\n input.allowedInputTokens !== undefined &&\n Math.floor((input.allowedInputTokens * conservativeRate) / TOKEN_BUDGET_RATE_SCALE) <\n TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES\n ) {\n assertSafeNonNegativeInteger(input.allowedInputTokens, 'allowedInputTokens');\n source = 'conservative_capacity_guard';\n effective = conservativeRate;\n } else if (gate.out_of_distribution) {\n source = 'conservative_dense_ascii_whitespace_gate';\n effective = conservativeRate;\n } else {\n source = 'calibrated_large_window';\n effective = configured;\n calibrationApplied = true;\n }\n\n const dominant = gate.out_of_distribution && input.profile.normal_bytes >= input.profile.multibyte_bytes\n ? 'dense_ascii'\n : input.profile.dominant_byte_class;\n const rateSourceInput = {\n source,\n family: input.family,\n profile: input.profile,\n gate,\n scope: input.scope,\n };\n return {\n calibration_version: TOKEN_BUDGET_CALIBRATION_VERSION,\n family: input.family,\n configured_rate_bytes_per_token_x100: configured,\n effective_rate_bytes_per_token_x100: effective,\n conservative_rate_bytes_per_token_x100: conservativeRate,\n delegate_conservative_rate_bytes_per_token_x100: TOKEN_BUDGET_DELEGATE_CONSERVATIVE_RATE_X100,\n affine_f_tokens: calibration.affine_f_tokens,\n scope: input.scope,\n source,\n backed,\n provenance: calibration.provenance,\n model_resolution: input.familyResolution,\n scope_guard_min_bytes: TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES,\n calibration_applied: calibrationApplied,\n prompt_profile: { ...input.profile, dominant_byte_class: dominant },\n dense_ascii_gate: gate,\n dominant_byte_class: dominant,\n warning: rateSourceWarning(rateSourceInput),\n };\n}\n\ninterface MutableRateBucket {\n rate: number;\n bytes: number;\n classes: TokenBudgetDominantByteClass[];\n}\n\nfunction addBucket(\n buckets: Map<number, MutableRateBucket>,\n rate: number,\n bytes: number,\n byteClass: TokenBudgetDominantByteClass,\n): void {\n if (bytes === 0) return;\n const existing = buckets.get(rate);\n if (existing === undefined) {\n buckets.set(rate, { rate, bytes, classes: [byteClass] });\n return;\n }\n existing.bytes += bytes;\n if (!existing.classes.includes(byteClass)) existing.classes.push(byteClass);\n}\n\nfunction finalizeBuckets(buckets: Map<number, MutableRateBucket>): TokenBudgetRateBucketEstimate[] {\n return [...buckets.values()]\n .sort((left, right) => left.rate - right.rate)\n .map((bucket) => ({\n rate_bytes_per_token_x100: bucket.rate,\n bytes: bucket.bytes,\n tokens: tokensAtRate(bucket.bytes, bucket.rate),\n byte_classes: [...bucket.classes].sort(),\n }));\n}\n\nfunction bucketTokenTotal(buckets: readonly TokenBudgetRateBucketEstimate[]): number {\n return buckets.reduce((sum, bucket) => sum + bucket.tokens, 0);\n}\n\nexport function estimateInputTokens(input: EstimateInputTokensInput): EstimateInputTokensResult {\n const scope = input.scope ?? 'fusion';\n const normalized: NormalizedTokenBudgetSegment[] = [];\n const total: TokenBudgetByteClassBreakdown = {\n total_bytes: 0,\n normal_bytes: 0,\n multibyte_bytes: 0,\n dense_bytes: 0,\n unknown_output_contract_bytes: 0,\n };\n for (const [index, rawSegment] of input.segments.entries()) {\n const segment = normalizeSegment(rawSegment, index);\n const unknownBytes = segment.kind === 'unknown_output_contract' ? segment.bytes : 0;\n const normalBytes =\n segment.kind === 'unknown_output_contract'\n ? 0\n : segment.bytes - segment.multibyteBytes - segment.denseBytes;\n const breakdown: TokenBudgetByteClassBreakdown = {\n total_bytes: segment.bytes,\n normal_bytes: normalBytes,\n multibyte_bytes: segment.multibyteBytes,\n dense_bytes: segment.denseBytes,\n unknown_output_contract_bytes: unknownBytes,\n };\n addBreakdown(total, breakdown);\n normalized.push(segment);\n }\n if (input.allowedInputTokens !== undefined) {\n assertSafeNonNegativeInteger(input.allowedInputTokens, 'allowedInputTokens');\n }\n const profile = profileForSegments(normalized, total);\n const rateSource = effectiveRateSource({\n family: input.family,\n allowedInputTokens: input.allowedInputTokens,\n scope,\n profile,\n calibrationBacked: input.calibrationBacked ?? true,\n familyResolution: input.familyResolution ?? 'family_direct',\n });\n\n const perSegment: TokenBudgetPerSegmentEstimate[] = [];\n const fatalBuckets = new Map<number, MutableRateBucket>();\n const advisoryBuckets = new Map<number, MutableRateBucket>();\n let multibyteAdvisoryTotal = 0;\n\n for (const segment of normalized) {\n const unknownBytes = segment.kind === 'unknown_output_contract' ? segment.bytes : 0;\n const normalBytes =\n segment.kind === 'unknown_output_contract'\n ? 0\n : segment.bytes - segment.multibyteBytes - segment.denseBytes;\n const normalRate =\n segment.kind === 'unknown_output_contract'\n ? TOKEN_BUDGET_PROVABLE_RATE_X100\n : rateSource.effective_rate_bytes_per_token_x100;\n const normalTokens = tokensAtRate(normalBytes, normalRate);\n const unknownTokens = tokensAtRate(unknownBytes, TOKEN_BUDGET_PROVABLE_RATE_X100);\n const multibyteTokens = tokensAtRate(segment.multibyteBytes, TOKEN_BUDGET_MULTIBYTE_FATAL_RATE_X100);\n const multibyteProvableTokens = tokensAtRate(segment.multibyteBytes, TOKEN_BUDGET_PROVABLE_RATE_X100);\n const denseTokens = tokensAtRate(segment.denseBytes, TOKEN_BUDGET_PROVABLE_RATE_X100);\n const tokens = normalTokens + unknownTokens + multibyteTokens + denseTokens;\n const breakdown: TokenBudgetByteClassBreakdown = {\n total_bytes: segment.bytes,\n normal_bytes: normalBytes,\n multibyte_bytes: segment.multibyteBytes,\n dense_bytes: segment.denseBytes,\n unknown_output_contract_bytes: unknownBytes,\n };\n addBucket(fatalBuckets, normalRate, normalBytes, 'normal');\n addBucket(fatalBuckets, TOKEN_BUDGET_MULTIBYTE_FATAL_RATE_X100, segment.multibyteBytes, 'multibyte');\n addBucket(fatalBuckets, TOKEN_BUDGET_PROVABLE_RATE_X100, segment.denseBytes, 'dense_ascii');\n addBucket(fatalBuckets, TOKEN_BUDGET_PROVABLE_RATE_X100, unknownBytes, 'unknown_output_contract');\n addBucket(advisoryBuckets, normalRate, normalBytes, 'normal');\n addBucket(advisoryBuckets, TOKEN_BUDGET_PROVABLE_RATE_X100, segment.multibyteBytes, 'multibyte');\n addBucket(advisoryBuckets, TOKEN_BUDGET_PROVABLE_RATE_X100, segment.denseBytes, 'dense_ascii');\n addBucket(advisoryBuckets, TOKEN_BUDGET_PROVABLE_RATE_X100, unknownBytes, 'unknown_output_contract');\n multibyteAdvisoryTotal += multibyteProvableTokens;\n perSegment.push({\n kind: segment.kind,\n ...breakdown,\n ascii_whitespace_bytes: segment.asciiWhitespaceBytes,\n normal_rate_bytes_per_token_x100: normalRate,\n normal_tokens: normalTokens,\n multibyte_rate_bytes_per_token_x100: TOKEN_BUDGET_MULTIBYTE_FATAL_RATE_X100,\n multibyte_tokens: multibyteTokens,\n multibyte_provable_tokens: multibyteProvableTokens,\n dense_tokens: denseTokens,\n unknown_output_contract_tokens: unknownTokens,\n tokens,\n });\n }\n const rateBuckets = finalizeBuckets(fatalBuckets);\n const advisoryRateBuckets = finalizeBuckets(advisoryBuckets);\n const variableTokenTotal = bucketTokenTotal(rateBuckets);\n return {\n tokens: variableTokenTotal + rateSource.affine_f_tokens,\n fixed_tokens: rateSource.affine_f_tokens,\n perSegment,\n byte_class_breakdown: total,\n rate_buckets: rateBuckets,\n advisory: {\n multibyte_provable_rate_bytes_per_token_x100: TOKEN_BUDGET_PROVABLE_RATE_X100,\n multibyte_provable_tokens: multibyteAdvisoryTotal,\n input_tokens_if_multibyte_used_provable_ceiling:\n bucketTokenTotal(advisoryRateBuckets) + rateSource.affine_f_tokens,\n rate_buckets: advisoryRateBuckets,\n },\n rateSource,\n };\n}\n\nexport function utf8ByteLength(value: string): number {\n return Buffer.byteLength(value, 'utf8');\n}\n\nfunction isAsciiWhitespace(byte: number): boolean {\n return byte === 0x20 || (byte >= 0x09 && byte <= 0x0d);\n}\n\nexport function utf8ByteClassBreakdown(value: string): {\n bytes: number;\n multibyteBytes: number;\n denseBytes: 0;\n asciiWhitespaceBytes: number;\n} {\n const bytes = Buffer.from(value, 'utf8');\n let multibyteBytes = 0;\n let asciiWhitespaceBytes = 0;\n for (const byte of bytes) {\n if (byte >= 0x80) multibyteBytes += 1;\n else if (isAsciiWhitespace(byte)) asciiWhitespaceBytes += 1;\n }\n return { bytes: bytes.length, multibyteBytes, denseBytes: 0, asciiWhitespaceBytes };\n}\n\nexport function knownTextSegment(value: string): TokenBudgetSegment {\n const breakdown = utf8ByteClassBreakdown(value);\n return {\n kind: 'known_text',\n bytes: breakdown.bytes,\n multibyteBytes: breakdown.multibyteBytes,\n denseBytes: breakdown.denseBytes,\n asciiWhitespaceBytes: breakdown.asciiWhitespaceBytes,\n };\n}\n\nexport function knownJsonSegment(value: string): TokenBudgetSegment {\n const breakdown = utf8ByteClassBreakdown(value);\n return {\n kind: 'known_json',\n bytes: breakdown.bytes,\n multibyteBytes: breakdown.multibyteBytes,\n denseBytes: breakdown.denseBytes,\n asciiWhitespaceBytes: breakdown.asciiWhitespaceBytes,\n };\n}\n\nexport function unknownOutputContractSegment(bytes: number): TokenBudgetSegment {\n assertSafeNonNegativeInteger(bytes, 'unknown output contract bytes');\n return { kind: 'unknown_output_contract', bytes, denseBytes: 0 };\n}\n\nexport function tokenUpperBound(utf8Bytes: number): number {\n return estimateInputTokens({\n family: 'unknown',\n scope: 'conservative',\n calibrationBacked: false,\n segments: [{ kind: 'known_text', bytes: utf8Bytes, multibyteBytes: 0, denseBytes: 0 }],\n }).tokens;\n}\n\nexport function maxKnownTextBytesForTokens(input: {\n family: TokenBudgetFamily;\n allowedInputTokens: number;\n scope?: TokenBudgetEstimatorScope | undefined;\n calibrationBacked?: boolean | undefined;\n familyResolution?: ResolvedTokenBudgetFamily['resolution'] | 'family_direct' | undefined;\n}): number {\n assertSafeNonNegativeInteger(input.allowedInputTokens, 'allowedInputTokens');\n const rate = effectiveRateSource({\n family: input.family,\n allowedInputTokens: input.allowedInputTokens,\n scope: input.scope ?? 'fusion',\n profile: profileForSegments([], {\n total_bytes: 0,\n normal_bytes: 0,\n multibyte_bytes: 0,\n dense_bytes: 0,\n unknown_output_contract_bytes: 0,\n }),\n calibrationBacked: input.calibrationBacked ?? true,\n familyResolution: input.familyResolution ?? 'family_direct',\n });\n const variableTokens = input.allowedInputTokens - rate.affine_f_tokens;\n if (variableTokens <= 0) return 0;\n return Math.floor((variableTokens * rate.effective_rate_bytes_per_token_x100) / TOKEN_BUDGET_RATE_SCALE);\n}\n\nexport interface RouteReserves {\n reservedOutputTokens: number;\n framingReserveTokens: number;\n safetyReserveTokens: number;\n}\n\n/**\n * Usable input tokens for one route.\n *\n * Returns a signed value. A caller that requires a minimum must check it and\n * fail loudly; this helper never clamps, never substitutes a default window, and\n * never silently returns zero for an unusable route.\n */\nexport function allowedInputTokens(contextWindowTokens: number, reserves: RouteReserves): number {\n return (\n contextWindowTokens -\n reserves.reservedOutputTokens -\n reserves.framingReserveTokens -\n reserves.safetyReserveTokens\n );\n}\n\n/** True only for a positive, finite, integral context window. */\nexport function isUsableContextWindow(value: number): boolean {\n return Number.isFinite(value) && Number.isInteger(value) && value > 0;\n}\n"]}
@@ -0,0 +1,390 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { canonicalJson } from '../canonical-json.js';
3
+ /**
4
+ * Frozen `visible-conversation-ledger-v2` transform.
5
+ *
6
+ * This is the single shared implementation of the package's conversation
7
+ * projection: visible user/assistant text verbatim, assistant thinking and all
8
+ * tool traffic replaced with deterministic hash-accounted omission receipts,
9
+ * images marker-only, unknown block types a loud error.
10
+ *
11
+ * The transform has **no behavioural knobs**. Every consumer receives exactly
12
+ * the same disposition for exactly the same input. Consumer identity — schema
13
+ * versions, policy ids, request authority, branch-filter provenance — lives
14
+ * entirely outside this module, so a consumer can never claim behaviour that did
15
+ * not occur. A semantic change requires a new transform id and a new
16
+ * implementation, never a flag added here.
17
+ *
18
+ * Fusion's persisted artifact bytes are frozen against this implementation and
19
+ * are proven bit-identical by `tests/unit/fusion-golden-bytes.test.ts`.
20
+ */
21
+ export const VISIBLE_CONVERSATION_TRANSFORM_ID = 'visible-conversation-ledger-v2';
22
+ export const CONVERSATION_IMAGE_OMISSION_PREFIX = '[Image omitted from fusion text transcript: ';
23
+ export const OMITTED_EVENT_KINDS = [
24
+ 'assistant_thinking',
25
+ 'tool_call',
26
+ 'tool_result_text',
27
+ 'tool_result_image',
28
+ ];
29
+ /** Raised when the transform meets a conversation block it refuses to silently drop. */
30
+ export class UnsupportedConversationBlockError extends Error {
31
+ label;
32
+ constructor(label) {
33
+ super(`fusion context projection encountered an unsupported conversation block: ${label}`);
34
+ this.name = 'UnsupportedConversationBlockError';
35
+ this.label = label;
36
+ }
37
+ }
38
+ function utf8Bytes(value) {
39
+ return Buffer.byteLength(value, 'utf8');
40
+ }
41
+ function sha256Hex(bytes) {
42
+ return createHash('sha256').update(bytes).digest('hex');
43
+ }
44
+ function uint64be(value) {
45
+ const out = Buffer.alloc(8);
46
+ out.writeBigUInt64BE(BigInt(value));
47
+ return out;
48
+ }
49
+ /** Length-prefixed framing so concatenated fields cannot collide across boundaries. */
50
+ function lengthPrefixed(bytes) {
51
+ return Buffer.concat([uint64be(bytes.length), bytes]);
52
+ }
53
+ function ledgerLeafHash(index, record) {
54
+ return createHash('sha256')
55
+ .update(Buffer.from('pi-fusion-ledger-leaf-v1\0', 'utf8'))
56
+ .update(uint64be(index))
57
+ .update(lengthPrefixed(Buffer.from(canonicalJson(record), 'utf8')))
58
+ .digest();
59
+ }
60
+ function ledgerRootHash(leaves) {
61
+ const hash = createHash('sha256')
62
+ .update(Buffer.from('pi-fusion-ledger-root-v1\0', 'utf8'))
63
+ .update(uint64be(leaves.length));
64
+ for (const leaf of leaves)
65
+ hash.update(leaf);
66
+ return hash.digest('hex');
67
+ }
68
+ function unsupportedBlock(label) {
69
+ return new UnsupportedConversationBlockError(label);
70
+ }
71
+ /**
72
+ * Fixed policy rule: a zero-valued kind is absent from the receipt rather than
73
+ * serialized as `0`. This keeps receipts compact without losing information —
74
+ * absent is defined by the policy version to mean exactly zero — and it is
75
+ * applied unconditionally, never adaptively because an input happens to be large.
76
+ */
77
+ function compactCounts(counts) {
78
+ const out = {};
79
+ if (counts.assistant_thinking > 0)
80
+ out.assistant_thinking = counts.assistant_thinking;
81
+ if (counts.tool_calls > 0)
82
+ out.tool_calls = counts.tool_calls;
83
+ if (counts.tool_result_texts > 0)
84
+ out.tool_result_texts = counts.tool_result_texts;
85
+ return out;
86
+ }
87
+ function imageMarker(mimeType) {
88
+ return `${CONVERSATION_IMAGE_OMISSION_PREFIX}${mimeType}]`;
89
+ }
90
+ /**
91
+ * Accumulates omitted-event ledger rows and turns maximal contiguous non-image
92
+ * omission runs into compact, source-ordered receipts inside the projection.
93
+ */
94
+ class ProjectionBuilder {
95
+ entries = [];
96
+ ledger = [];
97
+ leaves = [];
98
+ projectionMap = [];
99
+ toolCallNames = new Map();
100
+ pendingCounts;
101
+ pendingBytes = 0;
102
+ pendingLedgerFirst = 0;
103
+ pendingLedgerLast = 0;
104
+ pendingSourceFirst = 0;
105
+ pendingSourceLast = 0;
106
+ includedUserTextBytes = 0;
107
+ includedAssistantTextBytes = 0;
108
+ includedImageMarkers = 0;
109
+ emptyTextBlocks = 0;
110
+ addText(entry) {
111
+ this.flush();
112
+ this.entries.push(entry);
113
+ if (entry.role === 'user')
114
+ this.includedUserTextBytes += utf8Bytes(entry.text);
115
+ else
116
+ this.includedAssistantTextBytes += utf8Bytes(entry.text);
117
+ }
118
+ addOmission(sourceOrdinal, blockOrdinal, kind, payload, extra = {}) {
119
+ const index = this.ledger.length;
120
+ const record = {
121
+ index,
122
+ source_ordinal: sourceOrdinal,
123
+ block_ordinal: blockOrdinal,
124
+ kind,
125
+ payload_bytes: payload.length,
126
+ payload_sha256: sha256Hex(payload),
127
+ };
128
+ if (extra.toolName !== undefined)
129
+ record.tool_name = extra.toolName;
130
+ if (extra.toolCallId !== undefined)
131
+ record.tool_call_id = extra.toolCallId;
132
+ if (extra.mimeType !== undefined)
133
+ record.mime_type = extra.mimeType;
134
+ this.ledger.push(record);
135
+ this.leaves.push(ledgerLeafHash(index, record));
136
+ if (extra.toolName !== undefined && kind === 'tool_call') {
137
+ this.toolCallNames.set(extra.toolName, (this.toolCallNames.get(extra.toolName) ?? 0) + 1);
138
+ }
139
+ if (kind === 'tool_result_image') {
140
+ this.flush();
141
+ this.addLedgerOnlyImageMap(index);
142
+ return;
143
+ }
144
+ if (this.pendingCounts === undefined) {
145
+ this.pendingCounts = {
146
+ assistant_thinking: 0,
147
+ tool_calls: 0,
148
+ tool_result_texts: 0,
149
+ };
150
+ this.pendingBytes = 0;
151
+ this.pendingLedgerFirst = index;
152
+ this.pendingSourceFirst = sourceOrdinal;
153
+ }
154
+ this.pendingLedgerLast = index;
155
+ this.pendingSourceLast = sourceOrdinal;
156
+ this.pendingBytes += payload.length;
157
+ if (kind === 'assistant_thinking')
158
+ this.pendingCounts.assistant_thinking += 1;
159
+ else if (kind === 'tool_call')
160
+ this.pendingCounts.tool_calls += 1;
161
+ else
162
+ this.pendingCounts.tool_result_texts += 1;
163
+ }
164
+ addLedgerOnlyImageMap(index) {
165
+ const previous = this.projectionMap[this.projectionMap.length - 1];
166
+ if (previous !== undefined &&
167
+ previous.entry_kind === 'ledger_only_tool_result_image' &&
168
+ previous.ledger_index_last + 1 === index) {
169
+ previous.ledger_index_last = index;
170
+ return;
171
+ }
172
+ this.projectionMap.push({
173
+ entry_kind: 'ledger_only_tool_result_image',
174
+ ledger_index_first: index,
175
+ ledger_index_last: index,
176
+ });
177
+ }
178
+ flush() {
179
+ const counts = this.pendingCounts;
180
+ if (counts === undefined)
181
+ return;
182
+ const canonicalEntryIndex = this.entries.length;
183
+ const entry = {
184
+ at: [this.pendingSourceFirst, this.pendingSourceLast],
185
+ bytes: this.pendingBytes,
186
+ counts: compactCounts(counts),
187
+ kind: 'omitted_activity',
188
+ };
189
+ this.entries.push(entry);
190
+ this.projectionMap.push({
191
+ canonical_entry_index: canonicalEntryIndex,
192
+ entry_kind: 'omitted_activity',
193
+ ledger_index_first: this.pendingLedgerFirst,
194
+ ledger_index_last: this.pendingLedgerLast,
195
+ });
196
+ this.pendingCounts = undefined;
197
+ this.pendingBytes = 0;
198
+ }
199
+ finish(messageCount) {
200
+ this.flush();
201
+ const rootSha256 = ledgerRootHash(this.leaves);
202
+ let omittedRunCount = 0;
203
+ let includedTextEntries = 0;
204
+ let receiptBytes = 0;
205
+ for (const entry of this.entries) {
206
+ if (entry.kind === 'text')
207
+ includedTextEntries += 1;
208
+ else {
209
+ omittedRunCount += 1;
210
+ receiptBytes += utf8Bytes(canonicalJson(entry));
211
+ }
212
+ }
213
+ let thinkingBytes = 0;
214
+ let toolCallCount = 0;
215
+ let toolArgumentBytes = 0;
216
+ let toolResultTextCount = 0;
217
+ let toolResultTextBytes = 0;
218
+ let toolResultImageCount = 0;
219
+ let toolResultImageBytes = 0;
220
+ for (const row of this.ledger) {
221
+ if (row.kind === 'assistant_thinking')
222
+ thinkingBytes += row.payload_bytes;
223
+ else if (row.kind === 'tool_call') {
224
+ toolCallCount += 1;
225
+ toolArgumentBytes += row.payload_bytes;
226
+ }
227
+ else if (row.kind === 'tool_result_text') {
228
+ toolResultTextCount += 1;
229
+ toolResultTextBytes += row.payload_bytes;
230
+ }
231
+ else {
232
+ toolResultImageCount += 1;
233
+ toolResultImageBytes += row.payload_bytes;
234
+ }
235
+ }
236
+ const toolCallNames = [...this.toolCallNames.entries()]
237
+ .map(([name, calls]) => ({ name, calls }))
238
+ .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
239
+ const accounting = {
240
+ message_count: messageCount,
241
+ included_text_entry_count: includedTextEntries,
242
+ included_user_text_bytes: this.includedUserTextBytes,
243
+ included_assistant_text_bytes: this.includedAssistantTextBytes,
244
+ included_image_marker_count: this.includedImageMarkers,
245
+ empty_text_block_count: this.emptyTextBlocks,
246
+ omitted_run_count: omittedRunCount,
247
+ omitted_event_count: this.ledger.length,
248
+ omitted_thinking_bytes: thinkingBytes,
249
+ omitted_tool_call_count: toolCallCount,
250
+ omitted_tool_call_argument_bytes: toolArgumentBytes,
251
+ omitted_tool_result_text_count: toolResultTextCount,
252
+ omitted_tool_result_text_bytes: toolResultTextBytes,
253
+ omitted_tool_result_image_count: toolResultImageCount,
254
+ omitted_tool_result_image_bytes: toolResultImageBytes,
255
+ tool_call_names: toolCallNames,
256
+ ledger_entry_count: this.ledger.length,
257
+ ledger_root_sha256: rootSha256,
258
+ omission_receipt_utf8_bytes: receiptBytes,
259
+ };
260
+ return {
261
+ entries: this.entries,
262
+ accounting,
263
+ ledger: {
264
+ entries: this.ledger,
265
+ projection_map: this.projectionMap,
266
+ root_sha256: rootSha256,
267
+ },
268
+ };
269
+ }
270
+ }
271
+ /**
272
+ * Projects one user-role message. User text is retained verbatim; images stay
273
+ * marker-only so the child never receives raw bytes.
274
+ */
275
+ function projectUserMessage(builder, content, sourceOrdinal) {
276
+ if (typeof content === 'string') {
277
+ if (content.length === 0) {
278
+ builder.emptyTextBlocks += 1;
279
+ return;
280
+ }
281
+ builder.addText({
282
+ kind: 'text',
283
+ source_ordinal: sourceOrdinal,
284
+ block_ordinal: 0,
285
+ role: 'user',
286
+ text: content,
287
+ });
288
+ return;
289
+ }
290
+ for (const [blockOrdinal, block] of content.entries()) {
291
+ if (block.type === 'text') {
292
+ if (block.text.length === 0) {
293
+ builder.emptyTextBlocks += 1;
294
+ continue;
295
+ }
296
+ builder.addText({
297
+ kind: 'text',
298
+ source_ordinal: sourceOrdinal,
299
+ block_ordinal: blockOrdinal,
300
+ role: 'user',
301
+ text: block.text,
302
+ });
303
+ continue;
304
+ }
305
+ if (block.type === 'image') {
306
+ builder.includedImageMarkers += 1;
307
+ builder.addText({
308
+ kind: 'text',
309
+ source_ordinal: sourceOrdinal,
310
+ block_ordinal: blockOrdinal,
311
+ role: 'user',
312
+ text: imageMarker(block.mimeType),
313
+ });
314
+ continue;
315
+ }
316
+ throw unsupportedBlock(`user block ${String(Reflect.get(block, 'type'))}`);
317
+ }
318
+ }
319
+ function projectAssistantMessage(builder, content, sourceOrdinal) {
320
+ for (const [blockOrdinal, block] of content.entries()) {
321
+ if (block.type === 'text') {
322
+ if (block.text.length === 0) {
323
+ builder.emptyTextBlocks += 1;
324
+ continue;
325
+ }
326
+ builder.addText({
327
+ kind: 'text',
328
+ source_ordinal: sourceOrdinal,
329
+ block_ordinal: blockOrdinal,
330
+ role: 'assistant',
331
+ text: block.text,
332
+ });
333
+ continue;
334
+ }
335
+ if (block.type === 'thinking') {
336
+ builder.addOmission(sourceOrdinal, blockOrdinal, 'assistant_thinking', Buffer.from(block.thinking, 'utf8'));
337
+ continue;
338
+ }
339
+ if (block.type === 'toolCall') {
340
+ builder.addOmission(sourceOrdinal, blockOrdinal, 'tool_call', Buffer.from(canonicalJson(block.arguments), 'utf8'), { toolName: block.name, toolCallId: block.id });
341
+ continue;
342
+ }
343
+ throw unsupportedBlock(`assistant block ${String(Reflect.get(block, 'type'))}`);
344
+ }
345
+ }
346
+ function projectToolResultMessage(builder, message, sourceOrdinal) {
347
+ const content = message.content;
348
+ if (typeof content === 'string') {
349
+ builder.addOmission(sourceOrdinal, 0, 'tool_result_text', Buffer.from(content, 'utf8'), {
350
+ toolName: message.toolName,
351
+ toolCallId: message.toolCallId,
352
+ });
353
+ return;
354
+ }
355
+ for (const [blockOrdinal, block] of content.entries()) {
356
+ if (block.type === 'text') {
357
+ builder.addOmission(sourceOrdinal, blockOrdinal, 'tool_result_text', Buffer.from(block.text, 'utf8'), { toolName: message.toolName, toolCallId: message.toolCallId });
358
+ continue;
359
+ }
360
+ if (block.type === 'image') {
361
+ builder.addOmission(sourceOrdinal, blockOrdinal, 'tool_result_image', Buffer.from(block.data, 'utf8'), {
362
+ toolName: message.toolName,
363
+ toolCallId: message.toolCallId,
364
+ mimeType: block.mimeType,
365
+ });
366
+ continue;
367
+ }
368
+ throw unsupportedBlock(`tool result block ${String(Reflect.get(block, 'type'))}`);
369
+ }
370
+ }
371
+ /**
372
+ * Deterministic conversation projection. Every retained source block receives
373
+ * exactly one disposition: included verbatim, or represented as an omission
374
+ * ledger row. Unknown block types fail loudly instead of disappearing.
375
+ */
376
+ export function projectVisibleConversationV2(messages) {
377
+ const builder = new ProjectionBuilder();
378
+ for (const [sourceOrdinal, message] of messages.entries()) {
379
+ if (message.role === 'user')
380
+ projectUserMessage(builder, message.content, sourceOrdinal);
381
+ else if (message.role === 'assistant')
382
+ projectAssistantMessage(builder, message.content, sourceOrdinal);
383
+ else if (message.role === 'toolResult')
384
+ projectToolResultMessage(builder, message, sourceOrdinal);
385
+ else
386
+ throw unsupportedBlock(`message role ${String(Reflect.get(message, 'role'))}`);
387
+ }
388
+ return builder.finish(messages.length);
389
+ }
390
+ //# sourceMappingURL=visible-conversation-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visible-conversation-v2.js","sourceRoot":"","sources":["../../../../src/core/context/visible-conversation-v2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,gCAAgC,CAAC;AAElF,MAAM,CAAC,MAAM,kCAAkC,GAAG,8CAA8C,CAAC;AAEjG,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,oBAAoB;IACpB,WAAW;IACX,kBAAkB;IAClB,mBAAmB;CACX,CAAC;AA0GX,wFAAwF;AACxF,MAAM,OAAO,iCAAkC,SAAQ,KAAK;IACjD,KAAK,CAAS;IAEvB,YAAY,KAAa;QACvB,KAAK,CAAC,4EAA4E,KAAK,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC,IAAI,GAAG,mCAAmC,CAAC;QAChD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACpC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,uFAAuF;AACvF,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,cAAc,CAAC,KAAa,EAAE,MAA0B;IAC/D,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,MAAM,CAAC,CAAC;SACzD,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SACvB,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;SAClE,MAAM,EAAE,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,MAAyB;IAC/C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC;SAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,MAAM,CAAC,CAAC;SACzD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,MAAM;QAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAO,IAAI,iCAAiC,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAC,MAAkC;IACvD,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,IAAI,MAAM,CAAC,kBAAkB,GAAG,CAAC;QAAE,GAAG,CAAC,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,CAAC;IACtF,IAAI,MAAM,CAAC,UAAU,GAAG,CAAC;QAAE,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAC9D,IAAI,MAAM,CAAC,iBAAiB,GAAG,CAAC;QAAE,GAAG,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACnF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB;IACnC,OAAO,GAAG,kCAAkC,GAAG,QAAQ,GAAG,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,iBAAiB;IACJ,OAAO,GAAsB,EAAE,CAAC;IAChC,MAAM,GAAyB,EAAE,CAAC;IAClC,MAAM,GAAa,EAAE,CAAC;IACtB,aAAa,GAAgC,EAAE,CAAC;IAChD,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnD,aAAa,CAAyC;IACtD,YAAY,GAAG,CAAC,CAAC;IACjB,kBAAkB,GAAG,CAAC,CAAC;IACvB,iBAAiB,GAAG,CAAC,CAAC;IACtB,kBAAkB,GAAG,CAAC,CAAC;IACvB,iBAAiB,GAAG,CAAC,CAAC;IAE9B,qBAAqB,GAAG,CAAC,CAAC;IAC1B,0BAA0B,GAAG,CAAC,CAAC;IAC/B,oBAAoB,GAAG,CAAC,CAAC;IACzB,eAAe,GAAG,CAAC,CAAC;IAEpB,OAAO,CAAC,KAA0B;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,IAAI,CAAC,qBAAqB,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;;YAC1E,IAAI,CAAC,0BAA0B,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,WAAW,CACT,aAAqB,EACrB,YAAoB,EACpB,IAAsB,EACtB,OAAe,EACf,QAAuE,EAAE;QAEzE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACjC,MAAM,MAAM,GAAuB;YACjC,KAAK;YACL,cAAc,EAAE,aAAa;YAC7B,aAAa,EAAE,YAAY;YAC3B,IAAI;YACJ,aAAa,EAAE,OAAO,CAAC,MAAM;YAC7B,cAAc,EAAE,SAAS,CAAC,OAAO,CAAC;SACnC,CAAC;QACF,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC;QACpE,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;YAAE,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC;QAC3E,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC;QACpE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QAEhD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5F,CAAC;QAED,IAAI,IAAI,KAAK,mBAAmB,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC,aAAa,GAAG;gBACnB,kBAAkB,EAAE,CAAC;gBACrB,UAAU,EAAE,CAAC;gBACb,iBAAiB,EAAE,CAAC;aACrB,CAAC;YACF,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;YAChC,IAAI,CAAC,kBAAkB,GAAG,aAAa,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC,iBAAiB,GAAG,aAAa,CAAC;QACvC,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;QACpC,IAAI,IAAI,KAAK,oBAAoB;YAAE,IAAI,CAAC,aAAa,CAAC,kBAAkB,IAAI,CAAC,CAAC;aACzE,IAAI,IAAI,KAAK,WAAW;YAAE,IAAI,CAAC,aAAa,CAAC,UAAU,IAAI,CAAC,CAAC;;YAC7D,IAAI,CAAC,aAAa,CAAC,iBAAiB,IAAI,CAAC,CAAC;IACjD,CAAC;IAEO,qBAAqB,CAAC,KAAa;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnE,IACE,QAAQ,KAAK,SAAS;YACtB,QAAQ,CAAC,UAAU,KAAK,+BAA+B;YACvD,QAAQ,CAAC,iBAAiB,GAAG,CAAC,KAAK,KAAK,EACxC,CAAC;YACD,QAAQ,CAAC,iBAAiB,GAAG,KAAK,CAAC;YACnC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YACtB,UAAU,EAAE,+BAA+B;YAC3C,kBAAkB,EAAE,KAAK;YACzB,iBAAiB,EAAE,KAAK;SACzB,CAAC,CAAC;IACL,CAAC;IAEO,KAAK;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC;QAClC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO;QACjC,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAChD,MAAM,KAAK,GAA4B;YACrC,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,iBAAiB,CAAC;YACrD,KAAK,EAAE,IAAI,CAAC,YAAY;YACxB,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;YAC7B,IAAI,EAAE,kBAAkB;SACzB,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YACtB,qBAAqB,EAAE,mBAAmB;YAC1C,UAAU,EAAE,kBAAkB;YAC9B,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;SAC1C,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,YAAoB;QACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,eAAe,GAAG,CAAC,CAAC;QACxB,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,mBAAmB,IAAI,CAAC,CAAC;iBAC/C,CAAC;gBACJ,eAAe,IAAI,CAAC,CAAC;gBACrB,YAAY,IAAI,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QACD,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9B,IAAI,GAAG,CAAC,IAAI,KAAK,oBAAoB;gBAAE,aAAa,IAAI,GAAG,CAAC,aAAa,CAAC;iBACrE,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAClC,aAAa,IAAI,CAAC,CAAC;gBACnB,iBAAiB,IAAI,GAAG,CAAC,aAAa,CAAC;YACzC,CAAC;iBAAM,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC3C,mBAAmB,IAAI,CAAC,CAAC;gBACzB,mBAAmB,IAAI,GAAG,CAAC,aAAa,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,oBAAoB,IAAI,CAAC,CAAC;gBAC1B,oBAAoB,IAAI,GAAG,CAAC,aAAa,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,MAAM,aAAa,GAAwB,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;aACzE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;aACzC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzF,MAAM,UAAU,GAAyB;YACvC,aAAa,EAAE,YAAY;YAC3B,yBAAyB,EAAE,mBAAmB;YAC9C,wBAAwB,EAAE,IAAI,CAAC,qBAAqB;YACpD,6BAA6B,EAAE,IAAI,CAAC,0BAA0B;YAC9D,2BAA2B,EAAE,IAAI,CAAC,oBAAoB;YACtD,sBAAsB,EAAE,IAAI,CAAC,eAAe;YAC5C,iBAAiB,EAAE,eAAe;YAClC,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YACvC,sBAAsB,EAAE,aAAa;YACrC,uBAAuB,EAAE,aAAa;YACtC,gCAAgC,EAAE,iBAAiB;YACnD,8BAA8B,EAAE,mBAAmB;YACnD,8BAA8B,EAAE,mBAAmB;YACnD,+BAA+B,EAAE,oBAAoB;YACrD,+BAA+B,EAAE,oBAAoB;YACrD,eAAe,EAAE,aAAa;YAC9B,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YACtC,kBAAkB,EAAE,UAAU;YAC9B,2BAA2B,EAAE,YAAY;SAC1C,CAAC;QACF,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,IAAI,CAAC,MAAM;gBACpB,cAAc,EAAE,IAAI,CAAC,aAAa;gBAClC,WAAW,EAAE,UAAU;aACxB;SACF,CAAC;IACJ,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,kBAAkB,CACzB,OAA0B,EAC1B,OAA2B,EAC3B,aAAqB;IAErB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,OAAO,CAAC,OAAO,CAAC;YACd,IAAI,EAAE,MAAM;YACZ,cAAc,EAAE,aAAa;YAC7B,aAAa,EAAE,CAAC;YAChB,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACtD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;YACD,OAAO,CAAC,OAAO,CAAC;gBACd,IAAI,EAAE,MAAM;gBACZ,cAAc,EAAE,aAAa;gBAC7B,aAAa,EAAE,YAAY;gBAC3B,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,oBAAoB,IAAI,CAAC,CAAC;YAClC,OAAO,CAAC,OAAO,CAAC;gBACd,IAAI,EAAE,MAAM;gBACZ,cAAc,EAAE,aAAa;gBAC7B,aAAa,EAAE,YAAY;gBAC3B,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC;aAClC,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,gBAAgB,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAC9B,OAA0B,EAC1B,OAA2D,EAC3D,aAAqB;IAErB,KAAK,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACtD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;YACD,OAAO,CAAC,OAAO,CAAC;gBACd,IAAI,EAAE,MAAM;gBACZ,cAAc,EAAE,aAAa;gBAC7B,aAAa,EAAE,YAAY;gBAC3B,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC9B,OAAO,CAAC,WAAW,CACjB,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CACpC,CAAC;YACF,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC9B,OAAO,CAAC,WAAW,CACjB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,EACnD,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,CAC/C,CAAC;YACF,SAAS;QACX,CAAC;QACD,MAAM,gBAAgB,CAAC,mBAAmB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAC/B,OAA0B,EAC1B,OAAiD,EACjD,aAAqB;IAErB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC,EAAE,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;YACtF,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACtD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,OAAO,CAAC,WAAW,CACjB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,EAC/B,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAC/D,CAAC;YACF,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,WAAW,CACjB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,EAC/B;gBACE,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CACF,CAAC;YACF,SAAS;QACX,CAAC;QACD,MAAM,gBAAgB,CAAC,qBAAqB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;YAAE,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;aACpF,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;YACnC,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;aAC9D,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY;YACpC,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;;YACvD,MAAM,gBAAgB,CAAC,gBAAgB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC","sourcesContent":["import { createHash } from 'node:crypto';\nimport type { Message } from '@earendil-works/pi-ai';\nimport { canonicalJson } from '../canonical-json.js';\n\n/**\n * Frozen `visible-conversation-ledger-v2` transform.\n *\n * This is the single shared implementation of the package's conversation\n * projection: visible user/assistant text verbatim, assistant thinking and all\n * tool traffic replaced with deterministic hash-accounted omission receipts,\n * images marker-only, unknown block types a loud error.\n *\n * The transform has **no behavioural knobs**. Every consumer receives exactly\n * the same disposition for exactly the same input. Consumer identity — schema\n * versions, policy ids, request authority, branch-filter provenance — lives\n * entirely outside this module, so a consumer can never claim behaviour that did\n * not occur. A semantic change requires a new transform id and a new\n * implementation, never a flag added here.\n *\n * Fusion's persisted artifact bytes are frozen against this implementation and\n * are proven bit-identical by `tests/unit/fusion-golden-bytes.test.ts`.\n */\nexport const VISIBLE_CONVERSATION_TRANSFORM_ID = 'visible-conversation-ledger-v2';\n\nexport const CONVERSATION_IMAGE_OMISSION_PREFIX = '[Image omitted from fusion text transcript: ';\n\nexport const OMITTED_EVENT_KINDS = [\n 'assistant_thinking',\n 'tool_call',\n 'tool_result_text',\n 'tool_result_image',\n] as const;\nexport type OmittedEventKind = (typeof OMITTED_EVENT_KINDS)[number];\n\nexport interface OmittedEventRecord {\n index: number;\n source_ordinal: number;\n block_ordinal: number;\n kind: OmittedEventKind;\n payload_bytes: number;\n payload_sha256: string;\n tool_name?: string;\n tool_call_id?: string;\n mime_type?: string;\n}\n\nexport interface OmittedActivityProjectionMapEntry {\n canonical_entry_index: number;\n entry_kind: 'omitted_activity';\n ledger_index_first: number;\n ledger_index_last: number;\n}\n\nexport interface LedgerOnlyImageProjectionMapEntry {\n entry_kind: 'ledger_only_tool_result_image';\n ledger_index_first: number;\n ledger_index_last: number;\n}\n\nexport type ContextProjectionMapEntry =\n | OmittedActivityProjectionMapEntry\n | LedgerOnlyImageProjectionMapEntry;\n\nexport interface ProjectionTextEntry {\n kind: 'text';\n source_ordinal: number;\n block_ordinal: number;\n role: 'user' | 'assistant';\n text: string;\n}\n\n/**\n * Per-kind counts for one omitted run. Zero-valued kinds are omitted from the\n * serialized receipt by a fixed policy rule so receipt size does not scale with\n * the number of tracked kinds; absent means exactly zero.\n */\nexport interface OmittedRunCounts {\n assistant_thinking?: number;\n tool_calls?: number;\n tool_result_texts?: number;\n}\n\nexport interface ProjectionOmissionEntry {\n kind: 'omitted_activity';\n at: readonly [number, number];\n bytes: number;\n counts: OmittedRunCounts;\n}\n\nexport type ProjectionEntry = ProjectionTextEntry | ProjectionOmissionEntry;\n\nexport interface ToolCallNameCount {\n name: string;\n calls: number;\n}\n\nexport interface ProjectionAccounting {\n message_count: number;\n included_text_entry_count: number;\n included_user_text_bytes: number;\n included_assistant_text_bytes: number;\n included_image_marker_count: number;\n empty_text_block_count: number;\n omitted_run_count: number;\n omitted_event_count: number;\n omitted_thinking_bytes: number;\n omitted_tool_call_count: number;\n omitted_tool_call_argument_bytes: number;\n omitted_tool_result_text_count: number;\n omitted_tool_result_text_bytes: number;\n omitted_tool_result_image_count: number;\n omitted_tool_result_image_bytes: number;\n tool_call_names: readonly ToolCallNameCount[];\n ledger_entry_count: number;\n ledger_root_sha256: string;\n omission_receipt_utf8_bytes: number;\n}\n\n/**\n * Ledger body produced by the transform, carrying no consumer envelope.\n *\n * The ledger root commits only to the ledger rows, never to schema version,\n * policy id, or transform id, so this body can be sealed by different consumers\n * without changing the root. That property is pinned by a dedicated test.\n */\nexport interface LedgerBodyV2 {\n entries: readonly OmittedEventRecord[];\n projection_map: readonly ContextProjectionMapEntry[];\n root_sha256: string;\n}\n\nexport interface ProjectedConversationV2 {\n entries: readonly ProjectionEntry[];\n accounting: ProjectionAccounting;\n ledger: LedgerBodyV2;\n}\n\n/** Raised when the transform meets a conversation block it refuses to silently drop. */\nexport class UnsupportedConversationBlockError extends Error {\n readonly label: string;\n\n constructor(label: string) {\n super(`fusion context projection encountered an unsupported conversation block: ${label}`);\n this.name = 'UnsupportedConversationBlockError';\n this.label = label;\n }\n}\n\nfunction utf8Bytes(value: string): number {\n return Buffer.byteLength(value, 'utf8');\n}\n\nfunction sha256Hex(bytes: Buffer): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\nfunction uint64be(value: number): Buffer {\n const out = Buffer.alloc(8);\n out.writeBigUInt64BE(BigInt(value));\n return out;\n}\n\n/** Length-prefixed framing so concatenated fields cannot collide across boundaries. */\nfunction lengthPrefixed(bytes: Buffer): Buffer {\n return Buffer.concat([uint64be(bytes.length), bytes]);\n}\n\nfunction ledgerLeafHash(index: number, record: OmittedEventRecord): Buffer {\n return createHash('sha256')\n .update(Buffer.from('pi-fusion-ledger-leaf-v1\\0', 'utf8'))\n .update(uint64be(index))\n .update(lengthPrefixed(Buffer.from(canonicalJson(record), 'utf8')))\n .digest();\n}\n\nfunction ledgerRootHash(leaves: readonly Buffer[]): string {\n const hash = createHash('sha256')\n .update(Buffer.from('pi-fusion-ledger-root-v1\\0', 'utf8'))\n .update(uint64be(leaves.length));\n for (const leaf of leaves) hash.update(leaf);\n return hash.digest('hex');\n}\n\nfunction unsupportedBlock(label: string): UnsupportedConversationBlockError {\n return new UnsupportedConversationBlockError(label);\n}\n\n/**\n * Fixed policy rule: a zero-valued kind is absent from the receipt rather than\n * serialized as `0`. This keeps receipts compact without losing information —\n * absent is defined by the policy version to mean exactly zero — and it is\n * applied unconditionally, never adaptively because an input happens to be large.\n */\nfunction compactCounts(counts: Required<OmittedRunCounts>): OmittedRunCounts {\n const out: OmittedRunCounts = {};\n if (counts.assistant_thinking > 0) out.assistant_thinking = counts.assistant_thinking;\n if (counts.tool_calls > 0) out.tool_calls = counts.tool_calls;\n if (counts.tool_result_texts > 0) out.tool_result_texts = counts.tool_result_texts;\n return out;\n}\n\nfunction imageMarker(mimeType: string): string {\n return `${CONVERSATION_IMAGE_OMISSION_PREFIX}${mimeType}]`;\n}\n\n/**\n * Accumulates omitted-event ledger rows and turns maximal contiguous non-image\n * omission runs into compact, source-ordered receipts inside the projection.\n */\nclass ProjectionBuilder {\n private readonly entries: ProjectionEntry[] = [];\n private readonly ledger: OmittedEventRecord[] = [];\n private readonly leaves: Buffer[] = [];\n private readonly projectionMap: ContextProjectionMapEntry[] = [];\n private readonly toolCallNames = new Map<string, number>();\n private pendingCounts: Required<OmittedRunCounts> | undefined;\n private pendingBytes = 0;\n private pendingLedgerFirst = 0;\n private pendingLedgerLast = 0;\n private pendingSourceFirst = 0;\n private pendingSourceLast = 0;\n\n includedUserTextBytes = 0;\n includedAssistantTextBytes = 0;\n includedImageMarkers = 0;\n emptyTextBlocks = 0;\n\n addText(entry: ProjectionTextEntry): void {\n this.flush();\n this.entries.push(entry);\n if (entry.role === 'user') this.includedUserTextBytes += utf8Bytes(entry.text);\n else this.includedAssistantTextBytes += utf8Bytes(entry.text);\n }\n\n addOmission(\n sourceOrdinal: number,\n blockOrdinal: number,\n kind: OmittedEventKind,\n payload: Buffer,\n extra: { toolName?: string; toolCallId?: string; mimeType?: string } = {},\n ): void {\n const index = this.ledger.length;\n const record: OmittedEventRecord = {\n index,\n source_ordinal: sourceOrdinal,\n block_ordinal: blockOrdinal,\n kind,\n payload_bytes: payload.length,\n payload_sha256: sha256Hex(payload),\n };\n if (extra.toolName !== undefined) record.tool_name = extra.toolName;\n if (extra.toolCallId !== undefined) record.tool_call_id = extra.toolCallId;\n if (extra.mimeType !== undefined) record.mime_type = extra.mimeType;\n this.ledger.push(record);\n this.leaves.push(ledgerLeafHash(index, record));\n\n if (extra.toolName !== undefined && kind === 'tool_call') {\n this.toolCallNames.set(extra.toolName, (this.toolCallNames.get(extra.toolName) ?? 0) + 1);\n }\n\n if (kind === 'tool_result_image') {\n this.flush();\n this.addLedgerOnlyImageMap(index);\n return;\n }\n\n if (this.pendingCounts === undefined) {\n this.pendingCounts = {\n assistant_thinking: 0,\n tool_calls: 0,\n tool_result_texts: 0,\n };\n this.pendingBytes = 0;\n this.pendingLedgerFirst = index;\n this.pendingSourceFirst = sourceOrdinal;\n }\n this.pendingLedgerLast = index;\n this.pendingSourceLast = sourceOrdinal;\n this.pendingBytes += payload.length;\n if (kind === 'assistant_thinking') this.pendingCounts.assistant_thinking += 1;\n else if (kind === 'tool_call') this.pendingCounts.tool_calls += 1;\n else this.pendingCounts.tool_result_texts += 1;\n }\n\n private addLedgerOnlyImageMap(index: number): void {\n const previous = this.projectionMap[this.projectionMap.length - 1];\n if (\n previous !== undefined &&\n previous.entry_kind === 'ledger_only_tool_result_image' &&\n previous.ledger_index_last + 1 === index\n ) {\n previous.ledger_index_last = index;\n return;\n }\n this.projectionMap.push({\n entry_kind: 'ledger_only_tool_result_image',\n ledger_index_first: index,\n ledger_index_last: index,\n });\n }\n\n private flush(): void {\n const counts = this.pendingCounts;\n if (counts === undefined) return;\n const canonicalEntryIndex = this.entries.length;\n const entry: ProjectionOmissionEntry = {\n at: [this.pendingSourceFirst, this.pendingSourceLast],\n bytes: this.pendingBytes,\n counts: compactCounts(counts),\n kind: 'omitted_activity',\n };\n this.entries.push(entry);\n this.projectionMap.push({\n canonical_entry_index: canonicalEntryIndex,\n entry_kind: 'omitted_activity',\n ledger_index_first: this.pendingLedgerFirst,\n ledger_index_last: this.pendingLedgerLast,\n });\n this.pendingCounts = undefined;\n this.pendingBytes = 0;\n }\n\n finish(messageCount: number): ProjectedConversationV2 {\n this.flush();\n const rootSha256 = ledgerRootHash(this.leaves);\n let omittedRunCount = 0;\n let includedTextEntries = 0;\n let receiptBytes = 0;\n for (const entry of this.entries) {\n if (entry.kind === 'text') includedTextEntries += 1;\n else {\n omittedRunCount += 1;\n receiptBytes += utf8Bytes(canonicalJson(entry));\n }\n }\n let thinkingBytes = 0;\n let toolCallCount = 0;\n let toolArgumentBytes = 0;\n let toolResultTextCount = 0;\n let toolResultTextBytes = 0;\n let toolResultImageCount = 0;\n let toolResultImageBytes = 0;\n for (const row of this.ledger) {\n if (row.kind === 'assistant_thinking') thinkingBytes += row.payload_bytes;\n else if (row.kind === 'tool_call') {\n toolCallCount += 1;\n toolArgumentBytes += row.payload_bytes;\n } else if (row.kind === 'tool_result_text') {\n toolResultTextCount += 1;\n toolResultTextBytes += row.payload_bytes;\n } else {\n toolResultImageCount += 1;\n toolResultImageBytes += row.payload_bytes;\n }\n }\n const toolCallNames: ToolCallNameCount[] = [...this.toolCallNames.entries()]\n .map(([name, calls]) => ({ name, calls }))\n .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));\n const accounting: ProjectionAccounting = {\n message_count: messageCount,\n included_text_entry_count: includedTextEntries,\n included_user_text_bytes: this.includedUserTextBytes,\n included_assistant_text_bytes: this.includedAssistantTextBytes,\n included_image_marker_count: this.includedImageMarkers,\n empty_text_block_count: this.emptyTextBlocks,\n omitted_run_count: omittedRunCount,\n omitted_event_count: this.ledger.length,\n omitted_thinking_bytes: thinkingBytes,\n omitted_tool_call_count: toolCallCount,\n omitted_tool_call_argument_bytes: toolArgumentBytes,\n omitted_tool_result_text_count: toolResultTextCount,\n omitted_tool_result_text_bytes: toolResultTextBytes,\n omitted_tool_result_image_count: toolResultImageCount,\n omitted_tool_result_image_bytes: toolResultImageBytes,\n tool_call_names: toolCallNames,\n ledger_entry_count: this.ledger.length,\n ledger_root_sha256: rootSha256,\n omission_receipt_utf8_bytes: receiptBytes,\n };\n return {\n entries: this.entries,\n accounting,\n ledger: {\n entries: this.ledger,\n projection_map: this.projectionMap,\n root_sha256: rootSha256,\n },\n };\n }\n}\n\n/**\n * Projects one user-role message. User text is retained verbatim; images stay\n * marker-only so the child never receives raw bytes.\n */\nfunction projectUserMessage(\n builder: ProjectionBuilder,\n content: Message['content'],\n sourceOrdinal: number,\n): void {\n if (typeof content === 'string') {\n if (content.length === 0) {\n builder.emptyTextBlocks += 1;\n return;\n }\n builder.addText({\n kind: 'text',\n source_ordinal: sourceOrdinal,\n block_ordinal: 0,\n role: 'user',\n text: content,\n });\n return;\n }\n for (const [blockOrdinal, block] of content.entries()) {\n if (block.type === 'text') {\n if (block.text.length === 0) {\n builder.emptyTextBlocks += 1;\n continue;\n }\n builder.addText({\n kind: 'text',\n source_ordinal: sourceOrdinal,\n block_ordinal: blockOrdinal,\n role: 'user',\n text: block.text,\n });\n continue;\n }\n if (block.type === 'image') {\n builder.includedImageMarkers += 1;\n builder.addText({\n kind: 'text',\n source_ordinal: sourceOrdinal,\n block_ordinal: blockOrdinal,\n role: 'user',\n text: imageMarker(block.mimeType),\n });\n continue;\n }\n throw unsupportedBlock(`user block ${String(Reflect.get(block, 'type'))}`);\n }\n}\n\nfunction projectAssistantMessage(\n builder: ProjectionBuilder,\n content: Extract<Message, { role: 'assistant' }>['content'],\n sourceOrdinal: number,\n): void {\n for (const [blockOrdinal, block] of content.entries()) {\n if (block.type === 'text') {\n if (block.text.length === 0) {\n builder.emptyTextBlocks += 1;\n continue;\n }\n builder.addText({\n kind: 'text',\n source_ordinal: sourceOrdinal,\n block_ordinal: blockOrdinal,\n role: 'assistant',\n text: block.text,\n });\n continue;\n }\n if (block.type === 'thinking') {\n builder.addOmission(\n sourceOrdinal,\n blockOrdinal,\n 'assistant_thinking',\n Buffer.from(block.thinking, 'utf8'),\n );\n continue;\n }\n if (block.type === 'toolCall') {\n builder.addOmission(\n sourceOrdinal,\n blockOrdinal,\n 'tool_call',\n Buffer.from(canonicalJson(block.arguments), 'utf8'),\n { toolName: block.name, toolCallId: block.id },\n );\n continue;\n }\n throw unsupportedBlock(`assistant block ${String(Reflect.get(block, 'type'))}`);\n }\n}\n\nfunction projectToolResultMessage(\n builder: ProjectionBuilder,\n message: Extract<Message, { role: 'toolResult' }>,\n sourceOrdinal: number,\n): void {\n const content = message.content;\n if (typeof content === 'string') {\n builder.addOmission(sourceOrdinal, 0, 'tool_result_text', Buffer.from(content, 'utf8'), {\n toolName: message.toolName,\n toolCallId: message.toolCallId,\n });\n return;\n }\n for (const [blockOrdinal, block] of content.entries()) {\n if (block.type === 'text') {\n builder.addOmission(\n sourceOrdinal,\n blockOrdinal,\n 'tool_result_text',\n Buffer.from(block.text, 'utf8'),\n { toolName: message.toolName, toolCallId: message.toolCallId },\n );\n continue;\n }\n if (block.type === 'image') {\n builder.addOmission(\n sourceOrdinal,\n blockOrdinal,\n 'tool_result_image',\n Buffer.from(block.data, 'utf8'),\n {\n toolName: message.toolName,\n toolCallId: message.toolCallId,\n mimeType: block.mimeType,\n },\n );\n continue;\n }\n throw unsupportedBlock(`tool result block ${String(Reflect.get(block, 'type'))}`);\n }\n}\n\n/**\n * Deterministic conversation projection. Every retained source block receives\n * exactly one disposition: included verbatim, or represented as an omission\n * ledger row. Unknown block types fail loudly instead of disappearing.\n */\nexport function projectVisibleConversationV2(\n messages: readonly Message[],\n): ProjectedConversationV2 {\n const builder = new ProjectionBuilder();\n for (const [sourceOrdinal, message] of messages.entries()) {\n if (message.role === 'user') projectUserMessage(builder, message.content, sourceOrdinal);\n else if (message.role === 'assistant')\n projectAssistantMessage(builder, message.content, sourceOrdinal);\n else if (message.role === 'toolResult')\n projectToolResultMessage(builder, message, sourceOrdinal);\n else throw unsupportedBlock(`message role ${String(Reflect.get(message, 'role'))}`);\n }\n return builder.finish(messages.length);\n}\n"]}