@ponythewhite/base-context 1.0.7 → 1.0.9

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 (138) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/base-context-runtime/pyproject.toml +1 -1
  3. package/dist/base-context-runtime/src/rlm/__init__.py +3 -0
  4. package/dist/base-context-runtime/src/rlm/harness.py +86 -48
  5. package/dist/base-context-runtime/test/test_harness.py +215 -140
  6. package/dist/base-context-runtime/uv.lock +1 -1
  7. package/dist/build-info.json +1 -1
  8. package/dist/bundle/amazon-bedrock.js +3 -3
  9. package/dist/bundle/{anthropic-UV5GZDGU.js → anthropic-5PSCZEER.js} +2 -7
  10. package/dist/bundle/{azure-openai-responses-WSNPXLYC.js → azure-openai-responses-AYTLJR33.js} +2 -2
  11. package/dist/bundle/{bundled-modules-PS66L3IT.js → bundled-modules-5JRM6P4T.js} +5 -5
  12. package/dist/bundle/{chunk-UPVDERMD.js → chunk-2IPDSTDR.js} +11 -9
  13. package/dist/bundle/chunk-D3KOF57W.js +22040 -0
  14. package/dist/bundle/{chunk-VSIYFWYI.js → chunk-KT2BNEPE.js} +21 -8
  15. package/dist/bundle/{chunk-VCW3YDFF.js → chunk-NEHLB7JV.js} +1548 -574
  16. package/dist/bundle/{chunk-KTNETTHI.js → chunk-Q3MBSBEB.js} +3 -101
  17. package/dist/bundle/{chunk-LFPWHI42.js → chunk-QKIFBA7N.js} +2 -2
  18. package/dist/bundle/{chunk-PFROC4EV.js → chunk-VVI3UKGR.js} +12 -9
  19. package/dist/bundle/{cli-main-MMHTK7EB.js → cli-main-YUDBEYE2.js} +4 -4
  20. package/dist/bundle/cli.js +1 -1
  21. package/dist/bundle/{google-T32FMD4G.js → google-HTMCUJ7X.js} +2 -2
  22. package/dist/bundle/{google-vertex-56KP6I3B.js → google-vertex-ZQO65AXF.js} +2 -2
  23. package/dist/bundle/{main-XAIVH4Y7.js → main-ZLGGAAGU.js} +5 -5
  24. package/dist/bundle/{mistral-WGBMYIVU.js → mistral-SB7LU56G.js} +1 -1
  25. package/dist/bundle/{openai-codex-responses-PIV2RQ3G.js → openai-codex-responses-5CEW4VN3.js} +53 -27
  26. package/dist/bundle/{openai-completions-64C3JPR4.js → openai-completions-BAZJQSS2.js} +1 -1
  27. package/dist/bundle/{openai-responses-UI7RSTDV.js → openai-responses-VHOE427P.js} +48 -5
  28. package/dist/core/agent-session.d.ts +9 -1
  29. package/dist/core/agent-session.d.ts.map +1 -1
  30. package/dist/core/agent-session.js +225 -29
  31. package/dist/core/agent-session.js.map +1 -1
  32. package/dist/core/canonical-context.d.ts +8 -0
  33. package/dist/core/canonical-context.d.ts.map +1 -1
  34. package/dist/core/canonical-context.js +37 -5
  35. package/dist/core/canonical-context.js.map +1 -1
  36. package/dist/core/compaction/compaction.d.ts +2 -2
  37. package/dist/core/compaction/compaction.d.ts.map +1 -1
  38. package/dist/core/compaction/compaction.js +31 -13
  39. package/dist/core/compaction/compaction.js.map +1 -1
  40. package/dist/core/context-epoch.d.ts +1 -1
  41. package/dist/core/context-epoch.d.ts.map +1 -1
  42. package/dist/core/context-epoch.js +2 -1
  43. package/dist/core/context-epoch.js.map +1 -1
  44. package/dist/core/extensions/types.d.ts +2 -2
  45. package/dist/core/extensions/types.d.ts.map +1 -1
  46. package/dist/core/extensions/types.js.map +1 -1
  47. package/dist/core/history-index-worker.d.ts.map +1 -1
  48. package/dist/core/history-index-worker.js +29 -8
  49. package/dist/core/history-index-worker.js.map +1 -1
  50. package/dist/core/history-index.d.ts +11 -1
  51. package/dist/core/history-index.d.ts.map +1 -1
  52. package/dist/core/history-index.js +2 -1
  53. package/dist/core/history-index.js.map +1 -1
  54. package/dist/core/inference-coordinator.d.ts +1 -1
  55. package/dist/core/inference-coordinator.d.ts.map +1 -1
  56. package/dist/core/inference-coordinator.js +110 -15
  57. package/dist/core/inference-coordinator.js.map +1 -1
  58. package/dist/core/kernel/bootstrap.d.ts.map +1 -1
  59. package/dist/core/kernel/bootstrap.js +97 -107
  60. package/dist/core/kernel/bootstrap.js.map +1 -1
  61. package/dist/core/kernel/repl-manager.d.ts.map +1 -1
  62. package/dist/core/kernel/repl-manager.js +11 -0
  63. package/dist/core/kernel/repl-manager.js.map +1 -1
  64. package/dist/core/kernel/shared.d.ts +2 -0
  65. package/dist/core/kernel/shared.d.ts.map +1 -1
  66. package/dist/core/kernel/shared.js.map +1 -1
  67. package/dist/core/messages.d.ts.map +1 -1
  68. package/dist/core/messages.js +4 -1
  69. package/dist/core/messages.js.map +1 -1
  70. package/dist/core/prompts/rlm.d.ts.map +1 -1
  71. package/dist/core/prompts/rlm.js +4 -2
  72. package/dist/core/prompts/rlm.js.map +1 -1
  73. package/dist/core/public-context.d.ts.map +1 -1
  74. package/dist/core/public-context.js +16 -0
  75. package/dist/core/public-context.js.map +1 -1
  76. package/dist/core/refinement/refinement.d.ts +19 -5
  77. package/dist/core/refinement/refinement.d.ts.map +1 -1
  78. package/dist/core/refinement/refinement.js +90 -35
  79. package/dist/core/refinement/refinement.js.map +1 -1
  80. package/dist/core/request-view-selection.d.ts +13 -3
  81. package/dist/core/request-view-selection.d.ts.map +1 -1
  82. package/dist/core/request-view-selection.js +239 -101
  83. package/dist/core/request-view-selection.js.map +1 -1
  84. package/dist/core/retained-tool-output.d.ts +28 -0
  85. package/dist/core/retained-tool-output.d.ts.map +1 -0
  86. package/dist/core/retained-tool-output.js +102 -0
  87. package/dist/core/retained-tool-output.js.map +1 -0
  88. package/dist/core/selective-recovery.d.ts +47 -3
  89. package/dist/core/selective-recovery.d.ts.map +1 -1
  90. package/dist/core/selective-recovery.js +428 -109
  91. package/dist/core/selective-recovery.js.map +1 -1
  92. package/dist/core/session-history-index.d.ts +3 -1
  93. package/dist/core/session-history-index.d.ts.map +1 -1
  94. package/dist/core/session-history-index.js +1 -1
  95. package/dist/core/session-history-index.js.map +1 -1
  96. package/dist/core/session-manager.d.ts +2 -0
  97. package/dist/core/session-manager.d.ts.map +1 -1
  98. package/dist/core/session-manager.js +38 -13
  99. package/dist/core/session-manager.js.map +1 -1
  100. package/dist/core/settings-manager.d.ts +5 -0
  101. package/dist/core/settings-manager.d.ts.map +1 -1
  102. package/dist/core/settings-manager.js +3 -0
  103. package/dist/core/settings-manager.js.map +1 -1
  104. package/dist/core/system-prompt.d.ts +3 -1
  105. package/dist/core/system-prompt.d.ts.map +1 -1
  106. package/dist/core/system-prompt.js +3 -3
  107. package/dist/core/system-prompt.js.map +1 -1
  108. package/dist/core/task-frame.d.ts +1 -1
  109. package/dist/core/task-frame.d.ts.map +1 -1
  110. package/dist/core/task-frame.js +21 -1
  111. package/dist/core/task-frame.js.map +1 -1
  112. package/dist/core/task-state-reader.d.ts +10 -2
  113. package/dist/core/task-state-reader.d.ts.map +1 -1
  114. package/dist/core/task-state-reader.js +75 -9
  115. package/dist/core/task-state-reader.js.map +1 -1
  116. package/dist/core/tools/ipython.d.ts +5 -0
  117. package/dist/core/tools/ipython.d.ts.map +1 -1
  118. package/dist/core/tools/ipython.js +59 -17
  119. package/dist/core/tools/ipython.js.map +1 -1
  120. package/dist/core/tools/prime-context.d.ts.map +1 -1
  121. package/dist/core/tools/prime-context.js +1 -1
  122. package/dist/core/tools/prime-context.js.map +1 -1
  123. package/dist/core/view-units.d.ts +4 -0
  124. package/dist/core/view-units.d.ts.map +1 -1
  125. package/dist/core/view-units.js +28 -19
  126. package/dist/core/view-units.js.map +1 -1
  127. package/dist/installer.mjs +98 -77
  128. package/dist/modes/interactive/components/refinement-outcome-message.d.ts.map +1 -1
  129. package/dist/modes/interactive/components/refinement-outcome-message.js.map +1 -1
  130. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  131. package/dist/modes/interactive/interactive-mode.js +5 -5
  132. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  133. package/dist/skills/skill-creator/SKILL.md +18 -1
  134. package/docs/settings.md +45 -0
  135. package/docs/skills.md +77 -2
  136. package/package.json +4 -4
  137. package/skills/skill-creator/SKILL.md +18 -1
  138. package/dist/bundle/chunk-W46VZFI6.js +0 -21681
@@ -1 +1 @@
1
- {"version":3,"file":"request-view-selection.d.ts","sourceRoot":"","sources":["../../src/core/request-view-selection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@ponythewhite/base-context-agent\";\nimport {\n\ttype Context,\n\ttype ProviderRequestProjection,\n\ttype ProviderRequestPublicMessage,\n\ttype ProviderRequestRepresentation,\n\ttype RequestTokenAssessment,\n\tRequestTokenBudgetError,\n\ttype RequestTokenBudgetEvaluator,\n} from \"@ponythewhite/base-context-ai\";\nimport {\n\ttype CanonicalViewSelectionSource,\n\tcaptureCanonicalRequestMessages,\n\tgetCanonicalViewSelectionSource,\n\tpreparePublicContextWindow,\n\tprepareToolContinuationWindow,\n} from \"./canonical-context.js\";\nimport { convertToLlm } from \"./messages.js\";\nimport type { ContextEpochEntryRef, SourceSnapshotRef } from \"./request-events.js\";\nimport { bindMessageReplayUnits, closeViewSelection } from \"./view-units.js\";\n\n/** Actual adapter-public measurement, not a verdict about the opaque native request. */\nexport class PublicContextBudgetError extends RequestTokenBudgetError {\n\treadonly source: SourceSnapshotRef;\n\n\tconstructor(\n\t\tsource: SourceSnapshotRef,\n\t\tassessment: RequestTokenAssessment,\n\t\treadonly originalAssessment: RequestTokenAssessment,\n\t) {\n\t\tsuper(assessment);\n\t\tthis.name = \"PublicContextBudgetError\";\n\t\tthis.source = Object.freeze({ ...source });\n\t}\n}\n\nexport interface RequestViewCandidate {\n\treadonly source: SourceSnapshotRef;\n\treadonly selectedUnitIds: readonly string[];\n\treadonly request: ProviderRequestRepresentation;\n\treadonly projection: ProviderRequestProjection;\n\t// Absent only for mandatory full-view admission without a configured token budget.\n\treadonly assessment: RequestTokenAssessment | undefined;\n\treadonly originalAssessment: RequestTokenAssessment | undefined;\n\t/** Exact public messages represented by the accepted candidate, with captured source recipes. */\n\treadonly publicMessages?: readonly AgentMessage[];\n}\n\n/** Root resolves only after its canonical epoch checkpoint ACK. This module owns no epoch state. */\nexport type RequestViewCommit = (\n\tcandidate: RequestViewCandidate,\n) => Promise<ContextEpochEntryRef | undefined> | Promise<void>;\nexport type RequestViewValidate = (\n\trequest: ProviderRequestRepresentation,\n\tassessment: RequestTokenAssessment | undefined,\n) => void;\n\nexport type RequestViewFixedPrepare = (\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tassessment: RequestTokenAssessment | undefined,\n) => ContextEpochEntryRef | void | Promise<ContextEpochEntryRef | undefined> | Promise<void>;\n\nexport interface CapturedRequestViewBoundary extends CanonicalViewSelectionSource {\n\treadonly messages: readonly AgentMessage[];\n\t/** Provider logical positions mapped to the unchanged canonical messages/units. */\n\treadonly providerMessageIndices: readonly number[];\n\treadonly providerPendingPublicMessageGroups?: readonly (readonly number[])[];\n\treadonly commit: RequestViewCommit;\n\treadonly validate?: RequestViewValidate;\n\treadonly fixedPrepare?: RequestViewFixedPrepare;\n}\n\nexport function captureRequestViewBoundary(\n\tmessages: readonly AgentMessage[],\n\tcommit: RequestViewCommit,\n\tvalidate?: RequestViewValidate,\n\tfixedPrepare?: RequestViewFixedPrepare,\n): CapturedRequestViewBoundary {\n\tconst source = getCanonicalViewSelectionSource(messages);\n\tif (!source) throw new Error(\"Request view boundary requires compiled canonical messages\");\n\tconst providerMessageIndices = messages.flatMap((message, index) => convertToLlm([message]).map(() => index));\n\treturn {\n\t\t...source,\n\t\tmessages: captureCanonicalRequestMessages(messages),\n\t\tproviderMessageIndices,\n\t\t...(source.pendingPublicMessageGroups\n\t\t\t? {\n\t\t\t\t\tproviderPendingPublicMessageGroups: source.pendingPublicMessageGroups.map((group) =>\n\t\t\t\t\t\tgroup.map((index) => providerMessageIndex(providerMessageIndices, index)),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: {}),\n\t\tcommit,\n\t\tvalidate,\n\t\tfixedPrepare,\n\t};\n}\n\nfunction providerMessageIndex(indices: readonly number[], canonicalIndex: number): number {\n\tconst index = indices.indexOf(canonicalIndex);\n\tif (index < 0) throw new Error(\"Provider projection cannot address a filtered canonical message\");\n\treturn index;\n}\n\n/** Keep canonical UI barriers while translating the native serializer's provider-only positions. */\nfunction canonicalRequestProjection(\n\tboundary: CapturedRequestViewBoundary,\n\tprojection: ProviderRequestProjection,\n): ProviderRequestProjection {\n\tconst indices = boundary.providerMessageIndices;\n\tif (indices.length === boundary.messages.length) return projection;\n\tconst canonicalIndex = (index: number): number => {\n\t\tconst canonical = indices[index];\n\t\tif (canonical === undefined) throw new Error(\"Provider projection message index is outside its captured view\");\n\t\treturn canonical;\n\t};\n\treturn {\n\t\t...projection,\n\t\tmessageIndices: projection.messageIndices.map((index) => (index === null ? null : canonicalIndex(index))),\n\t\t...(projection.optionalMessageIndices\n\t\t\t? { optionalMessageIndices: projection.optionalMessageIndices.map(canonicalIndex) }\n\t\t\t: {}),\n\t\t...(projection.generatedMessageIndices\n\t\t\t? { generatedMessageIndices: projection.generatedMessageIndices.map(canonicalIndex) }\n\t\t\t: {}),\n\t\t...(projection.publicMessageGroups\n\t\t\t? { publicMessageGroups: projection.publicMessageGroups.map((group) => group.map(canonicalIndex)) }\n\t\t\t: {}),\n\t\t...(projection.pendingPublicMessageGroups\n\t\t\t? {\n\t\t\t\t\tpendingPublicMessageGroups: projection.pendingPublicMessageGroups.map((group) =>\n\t\t\t\t\t\tgroup.map(canonicalIndex),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: {}),\n\t\t...(projection.encodePublicWindow\n\t\t\t? {\n\t\t\t\t\tencodePublicWindow: (replacements: readonly ProviderRequestPublicMessage[]) => {\n\t\t\t\t\t\tconst encoded = projection.encodePublicWindow!(\n\t\t\t\t\t\t\treplacements.map((replacement) => ({\n\t\t\t\t\t\t\t\t...replacement,\n\t\t\t\t\t\t\t\tmessageIndex: providerMessageIndex(indices, replacement.messageIndex),\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tencoded && { ...encoded, projection: canonicalRequestProjection(boundary, encoded.projection) }\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nexport function matchesRequestView(\n\tboundary: CapturedRequestViewBoundary,\n\tsource: SourceSnapshotRef,\n\tcontext: Context,\n): boolean {\n\tconst expected = boundary.source;\n\tif (\n\t\texpected.sessionId !== source.sessionId ||\n\t\texpected.sessionFile !== source.sessionFile ||\n\t\texpected.leafId !== source.leafId ||\n\t\texpected.sourceSequence !== source.sourceSequence\n\t)\n\t\treturn false;\n\tconst rendered = convertToLlm([...boundary.messages]);\n\treturn (\n\t\tboundary.messages.length === boundary.units.length &&\n\t\trendered.length === boundary.providerMessageIndices.length &&\n\t\tJSON.stringify(rendered) === JSON.stringify(context.messages)\n\t);\n}\n\n/** Projection kinds describe their actual provider body, never an OpenAI-format route alias. */\nfunction requestInputKey(\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n): \"input\" | \"messages\" | undefined {\n\tif (\n\t\t(request.api === \"openai-responses\" || request.api === \"openai-codex-responses\") &&\n\t\t(projection.kind === \"openai-responses-text-v1\" || projection.kind === \"openai-responses-replay-v1\")\n\t)\n\t\treturn \"input\";\n\tif (\n\t\trequest.api === \"openai-completions\" &&\n\t\trequest.provider === \"deepseek\" &&\n\t\trequest.url === \"https://api.deepseek.com/chat/completions\" &&\n\t\tprojection.kind === \"deepseek-completions-text-tools-v1\" &&\n\t\trequest.body !== undefined &&\n\t\tJSON.parse(request.body).model === \"deepseek-flash\"\n\t)\n\t\treturn \"messages\";\n\treturn undefined;\n}\n\n/** Check the actual final mapping without selecting, converting, or committing another view. */\nexport async function prepareFixedRequestView(\n\tboundary: CapturedRequestViewBoundary,\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tassessment: RequestTokenAssessment | undefined,\n) {\n\tprojection = canonicalRequestProjection(boundary, projection);\n\tconst inputKey = requestInputKey(request, projection);\n\tconst payload = JSON.parse(request.body!) as Record<string, unknown> | null;\n\tconst input = inputKey && payload ? payload[inputKey] : undefined;\n\tif (!Array.isArray(input) || input.length !== projection.messageIndices.length)\n\t\tthrow new Error(\"Fixed context requires its final provider projection\");\n\tif (\n\t\tprojection.kind === \"openai-responses-text-v1\" &&\n\t\tboundary.messages.some(\n\t\t\t(message) =>\n\t\t\t\tmessage.role === \"toolResult\" ||\n\t\t\t\t(message.role === \"assistant\" && (message.content.length !== 1 || message.content[0].type !== \"text\")),\n\t\t)\n\t)\n\t\tthrow new Error(\"Fixed context requires its native replay adapter\");\n\tconst units = bindMessageReplayUnits(\n\t\tboundary.messages,\n\t\tboundary.units,\n\t\tboundary.limits,\n\t\tprojection.replayContract ?? \"complete-context\",\n\t);\n\tcloseViewSelection(\n\t\tunits,\n\t\tunits.map((unit) => unit.id),\n\t\tboundary.limits,\n\t);\n\treturn await boundary.fixedPrepare!(request, projection, assessment);\n}\n\n/** Only the actual serializer's established replay contract authorizes historical-literal omission. */\nexport async function selectRequestView(\n\tboundary: CapturedRequestViewBoundary,\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tbudget: RequestTokenBudgetEvaluator | undefined,\n\tallowShrink: boolean,\n): Promise<string | undefined> {\n\tprojection = canonicalRequestProjection(boundary, projection);\n\tconst full = budget?.measure(request);\n\tconst inputKey = requestInputKey(request, projection);\n\tif ((budget && full?.limitSource !== \"explicit-profile\") || !inputKey) return;\n\tif (!budget && !boundary.pendingPublicMessageGroups?.length) return;\n\tconst payload = JSON.parse(request.body!) as Record<string, unknown>;\n\tconst input = payload[inputKey];\n\tif (!Array.isArray(input) || input.length !== projection.messageIndices.length) return;\n\n\t// Absence is complete-context; a profile or tool-shaped message is never group authority.\n\tconst replayContract = projection.replayContract ?? \"complete-context\";\n\tif (\n\t\tprojection.kind === \"openai-responses-text-v1\" &&\n\t\tboundary.messages.some(\n\t\t\t(message) =>\n\t\t\t\tmessage.role === \"toolResult\" ||\n\t\t\t\t(message.role === \"assistant\" && (message.content.length !== 1 || message.content[0].type !== \"text\")),\n\t\t)\n\t)\n\t\treturn;\n\tconst units = bindMessageReplayUnits(\n\t\tboundary.messages,\n\t\tboundary.units,\n\t\tboundary.limits,\n\t\treplayContract,\n\t\tboundary.pendingPublicMessageGroups,\n\t);\n\tconst offer = async (\n\t\tselectedUnitIds: readonly string[],\n\t\tcandidateRequest: ProviderRequestRepresentation,\n\t\tcandidateProjection: ProviderRequestProjection,\n\t\tassessment: RequestTokenAssessment | undefined,\n\t\tpublicMessages?: readonly AgentMessage[],\n\t) =>\n\t\tboundary.commit(\n\t\t\tObject.freeze({\n\t\t\t\tsource: Object.freeze({ ...boundary.source }),\n\t\t\t\tselectedUnitIds: Object.freeze([...selectedUnitIds]),\n\t\t\t\trequest: Object.freeze({ ...candidateRequest }),\n\t\t\t\tprojection: Object.freeze({\n\t\t\t\t\t...candidateProjection,\n\t\t\t\t\treplayContract,\n\t\t\t\t\tmessageIndices: Object.freeze([...candidateProjection.messageIndices]),\n\t\t\t\t\t...(candidateProjection.optionalMessageIndices\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\toptionalMessageIndices: Object.freeze([...candidateProjection.optionalMessageIndices]),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(candidateProjection.generatedMessageIndices\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tgeneratedMessageIndices: Object.freeze([...candidateProjection.generatedMessageIndices]),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t}),\n\t\t\t\tassessment,\n\t\t\t\toriginalAssessment: full,\n\t\t\t\t...(publicMessages ? { publicMessages } : {}),\n\t\t\t}),\n\t\t);\n\tif (boundary.pendingPublicMessageGroups?.length) {\n\t\tif (\n\t\t\treplayContract !== \"message-groups\" ||\n\t\t\t!projection.publicWindow ||\n\t\t\t!projection.encodePublicWindow ||\n\t\t\tJSON.stringify(projection.pendingPublicMessageGroups) !== JSON.stringify(boundary.pendingPublicMessageGroups)\n\t\t)\n\t\t\tthrow new Error(\"Original tool group requires current native adapter public conversion\");\n\t\tconst publicView = prepareToolContinuationWindow(boundary.messages);\n\t\tconst encoded = projection.encodePublicWindow(publicView.replacements);\n\t\tif (!encoded || encoded.projection.pendingPublicMessageGroups?.length)\n\t\t\tthrow new Error(\"Native adapter did not convert the whole required tool group\");\n\t\tconst publicSource = getCanonicalViewSelectionSource(publicView.messages)!;\n\t\tconst publicUnits = bindMessageReplayUnits(\n\t\t\tpublicView.messages,\n\t\t\tpublicSource.units,\n\t\t\tboundary.limits,\n\t\t\treplayContract,\n\t\t);\n\t\tconst closed = closeViewSelection(\n\t\t\tpublicUnits,\n\t\t\tpublicUnits.map((unit) => unit.id),\n\t\t\tboundary.limits,\n\t\t);\n\t\tconst assessment = budget?.measure(encoded.request);\n\t\tif (assessment && full) {\n\t\t\tif (assessment.status === \"over-budget\") throw new PublicContextBudgetError(boundary.source, assessment, full);\n\t\t\tif (assessment.status !== \"within-estimate\")\n\t\t\t\tthrow new Error(\"Tool continuation public request exceeds its token budget\");\n\t\t}\n\t\tawait offer(\n\t\t\tclosed.map((unit) => unit.id),\n\t\t\tencoded.request,\n\t\t\tencoded.projection,\n\t\t\tassessment,\n\t\t\tpublicView.messages,\n\t\t);\n\t\treturn encoded.request.body;\n\t}\n\tif (projection.pendingPublicMessageGroups?.length)\n\t\tthrow new Error(\"Adapter pending group has no original owned source plan\");\n\t// Unbudgeted admission above retains every source unit; it never selects a smaller view.\n\tif (!budget || !full) return;\n\tconst offerPublicWindow = async (): Promise<string | undefined> => {\n\t\tif (\n\t\t\t!allowShrink ||\n\t\t\treplayContract !== \"message-groups\" ||\n\t\t\t!projection.publicWindow ||\n\t\t\t!projection.encodePublicWindow\n\t\t)\n\t\t\treturn;\n\t\tconst closed = closeViewSelection(\n\t\t\tunits,\n\t\t\tunits.map((unit) => unit.id),\n\t\t\tboundary.limits,\n\t\t);\n\t\tlet firstMessageIndex = 0;\n\t\tif (\n\t\t\tfull.status === \"unknown\" &&\n\t\t\tfull.unknown.length === 1 &&\n\t\t\tfull.unknown[0] === \"media, opaque or unsupported replay token coverage unknown\"\n\t\t) {\n\t\t\t// Credited items are not part of the unknown input. Keep original projection indices.\n\t\t\tconst firstUnmeteredItem = request.retainedPrefix?.inputItems ?? 0;\n\t\t\tconst reasoningItemIndex = input.findIndex(\n\t\t\t\t(item, index) => index >= firstUnmeteredItem && item?.type === \"reasoning\",\n\t\t\t);\n\t\t\tconst messageIndex = projection.messageIndices[reasoningItemIndex];\n\t\t\tconst group =\n\t\t\t\tmessageIndex == null\n\t\t\t\t\t? undefined\n\t\t\t\t\t: projection.publicMessageGroups?.find((members) => members.includes(messageIndex));\n\t\t\t// The adapter still accepts only complete groups; earlier meterable groups stay native.\n\t\t\tfirstMessageIndex = group ? Math.min(...group) : 0;\n\t\t}\n\t\tconst publicView = preparePublicContextWindow(boundary.messages, firstMessageIndex);\n\t\tif (!publicView) {\n\t\t\t// Keep the original measured refusal when no public conversion can be offered.\n\t\t\t// This is not a new recovery signal or permission to reprepare again.\n\t\t\tif (full.status === \"over-budget\") throw new RequestTokenBudgetError(full);\n\t\t\treturn;\n\t\t}\n\t\tconst encoded = projection.encodePublicWindow(publicView.replacements);\n\t\tif (!encoded) return;\n\t\tconst assessment = budget.measure(encoded.request);\n\t\tif (assessment.status === \"over-budget\") throw new PublicContextBudgetError(boundary.source, assessment, full);\n\t\tif (assessment.status !== \"within-estimate\") return;\n\t\tawait offer(\n\t\t\tclosed.map((unit) => unit.id),\n\t\t\tencoded.request,\n\t\t\tencoded.projection,\n\t\t\tassessment,\n\t\t\tpublicView.messages,\n\t\t);\n\t\treturn encoded.request.body;\n\t};\n\tif (full.status === \"within-estimate\") {\n\t\tconst closed = closeViewSelection(\n\t\t\tunits,\n\t\t\tunits.map((unit) => unit.id),\n\t\t\tboundary.limits,\n\t\t);\n\t\tawait offer(\n\t\t\tclosed.map((unit) => unit.id),\n\t\t\trequest,\n\t\t\tprojection,\n\t\t\tfull,\n\t\t);\n\t\treturn request.body;\n\t}\n\tif (!allowShrink || replayContract !== \"message-groups\") return;\n\tif (full.status !== \"over-budget\") return offerPublicWindow();\n\tlet latestAssistant = -1;\n\tfor (const [index, message] of boundary.messages.entries())\n\t\tif (message.role === \"assistant\") latestAssistant = index;\n\tconst retained = new Set(projection.messageIndices.slice(0, request.retainedPrefix?.inputItems ?? 0));\n\tconst projectedOptional =\n\t\tprojection.kind !== \"openai-responses-text-v1\" ? new Set(projection.optionalMessageIndices ?? []) : undefined;\n\tconst optional = units.filter((unit, index) => {\n\t\tconst message = boundary.messages[index];\n\t\treturn (\n\t\t\tindex !== latestAssistant &&\n\t\t\t!retained.has(index) &&\n\t\t\t(!projectedOptional || projectedOptional.has(index)) &&\n\t\t\tunit.kind === \"literal\" &&\n\t\t\tunit.authority === \"assistant-public\" &&\n\t\t\tmessage.role === \"assistant\" &&\n\t\t\tmessage.stopReason === \"stop\" &&\n\t\t\tmessage.content.length === 1 &&\n\t\t\tmessage.content[0].type === \"text\"\n\t\t);\n\t});\n\tconst generatedPositions = new Map<string, number>();\n\tconst generated =\n\t\tprojection.generatedMessageIndices ??\n\t\tboundary.messages.flatMap((message, index) =>\n\t\t\tmessage.role === \"assistant\" &&\n\t\t\tmessage.content.some((block) => block.type === \"text\" && block.textSignature === undefined)\n\t\t\t\t? [index]\n\t\t\t\t: [],\n\t\t);\n\tfor (const index of generated) generatedPositions.set(units[index].id, index);\n\t// All user inputs, the latest assistant, fixed/TaskFrame/recovery units and errors stay selected.\n\tconst selected = new Set(units.map((unit) => unit.id));\n\tfor (const unit of optional) {\n\t\tselected.delete(unit.id);\n\t\tconst closed = closeViewSelection(units, [...selected], boundary.limits);\n\t\t// Normal Responses rendering uses msg_<message index> for unsigned assistants.\n\t\t// Reject any subset that would change a retained generated item ID on reconstruction.\n\t\tif (closed.some((item, index) => generatedPositions.has(item.id) && generatedPositions.get(item.id) !== index))\n\t\t\tcontinue;\n\t\tconst closedIds = new Set(closed.map((item) => item.id));\n\t\tconst keepItem = (index: number) => {\n\t\t\tconst messageIndex = projection.messageIndices[index];\n\t\t\treturn messageIndex === null || closedIds.has(units[messageIndex].id);\n\t\t};\n\t\tconst body = JSON.stringify({ ...payload, [inputKey]: input.filter((_, index) => keepItem(index)) });\n\t\tconst candidateRequest = { ...request, body };\n\t\tconst assessment = budget.measure(candidateRequest);\n\t\tif (assessment.status !== \"within-estimate\") continue;\n\t\tawait offer(\n\t\t\tclosed.map((item) => item.id),\n\t\t\tcandidateRequest,\n\t\t\t{\n\t\t\t\t...projection,\n\t\t\t\tmessageIndices: projection.messageIndices.filter((_, index) => keepItem(index)),\n\t\t\t\t...(projection.optionalMessageIndices\n\t\t\t\t\t? {\n\t\t\t\t\t\t\toptionalMessageIndices: projection.optionalMessageIndices.filter((index) =>\n\t\t\t\t\t\t\t\tclosedIds.has(units[index].id),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(projection.generatedMessageIndices\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tgeneratedMessageIndices: projection.generatedMessageIndices.filter((index) =>\n\t\t\t\t\t\t\t\tclosedIds.has(units[index].id),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tassessment,\n\t\t);\n\t\treturn body;\n\t}\n\treturn offerPublicWindow();\n}\n"]}
1
+ {"version":3,"file":"request-view-selection.d.ts","sourceRoot":"","sources":["../../src/core/request-view-selection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@ponythewhite/base-context-agent\";\nimport {\n\ttype Context,\n\ttype ProviderRequestProjection,\n\ttype ProviderRequestPublicMessage,\n\ttype ProviderRequestRepresentation,\n\ttype RequestTokenAssessment,\n\tRequestTokenBudgetError,\n\ttype RequestTokenBudgetEvaluator,\n\twithRequestBody,\n} from \"@ponythewhite/base-context-ai\";\nimport {\n\ttype CanonicalViewSelectionSource,\n\tcaptureCanonicalRequestMessages,\n\tgetCanonicalEpochContext,\n\tgetCanonicalViewSelectionSource,\n\tpreparePublicContextWindow,\n\tprepareToolContinuationWindow,\n} from \"./canonical-context.js\";\nimport { convertToLlm } from \"./messages.js\";\nimport type { ContextEpochEntryRef, SourceSnapshotRef } from \"./request-events.js\";\nimport { bindMessageReplayUnits, closeViewSelection, prepareViewSelection } from \"./view-units.js\";\n\n/** Actual adapter-public measurement, not a verdict about the opaque native request. */\nexport class PublicContextBudgetError extends RequestTokenBudgetError {\n\treadonly source: SourceSnapshotRef;\n\t#compactionKey?: string;\n\t#summaryCapacity?: (retained: ReadonlySet<string>, wrapper: string) => number | undefined;\n\n\tremainingSummaryTokens(retained: ReadonlySet<string>, wrapper: string): number | undefined {\n\t\treturn this.#summaryCapacity?.(retained, wrapper);\n\t}\n\n\tgetCompactionKey(): string | undefined {\n\t\treturn this.#compactionKey;\n\t}\n\n\tconstructor(\n\t\tsource: SourceSnapshotRef,\n\t\tassessment: RequestTokenAssessment,\n\t\treadonly originalAssessment: RequestTokenAssessment,\n\t\treadonly mandatoryAssessment?: RequestTokenAssessment,\n\t\treadonly taskFrameRebaseAvailable = false,\n\t\tcompactionKey?: string,\n\t\tsummaryCapacity?: (retained: ReadonlySet<string>, wrapper: string) => number | undefined,\n\t\treadonly isSourceCurrent?: () => boolean,\n\t) {\n\t\tsuper(assessment);\n\t\tthis.name = \"PublicContextBudgetError\";\n\t\tif (mandatoryAssessment?.status === \"over-budget\")\n\t\t\tthis.message =\n\t\t\t\t\"Context capacity exceeded: instructions, tools, mandatory evidence and output allowance cannot fit. Summarizing unrelated history cannot resolve this request.\";\n\t\tthis.source = Object.freeze({ ...source });\n\t\tthis.#compactionKey = compactionKey;\n\t\tthis.#summaryCapacity = summaryCapacity;\n\t}\n}\n\nexport interface RequestViewCandidate {\n\t/** Session-local Responses ID namespace; a new owner requires a fresh representation. */\n\treadonly responseItemIdentity?: string;\n\treadonly source: SourceSnapshotRef;\n\treadonly selectedUnitIds: readonly string[];\n\treadonly request: ProviderRequestRepresentation;\n\treadonly projection: ProviderRequestProjection;\n\t// Absent only for mandatory full-view admission without a configured token budget.\n\treadonly assessment: RequestTokenAssessment | undefined;\n\treadonly originalAssessment: RequestTokenAssessment | undefined;\n\t/** Exact public messages represented by the accepted candidate, with captured source recipes. */\n\treadonly publicMessages?: readonly AgentMessage[];\n}\n\n/** Root resolves only after its canonical epoch checkpoint ACK. This module owns no epoch state. */\nexport type RequestViewCommit = (\n\tcandidate: RequestViewCandidate,\n) => Promise<ContextEpochEntryRef | undefined> | Promise<void>;\nexport type RequestViewValidate = (\n\trequest: ProviderRequestRepresentation,\n\tassessment: RequestTokenAssessment | undefined,\n) => void;\n\nexport type RequestViewFixedPrepare = (\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tassessment: RequestTokenAssessment | undefined,\n) => ContextEpochEntryRef | void | Promise<ContextEpochEntryRef | undefined> | Promise<void>;\n\nexport interface CapturedRequestViewBoundary extends CanonicalViewSelectionSource {\n\treadonly responseItemIdentity?: string;\n\treadonly messages: readonly AgentMessage[];\n\t/** Provider logical positions mapped to the unchanged canonical messages/units. */\n\treadonly providerMessageIndices: readonly number[];\n\treadonly providerPendingPublicMessageGroups?: readonly (readonly number[])[];\n\treadonly commit: RequestViewCommit;\n\treadonly validate?: RequestViewValidate;\n\treadonly fixedPrepare?: RequestViewFixedPrepare;\n\treadonly isSourceCurrent?: () => boolean;\n}\n\nexport function captureRequestViewBoundary(\n\tmessages: readonly AgentMessage[],\n\tcommit: RequestViewCommit,\n\tvalidate?: RequestViewValidate,\n\tfixedPrepare?: RequestViewFixedPrepare,\n\tisSourceCurrent?: () => boolean,\n): CapturedRequestViewBoundary {\n\tconst source = getCanonicalViewSelectionSource(messages);\n\tif (!source) throw new Error(\"Request view boundary requires compiled canonical messages\");\n\tconst providerMessageIndices = messages.flatMap((message, index) => convertToLlm([message]).map(() => index));\n\treturn {\n\t\t...source,\n\t\tmessages: captureCanonicalRequestMessages(messages),\n\t\tproviderMessageIndices,\n\t\t...(source.pendingPublicMessageGroups\n\t\t\t? {\n\t\t\t\t\tproviderPendingPublicMessageGroups: source.pendingPublicMessageGroups.map((group) =>\n\t\t\t\t\t\tgroup.map((index) => providerMessageIndex(providerMessageIndices, index)),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: {}),\n\t\tcommit,\n\t\tvalidate,\n\t\tfixedPrepare,\n\t\tisSourceCurrent,\n\t};\n}\n\nfunction providerMessageIndex(indices: readonly number[], canonicalIndex: number): number {\n\tconst index = indices.indexOf(canonicalIndex);\n\tif (index < 0) throw new Error(\"Provider projection cannot address a filtered canonical message\");\n\treturn index;\n}\n\n/** Keep canonical UI barriers while translating the native serializer's provider-only positions. */\nfunction canonicalRequestProjection(\n\tboundary: CapturedRequestViewBoundary,\n\tprojection: ProviderRequestProjection,\n): ProviderRequestProjection {\n\tconst indices = boundary.providerMessageIndices;\n\tif (indices.length === boundary.messages.length) return projection;\n\tconst canonicalIndex = (index: number): number => {\n\t\tconst canonical = indices[index];\n\t\tif (canonical === undefined) throw new Error(\"Provider projection message index is outside its captured view\");\n\t\treturn canonical;\n\t};\n\treturn {\n\t\t...projection,\n\t\tmessageIndices: projection.messageIndices.map((index) => (index === null ? null : canonicalIndex(index))),\n\t\t...(projection.optionalMessageIndices\n\t\t\t? { optionalMessageIndices: projection.optionalMessageIndices.map(canonicalIndex) }\n\t\t\t: {}),\n\t\t...(projection.generatedMessageIndices\n\t\t\t? { generatedMessageIndices: projection.generatedMessageIndices.map(canonicalIndex) }\n\t\t\t: {}),\n\t\t...(projection.publicMessageGroups\n\t\t\t? { publicMessageGroups: projection.publicMessageGroups.map((group) => group.map(canonicalIndex)) }\n\t\t\t: {}),\n\t\t...(projection.pendingPublicMessageGroups\n\t\t\t? {\n\t\t\t\t\tpendingPublicMessageGroups: projection.pendingPublicMessageGroups.map((group) =>\n\t\t\t\t\t\tgroup.map(canonicalIndex),\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: {}),\n\t\t...(projection.encodePublicWindow\n\t\t\t? {\n\t\t\t\t\tencodePublicWindow: (replacements: readonly ProviderRequestPublicMessage[]) => {\n\t\t\t\t\t\tconst encoded = projection.encodePublicWindow!(\n\t\t\t\t\t\t\treplacements.map((replacement) => ({\n\t\t\t\t\t\t\t\t...replacement,\n\t\t\t\t\t\t\t\tmessageIndex: providerMessageIndex(indices, replacement.messageIndex),\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tencoded && { ...encoded, projection: canonicalRequestProjection(boundary, encoded.projection) }\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nexport function matchesRequestView(\n\tboundary: CapturedRequestViewBoundary,\n\tsource: SourceSnapshotRef,\n\tcontext: Context,\n): boolean {\n\tconst expected = boundary.source;\n\tif (\n\t\texpected.sessionId !== source.sessionId ||\n\t\texpected.sessionFile !== source.sessionFile ||\n\t\texpected.leafId !== source.leafId ||\n\t\texpected.sourceSequence !== source.sourceSequence\n\t)\n\t\treturn false;\n\tconst rendered = convertToLlm([...boundary.messages]);\n\treturn (\n\t\tboundary.messages.length === boundary.units.length &&\n\t\trendered.length === boundary.providerMessageIndices.length &&\n\t\tJSON.stringify(rendered) === JSON.stringify(context.messages)\n\t);\n}\n\n/** Projection kinds describe their actual provider body, never an OpenAI-format route alias. */\nfunction requestInputKey(\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n): \"input\" | \"messages\" | undefined {\n\tif (\n\t\t(request.api === \"openai-responses\" || request.api === \"openai-codex-responses\") &&\n\t\t(projection.kind === \"openai-responses-text-v1\" || projection.kind === \"openai-responses-replay-v1\")\n\t)\n\t\treturn \"input\";\n\tif (\n\t\trequest.api === \"openai-completions\" &&\n\t\trequest.provider === \"deepseek\" &&\n\t\trequest.url === \"https://api.deepseek.com/chat/completions\" &&\n\t\tprojection.kind === \"deepseek-completions-text-tools-v1\" &&\n\t\trequest.body !== undefined &&\n\t\tJSON.parse(request.body).model === \"deepseek-flash\"\n\t)\n\t\treturn \"messages\";\n\treturn undefined;\n}\n\n/** A lower bound for compaction: fixed policy, current tail and required recorded evidence. */\nfunction publicBudgetFailure(\n\tboundary: CapturedRequestViewBoundary,\n\tmessages: readonly AgentMessage[],\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tbudget: RequestTokenBudgetEvaluator,\n\tassessment: RequestTokenAssessment,\n\toriginal: RequestTokenAssessment,\n): PublicContextBudgetError {\n\tconst context = getCanonicalEpochContext(messages)!;\n\tconst source = getCanonicalViewSelectionSource(messages)!;\n\tconst toolEntries = new Set(\n\t\tcontext.toolContinuations?.flatMap((group) => [\n\t\t\tgroup.assistantEntryId,\n\t\t\t...group.calls.flatMap((call) => (call.result ? [call.result.id] : [])),\n\t\t]),\n\t);\n\tlet tailSequence = -1;\n\tfor (const reference of context.references)\n\t\tif (reference && reference.ref.kind !== \"compaction\")\n\t\t\ttailSequence = Math.max(tailSequence, reference.ref.sequence);\n\tconst required = new Set(\n\t\tsource.units.flatMap((unit, index) => {\n\t\t\tconst reference = context.references[index];\n\t\t\treturn [\"task-frame\", \"resource-view\", \"recovery\"].includes(unit.kind) ||\n\t\t\t\tunit.id === \"native-selected-skill-versions\" ||\n\t\t\t\t(reference && (reference.ref.sequence === tailSequence || toolEntries.has(reference.ref.entryId)))\n\t\t\t\t? [index]\n\t\t\t\t: [];\n\t\t}),\n\t);\n\tconst inputKey = requestInputKey(request, projection)!;\n\tconst body = JSON.parse(request.body!) as Record<string, unknown>;\n\tconst input = body[inputKey];\n\tif (!Array.isArray(input) || input.length !== projection.messageIndices.length)\n\t\treturn new PublicContextBudgetError(\n\t\t\tboundary.source,\n\t\t\tassessment,\n\t\t\toriginal,\n\t\t\tundefined,\n\t\t\tfalse,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tboundary.isSourceCurrent,\n\t\t);\n\tconst graph = prepareViewSelection(source.units, boundary.limits);\n\tconst retainedInput = (retained: ReadonlySet<string>) => {\n\t\tconst roots = source.units\n\t\t\t.filter((_, index) => required.has(index) || retained.has(context.references[index]?.ref.entryId ?? \"\"))\n\t\t\t.map((unit) => unit.id);\n\t\tconst selected = new Set(graph.close(roots).map((unit) => unit.id));\n\t\treturn input.filter((_, index) => {\n\t\t\tconst messageIndex = projection.messageIndices[index];\n\t\t\treturn messageIndex === null || selected.has(source.units[messageIndex].id);\n\t\t});\n\t};\n\tconst minimum = withRequestBody(request, JSON.stringify({ ...body, [inputKey]: retainedInput(new Set()) }));\n\treturn new PublicContextBudgetError(\n\t\tboundary.source,\n\t\tassessment,\n\t\toriginal,\n\t\tbudget.measure(minimum),\n\t\t(context.taskFrame?.messages.length ?? 0) > 1,\n\t\tJSON.stringify([\n\t\t\tboundary.source.sessionId,\n\t\t\tboundary.source.sessionFile,\n\t\t\tsource.units.map((unit) => [unit.id, unit.sourceRevision]),\n\t\t\tassessment.api,\n\t\t\tassessment.provider,\n\t\t\tassessment.model,\n\t\t\tassessment.route,\n\t\t\tassessment.profile,\n\t\t\tassessment.availableInputTokens,\n\t\t\tassessment.outputReserveTokens,\n\t\t]),\n\t\t(retained, wrapper) => {\n\t\t\t// Meter only; this synthetic empty summary is never admitted or sent.\n\t\t\tconst summary =\n\t\t\t\tinputKey === \"messages\"\n\t\t\t\t\t? { role: \"user\", content: wrapper }\n\t\t\t\t\t: { role: \"user\", content: [{ type: \"input_text\", text: wrapper }] };\n\t\t\tconst kept = retainedInput(retained);\n\t\t\tconst position = kept.findIndex((item) => item?.role !== \"system\" && item?.role !== \"developer\");\n\t\t\tkept.splice(position < 0 ? kept.length : position, 0, summary);\n\t\t\tconst measured = budget.measure(withRequestBody(request, JSON.stringify({ ...body, [inputKey]: kept })));\n\t\t\treturn measured.status === \"unknown\" ||\n\t\t\t\tmeasured.availableInputTokens === null ||\n\t\t\t\tmeasured.estimatedInputTokens === null\n\t\t\t\t? undefined\n\t\t\t\t: Math.floor(measured.availableInputTokens - measured.estimatedInputTokens);\n\t\t},\n\t\tboundary.isSourceCurrent,\n\t);\n}\n\n/** Check the actual final mapping without selecting, converting, or committing another view. */\nexport async function prepareFixedRequestView(\n\tboundary: CapturedRequestViewBoundary,\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tassessment: RequestTokenAssessment | undefined,\n) {\n\tprojection = canonicalRequestProjection(boundary, projection);\n\tconst inputKey = requestInputKey(request, projection);\n\tconst payload = JSON.parse(request.body!) as Record<string, unknown> | null;\n\tconst input = inputKey && payload ? payload[inputKey] : undefined;\n\tif (!Array.isArray(input) || input.length !== projection.messageIndices.length)\n\t\tthrow new Error(\"Fixed context requires its final provider projection\");\n\tif (\n\t\tprojection.kind === \"openai-responses-text-v1\" &&\n\t\tboundary.messages.some(\n\t\t\t(message) =>\n\t\t\t\tmessage.role === \"toolResult\" ||\n\t\t\t\t(message.role === \"assistant\" && (message.content.length !== 1 || message.content[0].type !== \"text\")),\n\t\t)\n\t)\n\t\tthrow new Error(\"Fixed context requires its native replay adapter\");\n\tconst units = bindMessageReplayUnits(\n\t\tboundary.messages,\n\t\tboundary.units,\n\t\tboundary.limits,\n\t\tprojection.replayContract ?? \"complete-context\",\n\t);\n\tcloseViewSelection(\n\t\tunits,\n\t\tunits.map((unit) => unit.id),\n\t\tboundary.limits,\n\t);\n\treturn await boundary.fixedPrepare!(request, projection, assessment);\n}\n\n/** Reuse the same legal omission policy for native and already-converted public requests. */\nasync function offerOptionalSubset(\n\tmessages: readonly AgentMessage[],\n\tunits: CanonicalViewSelectionSource[\"units\"],\n\tselection: ReturnType<typeof prepareViewSelection>,\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tbudget: RequestTokenBudgetEvaluator,\n\toffer: (\n\t\tids: readonly string[],\n\t\trequest: ProviderRequestRepresentation,\n\t\tprojection: ProviderRequestProjection,\n\t\tassessment: RequestTokenAssessment,\n\t) => Promise<unknown>,\n): Promise<string | undefined> {\n\tconst inputKey = requestInputKey(request, projection);\n\tif (!inputKey) return;\n\tconst payload = JSON.parse(request.body!) as Record<string, unknown>;\n\tconst input = payload[inputKey];\n\tif (!Array.isArray(input) || input.length !== projection.messageIndices.length) return;\n\tlet latestAssistant = -1;\n\tfor (const [index, message] of messages.entries()) if (message.role === \"assistant\") latestAssistant = index;\n\tconst retained = new Set(projection.messageIndices.slice(0, request.retainedPrefix?.inputItems ?? 0));\n\tconst projectedOptional =\n\t\tprojection.kind !== \"openai-responses-text-v1\" ? new Set(projection.optionalMessageIndices ?? []) : undefined;\n\tconst optional = units.filter((unit, index) => {\n\t\tconst message = messages[index];\n\t\treturn (\n\t\t\tindex !== latestAssistant &&\n\t\t\t!retained.has(index) &&\n\t\t\t(!projectedOptional || projectedOptional.has(index)) &&\n\t\t\tunit.kind === \"literal\" &&\n\t\t\tunit.authority === \"assistant-public\" &&\n\t\t\tmessage.role === \"assistant\" &&\n\t\t\tmessage.stopReason === \"stop\" &&\n\t\t\tmessage.content.length === 1 &&\n\t\t\tmessage.content[0].type === \"text\"\n\t\t);\n\t});\n\tconst generatedPositions = new Map<string, number>();\n\tconst generated =\n\t\tprojection.generatedMessageIndices ??\n\t\tmessages.flatMap((message, index) =>\n\t\t\tmessage.role === \"assistant\" &&\n\t\t\tmessage.content.some((block) => block.type === \"text\" && block.textSignature === undefined)\n\t\t\t\t? [index]\n\t\t\t\t: [],\n\t\t);\n\tfor (const index of generated) generatedPositions.set(units[index].id, index);\n\t// All user inputs, the latest assistant, fixed/TaskFrame/recovery units and errors stay selected.\n\tconst selected = new Set(units.map((unit) => unit.id));\n\tfor (const unit of optional) {\n\t\tselected.delete(unit.id);\n\t\tconst closed = selection.close([...selected]);\n\t\t// Normal Responses rendering uses msg_<message index> for unsigned assistants.\n\t\t// Reject any subset that would change a retained generated item ID on reconstruction.\n\t\tif (closed.some((item, index) => generatedPositions.has(item.id) && generatedPositions.get(item.id) !== index))\n\t\t\tcontinue;\n\t\tconst closedIds = new Set(closed.map((item) => item.id));\n\t\tconst keepItem = (index: number) => {\n\t\t\tconst messageIndex = projection.messageIndices[index];\n\t\t\treturn messageIndex === null || closedIds.has(units[messageIndex].id);\n\t\t};\n\t\tconst body = JSON.stringify({ ...payload, [inputKey]: input.filter((_, index) => keepItem(index)) });\n\t\tconst candidateRequest = { ...request, body };\n\t\tconst assessment = budget.measure(candidateRequest);\n\t\tif (assessment.status !== \"within-estimate\") continue;\n\t\tawait offer(\n\t\t\tclosed.map((item) => item.id),\n\t\t\tcandidateRequest,\n\t\t\t{\n\t\t\t\t...projection,\n\t\t\t\tmessageIndices: projection.messageIndices.filter((_, index) => keepItem(index)),\n\t\t\t\t...(projection.optionalMessageIndices\n\t\t\t\t\t? {\n\t\t\t\t\t\t\toptionalMessageIndices: projection.optionalMessageIndices.filter((index) =>\n\t\t\t\t\t\t\t\tclosedIds.has(units[index].id),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(projection.generatedMessageIndices\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tgeneratedMessageIndices: projection.generatedMessageIndices.filter((index) =>\n\t\t\t\t\t\t\t\tclosedIds.has(units[index].id),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tassessment,\n\t\t);\n\t\treturn body;\n\t}\n\treturn;\n}\n\n/** Only the actual serializer's established replay contract authorizes historical-literal omission. */\nexport async function selectRequestView(\n\tboundary: CapturedRequestViewBoundary,\n\trequest: ProviderRequestRepresentation,\n\tprojection: ProviderRequestProjection,\n\tbudget: RequestTokenBudgetEvaluator | undefined,\n\tallowShrink: boolean,\n\tfinalizeMeasurement?: (\n\t\trequest: ProviderRequestRepresentation,\n\t\tassessment: RequestTokenAssessment | undefined,\n\t) => Promise<RequestTokenAssessment | undefined>,\n): Promise<string | undefined> {\n\tprojection = canonicalRequestProjection(boundary, projection);\n\tlet full = budget?.measure(request);\n\tconst inputKey = requestInputKey(request, projection);\n\tif ((budget && full?.limitSource !== \"explicit-profile\") || !inputKey) return;\n\tif (!budget && !boundary.requiresEpoch && !boundary.pendingPublicMessageGroups?.length) return;\n\tconst payload = JSON.parse(request.body!) as Record<string, unknown>;\n\tconst input = payload[inputKey];\n\tif (!Array.isArray(input) || input.length !== projection.messageIndices.length) return;\n\t// Resolve a near-limit estimate before discarding a stable native prefix. Original\n\t// protected tool groups must first pass their public conversion below.\n\tif (\n\t\tfull?.status === \"over-budget\" &&\n\t\t!boundary.pendingPublicMessageGroups?.length &&\n\t\t!projection.pendingPublicMessageGroups?.length\n\t)\n\t\tfull = (await finalizeMeasurement?.(request, full)) ?? full;\n\n\t// Absence is complete-context; a profile or tool-shaped message is never group authority.\n\tconst replayContract = projection.replayContract ?? \"complete-context\";\n\tif (\n\t\tprojection.kind === \"openai-responses-text-v1\" &&\n\t\tboundary.messages.some(\n\t\t\t(message) =>\n\t\t\t\tmessage.role === \"toolResult\" ||\n\t\t\t\t(message.role === \"assistant\" && (message.content.length !== 1 || message.content[0].type !== \"text\")),\n\t\t)\n\t)\n\t\treturn;\n\tconst units = bindMessageReplayUnits(\n\t\tboundary.messages,\n\t\tboundary.units,\n\t\tboundary.limits,\n\t\treplayContract,\n\t\tboundary.pendingPublicMessageGroups,\n\t);\n\tconst selection = prepareViewSelection(units, boundary.limits);\n\tconst offer = async (\n\t\tselectedUnitIds: readonly string[],\n\t\tcandidateRequest: ProviderRequestRepresentation,\n\t\tcandidateProjection: ProviderRequestProjection,\n\t\tassessment: RequestTokenAssessment | undefined,\n\t\tpublicMessages?: readonly AgentMessage[],\n\t) => {\n\t\tassessment = (await finalizeMeasurement?.(candidateRequest, assessment)) ?? assessment;\n\t\tif (budget && assessment) {\n\t\t\tif (assessment.status === \"over-budget\" && full)\n\t\t\t\tthrow publicBudgetFailure(\n\t\t\t\t\tboundary,\n\t\t\t\t\tpublicMessages ?? boundary.messages,\n\t\t\t\t\tcandidateRequest,\n\t\t\t\t\tcandidateProjection,\n\t\t\t\t\tbudget,\n\t\t\t\t\tassessment,\n\t\t\t\t\tfull,\n\t\t\t\t);\n\t\t\tbudget.assert(assessment);\n\t\t}\n\t\treturn boundary.commit(\n\t\t\tObject.freeze({\n\t\t\t\t...(boundary.responseItemIdentity ? { responseItemIdentity: boundary.responseItemIdentity } : {}),\n\t\t\t\tsource: Object.freeze({ ...boundary.source }),\n\t\t\t\tselectedUnitIds: Object.freeze([...selectedUnitIds]),\n\t\t\t\trequest: Object.freeze({ ...candidateRequest }),\n\t\t\t\tprojection: Object.freeze({\n\t\t\t\t\t...candidateProjection,\n\t\t\t\t\treplayContract,\n\t\t\t\t\tmessageIndices: Object.freeze([...candidateProjection.messageIndices]),\n\t\t\t\t\t...(candidateProjection.optionalMessageIndices\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\toptionalMessageIndices: Object.freeze([...candidateProjection.optionalMessageIndices]),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(candidateProjection.generatedMessageIndices\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tgeneratedMessageIndices: Object.freeze([...candidateProjection.generatedMessageIndices]),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t}),\n\t\t\t\tassessment,\n\t\t\t\toriginalAssessment: full,\n\t\t\t\t...(publicMessages ? { publicMessages } : {}),\n\t\t\t}),\n\t\t);\n\t};\n\tconst offerPublicSubset = async (\n\t\tmessages: readonly AgentMessage[],\n\t\trequest: ProviderRequestRepresentation,\n\t\tprojection: ProviderRequestProjection,\n\t): Promise<string | undefined> => {\n\t\tif (!allowShrink || !budget || replayContract !== \"message-groups\") return;\n\t\tconst source = getCanonicalViewSelectionSource(messages)!;\n\t\tconst units = bindMessageReplayUnits(messages, source.units, boundary.limits, replayContract);\n\t\treturn offerOptionalSubset(\n\t\t\tmessages,\n\t\t\tunits,\n\t\t\tprepareViewSelection(units, boundary.limits),\n\t\t\trequest,\n\t\t\tprojection,\n\t\t\tbudget,\n\t\t\t(ids, candidate, mapping, assessment) => offer(ids, candidate, mapping, assessment, messages),\n\t\t);\n\t};\n\tif (boundary.pendingPublicMessageGroups?.length) {\n\t\tif (\n\t\t\treplayContract !== \"message-groups\" ||\n\t\t\t!projection.publicWindow ||\n\t\t\t!projection.encodePublicWindow ||\n\t\t\tJSON.stringify(projection.pendingPublicMessageGroups) !== JSON.stringify(boundary.pendingPublicMessageGroups)\n\t\t)\n\t\t\tthrow new Error(\"Original tool group requires current native adapter public conversion\");\n\t\tconst publicView = prepareToolContinuationWindow(boundary.messages);\n\t\tconst encoded = projection.encodePublicWindow(publicView.replacements);\n\t\tif (!encoded || encoded.projection.pendingPublicMessageGroups?.length)\n\t\t\tthrow new Error(\"Native adapter did not convert the whole required tool group\");\n\t\tconst publicSource = getCanonicalViewSelectionSource(publicView.messages)!;\n\t\tconst publicUnits = bindMessageReplayUnits(\n\t\t\tpublicView.messages,\n\t\t\tpublicSource.units,\n\t\t\tboundary.limits,\n\t\t\treplayContract,\n\t\t);\n\t\tconst closed = closeViewSelection(\n\t\t\tpublicUnits,\n\t\t\tpublicUnits.map((unit) => unit.id),\n\t\t\tboundary.limits,\n\t\t);\n\t\tlet assessment = budget?.measure(encoded.request);\n\t\tif (assessment?.status === \"over-budget\")\n\t\t\tassessment = (await finalizeMeasurement?.(encoded.request, assessment)) ?? assessment;\n\t\tif (assessment && full) {\n\t\t\tif (assessment.status === \"over-budget\") {\n\t\t\t\tconst subset = await offerPublicSubset(publicView.messages, encoded.request, encoded.projection);\n\t\t\t\tif (subset !== undefined) return subset;\n\t\t\t\tthrow publicBudgetFailure(\n\t\t\t\t\tboundary,\n\t\t\t\t\tpublicView.messages,\n\t\t\t\t\tencoded.request,\n\t\t\t\t\tencoded.projection,\n\t\t\t\t\tbudget!,\n\t\t\t\t\tassessment,\n\t\t\t\t\tfull,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (assessment.status !== \"within-estimate\")\n\t\t\t\tthrow new Error(\"Tool continuation public request exceeds its token budget\");\n\t\t}\n\t\tawait offer(\n\t\t\tclosed.map((unit) => unit.id),\n\t\t\tencoded.request,\n\t\t\tencoded.projection,\n\t\t\tassessment,\n\t\t\tpublicView.messages,\n\t\t);\n\t\treturn encoded.request.body;\n\t}\n\tif (projection.pendingPublicMessageGroups?.length)\n\t\tthrow new Error(\"Adapter pending group has no original owned source plan\");\n\t// Without a configured budget, admit only the exact full native view. Never shrink it.\n\tif (!budget) {\n\t\tconst closed = selection.close(units.map((unit) => unit.id));\n\t\tawait offer(\n\t\t\tclosed.map((unit) => unit.id),\n\t\t\trequest,\n\t\t\tprojection,\n\t\t\tundefined,\n\t\t);\n\t\treturn request.body;\n\t}\n\tif (!full) return;\n\tconst offerPublicWindow = async (): Promise<string | undefined> => {\n\t\tif (\n\t\t\t!allowShrink ||\n\t\t\treplayContract !== \"message-groups\" ||\n\t\t\t!projection.publicWindow ||\n\t\t\t!projection.encodePublicWindow\n\t\t)\n\t\t\treturn;\n\t\tconst closed = selection.close(units.map((unit) => unit.id));\n\t\tlet firstMessageIndex = 0;\n\t\tif (\n\t\t\tfull.status === \"unknown\" &&\n\t\t\tfull.unknown.length === 1 &&\n\t\t\tfull.unknown[0] === \"media, opaque or unsupported replay token coverage unknown\"\n\t\t) {\n\t\t\t// Credited items are not part of the unknown input. Keep original projection indices.\n\t\t\tconst firstUnmeteredItem = request.retainedPrefix?.inputItems ?? 0;\n\t\t\tconst reasoningItemIndex = input.findIndex(\n\t\t\t\t(item, index) => index >= firstUnmeteredItem && item?.type === \"reasoning\",\n\t\t\t);\n\t\t\tconst messageIndex = projection.messageIndices[reasoningItemIndex];\n\t\t\tconst group =\n\t\t\t\tmessageIndex == null\n\t\t\t\t\t? undefined\n\t\t\t\t\t: projection.publicMessageGroups?.find((members) => members.includes(messageIndex));\n\t\t\t// The adapter still accepts only complete groups; earlier meterable groups stay native.\n\t\t\tfirstMessageIndex = group ? Math.min(...group) : 0;\n\t\t}\n\t\tconst publicView = preparePublicContextWindow(boundary.messages, firstMessageIndex);\n\t\tif (!publicView) {\n\t\t\t// Keep the original measured refusal when no public conversion can be offered.\n\t\t\t// This is not a new recovery signal or permission to reprepare again.\n\t\t\tif (full.status === \"over-budget\") throw new RequestTokenBudgetError(full);\n\t\t\treturn;\n\t\t}\n\t\tconst encoded = projection.encodePublicWindow(publicView.replacements);\n\t\tif (!encoded) return;\n\t\tlet assessment = budget.measure(encoded.request);\n\t\tif (assessment.status === \"over-budget\")\n\t\t\tassessment = (await finalizeMeasurement?.(encoded.request, assessment)) ?? assessment;\n\t\tif (assessment.status === \"over-budget\") {\n\t\t\tconst subset = await offerPublicSubset(publicView.messages, encoded.request, encoded.projection);\n\t\t\tif (subset !== undefined) return subset;\n\t\t\tthrow publicBudgetFailure(\n\t\t\t\tboundary,\n\t\t\t\tpublicView.messages,\n\t\t\t\tencoded.request,\n\t\t\t\tencoded.projection,\n\t\t\t\tbudget,\n\t\t\t\tassessment,\n\t\t\t\tfull,\n\t\t\t);\n\t\t}\n\t\tif (assessment.status !== \"within-estimate\") return;\n\t\tawait offer(\n\t\t\tclosed.map((unit) => unit.id),\n\t\t\tencoded.request,\n\t\t\tencoded.projection,\n\t\t\tassessment,\n\t\t\tpublicView.messages,\n\t\t);\n\t\treturn encoded.request.body;\n\t};\n\tif (full.status === \"within-estimate\") {\n\t\tconst closed = selection.close(units.map((unit) => unit.id));\n\t\tawait offer(\n\t\t\tclosed.map((unit) => unit.id),\n\t\t\trequest,\n\t\t\tprojection,\n\t\t\tfull,\n\t\t);\n\t\treturn request.body;\n\t}\n\tif (!allowShrink || replayContract !== \"message-groups\") return;\n\tif (full.status !== \"over-budget\") return offerPublicWindow();\n\tconst subset = await offerOptionalSubset(boundary.messages, units, selection, request, projection, budget, offer);\n\tif (subset !== undefined) return subset;\n\treturn offerPublicWindow();\n}\n"]}
@@ -1,19 +1,38 @@
1
- import { RequestTokenBudgetError, } from "@ponythewhite/base-context-ai";
2
- import { captureCanonicalRequestMessages, getCanonicalViewSelectionSource, preparePublicContextWindow, prepareToolContinuationWindow, } from "./canonical-context.js";
1
+ import { RequestTokenBudgetError, withRequestBody, } from "@ponythewhite/base-context-ai";
2
+ import { captureCanonicalRequestMessages, getCanonicalEpochContext, getCanonicalViewSelectionSource, preparePublicContextWindow, prepareToolContinuationWindow, } from "./canonical-context.js";
3
3
  import { convertToLlm } from "./messages.js";
4
- import { bindMessageReplayUnits, closeViewSelection } from "./view-units.js";
4
+ import { bindMessageReplayUnits, closeViewSelection, prepareViewSelection } from "./view-units.js";
5
5
  /** Actual adapter-public measurement, not a verdict about the opaque native request. */
6
6
  export class PublicContextBudgetError extends RequestTokenBudgetError {
7
7
  originalAssessment;
8
+ mandatoryAssessment;
9
+ taskFrameRebaseAvailable;
10
+ isSourceCurrent;
8
11
  source;
9
- constructor(source, assessment, originalAssessment) {
12
+ #compactionKey;
13
+ #summaryCapacity;
14
+ remainingSummaryTokens(retained, wrapper) {
15
+ return this.#summaryCapacity?.(retained, wrapper);
16
+ }
17
+ getCompactionKey() {
18
+ return this.#compactionKey;
19
+ }
20
+ constructor(source, assessment, originalAssessment, mandatoryAssessment, taskFrameRebaseAvailable = false, compactionKey, summaryCapacity, isSourceCurrent) {
10
21
  super(assessment);
11
22
  this.originalAssessment = originalAssessment;
23
+ this.mandatoryAssessment = mandatoryAssessment;
24
+ this.taskFrameRebaseAvailable = taskFrameRebaseAvailable;
25
+ this.isSourceCurrent = isSourceCurrent;
12
26
  this.name = "PublicContextBudgetError";
27
+ if (mandatoryAssessment?.status === "over-budget")
28
+ this.message =
29
+ "Context capacity exceeded: instructions, tools, mandatory evidence and output allowance cannot fit. Summarizing unrelated history cannot resolve this request.";
13
30
  this.source = Object.freeze({ ...source });
31
+ this.#compactionKey = compactionKey;
32
+ this.#summaryCapacity = summaryCapacity;
14
33
  }
15
34
  }
16
- export function captureRequestViewBoundary(messages, commit, validate, fixedPrepare) {
35
+ export function captureRequestViewBoundary(messages, commit, validate, fixedPrepare, isSourceCurrent) {
17
36
  const source = getCanonicalViewSelectionSource(messages);
18
37
  if (!source)
19
38
  throw new Error("Request view boundary requires compiled canonical messages");
@@ -30,6 +49,7 @@ export function captureRequestViewBoundary(messages, commit, validate, fixedPrep
30
49
  commit,
31
50
  validate,
32
51
  fixedPrepare,
52
+ isSourceCurrent,
33
53
  };
34
54
  }
35
55
  function providerMessageIndex(indices, canonicalIndex) {
@@ -105,6 +125,70 @@ function requestInputKey(request, projection) {
105
125
  return "messages";
106
126
  return undefined;
107
127
  }
128
+ /** A lower bound for compaction: fixed policy, current tail and required recorded evidence. */
129
+ function publicBudgetFailure(boundary, messages, request, projection, budget, assessment, original) {
130
+ const context = getCanonicalEpochContext(messages);
131
+ const source = getCanonicalViewSelectionSource(messages);
132
+ const toolEntries = new Set(context.toolContinuations?.flatMap((group) => [
133
+ group.assistantEntryId,
134
+ ...group.calls.flatMap((call) => (call.result ? [call.result.id] : [])),
135
+ ]));
136
+ let tailSequence = -1;
137
+ for (const reference of context.references)
138
+ if (reference && reference.ref.kind !== "compaction")
139
+ tailSequence = Math.max(tailSequence, reference.ref.sequence);
140
+ const required = new Set(source.units.flatMap((unit, index) => {
141
+ const reference = context.references[index];
142
+ return ["task-frame", "resource-view", "recovery"].includes(unit.kind) ||
143
+ unit.id === "native-selected-skill-versions" ||
144
+ (reference && (reference.ref.sequence === tailSequence || toolEntries.has(reference.ref.entryId)))
145
+ ? [index]
146
+ : [];
147
+ }));
148
+ const inputKey = requestInputKey(request, projection);
149
+ const body = JSON.parse(request.body);
150
+ const input = body[inputKey];
151
+ if (!Array.isArray(input) || input.length !== projection.messageIndices.length)
152
+ return new PublicContextBudgetError(boundary.source, assessment, original, undefined, false, undefined, undefined, boundary.isSourceCurrent);
153
+ const graph = prepareViewSelection(source.units, boundary.limits);
154
+ const retainedInput = (retained) => {
155
+ const roots = source.units
156
+ .filter((_, index) => required.has(index) || retained.has(context.references[index]?.ref.entryId ?? ""))
157
+ .map((unit) => unit.id);
158
+ const selected = new Set(graph.close(roots).map((unit) => unit.id));
159
+ return input.filter((_, index) => {
160
+ const messageIndex = projection.messageIndices[index];
161
+ return messageIndex === null || selected.has(source.units[messageIndex].id);
162
+ });
163
+ };
164
+ const minimum = withRequestBody(request, JSON.stringify({ ...body, [inputKey]: retainedInput(new Set()) }));
165
+ return new PublicContextBudgetError(boundary.source, assessment, original, budget.measure(minimum), (context.taskFrame?.messages.length ?? 0) > 1, JSON.stringify([
166
+ boundary.source.sessionId,
167
+ boundary.source.sessionFile,
168
+ source.units.map((unit) => [unit.id, unit.sourceRevision]),
169
+ assessment.api,
170
+ assessment.provider,
171
+ assessment.model,
172
+ assessment.route,
173
+ assessment.profile,
174
+ assessment.availableInputTokens,
175
+ assessment.outputReserveTokens,
176
+ ]), (retained, wrapper) => {
177
+ // Meter only; this synthetic empty summary is never admitted or sent.
178
+ const summary = inputKey === "messages"
179
+ ? { role: "user", content: wrapper }
180
+ : { role: "user", content: [{ type: "input_text", text: wrapper }] };
181
+ const kept = retainedInput(retained);
182
+ const position = kept.findIndex((item) => item?.role !== "system" && item?.role !== "developer");
183
+ kept.splice(position < 0 ? kept.length : position, 0, summary);
184
+ const measured = budget.measure(withRequestBody(request, JSON.stringify({ ...body, [inputKey]: kept })));
185
+ return measured.status === "unknown" ||
186
+ measured.availableInputTokens === null ||
187
+ measured.estimatedInputTokens === null
188
+ ? undefined
189
+ : Math.floor(measured.availableInputTokens - measured.estimatedInputTokens);
190
+ }, boundary.isSourceCurrent);
191
+ }
108
192
  /** Check the actual final mapping without selecting, converting, or committing another view. */
109
193
  export async function prepareFixedRequestView(boundary, request, projection, assessment) {
110
194
  projection = canonicalRequestProjection(boundary, projection);
@@ -121,19 +205,97 @@ export async function prepareFixedRequestView(boundary, request, projection, ass
121
205
  closeViewSelection(units, units.map((unit) => unit.id), boundary.limits);
122
206
  return await boundary.fixedPrepare(request, projection, assessment);
123
207
  }
208
+ /** Reuse the same legal omission policy for native and already-converted public requests. */
209
+ async function offerOptionalSubset(messages, units, selection, request, projection, budget, offer) {
210
+ const inputKey = requestInputKey(request, projection);
211
+ if (!inputKey)
212
+ return;
213
+ const payload = JSON.parse(request.body);
214
+ const input = payload[inputKey];
215
+ if (!Array.isArray(input) || input.length !== projection.messageIndices.length)
216
+ return;
217
+ let latestAssistant = -1;
218
+ for (const [index, message] of messages.entries())
219
+ if (message.role === "assistant")
220
+ latestAssistant = index;
221
+ const retained = new Set(projection.messageIndices.slice(0, request.retainedPrefix?.inputItems ?? 0));
222
+ const projectedOptional = projection.kind !== "openai-responses-text-v1" ? new Set(projection.optionalMessageIndices ?? []) : undefined;
223
+ const optional = units.filter((unit, index) => {
224
+ const message = messages[index];
225
+ return (index !== latestAssistant &&
226
+ !retained.has(index) &&
227
+ (!projectedOptional || projectedOptional.has(index)) &&
228
+ unit.kind === "literal" &&
229
+ unit.authority === "assistant-public" &&
230
+ message.role === "assistant" &&
231
+ message.stopReason === "stop" &&
232
+ message.content.length === 1 &&
233
+ message.content[0].type === "text");
234
+ });
235
+ const generatedPositions = new Map();
236
+ const generated = projection.generatedMessageIndices ??
237
+ messages.flatMap((message, index) => message.role === "assistant" &&
238
+ message.content.some((block) => block.type === "text" && block.textSignature === undefined)
239
+ ? [index]
240
+ : []);
241
+ for (const index of generated)
242
+ generatedPositions.set(units[index].id, index);
243
+ // All user inputs, the latest assistant, fixed/TaskFrame/recovery units and errors stay selected.
244
+ const selected = new Set(units.map((unit) => unit.id));
245
+ for (const unit of optional) {
246
+ selected.delete(unit.id);
247
+ const closed = selection.close([...selected]);
248
+ // Normal Responses rendering uses msg_<message index> for unsigned assistants.
249
+ // Reject any subset that would change a retained generated item ID on reconstruction.
250
+ if (closed.some((item, index) => generatedPositions.has(item.id) && generatedPositions.get(item.id) !== index))
251
+ continue;
252
+ const closedIds = new Set(closed.map((item) => item.id));
253
+ const keepItem = (index) => {
254
+ const messageIndex = projection.messageIndices[index];
255
+ return messageIndex === null || closedIds.has(units[messageIndex].id);
256
+ };
257
+ const body = JSON.stringify({ ...payload, [inputKey]: input.filter((_, index) => keepItem(index)) });
258
+ const candidateRequest = { ...request, body };
259
+ const assessment = budget.measure(candidateRequest);
260
+ if (assessment.status !== "within-estimate")
261
+ continue;
262
+ await offer(closed.map((item) => item.id), candidateRequest, {
263
+ ...projection,
264
+ messageIndices: projection.messageIndices.filter((_, index) => keepItem(index)),
265
+ ...(projection.optionalMessageIndices
266
+ ? {
267
+ optionalMessageIndices: projection.optionalMessageIndices.filter((index) => closedIds.has(units[index].id)),
268
+ }
269
+ : {}),
270
+ ...(projection.generatedMessageIndices
271
+ ? {
272
+ generatedMessageIndices: projection.generatedMessageIndices.filter((index) => closedIds.has(units[index].id)),
273
+ }
274
+ : {}),
275
+ }, assessment);
276
+ return body;
277
+ }
278
+ return;
279
+ }
124
280
  /** Only the actual serializer's established replay contract authorizes historical-literal omission. */
125
- export async function selectRequestView(boundary, request, projection, budget, allowShrink) {
281
+ export async function selectRequestView(boundary, request, projection, budget, allowShrink, finalizeMeasurement) {
126
282
  projection = canonicalRequestProjection(boundary, projection);
127
- const full = budget?.measure(request);
283
+ let full = budget?.measure(request);
128
284
  const inputKey = requestInputKey(request, projection);
129
285
  if ((budget && full?.limitSource !== "explicit-profile") || !inputKey)
130
286
  return;
131
- if (!budget && !boundary.pendingPublicMessageGroups?.length)
287
+ if (!budget && !boundary.requiresEpoch && !boundary.pendingPublicMessageGroups?.length)
132
288
  return;
133
289
  const payload = JSON.parse(request.body);
134
290
  const input = payload[inputKey];
135
291
  if (!Array.isArray(input) || input.length !== projection.messageIndices.length)
136
292
  return;
293
+ // Resolve a near-limit estimate before discarding a stable native prefix. Original
294
+ // protected tool groups must first pass their public conversion below.
295
+ if (full?.status === "over-budget" &&
296
+ !boundary.pendingPublicMessageGroups?.length &&
297
+ !projection.pendingPublicMessageGroups?.length)
298
+ full = (await finalizeMeasurement?.(request, full)) ?? full;
137
299
  // Absence is complete-context; a profile or tool-shaped message is never group authority.
138
300
  const replayContract = projection.replayContract ?? "complete-context";
139
301
  if (projection.kind === "openai-responses-text-v1" &&
@@ -141,29 +303,46 @@ export async function selectRequestView(boundary, request, projection, budget, a
141
303
  (message.role === "assistant" && (message.content.length !== 1 || message.content[0].type !== "text"))))
142
304
  return;
143
305
  const units = bindMessageReplayUnits(boundary.messages, boundary.units, boundary.limits, replayContract, boundary.pendingPublicMessageGroups);
144
- const offer = async (selectedUnitIds, candidateRequest, candidateProjection, assessment, publicMessages) => boundary.commit(Object.freeze({
145
- source: Object.freeze({ ...boundary.source }),
146
- selectedUnitIds: Object.freeze([...selectedUnitIds]),
147
- request: Object.freeze({ ...candidateRequest }),
148
- projection: Object.freeze({
149
- ...candidateProjection,
150
- replayContract,
151
- messageIndices: Object.freeze([...candidateProjection.messageIndices]),
152
- ...(candidateProjection.optionalMessageIndices
153
- ? {
154
- optionalMessageIndices: Object.freeze([...candidateProjection.optionalMessageIndices]),
155
- }
156
- : {}),
157
- ...(candidateProjection.generatedMessageIndices
158
- ? {
159
- generatedMessageIndices: Object.freeze([...candidateProjection.generatedMessageIndices]),
160
- }
161
- : {}),
162
- }),
163
- assessment,
164
- originalAssessment: full,
165
- ...(publicMessages ? { publicMessages } : {}),
166
- }));
306
+ const selection = prepareViewSelection(units, boundary.limits);
307
+ const offer = async (selectedUnitIds, candidateRequest, candidateProjection, assessment, publicMessages) => {
308
+ assessment = (await finalizeMeasurement?.(candidateRequest, assessment)) ?? assessment;
309
+ if (budget && assessment) {
310
+ if (assessment.status === "over-budget" && full)
311
+ throw publicBudgetFailure(boundary, publicMessages ?? boundary.messages, candidateRequest, candidateProjection, budget, assessment, full);
312
+ budget.assert(assessment);
313
+ }
314
+ return boundary.commit(Object.freeze({
315
+ ...(boundary.responseItemIdentity ? { responseItemIdentity: boundary.responseItemIdentity } : {}),
316
+ source: Object.freeze({ ...boundary.source }),
317
+ selectedUnitIds: Object.freeze([...selectedUnitIds]),
318
+ request: Object.freeze({ ...candidateRequest }),
319
+ projection: Object.freeze({
320
+ ...candidateProjection,
321
+ replayContract,
322
+ messageIndices: Object.freeze([...candidateProjection.messageIndices]),
323
+ ...(candidateProjection.optionalMessageIndices
324
+ ? {
325
+ optionalMessageIndices: Object.freeze([...candidateProjection.optionalMessageIndices]),
326
+ }
327
+ : {}),
328
+ ...(candidateProjection.generatedMessageIndices
329
+ ? {
330
+ generatedMessageIndices: Object.freeze([...candidateProjection.generatedMessageIndices]),
331
+ }
332
+ : {}),
333
+ }),
334
+ assessment,
335
+ originalAssessment: full,
336
+ ...(publicMessages ? { publicMessages } : {}),
337
+ }));
338
+ };
339
+ const offerPublicSubset = async (messages, request, projection) => {
340
+ if (!allowShrink || !budget || replayContract !== "message-groups")
341
+ return;
342
+ const source = getCanonicalViewSelectionSource(messages);
343
+ const units = bindMessageReplayUnits(messages, source.units, boundary.limits, replayContract);
344
+ return offerOptionalSubset(messages, units, prepareViewSelection(units, boundary.limits), request, projection, budget, (ids, candidate, mapping, assessment) => offer(ids, candidate, mapping, assessment, messages));
345
+ };
167
346
  if (boundary.pendingPublicMessageGroups?.length) {
168
347
  if (replayContract !== "message-groups" ||
169
348
  !projection.publicWindow ||
@@ -177,10 +356,16 @@ export async function selectRequestView(boundary, request, projection, budget, a
177
356
  const publicSource = getCanonicalViewSelectionSource(publicView.messages);
178
357
  const publicUnits = bindMessageReplayUnits(publicView.messages, publicSource.units, boundary.limits, replayContract);
179
358
  const closed = closeViewSelection(publicUnits, publicUnits.map((unit) => unit.id), boundary.limits);
180
- const assessment = budget?.measure(encoded.request);
359
+ let assessment = budget?.measure(encoded.request);
360
+ if (assessment?.status === "over-budget")
361
+ assessment = (await finalizeMeasurement?.(encoded.request, assessment)) ?? assessment;
181
362
  if (assessment && full) {
182
- if (assessment.status === "over-budget")
183
- throw new PublicContextBudgetError(boundary.source, assessment, full);
363
+ if (assessment.status === "over-budget") {
364
+ const subset = await offerPublicSubset(publicView.messages, encoded.request, encoded.projection);
365
+ if (subset !== undefined)
366
+ return subset;
367
+ throw publicBudgetFailure(boundary, publicView.messages, encoded.request, encoded.projection, budget, assessment, full);
368
+ }
184
369
  if (assessment.status !== "within-estimate")
185
370
  throw new Error("Tool continuation public request exceeds its token budget");
186
371
  }
@@ -189,8 +374,13 @@ export async function selectRequestView(boundary, request, projection, budget, a
189
374
  }
190
375
  if (projection.pendingPublicMessageGroups?.length)
191
376
  throw new Error("Adapter pending group has no original owned source plan");
192
- // Unbudgeted admission above retains every source unit; it never selects a smaller view.
193
- if (!budget || !full)
377
+ // Without a configured budget, admit only the exact full native view. Never shrink it.
378
+ if (!budget) {
379
+ const closed = selection.close(units.map((unit) => unit.id));
380
+ await offer(closed.map((unit) => unit.id), request, projection, undefined);
381
+ return request.body;
382
+ }
383
+ if (!full)
194
384
  return;
195
385
  const offerPublicWindow = async () => {
196
386
  if (!allowShrink ||
@@ -198,7 +388,7 @@ export async function selectRequestView(boundary, request, projection, budget, a
198
388
  !projection.publicWindow ||
199
389
  !projection.encodePublicWindow)
200
390
  return;
201
- const closed = closeViewSelection(units, units.map((unit) => unit.id), boundary.limits);
391
+ const closed = selection.close(units.map((unit) => unit.id));
202
392
  let firstMessageIndex = 0;
203
393
  if (full.status === "unknown" &&
204
394
  full.unknown.length === 1 &&
@@ -224,16 +414,22 @@ export async function selectRequestView(boundary, request, projection, budget, a
224
414
  const encoded = projection.encodePublicWindow(publicView.replacements);
225
415
  if (!encoded)
226
416
  return;
227
- const assessment = budget.measure(encoded.request);
417
+ let assessment = budget.measure(encoded.request);
228
418
  if (assessment.status === "over-budget")
229
- throw new PublicContextBudgetError(boundary.source, assessment, full);
419
+ assessment = (await finalizeMeasurement?.(encoded.request, assessment)) ?? assessment;
420
+ if (assessment.status === "over-budget") {
421
+ const subset = await offerPublicSubset(publicView.messages, encoded.request, encoded.projection);
422
+ if (subset !== undefined)
423
+ return subset;
424
+ throw publicBudgetFailure(boundary, publicView.messages, encoded.request, encoded.projection, budget, assessment, full);
425
+ }
230
426
  if (assessment.status !== "within-estimate")
231
427
  return;
232
428
  await offer(closed.map((unit) => unit.id), encoded.request, encoded.projection, assessment, publicView.messages);
233
429
  return encoded.request.body;
234
430
  };
235
431
  if (full.status === "within-estimate") {
236
- const closed = closeViewSelection(units, units.map((unit) => unit.id), boundary.limits);
432
+ const closed = selection.close(units.map((unit) => unit.id));
237
433
  await offer(closed.map((unit) => unit.id), request, projection, full);
238
434
  return request.body;
239
435
  }
@@ -241,67 +437,9 @@ export async function selectRequestView(boundary, request, projection, budget, a
241
437
  return;
242
438
  if (full.status !== "over-budget")
243
439
  return offerPublicWindow();
244
- let latestAssistant = -1;
245
- for (const [index, message] of boundary.messages.entries())
246
- if (message.role === "assistant")
247
- latestAssistant = index;
248
- const retained = new Set(projection.messageIndices.slice(0, request.retainedPrefix?.inputItems ?? 0));
249
- const projectedOptional = projection.kind !== "openai-responses-text-v1" ? new Set(projection.optionalMessageIndices ?? []) : undefined;
250
- const optional = units.filter((unit, index) => {
251
- const message = boundary.messages[index];
252
- return (index !== latestAssistant &&
253
- !retained.has(index) &&
254
- (!projectedOptional || projectedOptional.has(index)) &&
255
- unit.kind === "literal" &&
256
- unit.authority === "assistant-public" &&
257
- message.role === "assistant" &&
258
- message.stopReason === "stop" &&
259
- message.content.length === 1 &&
260
- message.content[0].type === "text");
261
- });
262
- const generatedPositions = new Map();
263
- const generated = projection.generatedMessageIndices ??
264
- boundary.messages.flatMap((message, index) => message.role === "assistant" &&
265
- message.content.some((block) => block.type === "text" && block.textSignature === undefined)
266
- ? [index]
267
- : []);
268
- for (const index of generated)
269
- generatedPositions.set(units[index].id, index);
270
- // All user inputs, the latest assistant, fixed/TaskFrame/recovery units and errors stay selected.
271
- const selected = new Set(units.map((unit) => unit.id));
272
- for (const unit of optional) {
273
- selected.delete(unit.id);
274
- const closed = closeViewSelection(units, [...selected], boundary.limits);
275
- // Normal Responses rendering uses msg_<message index> for unsigned assistants.
276
- // Reject any subset that would change a retained generated item ID on reconstruction.
277
- if (closed.some((item, index) => generatedPositions.has(item.id) && generatedPositions.get(item.id) !== index))
278
- continue;
279
- const closedIds = new Set(closed.map((item) => item.id));
280
- const keepItem = (index) => {
281
- const messageIndex = projection.messageIndices[index];
282
- return messageIndex === null || closedIds.has(units[messageIndex].id);
283
- };
284
- const body = JSON.stringify({ ...payload, [inputKey]: input.filter((_, index) => keepItem(index)) });
285
- const candidateRequest = { ...request, body };
286
- const assessment = budget.measure(candidateRequest);
287
- if (assessment.status !== "within-estimate")
288
- continue;
289
- await offer(closed.map((item) => item.id), candidateRequest, {
290
- ...projection,
291
- messageIndices: projection.messageIndices.filter((_, index) => keepItem(index)),
292
- ...(projection.optionalMessageIndices
293
- ? {
294
- optionalMessageIndices: projection.optionalMessageIndices.filter((index) => closedIds.has(units[index].id)),
295
- }
296
- : {}),
297
- ...(projection.generatedMessageIndices
298
- ? {
299
- generatedMessageIndices: projection.generatedMessageIndices.filter((index) => closedIds.has(units[index].id)),
300
- }
301
- : {}),
302
- }, assessment);
303
- return body;
304
- }
440
+ const subset = await offerOptionalSubset(boundary.messages, units, selection, request, projection, budget, offer);
441
+ if (subset !== undefined)
442
+ return subset;
305
443
  return offerPublicWindow();
306
444
  }
307
445
  //# sourceMappingURL=request-view-selection.js.map