@eddyskywalker/dsh-chatgpt-subscription 0.8.5 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +93 -38
  3. package/lib/client.js +2126 -1693
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +7588 -2772
  6. package/lib/types/client/claude/ClaudeComposerQuota.d.ts +33 -0
  7. package/lib/types/client/claude/ClaudeComposerQuota.d.ts.map +1 -0
  8. package/lib/types/client/{zhipu/ZhipuSection.d.ts → claude/ClaudeSection.d.ts} +2 -2
  9. package/lib/types/client/claude/ClaudeSection.d.ts.map +1 -0
  10. package/lib/types/client/claude/locales.d.ts +444 -0
  11. package/lib/types/client/claude/locales.d.ts.map +1 -0
  12. package/lib/types/client/claude/styles.d.ts +15 -0
  13. package/lib/types/client/claude/styles.d.ts.map +1 -0
  14. package/lib/types/client/index.d.ts +1 -1
  15. package/lib/types/client/index.d.ts.map +1 -1
  16. package/lib/types/host/claude/__probe-assert.d.ts +2 -0
  17. package/lib/types/host/claude/__probe-assert.d.ts.map +1 -0
  18. package/lib/types/host/claude/account-pool.d.ts +580 -0
  19. package/lib/types/host/claude/account-pool.d.ts.map +1 -0
  20. package/lib/types/host/claude/adapter.d.ts +267 -0
  21. package/lib/types/host/claude/adapter.d.ts.map +1 -0
  22. package/lib/types/host/claude/adopt.d.ts +292 -0
  23. package/lib/types/host/claude/adopt.d.ts.map +1 -0
  24. package/lib/types/host/claude/client.d.ts +513 -0
  25. package/lib/types/host/claude/client.d.ts.map +1 -0
  26. package/lib/types/host/claude/mapper.d.ts +510 -0
  27. package/lib/types/host/claude/mapper.d.ts.map +1 -0
  28. package/lib/types/host/claude/model-catalog.d.ts +365 -0
  29. package/lib/types/host/claude/model-catalog.d.ts.map +1 -0
  30. package/lib/types/host/claude/oauth.d.ts +393 -0
  31. package/lib/types/host/claude/oauth.d.ts.map +1 -0
  32. package/lib/types/host/claude/routes.d.ts +128 -0
  33. package/lib/types/host/claude/routes.d.ts.map +1 -0
  34. package/lib/types/host/claude/token-store.d.ts +312 -0
  35. package/lib/types/host/claude/token-store.d.ts.map +1 -0
  36. package/lib/types/host/claude/types.d.ts +237 -0
  37. package/lib/types/host/claude/types.d.ts.map +1 -0
  38. package/lib/types/index.d.ts +10 -7
  39. package/lib/types/index.d.ts.map +1 -1
  40. package/lib/types/shared/__probe-claude-import.d.ts +2 -0
  41. package/lib/types/shared/__probe-claude-import.d.ts.map +1 -0
  42. package/lib/types/shared/claude-contracts.d.ts +337 -0
  43. package/lib/types/shared/claude-contracts.d.ts.map +1 -0
  44. package/package.json +1 -1
  45. package/lib/types/client/zhipu/ZhipuComposerQuota.d.ts +0 -26
  46. package/lib/types/client/zhipu/ZhipuComposerQuota.d.ts.map +0 -1
  47. package/lib/types/client/zhipu/ZhipuSection.d.ts.map +0 -1
  48. package/lib/types/client/zhipu/locales.d.ts +0 -275
  49. package/lib/types/client/zhipu/locales.d.ts.map +0 -1
  50. package/lib/types/client/zhipu/styles.d.ts +0 -12
  51. package/lib/types/client/zhipu/styles.d.ts.map +0 -1
  52. package/lib/types/host/zhipu/account-pool.d.ts +0 -43
  53. package/lib/types/host/zhipu/account-pool.d.ts.map +0 -1
  54. package/lib/types/host/zhipu/adapter.d.ts +0 -93
  55. package/lib/types/host/zhipu/adapter.d.ts.map +0 -1
  56. package/lib/types/host/zhipu/client.d.ts +0 -153
  57. package/lib/types/host/zhipu/client.d.ts.map +0 -1
  58. package/lib/types/host/zhipu/mapper.d.ts +0 -111
  59. package/lib/types/host/zhipu/mapper.d.ts.map +0 -1
  60. package/lib/types/host/zhipu/model-catalog.d.ts +0 -73
  61. package/lib/types/host/zhipu/model-catalog.d.ts.map +0 -1
  62. package/lib/types/host/zhipu/routes.d.ts +0 -33
  63. package/lib/types/host/zhipu/routes.d.ts.map +0 -1
  64. package/lib/types/host/zhipu/token-store.d.ts +0 -112
  65. package/lib/types/host/zhipu/token-store.d.ts.map +0 -1
  66. package/lib/types/host/zhipu/types.d.ts +0 -125
  67. package/lib/types/host/zhipu/types.d.ts.map +0 -1
  68. package/lib/types/shared/zhipu-contracts.d.ts +0 -164
  69. package/lib/types/shared/zhipu-contracts.d.ts.map +0 -1
@@ -0,0 +1,510 @@
1
+ /**
2
+ * Wire mapping for the Anthropic Messages API behind a SUBSCRIPTION credential.
3
+ *
4
+ * WHAT THIS MODULE OWNS. Everything between DSH's GenerateOptions and the bytes
5
+ * of POST <API_BASE><MESSAGES_PATH>: the request body, and the SSE state machine
6
+ * that turns Anthropic's line-oriented event stream back into DSH StreamChunks.
7
+ * It holds no credential, performs no I/O, and never touches the network - the
8
+ * adapter owns transport and it owns the line splitting. Every function here is
9
+ * pure with respect to the wire: same options in, same body out.
10
+ *
11
+ * The module doc of the sibling model-catalog.ts is the authority for the
12
+ * per-model facts used below, and every claim marked TRANSCRIBED below was read
13
+ * out of that catalog's transcription of a locally installed reference
14
+ * implementation rather than recalled. Claims marked CHOICE are this module's
15
+ * own judgement and are flagged as such so a reviewer can disagree with one
16
+ * without having to re-derive the whole file.
17
+ *
18
+ * ---------------------------------------------------------------------------
19
+ * 1. THE SYSTEM ARRAY IS TWO BLOCKS AND THE FIRST ONE IS NOT OPTIONAL
20
+ * ---------------------------------------------------------------------------
21
+ *
22
+ * On the subscription route the system prompt is an ARRAY of text blocks whose
23
+ * FIRST entry must be the Claude Code identity line verbatim. This is not
24
+ * cosmetic and not a preference: a subscription request without that identity
25
+ * block is rejected, and the failure is a whole-turn failure rather than a
26
+ * degraded answer. It is therefore emitted unconditionally - even when the
27
+ * caller states no system prompt at all - and the caller's own prompt, when
28
+ * there is one, becomes the SECOND block. See CLAUDE_CODE_IDENTITY_TEXT.
29
+ *
30
+ * A role: 'system' entry in options.messages is FOLDED into that same second
31
+ * block rather than being sent as a message: the Messages wire has no system
32
+ * role, so a system message that reached messages[] would either be rejected or
33
+ * silently reinterpreted. The fold is order-stable (header first, then history
34
+ * order) because the system array is the head of the prefix the server caches.
35
+ *
36
+ * ---------------------------------------------------------------------------
37
+ * 2. THINKING - FOUR CASES, DISPATCHED IN THE CATALOG'S ORDER
38
+ * ---------------------------------------------------------------------------
39
+ *
40
+ * claudeThinkingMode(model) decides the form, and the order of the guards is
41
+ * the whole point:
42
+ *
43
+ * mid-convo -> { type: 'adaptive', display: 'summarized',
44
+ * block_binding: { prefix_mismatch_behavior: 'drop_block' } }
45
+ * PLUS output_config = { effort }. This case outranks
46
+ * everything, including a caller asking for thinking off: the
47
+ * block_binding exists so a prefix mismatch is dropped instead of
48
+ * surfacing as a persistent 400, and suppressing it is exactly
49
+ * how that 400 comes back.
50
+ * adaptive -> { type: 'adaptive', display: 'summarized' }, plus
51
+ * output_config = { effort } when an effort was named. The budget
52
+ * form is rejected by these models.
53
+ * budget -> { type: 'enabled', budget_tokens: <clamped>, display:
54
+ * 'summarized' }.
55
+ * none -> NO thinking field at all.
56
+ *
57
+ * Thinking OFF is a separate decision layered on top: when the caller asked for
58
+ * it and claudeModelCanDisableThinking(model) is true, { type: 'disabled' } is
59
+ * sent; when that predicate is false the disable request is NOT sent (the model
60
+ * forbids it) and the model's own form is used instead - a model that always
61
+ * thinks cannot be talked out of it, and the only honest request left is the
62
+ * normal one. CHOICE: nothing above the predicate is this module's invention,
63
+ * but "fall back to the model's own form" is, because the catalog only states
64
+ * that the disable request must not be sent.
65
+ *
66
+ * ---------------------------------------------------------------------------
67
+ * 3. THE BUDGET ARITHMETIC IS TRANSCRIBED, NOT RE-DERIVED
68
+ * ---------------------------------------------------------------------------
69
+ *
70
+ * RULE 4 of model-catalog.ts carries the reference arithmetic with line cites.
71
+ * adjustMaxTokensForThinking, thinkingBudgetForLevel, clampReasoning and
72
+ * clampThinkingBudgetToAnswerRoom below reproduce it statement for statement.
73
+ * Two traps that transcription exists to prevent:
74
+ *
75
+ * 1. an UNDEFINED caller cap must not be coerced to 0. Under the helper's own
76
+ * branch Math.min(0 + budget, modelMax) makes the thinking budget the
77
+ * entire response ceiling and leaves no room for an answer;
78
+ * 2. the value passed in as baseMax is the ALREADY-RESOLVED cap
79
+ * (buildBaseOptions resolves options.maxTokens ?? model.maxTokens before
80
+ * calling the helper), so feeding an unresolved value in changes which
81
+ * branch runs. resolveMaxTokens below is what resolves it, and the builder
82
+ * passes the result - never options.maxTokens directly.
83
+ *
84
+ * The one deviation from the transcription is that the reference's
85
+ * thinkingBudgetForLevel can yield undefined for a level its table does not
86
+ * name; the reference never hits that (its level always comes from the model's
87
+ * own ladder) while a caller here could. Every use below either substitutes the
88
+ * middle level or treats the result as "no thinking field", and never does
89
+ * arithmetic with undefined.
90
+ *
91
+ * ---------------------------------------------------------------------------
92
+ * 4. TOOL NAMES ARE CASE-NORMALIZED, AND MAPPED BACK
93
+ * ---------------------------------------------------------------------------
94
+ *
95
+ * A subscription token is served Claude Code's own tool vocabulary, and the
96
+ * reference case-normalizes the tool names it sends to that vocabulary. So a
97
+ * tool offered as 'bash' or 'WEBSEARCH' goes out as 'Bash' / 'WebSearch', and a
98
+ * returned canonical name is mapped BACK to the caller's spelling, because DSH
99
+ * dispatches on the name it declared. A name the vocabulary does not know is
100
+ * sent unchanged: inventing a spelling for an unknown tool would rename a tool
101
+ * the harness can no longer dispatch.
102
+ *
103
+ * The back-map is per request and case-insensitive, which is only sound while
104
+ * it is unambiguous. Two offered tools that would collapse onto one wire name
105
+ * (or onto one case-insensitive wire name) disable normalization for that
106
+ * request entirely and send the real names, so the model's reply can never be
107
+ * attributed to the wrong tool.
108
+ *
109
+ * ---------------------------------------------------------------------------
110
+ * 5. THINKING BLOCKS ARE REPLAYED VERBATIM OR NOT AT ALL
111
+ * ---------------------------------------------------------------------------
112
+ *
113
+ * A replayed thinking block must carry the signature the model produced beside
114
+ * it: a signed block without its signature is a 400, and dropping signed
115
+ * thinking blocks breaks multi-turn tool use under extended thinking because
116
+ * the assistant turn that made a tool call loses the reasoning the server
117
+ * expects to see again. redacted_thinking blocks are replayed too - they are
118
+ * opaque to us, which is precisely why only the payload that came off the wire
119
+ * can be sent back. A thinking block with NO signature cannot be replayed at
120
+ * all and is dropped rather than sent unsigned.
121
+ *
122
+ * For that to be possible across turns, the text and the signature are carried
123
+ * through the turn: each emitted reasoning block gets a matching entry in the
124
+ * finish chunk's replayState envelope, and the request builder reads it back on
125
+ * the next turn. CHOICE: the envelope shape is DSH's (the harness's
126
+ * ReplayEnvelope), but that this line needs one at all is a consequence of the
127
+ * rule above rather than something the catalog states.
128
+ *
129
+ * ---------------------------------------------------------------------------
130
+ * 6. THE STREAM IS LINE-ORIENTED, NOT data:-ONLY
131
+ * ---------------------------------------------------------------------------
132
+ *
133
+ * Anthropic sends 'event: <name>' and 'data: <json>' as separate lines, and the
134
+ * primitive below is fed ONE line at a time. It deliberately ignores the
135
+ * 'event:' line and dispatches on the payload's own 'type' field instead: the
136
+ * two must agree, and if they ever disagree the JSON is the copy that carries
137
+ * everything else. Unknown event types are ignored rather than rejected - a
138
+ * beta this plugin does not know about must not fail a working turn - while an
139
+ * 'error' event THROWS, because a severed reply flushed as a clean stop is a
140
+ * wrong answer rather than a visible failure.
141
+ *
142
+ * Reasoning deltas are BUFFERED and emitted as one block at content_block_stop
143
+ * (CHOICE, see emitPendingThinking): the signature that decides whether the
144
+ * block may be replayed at all arrives at the END of the block, so a signed
145
+ * block cannot be recognized before then, and a reasoning block that cannot be
146
+ * replayed is not content the caller should be told it received.
147
+ */
148
+ import { type ContentBlock, type GenerateOptions, type StreamChunk } from '../common/llm-compat.ts';
149
+ import type { AttachmentStore } from '@deepseek-ai/dsh-attachment';
150
+ /**
151
+ * The Claude Code identity block's exact text.
152
+ *
153
+ * MUST be system[0] on every subscription request (see the module doc). It is a
154
+ * single literal rather than a template so a test can compare it byte for byte.
155
+ */
156
+ export declare const CLAUDE_CODE_IDENTITY_TEXT = "You are Claude Code, Anthropic's official CLI for Claude.";
157
+ /** Answer room the budget clamp always leaves below the response ceiling. */
158
+ export declare const MIN_ANSWER_TOKENS = 1024;
159
+ /**
160
+ * Thinking budget one level asks for, before any clamp.
161
+ *
162
+ * TRANSCRIBED from simple-options.js lines 38-43. The values are the
163
+ * reference's, not a preference: a different table would silently change how
164
+ * much of the response ceiling a level spends.
165
+ */
166
+ export declare const DEFAULT_THINKING_BUDGETS: Readonly<Record<string, number>>;
167
+ /**
168
+ * Level used when a caller names none, or names one the table does not know.
169
+ *
170
+ * CHOICE. The reference always has a level because the adapter picks one off
171
+ * the model's own ladder; this mapper has to answer for a caller that named
172
+ * nothing or named a level from another provider's vocabulary. The middle of
173
+ * the table is the least surprising answer and, unlike 'high', it cannot turn a
174
+ * modest request into one whose budget eats the whole ceiling.
175
+ */
176
+ export declare const DEFAULT_THINKING_LEVEL = "medium";
177
+ /** Caller-supplied overrides for {@link DEFAULT_THINKING_BUDGETS}. */
178
+ export type ThinkingBudgets = Readonly<Record<string, number | undefined>>;
179
+ /**
180
+ * Collapse an effort onto the levels the budget table names.
181
+ *
182
+ * TRANSCRIBED from simple-options.js lines 44-46: xhigh and max are the two
183
+ * rungs the table has no entry for, and both resolve to high rather than to a
184
+ * budget invented here.
185
+ */
186
+ export declare function clampReasoning(effort: string | undefined | null): string | undefined;
187
+ /**
188
+ * Budget one level asks for, with the caller's overrides applied.
189
+ *
190
+ * TRANSCRIBED from simple-options.js lines 47-51. An unknown level yields
191
+ * undefined - the reference's spread-and-index does the same - and every caller
192
+ * below answers for that case explicitly instead of doing arithmetic with it.
193
+ */
194
+ export declare function thinkingBudgetForLevel(level: string | undefined | null, customBudgets?: ThinkingBudgets): number | undefined;
195
+ /**
196
+ * Shrink a budget until an answer still fits under the ceiling.
197
+ *
198
+ * TRANSCRIBED from simple-options.js lines 52-55, and reused verbatim as the
199
+ * wire clamp below, which the catalog writes out inline as exactly this
200
+ * expression.
201
+ */
202
+ export declare function clampThinkingBudgetToAnswerRoom(budget: number, ceiling: number): number;
203
+ /**
204
+ * Level {@link thinkingBudgetForLevel} should be asked about.
205
+ *
206
+ * A caller who named no level, or named one of the off-tokens, gets the middle
207
+ * level rather than an undefined lookup: the budget table names no 'off' rung,
208
+ * and a request that is going to think needs a budget fitted for it. A level
209
+ * the table does not know at all is passed through so the arithmetic, and not
210
+ * this function, is what reports it as unavailable.
211
+ */
212
+ export declare function thinkingBudgetLevel(effort: string | undefined | null): string;
213
+ /**
214
+ * Fit a thinking budget inside a response ceiling.
215
+ *
216
+ * TRANSCRIBED from simple-options.js lines 56-65. Read the two traps in the
217
+ * module doc before changing a branch here:
218
+ *
219
+ * - baseMaxTokens === undefined means NO EXPLICIT CALLER CAP and selects the
220
+ * model cap; coercing it to 0 would make maxTokens equal the budget and
221
+ * leaving nothing for an answer;
222
+ * - baseMaxTokens is the ALREADY-RESOLVED cap, so the caller resolves
223
+ * options.maxTokens ?? model.maxTokens first.
224
+ *
225
+ * The '?? 0' beside the budget is the deviation the module doc describes: the
226
+ * reference would compute NaN for a level its table does not name, and an
227
+ * unknown level is ordinary input here.
228
+ */
229
+ export declare function adjustMaxTokensForThinking(baseMaxTokens: number | undefined, modelMaxTokens: number, reasoningLevel: string | undefined | null, customBudgets?: ThinkingBudgets): {
230
+ maxTokens: number;
231
+ thinkingBudget: number | undefined;
232
+ };
233
+ /**
234
+ * The response ceiling one request asks for.
235
+ *
236
+ * options.maxTokens ?? the model's own cap. This is the resolution step the
237
+ * second trap refers to: an undefined caller cap becomes the MODEL cap, never
238
+ * zero, so the thinking branch fits inside a real ceiling.
239
+ */
240
+ export declare function resolveMaxTokens(options: GenerateOptions): number;
241
+ /** Whether one caller effort means 'thinking off'. */
242
+ export declare function thinkingRequestedOff(effort: string | undefined | null): boolean;
243
+ /** The thinking and output_config fields one request carries. */
244
+ export interface ClaudeThinkingFields {
245
+ thinking?: Record<string, unknown>;
246
+ outputConfig?: Record<string, unknown>;
247
+ }
248
+ /**
249
+ * Whether one request will actually think.
250
+ *
251
+ * This is what decides whether the response ceiling is inflated by the level's
252
+ * budget, and getting it wrong in the generous direction is not harmless: a
253
+ * non-thinking model whose ceiling was raised by a budget it never had would
254
+ * ask the server for tokens it cannot produce. mid-convo thinks whatever the
255
+ * caller asked for; the other forms think unless the disable request is going
256
+ * to be sent and the model allows one.
257
+ */
258
+ export declare function claudeRequestThinks(model: string, effort: string | undefined | null): boolean;
259
+ /**
260
+ * Dispatch the four thinking cases for one model and effort.
261
+ *
262
+ * The guard order is the catalog's and is load-bearing: mid-convo is checked
263
+ * first and unconditionally, so a caller asking for thinking off on a managed
264
+ * effort model still gets the adaptive form with its block_binding. See the
265
+ * module doc for what each form is and why.
266
+ *
267
+ * @param model - exact model id, resolved through the frozen catalog.
268
+ * @param effort - the caller's raw effort, passed through as-is.
269
+ * @param level - the level whose budget the budget form spends.
270
+ * @param maxTokens - the ALREADY-RESOLVED response ceiling. The budget form
271
+ * spends part of it, so it is the ceiling and not the budget that this
272
+ * function is told about.
273
+ */
274
+ export declare function claudeThinking(model: string, effort: string | undefined, level: string, maxTokens: number, customBudgets?: ThinkingBudgets): ClaudeThinkingFields;
275
+ /**
276
+ * Claude Code's canonical tool spellings.
277
+ *
278
+ * TRANSCRIBED from the reference implementation's own tool vocabulary. The
279
+ * order is the reference's; membership is what matters.
280
+ */
281
+ export declare const CLAUDE_CODE_TOOL_NAMES: readonly string[];
282
+ /**
283
+ * The canonical spelling of one tool name, or undefined when it has none.
284
+ *
285
+ * This is the single-name rule: case-insensitive membership, canonical output.
286
+ */
287
+ export declare function canonicalClaudeToolName(name: string): string | undefined;
288
+ /** The per-request tool-name translation both directions of the wire share. */
289
+ export interface ClaudeToolNames {
290
+ /** False when a collision disabled normalization; both maps are then identity. */
291
+ enabled: boolean;
292
+ /** Caller spelling -> the name to send. */
293
+ toWire: ReadonlyMap<string, string>;
294
+ /** Exact wire name -> caller spelling. */
295
+ byExact: ReadonlyMap<string, string>;
296
+ /** Lower-cased wire name -> caller spelling; consulted only after byExact. */
297
+ byLower: ReadonlyMap<string, string>;
298
+ }
299
+ /**
300
+ * Build the translation for one request's offered tools.
301
+ *
302
+ * Collisions disable normalization (see the module doc): the check is on the
303
+ * WIRE name, compared exactly and case-insensitively, because both are ways for
304
+ * one reply to be attributed to the wrong tool. Case-insensitivity is the
305
+ * stricter half and is CHOICE: two tools spelled 'read' and 'Read' send two
306
+ * distinct names and are therefore unambiguous on the request, but a reply of
307
+ * 'READ' could not be attributed, and refusing to guess costs only the
308
+ * canonical spelling.
309
+ */
310
+ export declare function claudeToolNames(tools?: readonly {
311
+ name: string;
312
+ }[]): ClaudeToolNames;
313
+ /** The wire name for one caller tool name under a request's translation. */
314
+ export declare function claudeWireToolName(name: string, names?: ClaudeToolNames): string;
315
+ /**
316
+ * The caller's tool name for one name the model returned.
317
+ *
318
+ * Exact match first, then case-insensitive: a model that relabels the case of a
319
+ * name it was given is still talking about the tool it was given, while a
320
+ * request that offered two names differing only by case must resolve the exact
321
+ * one. An unknown name is returned unchanged - it is not this layer's job to
322
+ * invent a tool.
323
+ */
324
+ export declare function claudeOriginalToolName(name: string, names?: ClaudeToolNames): string;
325
+ /** Attachment seam this route needs: verified bytes for one durable image. */
326
+ export type AttachmentImageReader = Pick<AttachmentStore, 'readImage'>;
327
+ /** One durable image resolved for an in-flight request, or proven unreadable. */
328
+ export type ResolvedRequestImage = {
329
+ readonly kind: 'inline';
330
+ readonly mediaType: string;
331
+ readonly data: string;
332
+ } | {
333
+ readonly kind: 'unavailable';
334
+ };
335
+ /** Resolved images keyed by durable attachment id; consumed by one request build. */
336
+ export type ResolvedRequestImages = ReadonlyMap<string, ResolvedRequestImage>;
337
+ /**
338
+ * Base64 image payload one request may carry.
339
+ *
340
+ * CHOICE, bounded on both sides. Anthropic's documented request ceiling is
341
+ * 32 MB, and its per-image ceiling is 5 MB of RAW bytes; 5 MB of raw bytes
342
+ * expands to about 6.8 MB of base64, so a bound below that would offload a
343
+ * single image the endpoint would have accepted. 8 MB leaves the conversation
344
+ * text, tool schemas and system prompt room inside the 32 MB envelope while
345
+ * still catching the runaway case locally rather than as a 413.
346
+ */
347
+ export declare const MAX_REQUEST_IMAGE_BYTES: number;
348
+ /**
349
+ * Replace the oldest inline images with a text placeholder once one request
350
+ * would carry more than {@link MAX_REQUEST_IMAGE_BYTES} of base64 image data.
351
+ * Durable history is untouched; only the request about to be sent changes, and
352
+ * the placeholder names the omission so the model asks for the picture again
353
+ * instead of answering about a blank.
354
+ */
355
+ export declare function offloadOldestRequestImages(options: GenerateOptions): GenerateOptions;
356
+ /**
357
+ * Read every durable { type: 'image', attachment } block one request carries.
358
+ * An unreadable image resolves to 'unavailable' rather than disappearing, so
359
+ * the model is told the picture is missing instead of answering about a blank.
360
+ */
361
+ export declare function resolveRequestImages(options: GenerateOptions, attachments: AttachmentImageReader | undefined, signal?: AbortSignal): Promise<ResolvedRequestImages>;
362
+ type AnthropicBlock = Record<string, unknown>;
363
+ /**
364
+ * Concatenated system-prompt text, or undefined when the caller stated none.
365
+ *
366
+ * Cache-stability invariant: the system array is the head of the prefix the
367
+ * server caches, so this must be a pure, order-stable fold of its inputs - the
368
+ * one-shot header first, then message text in history order, never re-sorted
369
+ * and never decorated with per-turn metadata. Any value that changes
370
+ * turn-over-turn belongs in a trailing user message, not here, because one
371
+ * changed byte at the head invalidates the whole cached prefix.
372
+ */
373
+ export declare function leadingSystemText(options: GenerateOptions): string | undefined;
374
+ /**
375
+ * The system array for one request: identity first, always.
376
+ *
377
+ * The identity block is not conditional on anything (see the module doc). The
378
+ * optional ephemeral cache marker is opt-in and goes on the LAST block, which
379
+ * is the Anthropic-recommended shape: a breakpoint at the end of the prompt
380
+ * caches everything above it, so marking the user block also covers the
381
+ * identity block, while marking the identity block alone would cache nothing
382
+ * that changes.
383
+ */
384
+ export declare function buildClaudeSystemBlocks(options: GenerateOptions, systemCacheControl?: boolean): AnthropicBlock[];
385
+ /** Options this builder reads beyond GenerateOptions. */
386
+ export interface ClaudeRequestOptions {
387
+ /**
388
+ * Put an ephemeral cache breakpoint on the last system block. Default false,
389
+ * so the marker is opt-in.
390
+ */
391
+ systemCacheControl?: boolean;
392
+ /**
393
+ * Tool-name translation to use. Pass the same value to createStreamState so
394
+ * the response side maps back through the identical table.
395
+ */
396
+ toolNames?: ClaudeToolNames;
397
+ /** Caller overrides for the thinking budget table. */
398
+ thinkingBudgets?: ThinkingBudgets;
399
+ }
400
+ /**
401
+ * Build one Messages request body.
402
+ *
403
+ * Field order in the returned object is irrelevant to the server and is kept
404
+ * readable only.
405
+ *
406
+ * @param options - request options carrying the normalized conversation.
407
+ * @param images - images read for this request by resolveRequestImages.
408
+ * @param request - cache and translation options.
409
+ */
410
+ export declare function buildClaudeRequestBody(options: GenerateOptions, images?: ResolvedRequestImages, request?: ClaudeRequestOptions): Record<string, unknown>;
411
+ /** One tool_use block accumulating across input_json_delta fragments. */
412
+ interface PendingToolCall {
413
+ /** Index of the DSH block this call occupies. */
414
+ index: number;
415
+ /** Wire id, kept beside the DSH-block id so a replay is byte-exact. */
416
+ id: string;
417
+ /** The name the CALLER declared, which is what DSH dispatches on. */
418
+ name: string;
419
+ /** The name the WIRE carried, which is what a replay must send back. */
420
+ wireName: string;
421
+ /** Concatenated partial_json fragments, verbatim. */
422
+ arguments: string;
423
+ }
424
+ /** One text block currently receiving deltas. */
425
+ interface OpenTextBlock {
426
+ index: number;
427
+ text: string;
428
+ }
429
+ /**
430
+ * One thinking or redacted_thinking block held until the block closes.
431
+ *
432
+ * Buffered rather than streamed because the signature that decides whether the
433
+ * block can ever be replayed arrives at the END of the block (see the module
434
+ * doc), and because a redacted block's payload must not be paraphrased into
435
+ * visible reasoning text.
436
+ */
437
+ interface PendingThinking {
438
+ index: number;
439
+ kind: 'thinking' | 'redacted_thinking';
440
+ text: string;
441
+ signature: string;
442
+ data: string;
443
+ }
444
+ /** Accumulated state of one Anthropic SSE stream. */
445
+ export interface ClaudeStreamState {
446
+ /** Emitted blocks by DSH index; a slot exists from the moment its block opens. */
447
+ blocks: ContentBlock[];
448
+ /** Anthropic content index -> the DSH index of the open text block. */
449
+ openText: Map<number, OpenTextBlock>;
450
+ /** Anthropic content index -> the accumulating tool call. */
451
+ toolCalls: Map<number, PendingToolCall>;
452
+ /** Anthropic content index -> a buffered thinking block. */
453
+ pending: Map<number, PendingThinking>;
454
+ /** Anthropic content index -> the wire block that produced the emitted block. */
455
+ replayBlocks: unknown[];
456
+ /** Tool-name translation the response side maps back through. */
457
+ toolNames: ClaudeToolNames | undefined;
458
+ sawMessageStart: boolean;
459
+ sawMessageStop: boolean;
460
+ hasContent: boolean;
461
+ hasToolCall: boolean;
462
+ /** Anthropic stop_reason, verbatim. */
463
+ finishReason: string | null;
464
+ inputTokens: number;
465
+ outputTokens: number;
466
+ cacheReadTokens: number;
467
+ cacheWriteTokens: number;
468
+ reasoningTokens: number;
469
+ sawUsage: boolean;
470
+ finished: boolean;
471
+ }
472
+ /**
473
+ * Fresh stream state.
474
+ *
475
+ * @param toolNames - the SAME ClaudeToolNames the request was built with, so a
476
+ * returned canonical tool name maps back to the spelling the caller declared.
477
+ * Omitted means names pass through unchanged.
478
+ */
479
+ export declare function createStreamState(toolNames?: ClaudeToolNames): ClaudeStreamState;
480
+ /**
481
+ * Flush every open block, then emit usage and the terminal finish.
482
+ *
483
+ * Idempotent: message_stop already closes the stream, so the adapter's own call
484
+ * after the body ends is a no-op rather than a duplicate finish. This function
485
+ * deliberately does NOT judge whether the stream was complete - that is
486
+ * assertStreamComplete's job, kept separate so the flush and the verdict can be
487
+ * reasoned about independently.
488
+ */
489
+ export declare function closeStream(state: ClaudeStreamState): StreamChunk[];
490
+ /**
491
+ * Assert the stream reached its terminal event.
492
+ *
493
+ * A stream that ended without message_stop is a severed reply, not a completed
494
+ * answer: everything already emitted is a prefix of something the model never
495
+ * finished saying, and flushing it as a clean stop is precisely the failure
496
+ * this check exists to prevent.
497
+ */
498
+ export declare function assertStreamComplete(state: ClaudeStreamState): void;
499
+ /**
500
+ * Feed one SSE line of a Messages response into the state.
501
+ *
502
+ * Emits DSH chunks for the events that carry content and ignores everything
503
+ * else, including the 'event:' line (the payload's own type is authoritative)
504
+ * and any event type this build does not know. An 'error' event THROWS: the
505
+ * reply is over, and continuing to flush it as a clean stop would report a
506
+ * wrong answer as a successful one.
507
+ */
508
+ export declare function processStreamLine(line: string, state: ClaudeStreamState): StreamChunk[];
509
+ export {};
510
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../../src/host/claude/mapper.ts"],"names":[],"mappings":"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"}