@wudao-org/providers 0.0.0-stage → 0.4.21

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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +8 -2
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/anthropic.d.ts +19 -0
  5. package/dist/anthropic.d.ts.map +1 -0
  6. package/dist/anthropic.js +621 -0
  7. package/dist/anthropic.js.map +1 -0
  8. package/dist/balance.d.ts +28 -0
  9. package/dist/balance.d.ts.map +1 -0
  10. package/dist/balance.js +105 -0
  11. package/dist/balance.js.map +1 -0
  12. package/dist/config.d.ts +328 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +623 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/dispatcher.d.ts +5 -0
  17. package/dist/dispatcher.d.ts.map +1 -0
  18. package/dist/dispatcher.js +21 -0
  19. package/dist/dispatcher.js.map +1 -0
  20. package/dist/effort-catalog.d.ts +17 -0
  21. package/dist/effort-catalog.d.ts.map +1 -0
  22. package/dist/effort-catalog.js +73 -0
  23. package/dist/effort-catalog.js.map +1 -0
  24. package/dist/error-body.d.ts +32 -0
  25. package/dist/error-body.d.ts.map +1 -0
  26. package/dist/error-body.js +74 -0
  27. package/dist/error-body.js.map +1 -0
  28. package/dist/header-validation.d.ts +57 -0
  29. package/dist/header-validation.d.ts.map +1 -0
  30. package/dist/header-validation.js +130 -0
  31. package/dist/header-validation.js.map +1 -0
  32. package/dist/index.d.ts +42 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +110 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/json-arguments.d.ts +17 -0
  37. package/dist/json-arguments.d.ts.map +1 -0
  38. package/dist/json-arguments.js +227 -0
  39. package/dist/json-arguments.js.map +1 -0
  40. package/dist/key-pool.d.ts +66 -0
  41. package/dist/key-pool.d.ts.map +1 -0
  42. package/dist/key-pool.js +207 -0
  43. package/dist/key-pool.js.map +1 -0
  44. package/dist/missing-reasoning-circuit.d.ts +17 -0
  45. package/dist/missing-reasoning-circuit.d.ts.map +1 -0
  46. package/dist/missing-reasoning-circuit.js +38 -0
  47. package/dist/missing-reasoning-circuit.js.map +1 -0
  48. package/dist/model-failure.d.ts +156 -0
  49. package/dist/model-failure.d.ts.map +1 -0
  50. package/dist/model-failure.js +253 -0
  51. package/dist/model-failure.js.map +1 -0
  52. package/dist/model-fallback.d.ts +18 -0
  53. package/dist/model-fallback.d.ts.map +1 -0
  54. package/dist/model-fallback.js +87 -0
  55. package/dist/model-fallback.js.map +1 -0
  56. package/dist/models.d.ts +20 -0
  57. package/dist/models.d.ts.map +1 -0
  58. package/dist/models.js +55 -0
  59. package/dist/models.js.map +1 -0
  60. package/dist/openai-compatible.d.ts +87 -0
  61. package/dist/openai-compatible.d.ts.map +1 -0
  62. package/dist/openai-compatible.js +368 -0
  63. package/dist/openai-compatible.js.map +1 -0
  64. package/dist/openai-engine.d.ts +18 -0
  65. package/dist/openai-engine.d.ts.map +1 -0
  66. package/dist/openai-engine.js +515 -0
  67. package/dist/openai-engine.js.map +1 -0
  68. package/dist/openai-images.d.ts +38 -0
  69. package/dist/openai-images.d.ts.map +1 -0
  70. package/dist/openai-images.js +301 -0
  71. package/dist/openai-images.js.map +1 -0
  72. package/dist/openai-messages.d.ts +40 -0
  73. package/dist/openai-messages.d.ts.map +1 -0
  74. package/dist/openai-messages.js +135 -0
  75. package/dist/openai-messages.js.map +1 -0
  76. package/dist/openai-wire.d.ts +93 -0
  77. package/dist/openai-wire.d.ts.map +1 -0
  78. package/dist/openai-wire.js +151 -0
  79. package/dist/openai-wire.js.map +1 -0
  80. package/dist/persona/apply.d.ts +19 -0
  81. package/dist/persona/apply.d.ts.map +1 -0
  82. package/dist/persona/apply.js +98 -0
  83. package/dist/persona/apply.js.map +1 -0
  84. package/dist/persona/builtins.d.ts +3 -0
  85. package/dist/persona/builtins.d.ts.map +1 -0
  86. package/dist/persona/builtins.js +180 -0
  87. package/dist/persona/builtins.js.map +1 -0
  88. package/dist/persona/decorator.d.ts +4 -0
  89. package/dist/persona/decorator.d.ts.map +1 -0
  90. package/dist/persona/decorator.js +112 -0
  91. package/dist/persona/decorator.js.map +1 -0
  92. package/dist/persona/files.d.ts +20 -0
  93. package/dist/persona/files.d.ts.map +1 -0
  94. package/dist/persona/files.js +84 -0
  95. package/dist/persona/files.js.map +1 -0
  96. package/dist/persona/ids.d.ts +9 -0
  97. package/dist/persona/ids.d.ts.map +1 -0
  98. package/dist/persona/ids.js +11 -0
  99. package/dist/persona/ids.js.map +1 -0
  100. package/dist/persona/registry.d.ts +12 -0
  101. package/dist/persona/registry.d.ts.map +1 -0
  102. package/dist/persona/registry.js +54 -0
  103. package/dist/persona/registry.js.map +1 -0
  104. package/dist/persona/runtime.d.ts +23 -0
  105. package/dist/persona/runtime.d.ts.map +1 -0
  106. package/dist/persona/runtime.js +32 -0
  107. package/dist/persona/runtime.js.map +1 -0
  108. package/dist/persona/schema.d.ts +27 -0
  109. package/dist/persona/schema.d.ts.map +1 -0
  110. package/dist/persona/schema.js +165 -0
  111. package/dist/persona/schema.js.map +1 -0
  112. package/dist/persona/types.d.ts +38 -0
  113. package/dist/persona/types.d.ts.map +1 -0
  114. package/dist/persona/types.js +2 -0
  115. package/dist/persona/types.js.map +1 -0
  116. package/dist/pricing.d.ts +40 -0
  117. package/dist/pricing.d.ts.map +1 -0
  118. package/dist/pricing.js +70 -0
  119. package/dist/pricing.js.map +1 -0
  120. package/dist/quota-park.d.ts +53 -0
  121. package/dist/quota-park.d.ts.map +1 -0
  122. package/dist/quota-park.js +135 -0
  123. package/dist/quota-park.js.map +1 -0
  124. package/dist/rate-pause.d.ts +28 -0
  125. package/dist/rate-pause.d.ts.map +1 -0
  126. package/dist/rate-pause.js +72 -0
  127. package/dist/rate-pause.js.map +1 -0
  128. package/dist/registry.d.ts +142 -0
  129. package/dist/registry.d.ts.map +1 -0
  130. package/dist/registry.js +471 -0
  131. package/dist/registry.js.map +1 -0
  132. package/dist/responses.d.ts +5 -0
  133. package/dist/responses.d.ts.map +1 -0
  134. package/dist/responses.js +290 -0
  135. package/dist/responses.js.map +1 -0
  136. package/dist/retry-after.d.ts +13 -0
  137. package/dist/retry-after.d.ts.map +1 -0
  138. package/dist/retry-after.js +64 -0
  139. package/dist/retry-after.js.map +1 -0
  140. package/dist/retry-ladder.d.ts +176 -0
  141. package/dist/retry-ladder.d.ts.map +1 -0
  142. package/dist/retry-ladder.js +664 -0
  143. package/dist/retry-ladder.js.map +1 -0
  144. package/dist/split-inband-thinking.d.ts +35 -0
  145. package/dist/split-inband-thinking.d.ts.map +1 -0
  146. package/dist/split-inband-thinking.js +117 -0
  147. package/dist/split-inband-thinking.js.map +1 -0
  148. package/dist/stream-idle.d.ts +97 -0
  149. package/dist/stream-idle.d.ts.map +1 -0
  150. package/dist/stream-idle.js +127 -0
  151. package/dist/stream-idle.js.map +1 -0
  152. package/dist/tool-call-ids.d.ts +16 -0
  153. package/dist/tool-call-ids.d.ts.map +1 -0
  154. package/dist/tool-call-ids.js +36 -0
  155. package/dist/tool-call-ids.js.map +1 -0
  156. package/package.json +32 -3
@@ -0,0 +1,301 @@
1
+ // 拆分运动 C:从 openai-compatible.ts 原样外提的 M79 §2 图片请求域
2
+ //(AttachmentResolver/ImageRequestContext、keep-K 窗口、imageWireMessages 走查)。
3
+ import { createHash } from "node:crypto";
4
+ import { UnsupportedContentError, imageOffloadPlaceholder, offloadRequestImages, } from "@wudao-org/core";
5
+ import { resolveInputModalities } from "./models.js";
6
+ import { restoreToolCallId } from "./tool-call-ids.js";
7
+ import { toOpenAIMessage } from "./openai-messages.js";
8
+ // ---------------------------------------------------------------------------
9
+ // M79 §2 — image-bearing requests (dsh parity; research 40 §1).
10
+ //
11
+ // gate images need a model that DECLARES the image input modality and
12
+ // an assembled attachment resolver; assistant history carrying
13
+ // images is structurally refused. All three fail with the typed
14
+ // UnsupportedContentError BEFORE any network call (and before a
15
+ // single image byte is read).
16
+ // shape a user turn with images → OpenAI-compatible content parts
17
+ // (`image_url` carrying the TRANSIENT data URL); a pure-text
18
+ // user turn keeps the compact string form, byte-identical to
19
+ // pre-M79.
20
+ // tool wire the `tool` role stays string-only: images riding tool results
21
+ // buffer into ONE synthetic user message immediately following
22
+ // the tool block, prefixed "Attached image(s) from tool result:".
23
+ // offload over the cumulative base64 budget, the OLDEST images become
24
+ // fixed text placeholders (deterministic); omitted bytes are
25
+ // never resolved.
26
+ // ---------------------------------------------------------------------------
27
+ /** Prefix of the synthetic user message that carries tool-result images. */
28
+ export const TOOL_IMAGE_NOTE = "Attached image(s) from tool result:";
29
+ /** ω99-138 keep-K — how many TOOL-RESULT images ride a request as image_url
30
+ * parts. The M79 byte budget (20MiB) bounds BYTES, not visual tokens: a long
31
+ * browser session's screenshots would all decode to image_url parts on EVERY
32
+ * request (40~200 images = the death spiral 135's risk list put first), so
33
+ * the request projection keeps a sliding window of the most recent K and
34
+ * stubs everything older with the FIXED text below. USER images are NOT
35
+ * windowed (zero drift — they keep their full M79 behavior).
36
+ *
37
+ * ω99-244: #3 — K 2→3 (computer arc C's screenshot-history stub, brief
38
+ * N=3): the SAME request-build projection seam — turn-boundary timing
39
+ * unchanged (projection happens between turns, at request build, never
40
+ * mid-flight), window-slide semantics unchanged, only one slot wider.
41
+ * M24 cache cost (declared, not hidden): widening K flips the 3rd-newest
42
+ * tool image from stub to image_url for sessions spanning the upgrade —
43
+ * ONE cross-version cold turn (cold turn expected), never inside a session;
44
+ * the stub text below changes bytes in the same version, same single break;
45
+ * the M24 compensation narrative in imageWireMessages covers both. Within a
46
+ * session the window self-heals every request build (a stubbed image that
47
+ * re-enters the window renders again — no compaction-timing cliff). */
48
+ const TOOL_IMAGE_KEEP_K = 3;
49
+ /** The fixed stub for window-evicted tool images — literal-pinned by tests
50
+ * (deterministic bytes: two builds of the same history project identically).
51
+ * ω99-244: derived from K so the two can never drift apart. */
52
+ const TOOL_IMAGE_KEEP_K_STUB = `[更早的截图已略:仅保留最近 ${TOOL_IMAGE_KEEP_K} 张]`;
53
+ /** The content a tool message shows when its bytes went to the following
54
+ * synthetic user message (dsh wire shape). */
55
+ const TOOL_IMAGE_CONTENT_FALLBACK = "(see attached image)";
56
+ // ---------------------------------------------------------------------------
57
+ // 借鉴弧 β1 — adjacent byte-dedup inside the keep-K window (hermes
58
+ // 682b973b32, digest-b C2). The incumbent window bounds COUNT, not
59
+ // REDUNDANCE: a static capture→act→capture loop fills all K slots with
60
+ // byte-identical frames and burns K× the visual tokens for ONE screen.
61
+ //
62
+ // Dedup lives at THIS request-build projection seam only — the same seam
63
+ // ω99-138/244 established (turn-boundary timing, per-request self-healing,
64
+ // persisted history untouched). The window members' transient data URLs are
65
+ // resolved once and hashed (sha256 over the full `data:<mime>;base64,…`
66
+ // string ≡ sha256(mime+bytes) — hermes's exact dedup key); a newest→oldest
67
+ // walk keeps the NEWEST frame of every identical-ADJACENT run and replaces
68
+ // older duplicates with the FIXED note below. USER images never take the
69
+ // note (zero drift, same as the window).
70
+ //
71
+ // M24 cache cost (declared, not hidden): the projection stays append-only —
72
+ // every ref remains in the JSONL, the note bytes are FIXED, so two builds of
73
+ // the same history project identically. When an adjacent duplicate lands,
74
+ // the previous anchor flips image_url → note: ONE additional deterministic
75
+ // flip at the same turn-boundary timing as the window slide (never
76
+ // mid-flight) — same cold-turn-expected class ω99-244 declared for K; in a
77
+ // static loop the request carries ONE image instead of K identical ones, so
78
+ // visual tokens strictly fall while request bytes get MORE stable (the
79
+ // multi-MiB duplicated blobs stop riding).
80
+ // ---------------------------------------------------------------------------
81
+ /** β1 — max consecutive adjacent-duplicate frames rendered as the note
82
+ * before a re-anchor image is forced (hermes's 省略连击上限: staleness guard
83
+ * — the kept frame can never drift arbitrarily far from the newest state,
84
+ * and a compaction/window eviction of the anchor degrades at most cap
85
+ * notes, not an unbounded run). At K=3 the cap admits the two older slots
86
+ * of a fully static window as notes; K widened later re-anchors at every
87
+ * cap+1 frames automatically (the walk is K-agnostic). */
88
+ const TOOL_IMAGE_DEDUP_OMIT_CAP = 2;
89
+ /** β1 — the fixed note replacing an adjacent-duplicate frame (literal-pinned
90
+ * by tests; deterministic bytes: same history ⇒ same projection). */
91
+ const TOOL_IMAGE_DEDUP_STUB = "[截图未变:本帧与相邻截图逐字节相同,已省略图片——保留帧即当前屏幕状态]";
92
+ /** β1 — the pure newest→oldest dedup walk over one window's content hashes
93
+ * (input in HISTORY order, oldest→newest). Returns per-frame verdicts:
94
+ * true = renders as image_url, false = the fixed note. A frame is omitted
95
+ * only when its hash equals its immediate NEWER neighbor's AND the
96
+ * omission streak stays under `omitCap`. Exported so the policy itself is
97
+ * unit-testable at any window width (the seam below only feeds it hashes
98
+ * — at K=3 the re-anchor branch needs a 4-wide window to show, which only
99
+ * the direct test can see). */
100
+ export function sameImageKeepVerdicts(hashes, omitCap) {
101
+ const verdicts = new Array(hashes.length);
102
+ let streak = 0;
103
+ for (let i = hashes.length - 1; i >= 0; i -= 1) {
104
+ const newer = hashes[i + 1];
105
+ if (newer !== undefined && hashes[i] === newer && streak < omitCap) {
106
+ verdicts[i] = false;
107
+ streak += 1;
108
+ }
109
+ else {
110
+ verdicts[i] = true;
111
+ streak = 0;
112
+ }
113
+ }
114
+ return verdicts;
115
+ }
116
+ /** Does any message in the input carry image blocks? (Cheap pre-filter —
117
+ * the no-image path below is the byte-identical pre-M79 construction.) */
118
+ export function inputHasImages(input) {
119
+ return input.messages.some((m) => {
120
+ const imgs = m.images;
121
+ return Array.isArray(imgs) && imgs.length > 0;
122
+ });
123
+ }
124
+ /** The pure pre-I/O capability/role gate. Throws the typed
125
+ * UnsupportedContentError — never retries (see isRetryableProviderError) —
126
+ * for (a) images addressed at a model without the `image` modality, and
127
+ * (b) ImageBlocks in assistant history (only user turns and tool results
128
+ * may carry images). Exported so the CLI can pre-check a submit. */
129
+ export function assertImagesSupported(input, modalities) {
130
+ let has = false;
131
+ for (const m of input.messages) {
132
+ const imgs = m.images;
133
+ if (!Array.isArray(imgs) || imgs.length === 0)
134
+ continue;
135
+ has = true;
136
+ if (m.role === "assistant") {
137
+ throw new UnsupportedContentError("image-in-unsupported-role", "images may ride user turns and tool results only — assistant history carries an ImageBlock");
138
+ }
139
+ }
140
+ if (has && !modalities.includes("image")) {
141
+ throw new UnsupportedContentError("model-no-image-modality", `model does not declare the image input modality (inputModalities: [${modalities.join(", ")}]) — refusing the image-bearing request`);
142
+ }
143
+ }
144
+ /** All image blocks of a request, in message order (oldest first). */
145
+ function collectRequestImages(input) {
146
+ const out = [];
147
+ for (const m of input.messages) {
148
+ const imgs = m.images;
149
+ if (Array.isArray(imgs) && imgs.length > 0)
150
+ out.push(...imgs);
151
+ }
152
+ return out;
153
+ }
154
+ /** The image-bearing message walk (system + per-message shaping + the
155
+ * synthetic tool-image user message). Only called when inputHasImages —
156
+ * the text-only path is toOpenAIRequest's, byte-identical. */
157
+ export async function imageWireMessages(config, input, imageCtx) {
158
+ // Gate BEFORE reading a single image byte (capability + role).
159
+ assertImagesSupported(input, resolveInputModalities(config));
160
+ if (imageCtx.resolver === undefined) {
161
+ throw new UnsupportedContentError("no-attachment-store", "no attachment resolver is assembled on this provider — image-bearing input cannot be built (images are never silently dropped)");
162
+ }
163
+ // Offload plan from the DURABLE refs' sizes (pure); only the survivors'
164
+ // bytes are ever resolved.
165
+ //
166
+ // ω99-138 keep-K window (M24: compensation ships BEFORE the feature).
167
+ // TOOL-result images beyond the most recent K drop out of the projection
168
+ // here — BEFORE the byte-budget offload plan — so an evicted image neither
169
+ // resolves bytes nor spends budget; on the wire its part is the fixed stub
170
+ // above (the carrier message keeps one part per image, position-stable).
171
+ // CACHE COST (M24 format): the window lives ONLY in this request build —
172
+ // persisted history keeps every ref (append-only, never rewritten). When
173
+ // the window slides (the K+1-st tool image lands), the oldest window
174
+ // member flips from image_url to the stub: the synthetic carrier's bytes
175
+ // change at that point and break the prefix ONCE there = cold turn
176
+ // expected. Turn-boundary timing holds by construction (projection happens
177
+ // between turns, at request build, never mid-flight).
178
+ const toolImageIdsInOrder = [];
179
+ const toolImageIds = new Set();
180
+ const toolImageRefById = new Map();
181
+ for (const m of input.messages) {
182
+ if (m.role !== "tool")
183
+ continue;
184
+ const imgs = m.images;
185
+ if (!Array.isArray(imgs))
186
+ continue;
187
+ for (const b of imgs) {
188
+ if (!toolImageIds.has(b.ref.attachmentId)) {
189
+ toolImageIds.add(b.ref.attachmentId);
190
+ toolImageIdsInOrder.push(b.ref.attachmentId);
191
+ toolImageRefById.set(b.ref.attachmentId, b.ref);
192
+ }
193
+ }
194
+ }
195
+ const keepKIds = new Set(toolImageIdsInOrder.slice(-TOOL_IMAGE_KEEP_K));
196
+ const isWindowStubbed = (b) => toolImageIds.has(b.ref.attachmentId) && !keepKIds.has(b.ref.attachmentId);
197
+ // β1 byte-dedup (see the block comment above the constants): resolve each
198
+ // WINDOW member once — the resolution doubles as the content hash source —
199
+ // then let the pure newest→oldest walk decide which frames still render.
200
+ // Hashing is an OPTIMIZATION seam and fails OPEN here (an unresolvable
201
+ // frame simply never dedups): the render path below keeps its exact
202
+ // pre-β1 surface (a kept frame resolves again and throws there if truly
203
+ // broken; an offloaded one never resolves, as ever).
204
+ const windowIds = toolImageIdsInOrder.slice(-TOOL_IMAGE_KEEP_K);
205
+ const urlById = new Map();
206
+ const hashById = new Map();
207
+ for (const id of windowIds) {
208
+ const r = toolImageRefById.get(id);
209
+ if (r === undefined)
210
+ continue;
211
+ try {
212
+ const url = await imageCtx.resolver.resolveDataUrl(r);
213
+ urlById.set(id, url);
214
+ hashById.set(id, createHash("sha256").update(url).digest("hex"));
215
+ }
216
+ catch {
217
+ // No hash for this frame — the sentinel below keeps it unique, so it
218
+ // rides (or offloads) exactly as it would have without β1.
219
+ }
220
+ }
221
+ const verdicts = sameImageKeepVerdicts(windowIds.map((id) => hashById.get(id) ?? `unresolved:${id}`), TOOL_IMAGE_DEDUP_OMIT_CAP);
222
+ const dedupOmitIds = new Set();
223
+ windowIds.forEach((id, i) => {
224
+ if (verdicts[i] === false)
225
+ dedupOmitIds.add(id);
226
+ });
227
+ const isDedupStubbed = (b) => toolImageIds.has(b.ref.attachmentId) && dedupOmitIds.has(b.ref.attachmentId);
228
+ // Dedup survivors only: a note consumes no image budget, so a static loop
229
+ // also stops pressuring the M79 offload ladder (the bytes it would have
230
+ // spent are simply never resolved).
231
+ const blocks = collectRequestImages(input)
232
+ .filter((b) => !isWindowStubbed(b))
233
+ .filter((b) => !isDedupStubbed(b));
234
+ const { kept } = offloadRequestImages(blocks, imageCtx.budgetBytes);
235
+ const keptIds = new Set(kept.map((b) => b.ref.attachmentId));
236
+ for (const b of kept) {
237
+ if (!urlById.has(b.ref.attachmentId)) {
238
+ urlById.set(b.ref.attachmentId, await imageCtx.resolver.resolveDataUrl(b.ref));
239
+ }
240
+ }
241
+ const partFor = (b, fromTool) => {
242
+ // ω99-138: an evicted tool image renders as the fixed stub — same
243
+ // position, deterministic bytes (user images never take this branch).
244
+ if (fromTool && isWindowStubbed(b))
245
+ return { type: "text", text: TOOL_IMAGE_KEEP_K_STUB };
246
+ // β1: an adjacent byte-duplicate renders as the fixed dedup note — same
247
+ // position-stable discipline (user images never take this branch either).
248
+ if (fromTool && isDedupStubbed(b))
249
+ return { type: "text", text: TOOL_IMAGE_DEDUP_STUB };
250
+ return keptIds.has(b.ref.attachmentId)
251
+ ? { type: "image_url", image_url: { url: urlById.get(b.ref.attachmentId) } }
252
+ : { type: "text", text: imageOffloadPlaceholder(b.ref) };
253
+ };
254
+ const replay = config.reasoningReplay ?? "never";
255
+ const out = [{ role: "system", content: input.systemPrompt }];
256
+ let toolImages = [];
257
+ const flushToolImages = () => {
258
+ if (toolImages.length === 0)
259
+ return;
260
+ out.push({
261
+ role: "user",
262
+ // ω99-138: each part follows its block's window verdict (image_url for
263
+ // the kept K, the fixed stub for the evicted ones — positions stable).
264
+ content: [{ type: "text", text: TOOL_IMAGE_NOTE }, ...toolImages.map((b) => partFor(b, true))],
265
+ });
266
+ toolImages = [];
267
+ };
268
+ for (const m of input.messages) {
269
+ const imgs = m.images;
270
+ const carries = Array.isArray(imgs) && imgs.length > 0;
271
+ if (m.role === "tool") {
272
+ out.push({
273
+ role: "tool",
274
+ // ω-1a: same outbound restore as toOpenAIMessage's tool case.
275
+ tool_call_id: restoreToolCallId(m.toolCallId, m.name),
276
+ content: carries ? (m.content !== "" ? m.content : TOOL_IMAGE_CONTENT_FALLBACK) : m.content,
277
+ });
278
+ if (carries)
279
+ toolImages.push(...imgs);
280
+ continue;
281
+ }
282
+ // The synthetic carrier follows the tool block it answers.
283
+ flushToolImages();
284
+ if (m.role === "user" && carries) {
285
+ // r5-C1: an image-ONLY turn (empty caption) omits the empty text part —
286
+ // a bare {type:"text",text:""} is rejected by several strict
287
+ // OpenAI-compatible endpoints; images alone are a well-formed content
288
+ // array.
289
+ const parts = m.content === "" ? [] : [{ type: "text", text: m.content }];
290
+ // ω99-138: user images are OUTSIDE the keep-K window — fromTool=false
291
+ // is the byte-for-byte M79 path (zero drift).
292
+ out.push({ role: "user", content: [...parts, ...imgs.map((b) => partFor(b, false))] });
293
+ continue;
294
+ }
295
+ out.push(toOpenAIMessage(m, replay));
296
+ }
297
+ // Trailing tool results (a run cut mid-tool-phase) still carry their images.
298
+ flushToolImages();
299
+ return out;
300
+ }
301
+ //# sourceMappingURL=openai-images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-images.js","sourceRoot":"","sources":["../src/openai-images.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { ModelInput } from "@wudao-org/core";
2
+ import type { ReasoningReplay } from "./config.js";
3
+ export declare const MAX_ACCUM_CHARS = 2000000;
4
+ export declare const TRUNCATED_MARK = "[truncated at 2M chars]";
5
+ /** Cap a finished accumulator: truncate at the cap and append the marker. */
6
+ export declare function capAccumulated(s: string): string;
7
+ /** ω-2a: is this reasoning string a tail the CLIENT truncated at the
8
+ * accumulator cap? The in-band marker is the truncation signal (every cap
9
+ * site appends exactly it) — a reasoning string ending in it is incomplete
10
+ * by construction and must never be treated as a complete tail. */
11
+ export declare function isCappedReasoning(reasoning: string | undefined): boolean;
12
+ export declare function toOpenAIMessage(m: ModelInput["messages"][number], replay?: ReasoningReplay): {
13
+ reasoning_content?: string | undefined;
14
+ tool_calls?: {
15
+ id: string;
16
+ type: string;
17
+ function: {
18
+ name: string;
19
+ arguments: string;
20
+ };
21
+ }[] | undefined;
22
+ role: string;
23
+ content: string;
24
+ tool_call_id?: undefined;
25
+ } | {
26
+ role: string;
27
+ tool_call_id: string;
28
+ content: string;
29
+ };
30
+ /** JSON with recursively sorted object keys (arrays keep their order). */
31
+ export declare function canonicalJson(value: unknown): string;
32
+ /** Deterministic byte serialization of a ModelInput's prompt content. NOTE
33
+ * (M47 §1): this pins the message SET (system+tools+messages) — the
34
+ * reasoning_replay field is provider-config-side and rides the wire only when
35
+ * `reasoningReplay` is enabled; its wire-shape pins live in the replay tests
36
+ * (raw request bodies), not here. M79: image-bearing turns pin their
37
+ * ImageAttachmentRefs (durable form); a text-only session's bytes are
38
+ * IDENTICAL to pre-M79. */
39
+ export declare function serializePrompt(input: ModelInput): string;
40
+ //# sourceMappingURL=openai-messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-messages.d.ts","sourceRoot":"","sources":["../src/openai-messages.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAyB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AASnD,eAAO,MAAM,eAAe,UAAY,CAAC;AACzC,eAAO,MAAM,cAAc,4BAA4B,CAAC;AAExD,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;oEAGoE;AACpE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAExE;AAgBD,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,GAAE,eAAyB;;;;;;;;;;;;;;;;;EAwBnG;AAkBD,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CASpD;AA8BD;;;;;;4BAM4B;AAC5B,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAWzD"}
@@ -0,0 +1,135 @@
1
+ import { truncateSafe } from "@wudao-org/core";
2
+ import { restoreToolCallId, restoreToolCallIds } from "./tool-call-ids.js";
3
+ // OOM fix: per-response accumulation caps. A degenerate endpoint (or an
4
+ // adversarial stream) can pump unbounded reasoning/content/argument bytes
5
+ // into a single response; every accumulator is capped so no downstream
6
+ // consumer (driver live state, history, persistence) can ever hold an
7
+ // unbounded per-response string. 2M chars ≈ the largest legitimate response
8
+ // by an order of magnitude; truncation is always marked.
9
+ export const MAX_ACCUM_CHARS = 2_000_000;
10
+ export const TRUNCATED_MARK = "[truncated at 2M chars]";
11
+ /** Cap a finished accumulator: truncate at the cap and append the marker. */
12
+ export function capAccumulated(s) {
13
+ return s.length > MAX_ACCUM_CHARS ? truncateSafe(s, MAX_ACCUM_CHARS) + TRUNCATED_MARK : s; // 113-A4
14
+ }
15
+ /** ω-2a: is this reasoning string a tail the CLIENT truncated at the
16
+ * accumulator cap? The in-band marker is the truncation signal (every cap
17
+ * site appends exactly it) — a reasoning string ending in it is incomplete
18
+ * by construction and must never be treated as a complete tail. */
19
+ export function isCappedReasoning(reasoning) {
20
+ return reasoning !== undefined && reasoning.endsWith(TRUNCATED_MARK);
21
+ }
22
+ /** M47 §1: does this assistant message's stored reasoning ride back out?
23
+ * Byte discipline: the value is passed through VERBATIM — never trimmed,
24
+ * never reformatted — so the replayed bytes equal the stored bytes. */
25
+ function replayReasoning(m, replay) {
26
+ if (replay === "never" || m.reasoning === undefined)
27
+ return undefined;
28
+ // ω-2a: a client-capped tail is incomplete — never replayed as complete.
29
+ // Omitting the optional reasoning_content keeps the request wire-valid
30
+ // (the pre-M47 shape every "never"-mode session already sends).
31
+ if (isCappedReasoning(m.reasoning))
32
+ return undefined;
33
+ if (replay === "always")
34
+ return m.reasoning;
35
+ // toolCallTurns: only the turns that carry tool calls (CLAUDE.md §4.4).
36
+ return m.toolCalls !== undefined && m.toolCalls.length > 0 ? m.reasoning : undefined;
37
+ }
38
+ export function toOpenAIMessage(m, replay = "never") {
39
+ switch (m.role) {
40
+ case "user":
41
+ return { role: "user", content: m.content };
42
+ case "assistant": {
43
+ const reasoning = replayReasoning(m, replay);
44
+ return {
45
+ role: "assistant",
46
+ content: m.content,
47
+ // ω-1a: the stored ids may carry the dedupe's `#n` suffix — the wire
48
+ // gets the provider-native shape back (real ids strip to themselves).
49
+ ...(m.toolCalls && m.toolCalls.length > 0
50
+ ? { tool_calls: restoreToolCallIds(m.toolCalls).map((tc) => ({ id: tc.id, type: "function", function: { name: tc.name, arguments: JSON.stringify(tc.arguments) } })) }
51
+ : {}),
52
+ // Appended AFTER the pinned fields: the default (never) request bytes
53
+ // are unchanged, and an enabled replay only grows the message tail.
54
+ ...(reasoning !== undefined ? { reasoning_content: reasoning } : {}),
55
+ };
56
+ }
57
+ case "tool":
58
+ // ω-1a: tool_result ids restore in lockstep with the assistant calls
59
+ // they answer (a stripped call with a suffixed result would 400).
60
+ return { role: "tool", tool_call_id: restoreToolCallId(m.toolCallId, m.name), content: m.content };
61
+ }
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Canonical prompt serialization (M24).
65
+ //
66
+ // serializePrompt is THE one serializer every byte-prefix assertion uses
67
+ // (det-06, fork prefix sharing, CLI miss attribution) — nowhere else may a
68
+ // hand-rolled comparison live. Shape:
69
+ // - one JSON line per segment, each terminated by "\n";
70
+ // - stable header FIRST (system line, then one line per tool), messages
71
+ // after — mirroring where the prompt bytes actually diverge: appending a
72
+ // message (append-only growth) only ever APPENDS bytes at the tail, so
73
+ // request N's serialization is a byte-prefix of request N+1's whenever
74
+ // the history grew append-only and the header stayed frozen;
75
+ // - canonical key order (recursive sort) — the caller's insertion order
76
+ // never leaks into the bytes.
77
+ // ---------------------------------------------------------------------------
78
+ /** JSON with recursively sorted object keys (arrays keep their order). */
79
+ export function canonicalJson(value) {
80
+ if (Array.isArray(value))
81
+ return `[${value.map(canonicalJson).join(",")}]`;
82
+ if (value !== null && typeof value === "object") {
83
+ const entries = Object.entries(value)
84
+ .filter(([, v]) => v !== undefined)
85
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
86
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(",")}}`;
87
+ }
88
+ return JSON.stringify(value);
89
+ }
90
+ /** M79: the CANONICAL (durable) form of one message. Image-bearing turns
91
+ * serialize their REFS — the transient data URL never appears here (it
92
+ * exists only inside one request build, and never in a byte-pin). Text-only
93
+ * turns return exactly toOpenAIMessage's shape, so every pre-M79 golden
94
+ * byte is unchanged. ω99-55: FILE-bearing user turns pin their blocks
95
+ * (same durable discipline — without this, a file turn and a text turn
96
+ * with equal content would pin identical bytes and the pin would lose the
97
+ * file identity; the projected handle is derived text, versioned by the
98
+ * projection, and rides only the wire). */
99
+ function canonicalMessage(m) {
100
+ const imgs = m.images;
101
+ const files = m.role === "user" ? m.files : undefined;
102
+ const hasImgs = Array.isArray(imgs) && imgs.length > 0;
103
+ const hasFiles = Array.isArray(files) && files.length > 0;
104
+ if (hasImgs || hasFiles) {
105
+ if (m.role === "user") {
106
+ return {
107
+ role: "user",
108
+ content: m.content,
109
+ ...(hasImgs ? { images: imgs } : {}),
110
+ ...(hasFiles ? { files } : {}),
111
+ };
112
+ }
113
+ if (m.role === "tool")
114
+ return { role: "tool", tool_call_id: m.toolCallId, content: m.content, images: imgs };
115
+ }
116
+ return toOpenAIMessage(m);
117
+ }
118
+ /** Deterministic byte serialization of a ModelInput's prompt content. NOTE
119
+ * (M47 §1): this pins the message SET (system+tools+messages) — the
120
+ * reasoning_replay field is provider-config-side and rides the wire only when
121
+ * `reasoningReplay` is enabled; its wire-shape pins live in the replay tests
122
+ * (raw request bodies), not here. M79: image-bearing turns pin their
123
+ * ImageAttachmentRefs (durable form); a text-only session's bytes are
124
+ * IDENTICAL to pre-M79. */
125
+ export function serializePrompt(input) {
126
+ const lines = [canonicalJson({ role: "system", content: input.systemPrompt })];
127
+ for (const t of input.tools) {
128
+ lines.push(canonicalJson({ type: "function", function: { name: t.name, description: t.description, parameters: t.parameters } }));
129
+ }
130
+ for (const m of input.messages) {
131
+ lines.push(canonicalJson(canonicalMessage(m)));
132
+ }
133
+ return lines.map((l) => `${l}\n`).join("");
134
+ }
135
+ //# sourceMappingURL=openai-messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-messages.js","sourceRoot":"","sources":["../src/openai-messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import type { ModelInput, ModelUsage } from "@wudao-org/core";
2
+ import type { ProviderConfig, ReasoningEffort, ReasoningReplay } from "./config.js";
3
+ import { type ImageRequestContext } from "./openai-images.js";
4
+ export interface MandatoryReasoningFlag {
5
+ applied: boolean;
6
+ onApplied?: () => void;
7
+ }
8
+ export interface MandatoryReasoningCall {
9
+ readonly flag: MandatoryReasoningFlag;
10
+ /** The repair body once armed (per call); undefined until a repairable
11
+ * rejection classified or the client came pre-armed. */
12
+ body?: Record<string, unknown>;
13
+ }
14
+ /** Create the per-call runtime; a pre-armed client starts with the repair
15
+ * body already set (the leg's own config shapes it). */
16
+ export declare function createMandatoryReasoningCall(flag: MandatoryReasoningFlag, config: ProviderConfig): MandatoryReasoningCall;
17
+ /** Arm the client flag (idempotent) after a repaired request was served. */
18
+ export declare function armMandatoryReasoningFlag(flag: MandatoryReasoningFlag): void;
19
+ /** The request's EFFECTIVE reasoning effort — a per-input effort (already
20
+ * parsed once at the public boundary) overrides the config's own. The single
21
+ * source both the request body and the ω-2a repair gates read, so a gate can
22
+ * never disagree with the bytes that actually went out. */
23
+ export declare function effectiveReasoningEffort(input: Pick<ModelInput, "reasoningEffort">, config: ProviderConfig): ReasoningEffort | undefined;
24
+ export interface ChatCompletionResponse {
25
+ choices?: Array<{
26
+ finish_reason?: string;
27
+ message: {
28
+ role: string;
29
+ content?: string;
30
+ reasoning_content?: string;
31
+ reasoning?: string;
32
+ thinking?: string;
33
+ tool_calls?: Array<{
34
+ id: string;
35
+ type: string;
36
+ function: {
37
+ name: string;
38
+ arguments: string;
39
+ };
40
+ }>;
41
+ };
42
+ }>;
43
+ usage?: WireUsage;
44
+ }
45
+ /** Wire usage shapes across OpenAI-compatible servers. */
46
+ export interface WireUsage {
47
+ prompt_tokens?: number;
48
+ completion_tokens?: number;
49
+ /** DeepSeek spelling. `prompt_tokens` INCLUDES these hits. */
50
+ prompt_cache_hit_tokens?: number;
51
+ /** DeepSeek spelling of the miss count (the tokens this call wrote to / paid
52
+ * uncached input for). */
53
+ prompt_cache_miss_tokens?: number;
54
+ /** Explicit cache-write spelling (endpoints that report it separately). */
55
+ prompt_cache_write_tokens?: number;
56
+ /** OpenAI spelling of the same quantities. */
57
+ prompt_tokens_details?: {
58
+ cached_tokens?: number;
59
+ };
60
+ completion_tokens_details?: {
61
+ reasoning_tokens?: number;
62
+ };
63
+ /** Flat reasoning spelling some gateways use instead of the details object. */
64
+ reasoning_tokens?: number;
65
+ }
66
+ /** Disjoint-count mapping (dsh rule): `prompt_tokens` includes cache hits, and
67
+ * the two wire spellings report the SAME quantity — prefer details, fall back
68
+ * to the flat field, never sum them (no double counting). Miss = the rest
69
+ * (DeepSeek's explicit miss spelling wins when present).
70
+ *
71
+ * M56 §2 (turn_usage, omit-never-null): `cacheWriteTokens` is set only when
72
+ * the wire actually reported a cache split — on DeepSeek-style endpoints
73
+ * every miss is written, so cache-write ≈ miss; `reasoningTokens` rides the
74
+ * completion details spelling when the endpoint reports it. Everything
75
+ * unknown stays OMITTED (never null, never zero-backfilled). */
76
+ export declare function toModelUsage(u: WireUsage): ModelUsage;
77
+ /** M56 §2: the receipt's client-side extras — the wall duration measured
78
+ * around the attempt (always set; CodeWhale's duration_ms-always rule) and
79
+ * the replayed-reasoning estimate (only when the replay contract sent bytes
80
+ * back out). */
81
+ export declare function enrichUsage(usage: ModelUsage, durationMs: number, replayTokens: number): ModelUsage;
82
+ /** Client-side estimate of the reasoning tokens sent BACK to the model this
83
+ * call (the M47 replay contract): CJK chars ≈ 1 token, ~4 others per token.
84
+ * An estimate by construction — no endpoint reports it. */
85
+ export declare function replayedReasoningTokens(messages: readonly ModelInput["messages"][number][], replay: ReasoningReplay): number;
86
+ /** The one request body builder (M79): the pre-M79 byte-identical
87
+ * construction when no images ride the input, the image walk above when
88
+ * they do. ω99-42: threads the mandatory-reasoning repair body through.
89
+ * ω99-55: FILE blocks project to handle text FIRST (dsh LlmRuntime parity
90
+ * — no wire ever receives file bytes); the projection is the identity when
91
+ * nothing rides files, so text/image request bytes are untouched. */
92
+ export declare function buildOpenAIRequestBody(config: ProviderConfig, input: ModelInput, imageCtx: ImageRequestContext, mr: MandatoryReasoningCall): Promise<Record<string, unknown>>;
93
+ //# sourceMappingURL=openai-wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-wire.d.ts","sourceRoot":"","sources":["../src/openai-wire.ts"],"names":[],"mappings":"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"}