@openrouter/sdk 0.3.15 → 0.4.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.
- package/esm/funcs/modelsListForUser.d.ts +5 -2
- package/esm/funcs/modelsListForUser.js +6 -3
- package/esm/index.d.ts +3 -2
- package/esm/index.js +1 -1
- package/esm/lib/config.d.ts +2 -2
- package/esm/lib/config.js +2 -2
- package/esm/lib/model-result.d.ts +25 -3
- package/esm/lib/model-result.js +93 -21
- package/esm/lib/stream-transformers.d.ts +12 -0
- package/esm/lib/stream-transformers.js +206 -0
- package/esm/lib/tool-executor.js +37 -13
- package/esm/lib/tool-types.d.ts +28 -2
- package/esm/lib/tool-types.js +6 -0
- package/esm/models/chatgenerationparams.d.ts +22 -22
- package/esm/models/chatgenerationparams.js +24 -21
- package/esm/models/index.d.ts +0 -5
- package/esm/models/index.js +0 -5
- package/esm/models/outputmodality.d.ts +1 -0
- package/esm/models/outputmodality.js +1 -0
- package/esm/models/publicendpoint.d.ts +8 -0
- package/esm/models/publicendpoint.js +4 -0
- package/esm/models/publicpricing.d.ts +4 -0
- package/esm/models/publicpricing.js +2 -0
- package/esm/sdk/models.d.ts +4 -1
- package/esm/sdk/models.js +4 -1
- package/esm/sdk/sdk.d.ts +0 -3
- package/esm/sdk/sdk.js +0 -4
- package/jsr.json +1 -1
- package/package.json +12 -12
- package/esm/funcs/completionsGenerate.d.ts +0 -18
- package/esm/funcs/completionsGenerate.js +0 -83
- package/esm/models/completionchoice.d.ts +0 -25
- package/esm/models/completionchoice.js +0 -34
- package/esm/models/completioncreateparams.d.ts +0 -120
- package/esm/models/completioncreateparams.js +0 -118
- package/esm/models/completionlogprobs.d.ts +0 -15
- package/esm/models/completionlogprobs.js +0 -24
- package/esm/models/completionresponse.d.ts +0 -19
- package/esm/models/completionresponse.js +0 -28
- package/esm/models/completionusage.d.ts +0 -12
- package/esm/models/completionusage.js +0 -23
- package/esm/sdk/completions.d.ts +0 -12
- package/esm/sdk/completions.js +0 -19
|
@@ -10,7 +10,10 @@ import * as operations from "../models/operations/index.js";
|
|
|
10
10
|
import { APIPromise } from "../types/async.js";
|
|
11
11
|
import { Result } from "../types/fp.js";
|
|
12
12
|
/**
|
|
13
|
-
* List models filtered by user provider preferences
|
|
13
|
+
* List models filtered by user provider preferences, privacy settings, and guardrails
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* List models filtered by user provider preferences, [privacy settings](https://openrouter.ai/docs/guides/privacy/logging), and [guardrails](https://openrouter.ai/docs/guides/features/guardrails). If requesting through `eu.openrouter.ai/api/v1/...` the results will be filtered to models that satisfy [EU in-region routing](https://openrouter.ai/docs/guides/privacy/logging#enterprise-eu-in-region-routing).
|
|
14
17
|
*/
|
|
15
|
-
export declare function modelsListForUser(client: OpenRouterCore, security: operations.ListModelsUserSecurity, options?: RequestOptions): APIPromise<Result<models.ModelsListResponse, errors.UnauthorizedResponseError | errors.InternalServerResponseError | OpenRouterError | ResponseValidationError | ConnectionError | RequestAbortedError | RequestTimeoutError | InvalidRequestError | UnexpectedClientError | SDKValidationError>>;
|
|
18
|
+
export declare function modelsListForUser(client: OpenRouterCore, security: operations.ListModelsUserSecurity, options?: RequestOptions): APIPromise<Result<models.ModelsListResponse, errors.UnauthorizedResponseError | errors.NotFoundResponseError | errors.InternalServerResponseError | OpenRouterError | ResponseValidationError | ConnectionError | RequestAbortedError | RequestTimeoutError | InvalidRequestError | UnexpectedClientError | SDKValidationError>>;
|
|
16
19
|
//# sourceMappingURL=modelsListForUser.d.ts.map
|
|
@@ -10,7 +10,10 @@ import * as errors from "../models/errors/index.js";
|
|
|
10
10
|
import * as models from "../models/index.js";
|
|
11
11
|
import { APIPromise } from "../types/async.js";
|
|
12
12
|
/**
|
|
13
|
-
* List models filtered by user provider preferences
|
|
13
|
+
* List models filtered by user provider preferences, privacy settings, and guardrails
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* List models filtered by user provider preferences, [privacy settings](https://openrouter.ai/docs/guides/privacy/logging), and [guardrails](https://openrouter.ai/docs/guides/features/guardrails). If requesting through `eu.openrouter.ai/api/v1/...` the results will be filtered to models that satisfy [EU in-region routing](https://openrouter.ai/docs/guides/privacy/logging#enterprise-eu-in-region-routing).
|
|
14
17
|
*/
|
|
15
18
|
export function modelsListForUser(client, security, options) {
|
|
16
19
|
return new APIPromise($do(client, security, options));
|
|
@@ -54,7 +57,7 @@ async function $do(client, security, options) {
|
|
|
54
57
|
const req = requestRes.value;
|
|
55
58
|
const doResult = await client._do(req, {
|
|
56
59
|
context,
|
|
57
|
-
errorCodes: ["401", "4XX", "500", "5XX"],
|
|
60
|
+
errorCodes: ["401", "404", "4XX", "500", "5XX"],
|
|
58
61
|
retryConfig: context.retryConfig,
|
|
59
62
|
retryCodes: context.retryCodes,
|
|
60
63
|
});
|
|
@@ -65,7 +68,7 @@ async function $do(client, security, options) {
|
|
|
65
68
|
const responseFields = {
|
|
66
69
|
HttpMeta: { Response: response, Request: req },
|
|
67
70
|
};
|
|
68
|
-
const [result] = await M.match(M.json(200, models.ModelsListResponse$inboundSchema), M.jsonErr(401, errors.UnauthorizedResponseError$inboundSchema), M.jsonErr(500, errors.InternalServerResponseError$inboundSchema), M.fail("4XX"), M.fail("5XX"))(response, req, { extraFields: responseFields });
|
|
71
|
+
const [result] = await M.match(M.json(200, models.ModelsListResponse$inboundSchema), M.jsonErr(401, errors.UnauthorizedResponseError$inboundSchema), M.jsonErr(404, errors.NotFoundResponseError$inboundSchema), M.jsonErr(500, errors.InternalServerResponseError$inboundSchema), M.fail("4XX"), M.fail("5XX"))(response, req, { extraFields: responseFields });
|
|
69
72
|
if (!result.ok) {
|
|
70
73
|
return [result, { status: "complete", request: req, response }];
|
|
71
74
|
}
|
package/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { CallModelInput, CallModelInputWithState, FieldOrAsyncFunction, ResolvedCallModelInput, } from './lib/async-params.js';
|
|
2
2
|
export type { Fetcher, HTTPClientOptions } from './lib/http.js';
|
|
3
|
-
export type { ChatStreamEvent, ConversationState, ConversationStatus, ResponseStreamEvent as EnhancedResponseStreamEvent, HasApprovalTools, InferToolEvent, InferToolEventsUnion, InferToolInput, InferToolOutput, ManualTool, NextTurnParamsContext, NextTurnParamsFunctions, ParsedToolCall, PartialResponse, StateAccessor, StepResult, StopCondition, StopWhen, Tool, ToolApprovalCheck, ToolExecutionResult, ToolExecutionResultUnion, ToolHasApproval, ToolPreliminaryResultEvent, ToolStreamEvent, ToolWithExecute, ToolWithGenerator, TurnContext, TypedToolCall, TypedToolCallUnion, UnsentToolResult, Warning, } from './lib/tool-types.js';
|
|
3
|
+
export type { ChatStreamEvent, ConversationState, ConversationStatus, ResponseStreamEvent as EnhancedResponseStreamEvent, HasApprovalTools, InferToolEvent, InferToolEventsUnion, InferToolInput, InferToolOutput, InferToolOutputsUnion, ManualTool, NextTurnParamsContext, NextTurnParamsFunctions, ParsedToolCall, PartialResponse, StateAccessor, StepResult, StopCondition, StopWhen, Tool, ToolApprovalCheck, ToolExecutionResult, ToolExecutionResultUnion, ToolHasApproval, ToolPreliminaryResultEvent, ToolResultEvent, ToolStreamEvent, ToolWithExecute, ToolWithGenerator, TurnContext, TypedToolCall, TypedToolCallUnion, UnsentToolResult, Warning, } from './lib/tool-types.js';
|
|
4
4
|
export type { BuildTurnContextOptions } from './lib/turn-context.js';
|
|
5
5
|
export type { ClaudeBase64ImageSource, ClaudeCacheControl, ClaudeCitationCharLocation, ClaudeCitationContentBlockLocation, ClaudeCitationPageLocation, ClaudeCitationSearchResultLocation, ClaudeCitationWebSearchResultLocation, ClaudeContentBlock, ClaudeContentBlockParam, ClaudeImageBlockParam, ClaudeMessage, ClaudeMessageParam, ClaudeRedactedThinkingBlock, ClaudeServerToolUseBlock, ClaudeStopReason, ClaudeTextBlock, ClaudeTextBlockParam, ClaudeTextCitation, ClaudeThinkingBlock, ClaudeToolResultBlockParam, ClaudeToolUseBlock, ClaudeToolUseBlockParam, ClaudeURLImageSource, ClaudeUsage, } from './models/claude-message.js';
|
|
6
6
|
export { fromClaudeMessages, toClaudeMessage } from './lib/anthropic-compat.js';
|
|
@@ -14,8 +14,9 @@ export { HTTPClient } from './lib/http.js';
|
|
|
14
14
|
export { applyNextTurnParamsToRequest, buildNextTurnParamsContext, executeNextTurnParamsFunctions, } from './lib/next-turn-params.js';
|
|
15
15
|
export { finishReasonIs, hasToolCall, isStopConditionMet, maxCost, maxTokensUsed, stepCountIs, } from './lib/stop-conditions.js';
|
|
16
16
|
export { extractUnsupportedContent, getUnsupportedContentSummary, hasUnsupportedContent, } from './lib/stream-transformers.js';
|
|
17
|
+
export type { StreamableOutputItem } from './lib/stream-transformers.js';
|
|
17
18
|
export { tool } from './lib/tool.js';
|
|
18
|
-
export { hasApprovalRequiredTools, hasExecuteFunction, isGeneratorTool, isRegularExecuteTool, isToolPreliminaryResultEvent, toolHasApprovalConfigured, ToolType, } from './lib/tool-types.js';
|
|
19
|
+
export { hasApprovalRequiredTools, hasExecuteFunction, isGeneratorTool, isRegularExecuteTool, isToolPreliminaryResultEvent, isToolResultEvent, toolHasApprovalConfigured, ToolType, } from './lib/tool-types.js';
|
|
19
20
|
export { buildTurnContext, normalizeInputToArray } from './lib/turn-context.js';
|
|
20
21
|
export { appendToMessages, createInitialState, createRejectedResult, createUnsentResult, generateConversationId, partitionToolCalls, toolRequiresApproval, updateState, } from './lib/conversation-state.js';
|
|
21
22
|
export { ToolEventBroadcaster } from './lib/tool-event-broadcaster.js';
|
package/esm/index.js
CHANGED
|
@@ -18,7 +18,7 @@ export { finishReasonIs, hasToolCall, isStopConditionMet, maxCost, maxTokensUsed
|
|
|
18
18
|
export { extractUnsupportedContent, getUnsupportedContentSummary, hasUnsupportedContent, } from './lib/stream-transformers.js';
|
|
19
19
|
// Tool creation helpers
|
|
20
20
|
export { tool } from './lib/tool.js';
|
|
21
|
-
export { hasApprovalRequiredTools, hasExecuteFunction, isGeneratorTool, isRegularExecuteTool, isToolPreliminaryResultEvent, toolHasApprovalConfigured, ToolType, } from './lib/tool-types.js';
|
|
21
|
+
export { hasApprovalRequiredTools, hasExecuteFunction, isGeneratorTool, isRegularExecuteTool, isToolPreliminaryResultEvent, isToolResultEvent, toolHasApprovalConfigured, ToolType, } from './lib/tool-types.js';
|
|
22
22
|
// Turn context helpers
|
|
23
23
|
export { buildTurnContext, normalizeInputToArray } from './lib/turn-context.js';
|
|
24
24
|
// Conversation state helpers
|
package/esm/lib/config.d.ts
CHANGED
|
@@ -45,8 +45,8 @@ export declare function serverURLFromOptions(options: SDKOptions): URL | null;
|
|
|
45
45
|
export declare const SDK_METADATA: {
|
|
46
46
|
readonly language: "typescript";
|
|
47
47
|
readonly openapiDocVersion: "1.0.0";
|
|
48
|
-
readonly sdkVersion: "0.
|
|
48
|
+
readonly sdkVersion: "0.4.0";
|
|
49
49
|
readonly genVersion: "2.788.4";
|
|
50
|
-
readonly userAgent: "speakeasy-sdk/typescript 0.
|
|
50
|
+
readonly userAgent: "speakeasy-sdk/typescript 0.4.0 2.788.4 1.0.0 @openrouter/sdk";
|
|
51
51
|
};
|
|
52
52
|
//# sourceMappingURL=config.d.ts.map
|
package/esm/lib/config.js
CHANGED
|
@@ -26,8 +26,8 @@ export function serverURLFromOptions(options) {
|
|
|
26
26
|
export const SDK_METADATA = {
|
|
27
27
|
language: "typescript",
|
|
28
28
|
openapiDocVersion: "1.0.0",
|
|
29
|
-
sdkVersion: "0.
|
|
29
|
+
sdkVersion: "0.4.0",
|
|
30
30
|
genVersion: "2.788.4",
|
|
31
|
-
userAgent: "speakeasy-sdk/typescript 0.
|
|
31
|
+
userAgent: "speakeasy-sdk/typescript 0.4.0 2.788.4 1.0.0 @openrouter/sdk",
|
|
32
32
|
};
|
|
33
33
|
//# sourceMappingURL=config.js.map
|
|
@@ -2,7 +2,8 @@ import type { OpenRouterCore } from '../core.js';
|
|
|
2
2
|
import type * as models from '../models/index.js';
|
|
3
3
|
import type { CallModelInput } from './async-params.js';
|
|
4
4
|
import type { RequestOptions } from './sdks.js';
|
|
5
|
-
import type { ConversationState, ResponseStreamEvent, InferToolEventsUnion, ParsedToolCall, StateAccessor, StopWhen, Tool, ToolStreamEvent, TurnContext } from './tool-types.js';
|
|
5
|
+
import type { ConversationState, ResponseStreamEvent, InferToolEventsUnion, InferToolOutputsUnion, ParsedToolCall, StateAccessor, StopWhen, Tool, ToolStreamEvent, TurnContext } from './tool-types.js';
|
|
6
|
+
import { type StreamableOutputItem } from './stream-transformers.js';
|
|
6
7
|
export interface GetResponseOptions<TTools extends readonly Tool[]> {
|
|
7
8
|
request: CallModelInput<TTools>;
|
|
8
9
|
client: OpenRouterCore;
|
|
@@ -57,6 +58,7 @@ export declare class ModelResult<TTools extends readonly Tool[]> {
|
|
|
57
58
|
/**
|
|
58
59
|
* Get or create the tool event broadcaster (lazy initialization).
|
|
59
60
|
* Ensures only one broadcaster exists for the lifetime of this ModelResult.
|
|
61
|
+
* Broadcasts both preliminary results and final tool results.
|
|
60
62
|
*/
|
|
61
63
|
private ensureBroadcaster;
|
|
62
64
|
/**
|
|
@@ -139,6 +141,7 @@ export declare class ModelResult<TTools extends readonly Tool[]> {
|
|
|
139
141
|
/**
|
|
140
142
|
* Execute all tools in a single round.
|
|
141
143
|
* Runs each tool call sequentially and collects results for API submission.
|
|
144
|
+
* Emits tool.result events after each tool execution completes.
|
|
142
145
|
*
|
|
143
146
|
* @param toolCalls - The tool calls to execute
|
|
144
147
|
* @param turnContext - The current turn context
|
|
@@ -234,15 +237,34 @@ export declare class ModelResult<TTools extends readonly Tool[]> {
|
|
|
234
237
|
/**
|
|
235
238
|
* Stream all response events as they arrive.
|
|
236
239
|
* Multiple consumers can iterate over this stream concurrently.
|
|
237
|
-
* Preliminary tool results are streamed in REAL-TIME as generator tools yield.
|
|
240
|
+
* Preliminary tool results and tool results are streamed in REAL-TIME as generator tools yield.
|
|
238
241
|
*/
|
|
239
|
-
getFullResponsesStream(): AsyncIterableIterator<ResponseStreamEvent<InferToolEventsUnion<TTools>>>;
|
|
242
|
+
getFullResponsesStream(): AsyncIterableIterator<ResponseStreamEvent<InferToolEventsUnion<TTools>, InferToolOutputsUnion<TTools>>>;
|
|
240
243
|
/**
|
|
241
244
|
* Stream only text deltas as they arrive.
|
|
242
245
|
* This filters the full event stream to only yield text content.
|
|
243
246
|
*/
|
|
244
247
|
getTextStream(): AsyncIterableIterator<string>;
|
|
245
248
|
/**
|
|
249
|
+
* Stream all output items cumulatively as they arrive.
|
|
250
|
+
* Items are emitted with the same ID but progressively updated content as streaming progresses.
|
|
251
|
+
* Also yields tool results (function_call_output) after tool execution completes.
|
|
252
|
+
*
|
|
253
|
+
* Item types include:
|
|
254
|
+
* - message: Assistant text responses (emitted cumulatively as text streams)
|
|
255
|
+
* - function_call: Tool calls (emitted cumulatively as arguments stream)
|
|
256
|
+
* - reasoning: Model reasoning (emitted cumulatively as thinking streams)
|
|
257
|
+
* - web_search_call: Web search operations
|
|
258
|
+
* - file_search_call: File search operations
|
|
259
|
+
* - image_generation_call: Image generation operations
|
|
260
|
+
* - function_call_output: Results from executed tools
|
|
261
|
+
*/
|
|
262
|
+
getItemsStream(): AsyncIterableIterator<StreamableOutputItem>;
|
|
263
|
+
/**
|
|
264
|
+
* @deprecated Use `getItemsStream()` instead. This method only streams messages,
|
|
265
|
+
* while `getItemsStream()` streams all output item types (messages, function_calls,
|
|
266
|
+
* reasoning, etc.) with cumulative updates.
|
|
267
|
+
*
|
|
246
268
|
* Stream incremental message updates as content is added in responses format.
|
|
247
269
|
* Each iteration yields an updated version of the message with new content.
|
|
248
270
|
* Also yields OpenResponsesFunctionCallOutput after tool execution completes.
|
package/esm/lib/model-result.js
CHANGED
|
@@ -3,11 +3,12 @@ import { betaResponsesSend } from '../funcs/betaResponsesSend.js';
|
|
|
3
3
|
import { hasAsyncFunctions, resolveAsyncFunctions, } from './async-params.js';
|
|
4
4
|
import { appendToMessages, createInitialState, createRejectedResult, createUnsentResult, extractTextFromResponse as extractTextFromResponseState, partitionToolCalls, unsentResultsToAPIFormat, updateState, } from './conversation-state.js';
|
|
5
5
|
import { ReusableReadableStream } from './reusable-stream.js';
|
|
6
|
-
import { buildResponsesMessageStream, buildToolCallStream, consumeStreamForCompletion, extractReasoningDeltas, extractResponsesMessageFromResponse, extractTextDeltas, extractTextFromResponse, extractToolCallsFromResponse, extractToolDeltas, } from './stream-transformers.js';
|
|
6
|
+
import { buildItemsStream, buildResponsesMessageStream, buildToolCallStream, consumeStreamForCompletion, extractReasoningDeltas, extractResponsesMessageFromResponse, extractTextDeltas, extractTextFromResponse, extractToolCallsFromResponse, extractToolDeltas, } from './stream-transformers.js';
|
|
7
7
|
import { executeTool } from './tool-executor.js';
|
|
8
8
|
import { executeNextTurnParamsFunctions, applyNextTurnParamsToRequest } from './next-turn-params.js';
|
|
9
9
|
import { hasExecuteFunction } from './tool-types.js';
|
|
10
10
|
import { isStopConditionMet, stepCountIs } from './stop-conditions.js';
|
|
11
|
+
import { isOutputMessage, isFunctionCallOutputItem, isReasoningOutputItem, isWebSearchCallOutputItem, isFileSearchCallOutputItem, isImageGenerationCallOutputItem, hasTypeProperty, } from './stream-type-guards.js';
|
|
11
12
|
/**
|
|
12
13
|
* Default maximum number of tool execution steps if no stopWhen is specified.
|
|
13
14
|
* This prevents infinite loops in tool execution.
|
|
@@ -30,15 +31,6 @@ function isEventStream(value) {
|
|
|
30
31
|
const maybeStream = value;
|
|
31
32
|
return typeof maybeStream.toReadableStream === 'function';
|
|
32
33
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Type guard for output items with a type property
|
|
35
|
-
*/
|
|
36
|
-
function hasTypeProperty(item) {
|
|
37
|
-
return (typeof item === 'object' &&
|
|
38
|
-
item !== null &&
|
|
39
|
-
'type' in item &&
|
|
40
|
-
typeof item.type === 'string');
|
|
41
|
-
}
|
|
42
34
|
/**
|
|
43
35
|
* A wrapper around a streaming response that provides multiple consumption patterns.
|
|
44
36
|
*
|
|
@@ -93,6 +85,7 @@ export class ModelResult {
|
|
|
93
85
|
/**
|
|
94
86
|
* Get or create the tool event broadcaster (lazy initialization).
|
|
95
87
|
* Ensures only one broadcaster exists for the lifetime of this ModelResult.
|
|
88
|
+
* Broadcasts both preliminary results and final tool results.
|
|
96
89
|
*/
|
|
97
90
|
ensureBroadcaster() {
|
|
98
91
|
if (!this.toolEventBroadcaster) {
|
|
@@ -300,6 +293,7 @@ export class ModelResult {
|
|
|
300
293
|
/**
|
|
301
294
|
* Execute all tools in a single round.
|
|
302
295
|
* Runs each tool call sequentially and collects results for API submission.
|
|
296
|
+
* Emits tool.result events after each tool execution completes.
|
|
303
297
|
*
|
|
304
298
|
* @param toolCalls - The tool calls to execute
|
|
305
299
|
* @param turnContext - The current turn context
|
|
@@ -311,17 +305,33 @@ export class ModelResult {
|
|
|
311
305
|
const tool = this.options.tools?.find((t) => t.function.name === toolCall.name);
|
|
312
306
|
if (!tool || !hasExecuteFunction(tool))
|
|
313
307
|
continue;
|
|
308
|
+
// Track preliminary results for this specific tool call
|
|
309
|
+
const preliminaryResultsForCall = [];
|
|
314
310
|
// Create callback for real-time preliminary results
|
|
315
311
|
const onPreliminaryResult = this.toolEventBroadcaster
|
|
316
312
|
? (callId, resultValue) => {
|
|
313
|
+
// Track preliminary results for the tool.result event
|
|
314
|
+
const typedResult = resultValue;
|
|
315
|
+
preliminaryResultsForCall.push(typedResult);
|
|
316
|
+
// Emit preliminary result event
|
|
317
317
|
this.toolEventBroadcaster?.push({
|
|
318
318
|
type: 'preliminary_result',
|
|
319
319
|
toolCallId: callId,
|
|
320
|
-
result:
|
|
320
|
+
result: typedResult,
|
|
321
321
|
});
|
|
322
322
|
}
|
|
323
323
|
: undefined;
|
|
324
324
|
const result = await executeTool(tool, toolCall, turnContext, onPreliminaryResult);
|
|
325
|
+
// Emit tool.result event with final result and any preliminary results
|
|
326
|
+
if (this.toolEventBroadcaster) {
|
|
327
|
+
const toolResultEvent = {
|
|
328
|
+
type: 'tool_result',
|
|
329
|
+
toolCallId: toolCall.id,
|
|
330
|
+
result: (result.error ? { error: result.error.message } : result.result),
|
|
331
|
+
...(preliminaryResultsForCall.length > 0 && { preliminaryResults: preliminaryResultsForCall }),
|
|
332
|
+
};
|
|
333
|
+
this.toolEventBroadcaster.push(toolResultEvent);
|
|
334
|
+
}
|
|
325
335
|
toolResults.push({
|
|
326
336
|
type: 'function_call_output',
|
|
327
337
|
id: `output_${toolCall.id}`,
|
|
@@ -799,7 +809,7 @@ export class ModelResult {
|
|
|
799
809
|
/**
|
|
800
810
|
* Stream all response events as they arrive.
|
|
801
811
|
* Multiple consumers can iterate over this stream concurrently.
|
|
802
|
-
* Preliminary tool results are streamed in REAL-TIME as generator tools yield.
|
|
812
|
+
* Preliminary tool results and tool results are streamed in REAL-TIME as generator tools yield.
|
|
803
813
|
*/
|
|
804
814
|
getFullResponsesStream() {
|
|
805
815
|
return async function* () {
|
|
@@ -819,14 +829,25 @@ export class ModelResult {
|
|
|
819
829
|
for await (const event of consumer) {
|
|
820
830
|
yield event;
|
|
821
831
|
}
|
|
822
|
-
// Yield tool
|
|
832
|
+
// Yield tool events as they arrive (real-time!)
|
|
823
833
|
for await (const event of toolEventConsumer) {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
834
|
+
if (event.type === 'preliminary_result') {
|
|
835
|
+
yield {
|
|
836
|
+
type: 'tool.preliminary_result',
|
|
837
|
+
toolCallId: event.toolCallId,
|
|
838
|
+
result: event.result,
|
|
839
|
+
timestamp: Date.now(),
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
else if (event.type === 'tool_result') {
|
|
843
|
+
yield {
|
|
844
|
+
type: 'tool.result',
|
|
845
|
+
toolCallId: event.toolCallId,
|
|
846
|
+
result: event.result,
|
|
847
|
+
timestamp: Date.now(),
|
|
848
|
+
...(event.preliminaryResults && { preliminaryResults: event.preliminaryResults }),
|
|
849
|
+
};
|
|
850
|
+
}
|
|
830
851
|
}
|
|
831
852
|
// Ensure execution completed (handles errors)
|
|
832
853
|
await executionPromise;
|
|
@@ -846,6 +867,55 @@ export class ModelResult {
|
|
|
846
867
|
}.call(this);
|
|
847
868
|
}
|
|
848
869
|
/**
|
|
870
|
+
* Stream all output items cumulatively as they arrive.
|
|
871
|
+
* Items are emitted with the same ID but progressively updated content as streaming progresses.
|
|
872
|
+
* Also yields tool results (function_call_output) after tool execution completes.
|
|
873
|
+
*
|
|
874
|
+
* Item types include:
|
|
875
|
+
* - message: Assistant text responses (emitted cumulatively as text streams)
|
|
876
|
+
* - function_call: Tool calls (emitted cumulatively as arguments stream)
|
|
877
|
+
* - reasoning: Model reasoning (emitted cumulatively as thinking streams)
|
|
878
|
+
* - web_search_call: Web search operations
|
|
879
|
+
* - file_search_call: File search operations
|
|
880
|
+
* - image_generation_call: Image generation operations
|
|
881
|
+
* - function_call_output: Results from executed tools
|
|
882
|
+
*/
|
|
883
|
+
getItemsStream() {
|
|
884
|
+
return async function* () {
|
|
885
|
+
await this.initStream();
|
|
886
|
+
if (!this.reusableStream) {
|
|
887
|
+
throw new Error('Stream not initialized');
|
|
888
|
+
}
|
|
889
|
+
// Stream all items from the API response cumulatively
|
|
890
|
+
yield* buildItemsStream(this.reusableStream);
|
|
891
|
+
// Execute tools if needed
|
|
892
|
+
await this.executeToolsIfNeeded();
|
|
893
|
+
// Yield function call outputs for each executed tool
|
|
894
|
+
for (const round of this.allToolExecutionRounds) {
|
|
895
|
+
for (const toolResult of round.toolResults) {
|
|
896
|
+
yield toolResult;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
// If tools were executed, yield all items from the final response
|
|
900
|
+
if (this.finalResponse && this.allToolExecutionRounds.length > 0) {
|
|
901
|
+
for (const item of this.finalResponse.output) {
|
|
902
|
+
if (isOutputMessage(item) ||
|
|
903
|
+
isFunctionCallOutputItem(item) ||
|
|
904
|
+
isReasoningOutputItem(item) ||
|
|
905
|
+
isWebSearchCallOutputItem(item) ||
|
|
906
|
+
isFileSearchCallOutputItem(item) ||
|
|
907
|
+
isImageGenerationCallOutputItem(item)) {
|
|
908
|
+
yield item;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}.call(this);
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* @deprecated Use `getItemsStream()` instead. This method only streams messages,
|
|
916
|
+
* while `getItemsStream()` streams all output item types (messages, function_calls,
|
|
917
|
+
* reasoning, etc.) with cumulative updates.
|
|
918
|
+
*
|
|
849
919
|
* Stream incremental message updates as content is added in responses format.
|
|
850
920
|
* Each iteration yields an updated version of the message with new content.
|
|
851
921
|
* Also yields OpenResponsesFunctionCallOutput after tool execution completes.
|
|
@@ -916,9 +986,11 @@ export class ModelResult {
|
|
|
916
986
|
content: delta,
|
|
917
987
|
};
|
|
918
988
|
}
|
|
919
|
-
// Yield
|
|
989
|
+
// Yield only preliminary_result events (filter out tool_result events)
|
|
920
990
|
for await (const event of toolEventConsumer) {
|
|
921
|
-
|
|
991
|
+
if (event.type === 'preliminary_result') {
|
|
992
|
+
yield event;
|
|
993
|
+
}
|
|
922
994
|
}
|
|
923
995
|
// Ensure execution completed (handles errors)
|
|
924
996
|
await executionPromise;
|
|
@@ -18,6 +18,18 @@ export declare function extractToolDeltas(stream: ReusableReadableStream<models.
|
|
|
18
18
|
* Returns ResponsesOutputMessage (assistant/responses format)
|
|
19
19
|
*/
|
|
20
20
|
export declare function buildResponsesMessageStream(stream: ReusableReadableStream<models.OpenResponsesStreamEvent>): AsyncIterableIterator<models.ResponsesOutputMessage>;
|
|
21
|
+
/**
|
|
22
|
+
* Output item types that can be streamed from a response.
|
|
23
|
+
* This is the union of all item types that appear in response output,
|
|
24
|
+
* plus function_call_output for tool results.
|
|
25
|
+
*/
|
|
26
|
+
export type StreamableOutputItem = models.ResponsesOutputMessage | models.ResponsesOutputItemFunctionCall | models.ResponsesOutputItemReasoning | models.ResponsesWebSearchCallOutput | models.ResponsesOutputItemFileSearchCall | models.ResponsesImageGenerationCall | models.OpenResponsesFunctionCallOutput;
|
|
27
|
+
/**
|
|
28
|
+
* Build incremental output item updates from responses stream events.
|
|
29
|
+
* Yields all item types cumulatively - same item may be emitted multiple times
|
|
30
|
+
* with the same ID but progressively updated content as streaming progresses.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildItemsStream(stream: ReusableReadableStream<models.OpenResponsesStreamEvent>): AsyncIterableIterator<StreamableOutputItem>;
|
|
21
33
|
/**
|
|
22
34
|
* Build incremental message updates from responses stream events
|
|
23
35
|
* Returns AssistantMessage (chat format) instead of ResponsesOutputMessage
|
|
@@ -127,6 +127,212 @@ export async function* buildResponsesMessageStream(stream) {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Handle output_item.added event - Initialize tracking for new items
|
|
132
|
+
*/
|
|
133
|
+
function handleOutputItemAdded(event, itemsInProgress) {
|
|
134
|
+
if (!isOutputItemAddedEvent(event) || !event.item) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
const item = event.item;
|
|
138
|
+
if (isOutputMessage(item)) {
|
|
139
|
+
itemsInProgress.set(item.id, {
|
|
140
|
+
type: 'message',
|
|
141
|
+
id: item.id,
|
|
142
|
+
textContent: '',
|
|
143
|
+
});
|
|
144
|
+
return {
|
|
145
|
+
id: item.id,
|
|
146
|
+
type: 'message',
|
|
147
|
+
role: 'assistant',
|
|
148
|
+
status: 'in_progress',
|
|
149
|
+
content: [],
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (isFunctionCallOutputItem(item)) {
|
|
153
|
+
// Use item.id if available (matches itemId in delta events), fall back to callId
|
|
154
|
+
const itemKey = item.id ?? item.callId;
|
|
155
|
+
itemsInProgress.set(itemKey, {
|
|
156
|
+
type: 'function_call',
|
|
157
|
+
id: itemKey,
|
|
158
|
+
name: item.name,
|
|
159
|
+
callId: item.callId,
|
|
160
|
+
argumentsAccumulated: '',
|
|
161
|
+
});
|
|
162
|
+
return {
|
|
163
|
+
type: 'function_call',
|
|
164
|
+
id: item.id,
|
|
165
|
+
callId: item.callId,
|
|
166
|
+
name: item.name,
|
|
167
|
+
arguments: '',
|
|
168
|
+
status: 'in_progress',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (isReasoningOutputItem(item)) {
|
|
172
|
+
itemsInProgress.set(item.id, {
|
|
173
|
+
type: 'reasoning',
|
|
174
|
+
id: item.id,
|
|
175
|
+
reasoningContent: '',
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
type: 'reasoning',
|
|
179
|
+
id: item.id,
|
|
180
|
+
status: 'in_progress',
|
|
181
|
+
summary: [],
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (isWebSearchCallOutputItem(item)) {
|
|
185
|
+
return item;
|
|
186
|
+
}
|
|
187
|
+
if (isFileSearchCallOutputItem(item)) {
|
|
188
|
+
return item;
|
|
189
|
+
}
|
|
190
|
+
if (isImageGenerationCallOutputItem(item)) {
|
|
191
|
+
return item;
|
|
192
|
+
}
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Handle text delta event for messages
|
|
197
|
+
*/
|
|
198
|
+
function handleTextDelta(event, itemsInProgress) {
|
|
199
|
+
if (!isOutputTextDeltaEvent(event) || !event.delta) {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
const item = itemsInProgress.get(event.itemId);
|
|
203
|
+
if (item?.type === 'message') {
|
|
204
|
+
item.textContent += event.delta;
|
|
205
|
+
return {
|
|
206
|
+
id: item.id,
|
|
207
|
+
type: 'message',
|
|
208
|
+
role: 'assistant',
|
|
209
|
+
status: 'in_progress',
|
|
210
|
+
content: [
|
|
211
|
+
{
|
|
212
|
+
type: 'output_text',
|
|
213
|
+
text: item.textContent,
|
|
214
|
+
annotations: [],
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Handle function call argument delta event
|
|
223
|
+
*/
|
|
224
|
+
function handleFunctionCallDelta(event, itemsInProgress) {
|
|
225
|
+
if (!isFunctionCallArgumentsDeltaEvent(event) || !event.delta) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
const item = itemsInProgress.get(event.itemId);
|
|
229
|
+
if (item?.type === 'function_call') {
|
|
230
|
+
item.argumentsAccumulated += event.delta;
|
|
231
|
+
return {
|
|
232
|
+
type: 'function_call',
|
|
233
|
+
// Include id if it differs from callId (means API provided an id)
|
|
234
|
+
id: item.id !== item.callId ? item.id : undefined,
|
|
235
|
+
callId: item.callId,
|
|
236
|
+
name: item.name,
|
|
237
|
+
arguments: item.argumentsAccumulated,
|
|
238
|
+
status: 'in_progress',
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Handle reasoning text delta event
|
|
245
|
+
*/
|
|
246
|
+
function handleReasoningDelta(event, itemsInProgress) {
|
|
247
|
+
if (!isReasoningDeltaEvent(event) || !event.delta) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
const item = itemsInProgress.get(event.itemId);
|
|
251
|
+
if (item?.type === 'reasoning') {
|
|
252
|
+
item.reasoningContent += event.delta;
|
|
253
|
+
return {
|
|
254
|
+
type: 'reasoning',
|
|
255
|
+
id: item.id,
|
|
256
|
+
status: 'in_progress',
|
|
257
|
+
summary: [
|
|
258
|
+
{
|
|
259
|
+
type: 'summary_text',
|
|
260
|
+
text: item.reasoningContent,
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Handle output_item.done event - Yield final complete item
|
|
269
|
+
*/
|
|
270
|
+
function handleOutputItemDone(event, itemsInProgress) {
|
|
271
|
+
if (!isOutputItemDoneEvent(event) || !event.item) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
const item = event.item;
|
|
275
|
+
if (isOutputMessage(item)) {
|
|
276
|
+
itemsInProgress.delete(item.id);
|
|
277
|
+
return item;
|
|
278
|
+
}
|
|
279
|
+
if (isFunctionCallOutputItem(item)) {
|
|
280
|
+
// Use item.id if available (matches itemId in delta events), fall back to callId
|
|
281
|
+
itemsInProgress.delete(item.id ?? item.callId);
|
|
282
|
+
return item;
|
|
283
|
+
}
|
|
284
|
+
if (isReasoningOutputItem(item)) {
|
|
285
|
+
itemsInProgress.delete(item.id);
|
|
286
|
+
return item;
|
|
287
|
+
}
|
|
288
|
+
if (isWebSearchCallOutputItem(item)) {
|
|
289
|
+
return item;
|
|
290
|
+
}
|
|
291
|
+
if (isFileSearchCallOutputItem(item)) {
|
|
292
|
+
return item;
|
|
293
|
+
}
|
|
294
|
+
if (isImageGenerationCallOutputItem(item)) {
|
|
295
|
+
return item;
|
|
296
|
+
}
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
const itemsStreamHandlers = {
|
|
300
|
+
'response.output_item.added': handleOutputItemAdded,
|
|
301
|
+
'response.output_text.delta': handleTextDelta,
|
|
302
|
+
'response.function_call_arguments.delta': handleFunctionCallDelta,
|
|
303
|
+
'response.reasoning_text.delta': handleReasoningDelta,
|
|
304
|
+
'response.output_item.done': handleOutputItemDone,
|
|
305
|
+
};
|
|
306
|
+
const streamTerminationEvents = new Set([
|
|
307
|
+
'response.completed',
|
|
308
|
+
'response.failed',
|
|
309
|
+
'response.incomplete',
|
|
310
|
+
]);
|
|
311
|
+
//#endregion
|
|
312
|
+
/**
|
|
313
|
+
* Build incremental output item updates from responses stream events.
|
|
314
|
+
* Yields all item types cumulatively - same item may be emitted multiple times
|
|
315
|
+
* with the same ID but progressively updated content as streaming progresses.
|
|
316
|
+
*/
|
|
317
|
+
export async function* buildItemsStream(stream) {
|
|
318
|
+
const consumer = stream.createConsumer();
|
|
319
|
+
const itemsInProgress = new Map();
|
|
320
|
+
for await (const event of consumer) {
|
|
321
|
+
if (!('type' in event)) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
if (streamTerminationEvents.has(event.type)) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const handler = itemsStreamHandlers[event.type];
|
|
328
|
+
if (handler) {
|
|
329
|
+
const result = handler(event, itemsInProgress);
|
|
330
|
+
if (result) {
|
|
331
|
+
yield result;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
130
336
|
/**
|
|
131
337
|
* Build incremental message updates from responses stream events
|
|
132
338
|
* Returns AssistantMessage (chat format) instead of ResponsesOutputMessage
|