@openrouter/sdk 0.1.25 → 0.2.6
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/biome.json +171 -0
- package/esm/funcs/callModel.d.ts +7 -7
- package/esm/funcs/callModel.js +35 -23
- package/esm/funcs/oAuthCreateAuthorizationUrl.d.ts +3 -3
- package/esm/funcs/oAuthCreateAuthorizationUrl.js +30 -14
- package/esm/funcs/oAuthCreateSHA256CodeChallenge.d.ts +2 -2
- package/esm/funcs/oAuthCreateSHA256CodeChallenge.js +13 -12
- package/esm/hooks/registration.d.ts +2 -2
- package/esm/hooks/registration.js +1 -2
- package/esm/lib/config.d.ts +3 -3
- package/esm/lib/config.js +3 -3
- package/esm/lib/encodings.d.ts +1 -0
- package/esm/lib/encodings.js +12 -1
- package/esm/lib/response-wrapper.d.ts +5 -5
- package/esm/lib/response-wrapper.js +76 -55
- package/esm/lib/reusable-stream.js +26 -7
- package/esm/lib/stream-transformers.d.ts +3 -3
- package/esm/lib/stream-transformers.js +43 -41
- package/esm/lib/tool-executor.d.ts +9 -9
- package/esm/lib/tool-executor.js +9 -9
- package/esm/lib/tool-orchestrator.d.ts +3 -3
- package/esm/lib/tool-orchestrator.js +6 -8
- package/esm/lib/tool-types.d.ts +26 -25
- package/esm/lib/tool-types.js +3 -3
- package/esm/models/chatcompletionfinishreason.d.ts +13 -0
- package/esm/models/chatcompletionfinishreason.js +14 -0
- package/esm/models/chatgenerationparams.d.ts +4 -4
- package/esm/models/chatgenerationparams.js +4 -4
- package/esm/models/chatmessagecontentitem.d.ts +2 -19
- package/esm/models/chatmessagecontentitem.js +6 -9
- package/esm/models/chatmessagecontentitemcachecontrol.d.ts +29 -0
- package/esm/models/chatmessagecontentitemcachecontrol.js +33 -0
- package/esm/models/chatmessagecontentitemtext.d.ts +3 -0
- package/esm/models/chatmessagecontentitemtext.js +12 -0
- package/esm/models/chatmessagecontentitemvideo.d.ts +23 -11
- package/esm/models/chatmessagecontentitemvideo.js +24 -11
- package/esm/models/chatresponsechoice.d.ts +1 -21
- package/esm/models/chatresponsechoice.js +1 -25
- package/esm/models/chatstreamingchoice.d.ts +16 -0
- package/esm/models/chatstreamingchoice.js +24 -0
- package/esm/models/chatstreamingresponsechunk.d.ts +1 -1
- package/esm/models/chatstreamingresponsechunk.js +1 -1
- package/esm/models/completionchoice.d.ts +2 -0
- package/esm/models/completionchoice.js +3 -0
- package/esm/models/completioncreateparams.d.ts +4 -4
- package/esm/models/completioncreateparams.js +4 -4
- package/esm/models/completionresponse.d.ts +1 -0
- package/esm/models/completionresponse.js +1 -0
- package/esm/models/filecitation.d.ts +2 -11
- package/esm/models/filecitation.js +2 -9
- package/esm/models/filepath.d.ts +2 -11
- package/esm/models/filepath.js +2 -10
- package/esm/models/index.d.ts +3 -2
- package/esm/models/index.js +3 -2
- package/esm/models/message.d.ts +2 -2
- package/esm/models/message.js +1 -1
- package/esm/models/openairesponsesannotation.d.ts +2 -2
- package/esm/models/openairesponsesannotation.js +2 -2
- package/esm/models/openairesponsesinputunion.d.ts +5 -45
- package/esm/models/openairesponsesinputunion.js +20 -20
- package/esm/models/openairesponsesrefusalcontent.d.ts +2 -11
- package/esm/models/openairesponsesrefusalcontent.js +2 -9
- package/esm/models/openresponseseasyinputmessage.d.ts +6 -54
- package/esm/models/openresponseseasyinputmessage.js +12 -12
- package/esm/models/openresponseserrorevent.d.ts +1 -8
- package/esm/models/openresponseserrorevent.js +1 -6
- package/esm/models/openresponsesimagegencallcompleted.d.ts +1 -8
- package/esm/models/openresponsesimagegencallcompleted.js +1 -6
- package/esm/models/openresponsesimagegencallgenerating.d.ts +1 -8
- package/esm/models/openresponsesimagegencallgenerating.js +1 -6
- package/esm/models/openresponsesimagegencallinprogress.d.ts +1 -8
- package/esm/models/openresponsesimagegencallinprogress.js +1 -6
- package/esm/models/openresponsesimagegencallpartialimage.d.ts +1 -8
- package/esm/models/openresponsesimagegencallpartialimage.js +1 -6
- package/esm/models/openresponsesinputmessageitem.d.ts +4 -36
- package/esm/models/openresponsesinputmessageitem.js +8 -8
- package/esm/models/openresponsesnonstreamingresponse.d.ts +1 -7
- package/esm/models/openresponsesnonstreamingresponse.js +1 -6
- package/esm/models/openresponsesreasoningdeltaevent.d.ts +1 -8
- package/esm/models/openresponsesreasoningdeltaevent.js +1 -6
- package/esm/models/openresponsesreasoningdoneevent.d.ts +1 -8
- package/esm/models/openresponsesreasoningdoneevent.js +1 -6
- package/esm/models/openresponsesreasoningsummarypartaddedevent.d.ts +1 -8
- package/esm/models/openresponsesreasoningsummarypartaddedevent.js +1 -6
- package/esm/models/openresponsesreasoningsummarytextdeltaevent.d.ts +1 -8
- package/esm/models/openresponsesreasoningsummarytextdeltaevent.js +1 -6
- package/esm/models/openresponsesreasoningsummarytextdoneevent.d.ts +1 -8
- package/esm/models/openresponsesreasoningsummarytextdoneevent.js +1 -6
- package/esm/models/openresponsesrequest.d.ts +26 -44
- package/esm/models/openresponsesrequest.js +15 -32
- package/esm/models/openresponsesstreamevent.d.ts +30 -125
- package/esm/models/openresponsesstreamevent.js +34 -119
- package/esm/models/openresponseswebsearch20250826tool.d.ts +2 -11
- package/esm/models/openresponseswebsearch20250826tool.js +2 -9
- package/esm/models/openresponseswebsearchpreview20250311tool.d.ts +2 -11
- package/esm/models/openresponseswebsearchpreview20250311tool.js +2 -9
- package/esm/models/openresponseswebsearchpreviewtool.d.ts +2 -11
- package/esm/models/openresponseswebsearchpreviewtool.js +2 -9
- package/esm/models/openresponseswebsearchtool.d.ts +2 -11
- package/esm/models/openresponseswebsearchtool.js +2 -9
- package/esm/models/operations/createembeddings.d.ts +4 -16
- package/esm/models/operations/createembeddings.js +2 -13
- package/esm/models/operations/getcredits.d.ts +16 -1
- package/esm/models/operations/getcredits.js +17 -1
- package/esm/models/operations/getparameters.d.ts +5 -1
- package/esm/models/operations/getparameters.js +5 -1
- package/esm/models/providername.d.ts +5 -1
- package/esm/models/providername.js +5 -1
- package/esm/models/responseformattextconfig.d.ts +2 -2
- package/esm/models/responseformattextconfig.js +2 -2
- package/esm/models/responseinputaudio.d.ts +3 -11
- package/esm/models/responseinputaudio.js +2 -9
- package/esm/models/responseinputfile.d.ts +2 -11
- package/esm/models/responseinputfile.js +2 -9
- package/esm/models/responseinputimage.d.ts +3 -11
- package/esm/models/responseinputimage.js +2 -9
- package/esm/models/responseinputtext.d.ts +2 -11
- package/esm/models/responseinputtext.js +2 -9
- package/esm/models/responseoutputtext.d.ts +2 -11
- package/esm/models/responseoutputtext.js +2 -9
- package/esm/models/responsesformatjsonobject.d.ts +2 -11
- package/esm/models/responsesformatjsonobject.js +2 -9
- package/esm/models/responsesformattext.d.ts +2 -11
- package/esm/models/responsesformattext.js +2 -9
- package/esm/models/responsesformattextjsonschemaconfig.d.ts +2 -11
- package/esm/models/responsesformattextjsonschemaconfig.js +2 -9
- package/esm/models/responsesoutputitem.d.ts +13 -1
- package/esm/models/responsesoutputitem.js +6 -6
- package/esm/models/urlcitation.d.ts +2 -11
- package/esm/models/urlcitation.js +2 -9
- package/esm/sdk/oauth.d.ts +2 -2
- package/esm/sdk/oauth.js +2 -3
- package/esm/sdk/sdk.d.ts +9 -8
- package/esm/types/unrecognized.d.ts +7 -1
- package/esm/types/unrecognized.js +9 -1
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/tsconfig.json +0 -1
- package/vitest.config.ts +14 -8
- package/esm/models/chatmessagecontentitemfile.d.ts +0 -36
- package/esm/models/chatmessagecontentitemfile.js +0 -51
- package/esm/models/videourl.d.ts +0 -17
- package/esm/models/videourl.js +0 -21
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { betaResponsesSend } from
|
|
2
|
-
import { ReusableReadableStream } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { betaResponsesSend } from '../funcs/betaResponsesSend.js';
|
|
2
|
+
import { ReusableReadableStream } from './reusable-stream.js';
|
|
3
|
+
import { buildMessageStream, buildToolCallStream, consumeStreamForCompletion, extractMessageFromResponse, extractReasoningDeltas, extractTextDeltas, extractTextFromResponse, extractToolCallsFromResponse, extractToolDeltas, } from './stream-transformers.js';
|
|
4
|
+
import { executeTool } from './tool-executor.js';
|
|
5
|
+
import { hasExecuteFunction } from './tool-types.js';
|
|
6
6
|
/**
|
|
7
7
|
* A wrapper around a streaming response that provides multiple consumption patterns.
|
|
8
8
|
*
|
|
@@ -39,7 +39,10 @@ export class ResponseWrapper {
|
|
|
39
39
|
}
|
|
40
40
|
this.initPromise = (async () => {
|
|
41
41
|
// Force stream mode
|
|
42
|
-
const request = {
|
|
42
|
+
const request = {
|
|
43
|
+
...this.options.request,
|
|
44
|
+
stream: true,
|
|
45
|
+
};
|
|
43
46
|
// Create the stream promise
|
|
44
47
|
this.streamPromise = betaResponsesSend(this.options.client, request, this.options.options).then((result) => {
|
|
45
48
|
if (!result.ok) {
|
|
@@ -64,14 +67,14 @@ export class ResponseWrapper {
|
|
|
64
67
|
this.toolExecutionPromise = (async () => {
|
|
65
68
|
await this.initStream();
|
|
66
69
|
if (!this.reusableStream) {
|
|
67
|
-
throw new Error(
|
|
70
|
+
throw new Error('Stream not initialized');
|
|
68
71
|
}
|
|
69
72
|
// Get the initial response
|
|
70
73
|
const initialResponse = await consumeStreamForCompletion(this.reusableStream);
|
|
71
74
|
// Check if we have tools and if auto-execution is enabled
|
|
72
75
|
const shouldAutoExecute = this.options.tools &&
|
|
73
76
|
this.options.tools.length > 0 &&
|
|
74
|
-
initialResponse.output.some((item) =>
|
|
77
|
+
initialResponse.output.some((item) => 'type' in item && item.type === 'function_call');
|
|
75
78
|
if (!shouldAutoExecute) {
|
|
76
79
|
// No tools to execute, use initial response
|
|
77
80
|
this.finalResponse = initialResponse;
|
|
@@ -107,18 +110,22 @@ export class ResponseWrapper {
|
|
|
107
110
|
break;
|
|
108
111
|
}
|
|
109
112
|
// Check if we should continue based on maxToolRounds
|
|
110
|
-
if (typeof maxToolRounds ===
|
|
113
|
+
if (typeof maxToolRounds === 'number') {
|
|
111
114
|
if (currentRound >= maxToolRounds) {
|
|
112
115
|
break;
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
|
-
else if (typeof maxToolRounds ===
|
|
118
|
+
else if (typeof maxToolRounds === 'function') {
|
|
116
119
|
// Function signature: (context: TurnContext) => boolean
|
|
117
120
|
const turnContext = {
|
|
118
121
|
numberOfTurns: currentRound + 1,
|
|
119
122
|
messageHistory: currentInput,
|
|
120
|
-
...(this.options.request.model && {
|
|
121
|
-
|
|
123
|
+
...(this.options.request.model && {
|
|
124
|
+
model: this.options.request.model,
|
|
125
|
+
}),
|
|
126
|
+
...(this.options.request.models && {
|
|
127
|
+
models: this.options.request.models,
|
|
128
|
+
}),
|
|
122
129
|
};
|
|
123
130
|
const shouldContinue = maxToolRounds(turnContext);
|
|
124
131
|
if (!shouldContinue) {
|
|
@@ -135,8 +142,12 @@ export class ResponseWrapper {
|
|
|
135
142
|
const turnContext = {
|
|
136
143
|
numberOfTurns: currentRound + 1, // 1-indexed
|
|
137
144
|
messageHistory: currentInput,
|
|
138
|
-
...(this.options.request.model && {
|
|
139
|
-
|
|
145
|
+
...(this.options.request.model && {
|
|
146
|
+
model: this.options.request.model,
|
|
147
|
+
}),
|
|
148
|
+
...(this.options.request.models && {
|
|
149
|
+
models: this.options.request.models,
|
|
150
|
+
}),
|
|
140
151
|
};
|
|
141
152
|
// Execute all tool calls
|
|
142
153
|
const toolResults = [];
|
|
@@ -151,18 +162,24 @@ export class ResponseWrapper {
|
|
|
151
162
|
this.preliminaryResults.set(toolCall.id, result.preliminaryResults);
|
|
152
163
|
}
|
|
153
164
|
toolResults.push({
|
|
154
|
-
type:
|
|
165
|
+
type: 'function_call_output',
|
|
155
166
|
id: `output_${toolCall.id}`,
|
|
156
167
|
callId: toolCall.id,
|
|
157
168
|
output: result.error
|
|
158
|
-
? JSON.stringify({
|
|
169
|
+
? JSON.stringify({
|
|
170
|
+
error: result.error.message,
|
|
171
|
+
})
|
|
159
172
|
: JSON.stringify(result.result),
|
|
160
173
|
});
|
|
161
174
|
}
|
|
162
175
|
// Build new input with tool results
|
|
163
176
|
// For the Responses API, we need to include the tool results in the input
|
|
164
177
|
const newInput = [
|
|
165
|
-
...(Array.isArray(currentResponse.output)
|
|
178
|
+
...(Array.isArray(currentResponse.output)
|
|
179
|
+
? currentResponse.output
|
|
180
|
+
: [
|
|
181
|
+
currentResponse.output,
|
|
182
|
+
]),
|
|
166
183
|
...toolResults,
|
|
167
184
|
];
|
|
168
185
|
// Update current input for next iteration
|
|
@@ -179,7 +196,7 @@ export class ResponseWrapper {
|
|
|
179
196
|
}
|
|
180
197
|
// Handle the result - it might be a stream or a response
|
|
181
198
|
const value = newResult.value;
|
|
182
|
-
if (value && typeof value ===
|
|
199
|
+
if (value && typeof value === 'object' && 'toReadableStream' in value) {
|
|
183
200
|
// It's a stream, consume it
|
|
184
201
|
const stream = new ReusableReadableStream(value);
|
|
185
202
|
currentResponse = await consumeStreamForCompletion(stream);
|
|
@@ -205,7 +222,7 @@ export class ResponseWrapper {
|
|
|
205
222
|
this.messagePromise = (async () => {
|
|
206
223
|
await this.executeToolsIfNeeded();
|
|
207
224
|
if (!this.finalResponse) {
|
|
208
|
-
throw new Error(
|
|
225
|
+
throw new Error('Response not available');
|
|
209
226
|
}
|
|
210
227
|
return extractMessageFromResponse(this.finalResponse);
|
|
211
228
|
})();
|
|
@@ -222,7 +239,7 @@ export class ResponseWrapper {
|
|
|
222
239
|
this.textPromise = (async () => {
|
|
223
240
|
await this.executeToolsIfNeeded();
|
|
224
241
|
if (!this.finalResponse) {
|
|
225
|
-
throw new Error(
|
|
242
|
+
throw new Error('Response not available');
|
|
226
243
|
}
|
|
227
244
|
return extractTextFromResponse(this.finalResponse);
|
|
228
245
|
})();
|
|
@@ -236,7 +253,7 @@ export class ResponseWrapper {
|
|
|
236
253
|
async getResponse() {
|
|
237
254
|
await this.executeToolsIfNeeded();
|
|
238
255
|
if (!this.finalResponse) {
|
|
239
|
-
throw new Error(
|
|
256
|
+
throw new Error('Response not available');
|
|
240
257
|
}
|
|
241
258
|
return this.finalResponse;
|
|
242
259
|
}
|
|
@@ -246,10 +263,10 @@ export class ResponseWrapper {
|
|
|
246
263
|
* Includes preliminary tool result events after tool execution.
|
|
247
264
|
*/
|
|
248
265
|
getFullResponsesStream() {
|
|
249
|
-
return
|
|
266
|
+
return async function* () {
|
|
250
267
|
await this.initStream();
|
|
251
268
|
if (!this.reusableStream) {
|
|
252
|
-
throw new Error(
|
|
269
|
+
throw new Error('Stream not initialized');
|
|
253
270
|
}
|
|
254
271
|
const consumer = this.reusableStream.createConsumer();
|
|
255
272
|
// Yield original events directly
|
|
@@ -262,27 +279,27 @@ export class ResponseWrapper {
|
|
|
262
279
|
for (const [toolCallId, results] of this.preliminaryResults) {
|
|
263
280
|
for (const result of results) {
|
|
264
281
|
yield {
|
|
265
|
-
type:
|
|
282
|
+
type: 'tool.preliminary_result',
|
|
266
283
|
toolCallId,
|
|
267
284
|
result,
|
|
268
285
|
timestamp: Date.now(),
|
|
269
286
|
};
|
|
270
287
|
}
|
|
271
288
|
}
|
|
272
|
-
}.call(this)
|
|
289
|
+
}.call(this);
|
|
273
290
|
}
|
|
274
291
|
/**
|
|
275
292
|
* Stream only text deltas as they arrive.
|
|
276
293
|
* This filters the full event stream to only yield text content.
|
|
277
294
|
*/
|
|
278
295
|
getTextStream() {
|
|
279
|
-
return
|
|
296
|
+
return async function* () {
|
|
280
297
|
await this.initStream();
|
|
281
298
|
if (!this.reusableStream) {
|
|
282
|
-
throw new Error(
|
|
299
|
+
throw new Error('Stream not initialized');
|
|
283
300
|
}
|
|
284
301
|
yield* extractTextDeltas(this.reusableStream);
|
|
285
|
-
}.call(this)
|
|
302
|
+
}.call(this);
|
|
286
303
|
}
|
|
287
304
|
/**
|
|
288
305
|
* Stream incremental message updates as content is added.
|
|
@@ -291,10 +308,10 @@ export class ResponseWrapper {
|
|
|
291
308
|
* Returns AssistantMessage or ToolResponseMessage in chat format.
|
|
292
309
|
*/
|
|
293
310
|
getNewMessagesStream() {
|
|
294
|
-
return
|
|
311
|
+
return async function* () {
|
|
295
312
|
await this.initStream();
|
|
296
313
|
if (!this.reusableStream) {
|
|
297
|
-
throw new Error(
|
|
314
|
+
throw new Error('Stream not initialized');
|
|
298
315
|
}
|
|
299
316
|
// First yield assistant messages from the stream
|
|
300
317
|
yield* buildMessageStream(this.reusableStream);
|
|
@@ -315,8 +332,8 @@ export class ResponseWrapper {
|
|
|
315
332
|
: undefined;
|
|
316
333
|
// Yield tool response message
|
|
317
334
|
yield {
|
|
318
|
-
role:
|
|
319
|
-
content: result !== undefined ? JSON.stringify(result) :
|
|
335
|
+
role: 'tool',
|
|
336
|
+
content: result !== undefined ? JSON.stringify(result) : '',
|
|
320
337
|
toolCallId: toolCall.id,
|
|
321
338
|
};
|
|
322
339
|
}
|
|
@@ -324,25 +341,25 @@ export class ResponseWrapper {
|
|
|
324
341
|
// If tools were executed, yield the final assistant message (if there is one)
|
|
325
342
|
if (this.finalResponse && this.allToolExecutionRounds.length > 0) {
|
|
326
343
|
// Check if the final response contains a message
|
|
327
|
-
const hasMessage = this.finalResponse.output.some((item) =>
|
|
344
|
+
const hasMessage = this.finalResponse.output.some((item) => 'type' in item && item.type === 'message');
|
|
328
345
|
if (hasMessage) {
|
|
329
346
|
yield extractMessageFromResponse(this.finalResponse);
|
|
330
347
|
}
|
|
331
348
|
}
|
|
332
|
-
}.call(this)
|
|
349
|
+
}.call(this);
|
|
333
350
|
}
|
|
334
351
|
/**
|
|
335
352
|
* Stream only reasoning deltas as they arrive.
|
|
336
353
|
* This filters the full event stream to only yield reasoning content.
|
|
337
354
|
*/
|
|
338
355
|
getReasoningStream() {
|
|
339
|
-
return
|
|
356
|
+
return async function* () {
|
|
340
357
|
await this.initStream();
|
|
341
358
|
if (!this.reusableStream) {
|
|
342
|
-
throw new Error(
|
|
359
|
+
throw new Error('Stream not initialized');
|
|
343
360
|
}
|
|
344
361
|
yield* extractReasoningDeltas(this.reusableStream);
|
|
345
|
-
}.call(this)
|
|
362
|
+
}.call(this);
|
|
346
363
|
}
|
|
347
364
|
/**
|
|
348
365
|
* Stream tool call argument deltas and preliminary results.
|
|
@@ -351,14 +368,17 @@ export class ResponseWrapper {
|
|
|
351
368
|
* - Preliminary results as { type: "preliminary_result", toolCallId, result }
|
|
352
369
|
*/
|
|
353
370
|
getToolStream() {
|
|
354
|
-
return
|
|
371
|
+
return async function* () {
|
|
355
372
|
await this.initStream();
|
|
356
373
|
if (!this.reusableStream) {
|
|
357
|
-
throw new Error(
|
|
374
|
+
throw new Error('Stream not initialized');
|
|
358
375
|
}
|
|
359
376
|
// Yield tool deltas as structured events
|
|
360
377
|
for await (const delta of extractToolDeltas(this.reusableStream)) {
|
|
361
|
-
yield {
|
|
378
|
+
yield {
|
|
379
|
+
type: 'delta',
|
|
380
|
+
content: delta,
|
|
381
|
+
};
|
|
362
382
|
}
|
|
363
383
|
// After stream completes, check if tools were executed and emit preliminary results
|
|
364
384
|
await this.executeToolsIfNeeded();
|
|
@@ -366,13 +386,13 @@ export class ResponseWrapper {
|
|
|
366
386
|
for (const [toolCallId, results] of this.preliminaryResults) {
|
|
367
387
|
for (const result of results) {
|
|
368
388
|
yield {
|
|
369
|
-
type:
|
|
389
|
+
type: 'preliminary_result',
|
|
370
390
|
toolCallId,
|
|
371
391
|
result,
|
|
372
392
|
};
|
|
373
393
|
}
|
|
374
394
|
}
|
|
375
|
-
}.call(this)
|
|
395
|
+
}.call(this);
|
|
376
396
|
}
|
|
377
397
|
/**
|
|
378
398
|
* Stream events in chat format (compatibility layer).
|
|
@@ -385,28 +405,29 @@ export class ResponseWrapper {
|
|
|
385
405
|
* this may not be a perfect mapping.
|
|
386
406
|
*/
|
|
387
407
|
getFullChatStream() {
|
|
388
|
-
return
|
|
408
|
+
return async function* () {
|
|
389
409
|
await this.initStream();
|
|
390
410
|
if (!this.reusableStream) {
|
|
391
|
-
throw new Error(
|
|
411
|
+
throw new Error('Stream not initialized');
|
|
392
412
|
}
|
|
393
413
|
const consumer = this.reusableStream.createConsumer();
|
|
394
414
|
for await (const event of consumer) {
|
|
395
|
-
if (!(
|
|
415
|
+
if (!('type' in event)) {
|
|
396
416
|
continue;
|
|
417
|
+
}
|
|
397
418
|
// Transform responses events to chat-like format
|
|
398
419
|
// This is a simplified transformation - you may need to adjust based on your needs
|
|
399
|
-
if (event.type ===
|
|
420
|
+
if (event.type === 'response.output_text.delta') {
|
|
400
421
|
const deltaEvent = event;
|
|
401
422
|
yield {
|
|
402
|
-
type:
|
|
423
|
+
type: 'content.delta',
|
|
403
424
|
delta: deltaEvent.delta,
|
|
404
425
|
};
|
|
405
426
|
}
|
|
406
|
-
else if (event.type ===
|
|
427
|
+
else if (event.type === 'response.completed') {
|
|
407
428
|
const completedEvent = event;
|
|
408
429
|
yield {
|
|
409
|
-
type:
|
|
430
|
+
type: 'message.complete',
|
|
410
431
|
response: completedEvent.response,
|
|
411
432
|
};
|
|
412
433
|
}
|
|
@@ -424,13 +445,13 @@ export class ResponseWrapper {
|
|
|
424
445
|
for (const [toolCallId, results] of this.preliminaryResults) {
|
|
425
446
|
for (const result of results) {
|
|
426
447
|
yield {
|
|
427
|
-
type:
|
|
448
|
+
type: 'tool.preliminary_result',
|
|
428
449
|
toolCallId,
|
|
429
450
|
result,
|
|
430
451
|
};
|
|
431
452
|
}
|
|
432
453
|
}
|
|
433
|
-
}.call(this)
|
|
454
|
+
}.call(this);
|
|
434
455
|
}
|
|
435
456
|
/**
|
|
436
457
|
* Get all tool calls from the completed response (before auto-execution).
|
|
@@ -441,7 +462,7 @@ export class ResponseWrapper {
|
|
|
441
462
|
async getToolCalls() {
|
|
442
463
|
await this.initStream();
|
|
443
464
|
if (!this.reusableStream) {
|
|
444
|
-
throw new Error(
|
|
465
|
+
throw new Error('Stream not initialized');
|
|
445
466
|
}
|
|
446
467
|
const completedResponse = await consumeStreamForCompletion(this.reusableStream);
|
|
447
468
|
return extractToolCallsFromResponse(completedResponse);
|
|
@@ -451,13 +472,13 @@ export class ResponseWrapper {
|
|
|
451
472
|
* Each iteration yields a complete tool call with parsed arguments.
|
|
452
473
|
*/
|
|
453
474
|
getToolCallsStream() {
|
|
454
|
-
return
|
|
475
|
+
return async function* () {
|
|
455
476
|
await this.initStream();
|
|
456
477
|
if (!this.reusableStream) {
|
|
457
|
-
throw new Error(
|
|
478
|
+
throw new Error('Stream not initialized');
|
|
458
479
|
}
|
|
459
480
|
yield* buildToolCallStream(this.reusableStream);
|
|
460
|
-
}.call(this)
|
|
481
|
+
}.call(this);
|
|
461
482
|
}
|
|
462
483
|
/**
|
|
463
484
|
* Cancel the underlying stream and all consumers
|
|
@@ -41,22 +41,34 @@ export class ReusableReadableStream {
|
|
|
41
41
|
async next() {
|
|
42
42
|
const consumer = self.consumers.get(consumerId);
|
|
43
43
|
if (!consumer) {
|
|
44
|
-
return {
|
|
44
|
+
return {
|
|
45
|
+
done: true,
|
|
46
|
+
value: undefined,
|
|
47
|
+
};
|
|
45
48
|
}
|
|
46
49
|
if (consumer.cancelled) {
|
|
47
|
-
return {
|
|
50
|
+
return {
|
|
51
|
+
done: true,
|
|
52
|
+
value: undefined,
|
|
53
|
+
};
|
|
48
54
|
}
|
|
49
55
|
// If we have buffered data at this position, return it
|
|
50
56
|
if (consumer.position < self.buffer.length) {
|
|
51
57
|
const value = self.buffer[consumer.position];
|
|
52
58
|
consumer.position++;
|
|
53
59
|
// Note: We don't clean up buffer to allow sequential/reusable access
|
|
54
|
-
return {
|
|
60
|
+
return {
|
|
61
|
+
done: false,
|
|
62
|
+
value,
|
|
63
|
+
};
|
|
55
64
|
}
|
|
56
65
|
// If source is complete and we've read everything, we're done
|
|
57
66
|
if (self.sourceComplete) {
|
|
58
67
|
self.consumers.delete(consumerId);
|
|
59
|
-
return {
|
|
68
|
+
return {
|
|
69
|
+
done: true,
|
|
70
|
+
value: undefined,
|
|
71
|
+
};
|
|
60
72
|
}
|
|
61
73
|
// If source had an error, propagate it
|
|
62
74
|
if (self.sourceError) {
|
|
@@ -66,7 +78,10 @@ export class ReusableReadableStream {
|
|
|
66
78
|
// Wait for more data - but check conditions after setting up the promise
|
|
67
79
|
// to avoid race condition where source completes between check and wait
|
|
68
80
|
const waitPromise = new Promise((resolve, reject) => {
|
|
69
|
-
consumer.waitingPromise = {
|
|
81
|
+
consumer.waitingPromise = {
|
|
82
|
+
resolve,
|
|
83
|
+
reject,
|
|
84
|
+
};
|
|
70
85
|
});
|
|
71
86
|
// Double-check conditions after setting up promise to handle race
|
|
72
87
|
if (self.sourceComplete || self.sourceError || consumer.position < self.buffer.length) {
|
|
@@ -86,7 +101,10 @@ export class ReusableReadableStream {
|
|
|
86
101
|
consumer.cancelled = true;
|
|
87
102
|
self.consumers.delete(consumerId);
|
|
88
103
|
}
|
|
89
|
-
return {
|
|
104
|
+
return {
|
|
105
|
+
done: true,
|
|
106
|
+
value: undefined,
|
|
107
|
+
};
|
|
90
108
|
},
|
|
91
109
|
async throw(e) {
|
|
92
110
|
const consumer = self.consumers.get(consumerId);
|
|
@@ -105,8 +123,9 @@ export class ReusableReadableStream {
|
|
|
105
123
|
* Start pumping data from the source stream into the buffer
|
|
106
124
|
*/
|
|
107
125
|
startPump() {
|
|
108
|
-
if (this.pumpStarted)
|
|
126
|
+
if (this.pumpStarted) {
|
|
109
127
|
return;
|
|
128
|
+
}
|
|
110
129
|
this.pumpStarted = true;
|
|
111
130
|
this.sourceReader = this.sourceStream.getReader();
|
|
112
131
|
void (async () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as models from
|
|
2
|
-
import { ReusableReadableStream } from
|
|
3
|
-
import { ParsedToolCall } from
|
|
1
|
+
import type * as models from '../models/index.js';
|
|
2
|
+
import type { ReusableReadableStream } from './reusable-stream.js';
|
|
3
|
+
import type { ParsedToolCall } from './tool-types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Extract text deltas from responses stream events
|
|
6
6
|
*/
|