dsh-lcx-codex 0.3.3 → 0.4.0-rc.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/compact-v2.js CHANGED
@@ -1,307 +1,158 @@
1
- import { normalizeCompactionResponse } from './compact.js'
2
- import { fetchSseWithRetry } from './transport.js'
1
+ import { consumeSse, fetchSseWithRetry } from './transport.js'
2
+ import { responsesTools } from './dsh-responses.js'
3
3
 
4
- const REMOTE_COMPACTION_V2_FEATURE = 'remote_compaction_v2'
5
- const DEFAULT_MAX_SSE_BYTES = 8 * 1024 * 1024
4
+ export const REMOTE_COMPACTION_V2_FEATURE = 'remote_compaction_v2'
6
5
 
7
- function isObject(value) {
8
- return value !== null && typeof value === 'object' && !Array.isArray(value)
6
+ function isObject(value) { return value !== null && typeof value === 'object' && !Array.isArray(value) }
7
+ function fail(message, code = 'LCX_COMPACT_INVALID_RESPONSE') { const e = new Error(message); e.code = code; return e }
8
+ function safeMachineField(value) {
9
+ if (typeof value !== 'string' || value.length === 0 || value.length > 96) return undefined
10
+ return /^[A-Za-z0-9_.:\[\]-]+$/u.test(value) ? value : undefined
9
11
  }
10
12
 
11
- function protocolError(message, code = 'LCX_COMPACT_INVALID_SSE') {
12
- const error = new Error(message)
13
- error.code = code
14
- return error
15
- }
16
-
17
- function outputItemIdentity(event) {
18
- const outputIndex = Number.isInteger(event?.output_index) && event.output_index >= 0
19
- ? `index:${event.output_index}`
20
- : undefined
21
- const itemIds = [event?.item?.id, event?.item_id]
22
- .filter((value) => typeof value === 'string' && value.length > 0)
23
- .map((value) => `id:${value}`)
24
- const uniqueItemIds = [...new Set(itemIds)]
25
- if (uniqueItemIds.length > 1) {
26
- throw protocolError('Native compaction SSE event contains conflicting item identities')
27
- }
28
- return { outputIndex, itemId: uniqueItemIds[0] }
29
- }
30
-
31
- function mergeOutputItem(event, items, recordsByIndex, recordsById) {
32
- if (!isObject(event?.item)) return
33
- const { outputIndex, itemId } = outputItemIdentity(event)
34
- const mappedRecords = new Set()
35
- if (outputIndex && recordsByIndex.has(outputIndex)) mappedRecords.add(recordsByIndex.get(outputIndex))
36
- if (itemId && recordsById.has(itemId)) mappedRecords.add(recordsById.get(itemId))
37
- if (mappedRecords.size > 1) {
38
- throw protocolError('Native compaction SSE event maps output_index and item id to different items')
39
- }
40
-
41
- let record = mappedRecords.values().next().value
42
- if (!record && event.type === 'response.output_item.done') {
43
- const pending = items.filter((candidate) => !candidate.done &&
44
- (!candidate.item.type || !event.item.type || candidate.item.type === event.item.type))
45
- if (pending.length === 1) record = pending[0]
46
- else if (pending.length > 1) {
47
- throw protocolError('Native compaction SSE output item has ambiguous aliases')
48
- }
49
- }
50
- if (!record) {
51
- record = { item: {}, outputIndex: undefined, itemId: undefined, done: false }
52
- items.push(record)
53
- }
54
-
55
- if (outputIndex && record.outputIndex && outputIndex !== record.outputIndex) {
56
- throw protocolError('Native compaction SSE output_index changed for one item')
57
- }
58
- if (itemId && record.itemId && itemId !== record.itemId) {
59
- throw protocolError('Native compaction SSE item id changed for one item')
60
- }
61
- if (outputIndex && recordsByIndex.has(outputIndex) && recordsByIndex.get(outputIndex) !== record) {
62
- throw protocolError('Native compaction SSE output_index is reused by different items')
63
- }
64
- if (itemId && recordsById.has(itemId) && recordsById.get(itemId) !== record) {
65
- throw protocolError('Native compaction SSE item id is reused by different items')
66
- }
67
-
68
- const previousEncryptedContent = typeof record.item.encrypted_content === 'string' && record.item.encrypted_content.length > 0
69
- ? record.item.encrypted_content
70
- : undefined
71
- Object.assign(record.item, structuredClone(event.item))
72
- if ((!record.item.encrypted_content || typeof record.item.encrypted_content !== 'string') && previousEncryptedContent) {
73
- record.item.encrypted_content = previousEncryptedContent
74
- }
75
- if (outputIndex) {
76
- record.outputIndex = outputIndex
77
- recordsByIndex.set(outputIndex, record)
78
- }
79
- if (itemId) {
80
- record.itemId = itemId
81
- recordsById.set(itemId, record)
82
- }
83
- if (event.type === 'response.output_item.done') record.done = true
13
+ export function mergeFeatureHeader(headers = {}) {
14
+ const result = { ...headers }
15
+ const key = Object.keys(result).find((name) => name.toLowerCase() === 'x-codex-beta-features')
16
+ const values = String(key ? result[key] ?? '' : '').split(',').map((x) => x.trim()).filter(Boolean)
17
+ if (!values.includes(REMOTE_COMPACTION_V2_FEATURE)) values.push(REMOTE_COMPACTION_V2_FEATURE)
18
+ result[key ?? 'x-codex-beta-features'] = values.join(',')
19
+ return result
84
20
  }
85
21
 
86
- function validCompletedOutput(output) {
87
- if (!Array.isArray(output)) return false
88
- try {
89
- normalizeCompactionResponse({ object: 'response.compaction', output })
90
- return true
91
- } catch {
92
- return false
22
+ export function responsesGenerationEnvelope({ reasoningEffort, temperature, maxTokens } = {}) {
23
+ const result = {}
24
+ if (reasoningEffort !== undefined && reasoningEffort !== 'off') {
25
+ result.reasoning = { effort: String(reasoningEffort), summary: 'auto' }
26
+ result.include = ['reasoning.encrypted_content']
93
27
  }
94
- }
95
-
96
- function usageFrom(response) {
97
- const usage = response?.usage
98
- if (!isObject(usage)) return undefined
99
- const totalInputTokens = Number(usage.input_tokens ?? 0)
100
- const outputTokens = Number(usage.output_tokens ?? 0)
101
- const cacheReadValue = Number(usage.input_tokens_details?.cached_tokens ?? usage.input_token_details?.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? 0)
102
- const cacheWriteValue = Number(usage.input_tokens_details?.cache_write_tokens ?? usage.input_token_details?.cache_write_tokens ?? usage.prompt_tokens_details?.cache_write_tokens ?? 0)
103
- const cacheReadTokens = Number.isFinite(cacheReadValue) && cacheReadValue > 0 ? cacheReadValue : 0
104
- const cacheWriteTokens = Number.isFinite(cacheWriteValue) && cacheWriteValue > 0 ? cacheWriteValue : 0
105
- const inputTokens = Number.isFinite(totalInputTokens)
106
- ? Math.max(0, totalInputTokens - cacheReadTokens - cacheWriteTokens)
107
- : 0
108
- const normalizedOutputTokens = Number.isFinite(outputTokens) && outputTokens > 0 ? outputTokens : 0
109
- if (![inputTokens, cacheReadTokens, cacheWriteTokens, normalizedOutputTokens].some((value) => value > 0)) return undefined
110
- return {
111
- inputTokens,
112
- outputTokens: normalizedOutputTokens,
113
- ...(cacheReadTokens > 0 ? { cacheReadTokens } : {}),
114
- ...(cacheWriteTokens > 0 ? { cacheWriteTokens } : {}),
115
- ...(Number.isFinite(usage.output_token_details?.reasoning_tokens) && usage.output_token_details.reasoning_tokens > 0
116
- ? { reasoningTokens: Number(usage.output_token_details.reasoning_tokens) }
117
- : {}),
28
+ if (temperature !== undefined) {
29
+ if (!Number.isFinite(temperature)) throw fail('Responses temperature must be finite', 'LCX_COMPACT_INVALID_INPUT')
30
+ result.temperature = Number(temperature)
118
31
  }
119
- }
120
-
121
- function validToolDeclaration(tool) {
122
- if (!isObject(tool)) return false
123
- if (tool.type === undefined) return typeof tool.name === 'string' && tool.name.length > 0
124
- if (typeof tool.type !== 'string' || tool.type.length === 0) return false
125
- if (tool.type === 'function' || tool.type === 'custom') {
126
- const name = tool.name ?? tool.function?.name
127
- return typeof name === 'string' && name.length > 0
32
+ if (maxTokens !== undefined) {
33
+ if (!Number.isSafeInteger(maxTokens) || maxTokens <= 0) throw fail('Responses maxTokens must be a positive safe integer', 'LCX_COMPACT_INVALID_INPUT')
34
+ result.max_output_tokens = Math.max(16, maxTokens)
128
35
  }
129
- return true
130
- }
131
-
132
- export function responsesTools(tools) {
133
- if (tools === undefined) return undefined
134
- if (!Array.isArray(tools) || !tools.every(validToolDeclaration)) {
135
- throw protocolError('Native compaction tools contain an invalid declaration', 'LCX_COMPACT_INVALID_TOOLS')
136
- }
137
- return tools.map((tool) => {
138
- if (tool.type !== undefined) return structuredClone(tool)
139
- return {
140
- type: 'function',
141
- ...structuredClone(tool),
142
- description: typeof tool.description === 'string' ? tool.description : '',
143
- parameters: tool.parameters && typeof tool.parameters === 'object' ? structuredClone(tool.parameters) : { type: 'object', properties: {} },
144
- strict: false,
145
- }
146
- })
147
- }
148
-
149
- export function mergeFeatureHeader(headers) {
150
- const result = { ...(headers ?? {}) }
151
- const key = Object.keys(result).find((name) => name.toLowerCase() === 'x-codex-beta-features')
152
- const existing = key ? String(result[key] ?? '').trim() : ''
153
- const features = existing.split(',').map((value) => value.trim()).filter(Boolean)
154
- if (!features.includes(REMOTE_COMPACTION_V2_FEATURE)) features.push(REMOTE_COMPACTION_V2_FEATURE)
155
- result[key ?? 'x-codex-beta-features'] = features.join(',')
156
36
  return result
157
37
  }
158
38
 
159
- export function buildNativeCompactionBody({ model, input, instructions, promptCacheKey, promptCacheRetention, tools }) {
160
- if (!Array.isArray(input)) throw protocolError('Native compaction input must be an array', 'LCX_COMPACT_INVALID_INPUT')
161
- if (input.some((item) => isObject(item) && item.type === 'compaction_trigger')) {
162
- throw protocolError('Native compaction input already contains compaction_trigger', 'LCX_COMPACT_DUPLICATE_TRIGGER')
163
- }
39
+ export function buildNativeCompactionBody({ model, input, instructions, tools, promptCacheKey, promptCacheRetention, reasoningEffort, temperature, maxTokens }) {
40
+ if (!Array.isArray(input)) throw fail('native compaction input must be an array', 'LCX_COMPACT_INVALID_INPUT')
41
+ if (input.some((item) => item?.type === 'compaction_trigger')) throw fail('native compaction input already contains compaction_trigger', 'LCX_COMPACT_DUPLICATE_TRIGGER')
164
42
  const nativeTools = responsesTools(tools)
165
43
  return {
166
44
  model,
167
45
  input: [...structuredClone(input), { type: 'compaction_trigger' }],
168
46
  stream: true,
169
47
  store: false,
48
+ tool_choice: 'auto',
49
+ parallel_tool_calls: true,
50
+ ...(instructions !== undefined ? { instructions } : {}),
170
51
  ...(nativeTools !== undefined ? { tools: nativeTools } : {}),
171
- ...(instructions !== undefined ? { instructions: structuredClone(instructions) } : {}),
172
- ...(promptCacheKey !== undefined && promptCacheKey !== null ? { prompt_cache_key: String(promptCacheKey) } : {}),
173
- ...(promptCacheRetention !== undefined && promptCacheRetention !== null ? { prompt_cache_retention: String(promptCacheRetention) } : {}),
52
+ ...(promptCacheKey ? { prompt_cache_key: String(promptCacheKey) } : {}),
53
+ ...(promptCacheRetention ? { prompt_cache_retention: String(promptCacheRetention) } : {}),
54
+ ...responsesGenerationEnvelope({ reasoningEffort, temperature, maxTokens }),
174
55
  }
175
56
  }
176
57
 
177
- function parseSseEvent(dataLines) {
178
- if (dataLines.length === 0) return undefined
179
- const data = dataLines.join('\n')
180
- if (data === '[DONE]') return undefined
181
- try {
182
- const parsed = JSON.parse(data)
183
- if (!isObject(parsed)) throw new Error('SSE event is not an object')
184
- return parsed
185
- } catch (error) {
186
- throw protocolError(`Native compaction returned malformed SSE JSON: ${String(error)}`)
187
- }
58
+ function usageFrom(raw) {
59
+ if (!isObject(raw)) return undefined
60
+ const inputTotal = Number(raw.input_tokens ?? 0)
61
+ const output = Number(raw.output_tokens ?? 0)
62
+ const details = raw.input_tokens_details ?? raw.input_token_details ?? raw.prompt_tokens_details ?? {}
63
+ const cacheRead = Number(details.cached_tokens ?? 0)
64
+ const cacheWrite = Number(details.cache_write_tokens ?? 0)
65
+ const result = {
66
+ inputTokens: Math.max(0, Number.isFinite(inputTotal) ? inputTotal - (Number.isFinite(cacheRead) ? cacheRead : 0) - (Number.isFinite(cacheWrite) ? cacheWrite : 0) : 0),
67
+ outputTokens: Number.isFinite(output) && output > 0 ? output : 0,
68
+ }
69
+ if (Number.isFinite(cacheRead) && cacheRead > 0) result.cacheReadTokens = cacheRead
70
+ if (Number.isFinite(cacheWrite) && cacheWrite > 0) result.cacheWriteTokens = cacheWrite
71
+ const reasoning = Number(raw.output_tokens_details?.reasoning_tokens ?? raw.output_token_details?.reasoning_tokens ?? 0)
72
+ if (Number.isFinite(reasoning) && reasoning > 0) result.reasoningTokens = reasoning
73
+ return Object.values(result).some((v) => Number(v) > 0) ? result : undefined
188
74
  }
189
75
 
190
- export async function parseNativeCompactionSse(response, options = {}) {
191
- if (!response?.body) throw protocolError('Native compaction response did not include an SSE body', 'LCX_INVALID_SSE')
192
- const maxBytes = options.maxResponseBytes ?? DEFAULT_MAX_SSE_BYTES
193
- const reader = response.body.getReader()
194
- const decoder = new TextDecoder()
195
- const eventItems = []
196
- const recordsByIndex = new Map()
197
- const recordsById = new Map()
198
- let completedResponse
199
- let completedOutput
200
- let pending = ''
201
- let dataLines = []
202
- let bytes = 0
203
- let sawTerminal = false
204
-
205
- const dispatch = () => {
206
- const event = parseSseEvent(dataLines)
207
- dataLines = []
208
- if (!event) return
209
- if (event.type === 'error' || event.type === 'response.failed' || event.type === 'response.incomplete') {
210
- const message = event.error?.message ?? event.response?.error?.message ?? `Native compaction ended with ${String(event.type)}`
211
- throw protocolError(message, 'LCX_COMPACT_UPSTREAM_ERROR')
212
- }
213
- if (event.type === 'response.output_item.added' || event.type === 'response.output_item.done') {
214
- mergeOutputItem(event, eventItems, recordsByIndex, recordsById)
215
- }
216
- if (event.type === 'response.completed') {
217
- sawTerminal = true
218
- completedResponse = isObject(event.response) ? event.response : {}
219
- completedOutput = Array.isArray(completedResponse.output) ? structuredClone(completedResponse.output) : undefined
76
+ function validateOutput(output) {
77
+ if (!Array.isArray(output) || output.length === 0) throw fail('native compaction output is empty')
78
+ const compactions = output.filter((item) => isObject(item) && item.type === 'compaction')
79
+ if (compactions.length !== 1) throw fail(`native compaction must return exactly one compaction item, got ${compactions.length}`)
80
+ const compact = compactions[0]
81
+ if (typeof compact.encrypted_content !== 'string' || compact.encrypted_content.length === 0) throw fail('native compaction item has no encrypted_content')
82
+ const calls = new Set()
83
+ const results = new Set()
84
+ for (const item of output) {
85
+ if (!isObject(item) || typeof item.type !== 'string') throw fail('native compaction output contains a malformed item')
86
+ if (item.type === 'function_call') {
87
+ if (typeof item.call_id !== 'string' || !item.call_id || calls.has(item.call_id)) throw fail('native compaction output contains an invalid function_call')
88
+ calls.add(item.call_id)
89
+ } else if (item.type === 'function_call_output') {
90
+ if (typeof item.call_id !== 'string' || !item.call_id || results.has(item.call_id)) throw fail('native compaction output contains an invalid function_call_output')
91
+ results.add(item.call_id)
220
92
  }
221
93
  }
94
+ for (const id of calls) if (!results.has(id)) throw fail(`native compaction output has orphan function_call ${id}`)
95
+ for (const id of results) if (!calls.has(id)) throw fail(`native compaction output has orphan function_call_output ${id}`)
96
+ return { output: structuredClone(output), compaction: structuredClone(compact) }
97
+ }
222
98
 
223
- try {
224
- while (true) {
225
- if (options.signal?.aborted) throw options.signal.reason ?? new Error('request aborted')
226
- const result = await reader.read()
227
- if (result.done) break
228
- bytes += result.value.byteLength
229
- if (bytes > maxBytes) throw protocolError(`Native compaction SSE response exceeds ${maxBytes} bytes`, 'LCX_RESPONSE_TOO_LARGE')
230
- pending += decoder.decode(result.value, { stream: true })
231
- let newline
232
- while ((newline = pending.indexOf('\n')) >= 0) {
233
- const line = pending.slice(0, newline).replace(/\r$/u, '')
234
- pending = pending.slice(newline + 1)
235
- if (line === '') dispatch()
236
- else if (!line.startsWith(':')) {
237
- if (line.startsWith('data:')) dataLines.push(line.slice(5).replace(/^ /u, ''))
238
- }
239
- }
240
- }
241
- pending += decoder.decode()
242
- if (pending.length > 0) {
243
- const line = pending.replace(/\r$/u, '')
244
- if (line.startsWith('data:')) dataLines.push(line.slice(5).replace(/^ /u, ''))
99
+ export async function parseNativeCompactionSse(response, options = {}) {
100
+ const byIndex = new Map()
101
+ const byId = new Map()
102
+ let terminal
103
+ const mergeItem = (event) => {
104
+ if (!isObject(event?.item)) return
105
+ const index = Number.isInteger(event.output_index) ? event.output_index : undefined
106
+ const id = typeof event.item.id === 'string' ? event.item.id : typeof event.item_id === 'string' ? event.item_id : undefined
107
+ let record = (index !== undefined ? byIndex.get(index) : undefined) ?? (id ? byId.get(id) : undefined)
108
+ if (!record) record = {}
109
+ const encrypted = record.encrypted_content
110
+ Object.assign(record, structuredClone(event.item))
111
+ if (typeof record.encrypted_content !== 'string' && typeof encrypted === 'string') record.encrypted_content = encrypted
112
+ if (index !== undefined) byIndex.set(index, record)
113
+ if (id) byId.set(id, record)
114
+ }
115
+ await consumeSse(response, (event) => {
116
+ if (!isObject(event)) return
117
+ if (event.type === 'error' || event.type === 'response.failed' || event.type === 'response.incomplete') {
118
+ const upstream = event.type === 'response.failed' ? event.response?.error : event.error
119
+ const providerCode = safeMachineField(upstream?.code)
120
+ const providerType = safeMachineField(upstream?.type)
121
+ const providerParam = safeMachineField(upstream?.param)
122
+ const diagnostics = [
123
+ providerCode ? `providerCode=${providerCode}` : '',
124
+ providerType ? `providerType=${providerType}` : '',
125
+ providerParam ? `providerParam=${providerParam}` : '',
126
+ ].filter(Boolean).join(' ')
127
+ const e = fail(`native compaction ended with ${event.type}${diagnostics ? ` ${diagnostics}` : ''}`, 'LCX_COMPACT_UPSTREAM_ERROR')
128
+ if (Number.isInteger(upstream?.status ?? event.error?.status)) e.status = upstream?.status ?? event.error?.status
129
+ if (providerCode) e.providerCode = providerCode
130
+ if (providerType) e.providerType = providerType
131
+ if (providerParam) e.providerParam = providerParam
132
+ throw e
245
133
  }
246
- dispatch()
247
- } finally {
248
- await reader.cancel().catch(() => undefined)
249
- }
250
-
251
- if (!sawTerminal || !completedResponse) {
252
- throw protocolError('Native compaction SSE ended without response.completed', 'LCX_COMPACT_INCOMPLETE_SSE')
253
- }
254
-
255
- if (completedResponse.object !== undefined && !['response.compaction', 'response'].includes(completedResponse.object)) {
256
- throw protocolError(`Native compaction returned unexpected response object: ${String(completedResponse.object)}`, 'LCX_COMPACT_INVALID_RESPONSE')
257
- }
258
- const mergedEventOutput = eventItems.map((record) => record.item)
259
- const output = validCompletedOutput(completedOutput) ? completedOutput : mergedEventOutput
260
- const normalized = normalizeCompactionResponse({
261
- object: completedResponse.object ?? 'response.compaction',
262
- id: typeof completedResponse.id === 'string' ? completedResponse.id : undefined,
263
- output,
264
- })
134
+ if (event.type === 'response.output_item.added' || event.type === 'response.output_item.done') mergeItem(event)
135
+ if (event.type === 'response.completed') terminal = event.response
136
+ }, options)
137
+ if (!isObject(terminal)) throw fail('native compaction stream ended without response.completed', 'LCX_COMPACT_INCOMPLETE_SSE')
138
+ if (terminal.status !== 'completed') throw fail('native compaction response.completed did not carry completed status', 'LCX_COMPACT_INCOMPLETE_SSE')
139
+ const eventItems = [...new Set([...byIndex.values(), ...byId.values()])]
140
+ const output = Array.isArray(terminal.output) && terminal.output.length > 0 ? terminal.output : eventItems
141
+ const normalized = validateOutput(output)
265
142
  return {
143
+ object: terminal.object ?? 'response.compaction',
144
+ ...(typeof terminal.id === 'string' ? { id: terminal.id } : {}),
266
145
  ...normalized,
267
- usage: usageFrom(completedResponse),
146
+ usage: usageFrom(terminal.usage),
268
147
  }
269
148
  }
270
149
 
271
- export async function requestNativeCompaction({
272
- baseURL,
273
- model,
274
- input,
275
- instructions,
276
- promptCacheKey,
277
- promptCacheRetention,
278
- idempotencyKey,
279
- tools,
280
- headers,
281
- signal,
282
- timeoutMs,
283
- maxAttempts,
284
- maxResponseBytes,
285
- }) {
286
- const body = buildNativeCompactionBody({ model, input, instructions, promptCacheKey, promptCacheRetention, tools })
287
- const requestHeaders = { ...(headers ?? {}) }
288
- if (idempotencyKey !== undefined && idempotencyKey !== null && !Object.keys(requestHeaders).some((name) => name.toLowerCase() === 'idempotency-key')) {
289
- requestHeaders['idempotency-key'] = String(idempotencyKey)
290
- }
291
- const featureHeaders = mergeFeatureHeader(requestHeaders)
292
- return fetchSseWithRetry(
293
- `${String(baseURL).replace(/\/+$/u, '')}/responses`,
294
- body,
295
- featureHeaders,
296
- signal,
297
- timeoutMs,
298
- {
299
- maxAttempts,
300
- maxResponseBytes,
301
- consume: (response, consumeOptions = {}) => parseNativeCompactionSse(response, {
302
- signal: consumeOptions.requestSignal ?? signal,
303
- maxResponseBytes,
304
- }),
305
- },
306
- )
150
+ export async function requestNativeCompaction({ baseURL, model, input, instructions, tools, promptCacheKey, promptCacheRetention, reasoningEffort, temperature, maxTokens, idempotencyKey, headers, signal, timeoutMs, maxAttempts, maxResponseBytes }) {
151
+ const body = buildNativeCompactionBody({ model, input, instructions, tools, promptCacheKey, promptCacheRetention, reasoningEffort, temperature, maxTokens })
152
+ const requestHeaders = mergeFeatureHeader({ ...headers, ...(idempotencyKey ? { 'idempotency-key': String(idempotencyKey) } : {}) })
153
+ return fetchSseWithRetry(`${String(baseURL).replace(/\/+$/u, '')}/responses`, body, requestHeaders, signal, timeoutMs, {
154
+ maxAttempts,
155
+ maxResponseBytes,
156
+ consume: (response, consumeOptions) => parseNativeCompactionSse(response, { signal: consumeOptions.requestSignal ?? signal, maxResponseBytes }),
157
+ })
307
158
  }