@openrouter/sdk 0.3.16 → 0.5.1

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 (40) hide show
  1. package/esm/funcs/modelsListForUser.d.ts +5 -2
  2. package/esm/funcs/modelsListForUser.js +6 -3
  3. package/esm/index.d.ts +1 -0
  4. package/esm/lib/config.d.ts +8 -2
  5. package/esm/lib/config.js +2 -2
  6. package/esm/lib/model-result.d.ts +24 -3
  7. package/esm/lib/model-result.js +116 -16
  8. package/esm/lib/sdks.d.ts +1 -1
  9. package/esm/lib/sdks.js +28 -8
  10. package/esm/lib/stream-transformers.d.ts +12 -0
  11. package/esm/lib/stream-transformers.js +211 -5
  12. package/esm/lib/stream-type-guards.d.ts +1 -1
  13. package/esm/lib/stream-type-guards.js +1 -1
  14. package/esm/lib/tool-executor.js +11 -14
  15. package/esm/lib/tool-orchestrator.js +2 -2
  16. package/esm/lib/tool-types.d.ts +2 -1
  17. package/esm/models/chatgenerationparams.d.ts +22 -22
  18. package/esm/models/chatgenerationparams.js +24 -21
  19. package/esm/models/index.d.ts +0 -5
  20. package/esm/models/index.js +0 -5
  21. package/esm/sdk/models.d.ts +4 -1
  22. package/esm/sdk/models.js +4 -1
  23. package/esm/sdk/sdk.d.ts +0 -3
  24. package/esm/sdk/sdk.js +0 -4
  25. package/jsr.json +1 -1
  26. package/package.json +11 -11
  27. package/esm/funcs/completionsGenerate.d.ts +0 -18
  28. package/esm/funcs/completionsGenerate.js +0 -83
  29. package/esm/models/completionchoice.d.ts +0 -25
  30. package/esm/models/completionchoice.js +0 -34
  31. package/esm/models/completioncreateparams.d.ts +0 -120
  32. package/esm/models/completioncreateparams.js +0 -118
  33. package/esm/models/completionlogprobs.d.ts +0 -15
  34. package/esm/models/completionlogprobs.js +0 -24
  35. package/esm/models/completionresponse.d.ts +0 -19
  36. package/esm/models/completionresponse.js +0 -28
  37. package/esm/models/completionusage.d.ts +0 -12
  38. package/esm/models/completionusage.js +0 -23
  39. package/esm/sdk/completions.d.ts +0 -12
  40. 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
@@ -14,6 +14,7 @@ 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
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';
@@ -1,3 +1,4 @@
1
+ import type { Hook } from "../hooks/types.js";
1
2
  import { HTTPClient } from "./http.js";
2
3
  import { Logger } from "./logger.js";
3
4
  import { RetryConfig } from "./retries.js";
@@ -40,13 +41,18 @@ export type SDKOptions = {
40
41
  retryConfig?: RetryConfig;
41
42
  timeoutMs?: number;
42
43
  debugLogger?: Logger;
44
+ /**
45
+ * Hooks for request/response lifecycle events.
46
+ * Can be a single hook object or an array of hooks.
47
+ */
48
+ hooks?: Hook | Hook[];
43
49
  };
44
50
  export declare function serverURLFromOptions(options: SDKOptions): URL | null;
45
51
  export declare const SDK_METADATA: {
46
52
  readonly language: "typescript";
47
53
  readonly openapiDocVersion: "1.0.0";
48
- readonly sdkVersion: "0.3.16";
54
+ readonly sdkVersion: "0.5.1";
49
55
  readonly genVersion: "2.788.4";
50
- readonly userAgent: "speakeasy-sdk/typescript 0.3.16 2.788.4 1.0.0 @openrouter/sdk";
56
+ readonly userAgent: "speakeasy-sdk/typescript 0.5.1 2.788.4 1.0.0 @openrouter/sdk";
51
57
  };
52
58
  //# 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.3.16",
29
+ sdkVersion: "0.5.1",
30
30
  genVersion: "2.788.4",
31
- userAgent: "speakeasy-sdk/typescript 0.3.16 2.788.4 1.0.0 @openrouter/sdk",
31
+ userAgent: "speakeasy-sdk/typescript 0.5.1 2.788.4 1.0.0 @openrouter/sdk",
32
32
  };
33
33
  //# sourceMappingURL=config.js.map
@@ -3,6 +3,7 @@ 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
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;
@@ -245,12 +246,32 @@ export declare class ModelResult<TTools extends readonly Tool[]> {
245
246
  */
246
247
  getTextStream(): AsyncIterableIterator<string>;
247
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
+ *
248
268
  * Stream incremental message updates as content is added in responses format.
249
269
  * Each iteration yields an updated version of the message with new content.
250
- * Also yields OpenResponsesFunctionCallOutput after tool execution completes.
251
- * Returns ResponsesOutputMessage or OpenResponsesFunctionCallOutput compatible with OpenAI Responses API format.
270
+ * Also yields function_call items and OpenResponsesFunctionCallOutput after tool execution completes.
271
+ * Returns ResponsesOutputMessage, ResponsesOutputItemFunctionCall, or OpenResponsesFunctionCallOutput
272
+ * compatible with OpenAI Responses API format.
252
273
  */
253
- getNewMessagesStream(): AsyncIterableIterator<models.ResponsesOutputMessage | models.OpenResponsesFunctionCallOutput>;
274
+ getNewMessagesStream(): AsyncIterableIterator<models.ResponsesOutputMessage | models.OpenResponsesFunctionCallOutput | models.ResponsesOutputItemFunctionCall>;
254
275
  /**
255
276
  * Stream only reasoning deltas as they arrive.
256
277
  * This filters the full event stream to only yield reasoning content.
@@ -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, isFunctionCallItem, 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
  *
@@ -313,6 +305,32 @@ export class ModelResult {
313
305
  const tool = this.options.tools?.find((t) => t.function.name === toolCall.name);
314
306
  if (!tool || !hasExecuteFunction(tool))
315
307
  continue;
308
+ // Check if arguments failed to parse (remained as string instead of object)
309
+ // This happens when the model returns invalid JSON for tool call arguments
310
+ // We use 'unknown' cast because the type system doesn't know arguments can be a string
311
+ // when JSON parsing fails in stream-transformers.ts
312
+ const args = toolCall.arguments;
313
+ if (typeof args === 'string') {
314
+ const rawArgs = args;
315
+ const errorMessage = `Failed to parse tool call arguments for "${toolCall.name}": The model provided invalid JSON. ` +
316
+ `Raw arguments received: "${rawArgs}". ` +
317
+ `Please provide valid JSON arguments for this tool call.`;
318
+ // Emit error event if broadcaster exists
319
+ if (this.toolEventBroadcaster) {
320
+ this.toolEventBroadcaster.push({
321
+ type: 'tool_result',
322
+ toolCallId: toolCall.id,
323
+ result: { error: errorMessage },
324
+ });
325
+ }
326
+ toolResults.push({
327
+ type: 'function_call_output',
328
+ id: `output_${toolCall.id}`,
329
+ callId: toolCall.id,
330
+ output: JSON.stringify({ error: errorMessage }),
331
+ });
332
+ continue;
333
+ }
316
334
  // Track preliminary results for this specific tool call
317
335
  const preliminaryResultsForCall = [];
318
336
  // Create callback for real-time preliminary results
@@ -360,7 +378,13 @@ export class ModelResult {
360
378
  async resolveAsyncFunctionsForTurn(turnContext) {
361
379
  if (hasAsyncFunctions(this.options.request)) {
362
380
  const resolved = await resolveAsyncFunctions(this.options.request, turnContext);
363
- this.resolvedRequest = { ...resolved, stream: false };
381
+ // Preserve accumulated input from previous turns
382
+ const preservedInput = this.resolvedRequest?.input;
383
+ this.resolvedRequest = {
384
+ ...resolved,
385
+ stream: false,
386
+ ...(preservedInput !== undefined && { input: preservedInput }),
387
+ };
364
388
  }
365
389
  }
366
390
  /**
@@ -387,8 +411,15 @@ export class ModelResult {
387
411
  * @returns The new response from the API
388
412
  */
389
413
  async makeFollowupRequest(currentResponse, toolResults) {
390
- // Build new input with tool results
414
+ // Build new input preserving original conversation + tool results
415
+ const originalInput = this.resolvedRequest?.input;
416
+ const normalizedOriginalInput = Array.isArray(originalInput)
417
+ ? originalInput
418
+ : originalInput
419
+ ? [{ role: 'user', content: originalInput }]
420
+ : [];
391
421
  const newInput = [
422
+ ...normalizedOriginalInput,
392
423
  ...(Array.isArray(currentResponse.output)
393
424
  ? currentResponse.output
394
425
  : [currentResponse.output]),
@@ -397,9 +428,13 @@ export class ModelResult {
397
428
  if (!this.resolvedRequest) {
398
429
  throw new Error('Request not initialized');
399
430
  }
400
- const newRequest = {
431
+ // Update resolvedRequest.input with accumulated conversation for next turn
432
+ this.resolvedRequest = {
401
433
  ...this.resolvedRequest,
402
434
  input: newInput,
435
+ };
436
+ const newRequest = {
437
+ ...this.resolvedRequest,
403
438
  stream: false,
404
439
  };
405
440
  const newResult = await betaResponsesSend(this.options.client, newRequest, this.options.options);
@@ -875,10 +910,68 @@ export class ModelResult {
875
910
  }.call(this);
876
911
  }
877
912
  /**
913
+ * Stream all output items cumulatively as they arrive.
914
+ * Items are emitted with the same ID but progressively updated content as streaming progresses.
915
+ * Also yields tool results (function_call_output) after tool execution completes.
916
+ *
917
+ * Item types include:
918
+ * - message: Assistant text responses (emitted cumulatively as text streams)
919
+ * - function_call: Tool calls (emitted cumulatively as arguments stream)
920
+ * - reasoning: Model reasoning (emitted cumulatively as thinking streams)
921
+ * - web_search_call: Web search operations
922
+ * - file_search_call: File search operations
923
+ * - image_generation_call: Image generation operations
924
+ * - function_call_output: Results from executed tools
925
+ */
926
+ getItemsStream() {
927
+ return async function* () {
928
+ await this.initStream();
929
+ if (!this.reusableStream) {
930
+ throw new Error('Stream not initialized');
931
+ }
932
+ // Stream all items from the API response cumulatively
933
+ yield* buildItemsStream(this.reusableStream);
934
+ // Execute tools if needed
935
+ await this.executeToolsIfNeeded();
936
+ // Yield function calls and outputs for each tool round
937
+ for (const round of this.allToolExecutionRounds) {
938
+ // Round 0's function_calls already yielded via buildItemsStream
939
+ if (round.round > 0) {
940
+ for (const item of round.response.output) {
941
+ if (isFunctionCallItem(item)) {
942
+ yield item;
943
+ }
944
+ }
945
+ }
946
+ for (const toolResult of round.toolResults) {
947
+ yield toolResult;
948
+ }
949
+ }
950
+ // If tools were executed, yield all items from the final response
951
+ if (this.finalResponse && this.allToolExecutionRounds.length > 0) {
952
+ for (const item of this.finalResponse.output) {
953
+ if (isOutputMessage(item) ||
954
+ isFunctionCallItem(item) ||
955
+ isReasoningOutputItem(item) ||
956
+ isWebSearchCallOutputItem(item) ||
957
+ isFileSearchCallOutputItem(item) ||
958
+ isImageGenerationCallOutputItem(item)) {
959
+ yield item;
960
+ }
961
+ }
962
+ }
963
+ }.call(this);
964
+ }
965
+ /**
966
+ * @deprecated Use `getItemsStream()` instead. This method only streams messages,
967
+ * while `getItemsStream()` streams all output item types (messages, function_calls,
968
+ * reasoning, etc.) with cumulative updates.
969
+ *
878
970
  * Stream incremental message updates as content is added in responses format.
879
971
  * Each iteration yields an updated version of the message with new content.
880
- * Also yields OpenResponsesFunctionCallOutput after tool execution completes.
881
- * Returns ResponsesOutputMessage or OpenResponsesFunctionCallOutput compatible with OpenAI Responses API format.
972
+ * Also yields function_call items and OpenResponsesFunctionCallOutput after tool execution completes.
973
+ * Returns ResponsesOutputMessage, ResponsesOutputItemFunctionCall, or OpenResponsesFunctionCallOutput
974
+ * compatible with OpenAI Responses API format.
882
975
  */
883
976
  getNewMessagesStream() {
884
977
  return async function* () {
@@ -890,8 +983,15 @@ export class ModelResult {
890
983
  yield* buildResponsesMessageStream(this.reusableStream);
891
984
  // Execute tools if needed
892
985
  await this.executeToolsIfNeeded();
893
- // Yield function call outputs for each executed tool
986
+ // Yield function calls and their outputs for each executed tool
894
987
  for (const round of this.allToolExecutionRounds) {
988
+ // First yield the function_call items from the response that triggered tool execution
989
+ for (const item of round.response.output) {
990
+ if (isFunctionCallItem(item)) {
991
+ yield item;
992
+ }
993
+ }
994
+ // Then yield the function_call_output results
895
995
  for (const toolResult of round.toolResults) {
896
996
  yield toolResult;
897
997
  }
package/esm/lib/sdks.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SDKHooks } from "../hooks/hooks.js";
2
- import { HookContext } from "../hooks/types.js";
2
+ import type { HookContext } from "../hooks/types.js";
3
3
  import { ConnectionError, InvalidRequestError, RequestAbortedError, RequestTimeoutError, UnexpectedClientError } from "../models/errors/httpclienterrors.js";
4
4
  import { Result } from "../types/fp.js";
5
5
  import { SDKOptions } from "./config.js";
package/esm/lib/sdks.js CHANGED
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
14
14
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
15
  };
16
- var _ClientSDK_httpClient, _ClientSDK_hooks, _ClientSDK_logger;
16
+ var _ClientSDK_instances, _ClientSDK_httpClient, _ClientSDK_hooks, _ClientSDK_logger, _ClientSDK_registerHook;
17
17
  import { SDKHooks } from "../hooks/hooks.js";
18
18
  import { ConnectionError, InvalidRequestError, RequestAbortedError, RequestTimeoutError, UnexpectedClientError, } from "../models/errors/httpclienterrors.js";
19
19
  import { ERR, OK } from "../types/fp.js";
@@ -33,18 +33,22 @@ const isBrowserLike = webWorkerLike
33
33
  || (typeof window === "object" && typeof window.document !== "undefined");
34
34
  export class ClientSDK {
35
35
  constructor(options = {}) {
36
+ _ClientSDK_instances.add(this);
36
37
  _ClientSDK_httpClient.set(this, void 0);
37
38
  _ClientSDK_hooks.set(this, void 0);
38
39
  _ClientSDK_logger.set(this, void 0);
39
- const opt = options;
40
- if (typeof opt === "object"
41
- && opt != null
42
- && "hooks" in opt
43
- && opt.hooks instanceof SDKHooks) {
44
- __classPrivateFieldSet(this, _ClientSDK_hooks, opt.hooks, "f");
40
+ // Reuse existing SDKHooks if passed (for sub-SDKs)
41
+ if (options.hooks instanceof SDKHooks) {
42
+ __classPrivateFieldSet(this, _ClientSDK_hooks, options.hooks, "f");
45
43
  }
46
44
  else {
47
45
  __classPrivateFieldSet(this, _ClientSDK_hooks, new SDKHooks(), "f");
46
+ if (options.hooks) {
47
+ const hooksArray = Array.isArray(options.hooks) ? options.hooks : [options.hooks];
48
+ for (const hook of hooksArray) {
49
+ __classPrivateFieldGet(this, _ClientSDK_instances, "m", _ClientSDK_registerHook).call(this, hook);
50
+ }
51
+ }
48
52
  }
49
53
  const defaultHttpClient = new HTTPClient();
50
54
  options.httpClient = options.httpClient || defaultHttpClient;
@@ -185,7 +189,23 @@ export class ClientSDK {
185
189
  });
186
190
  }
187
191
  }
188
- _ClientSDK_httpClient = new WeakMap(), _ClientSDK_hooks = new WeakMap(), _ClientSDK_logger = new WeakMap();
192
+ _ClientSDK_httpClient = new WeakMap(), _ClientSDK_hooks = new WeakMap(), _ClientSDK_logger = new WeakMap(), _ClientSDK_instances = new WeakSet(), _ClientSDK_registerHook = function _ClientSDK_registerHook(hook) {
193
+ if ("sdkInit" in hook) {
194
+ __classPrivateFieldGet(this, _ClientSDK_hooks, "f").registerSDKInitHook(hook);
195
+ }
196
+ if ("beforeCreateRequest" in hook) {
197
+ __classPrivateFieldGet(this, _ClientSDK_hooks, "f").registerBeforeCreateRequestHook(hook);
198
+ }
199
+ if ("beforeRequest" in hook) {
200
+ __classPrivateFieldGet(this, _ClientSDK_hooks, "f").registerBeforeRequestHook(hook);
201
+ }
202
+ if ("afterSuccess" in hook) {
203
+ __classPrivateFieldGet(this, _ClientSDK_hooks, "f").registerAfterSuccessHook(hook);
204
+ }
205
+ if ("afterError" in hook) {
206
+ __classPrivateFieldGet(this, _ClientSDK_hooks, "f").registerAfterErrorHook(hook);
207
+ }
208
+ };
189
209
  const jsonLikeContentTypeRE = /(application|text)\/.*?\+*json.*/;
190
210
  const jsonlLikeContentTypeRE = /(application|text)\/(.*?\+*\bjsonl\b.*|.*?\+*\bx-ndjson\b.*)/;
191
211
  async function logRequest(logger, req) {
@@ -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