@jerome-benoit/sap-ai-provider-v2 5.0.2 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +44 -24
  2. package/dist/chunk-4ILJD6PI.js +333 -0
  3. package/dist/chunk-4ILJD6PI.js.map +1 -0
  4. package/dist/chunk-BHA5MIN6.js +224 -0
  5. package/dist/chunk-BHA5MIN6.js.map +1 -0
  6. package/dist/{chunk-LEME2MFD.js → chunk-DLGBK3C3.js} +91 -7
  7. package/dist/chunk-DLGBK3C3.js.map +1 -0
  8. package/dist/{chunk-NLMWIVG7.js → chunk-EUBI5ENK.js} +54 -27
  9. package/dist/chunk-EUBI5ENK.js.map +1 -0
  10. package/dist/{chunk-YP3AADWD.js → chunk-FKHOJ3ZC.js} +24 -3
  11. package/dist/chunk-FKHOJ3ZC.js.map +1 -0
  12. package/dist/{chunk-77JSAAPE.js → chunk-QFMHNGLB.js} +56 -218
  13. package/dist/chunk-QFMHNGLB.js.map +1 -0
  14. package/dist/{chunk-U6WJSLR7.js → chunk-QQQYMQPU.js} +19 -10
  15. package/dist/chunk-QQQYMQPU.js.map +1 -0
  16. package/dist/{chunk-QZOZ3PZT.js → chunk-ZOBD7PXJ.js} +118 -22
  17. package/dist/chunk-ZOBD7PXJ.js.map +1 -0
  18. package/dist/{foundation-models-embedding-model-strategy-A3WDDAYK.js → foundation-models-embedding-model-strategy-3WAKJXBY.js} +5 -4
  19. package/dist/{foundation-models-embedding-model-strategy-A3WDDAYK.js.map → foundation-models-embedding-model-strategy-3WAKJXBY.js.map} +1 -1
  20. package/dist/{foundation-models-language-model-strategy-6U6KK6KH.js → foundation-models-language-model-strategy-PJ26VXEA.js} +22 -9
  21. package/dist/foundation-models-language-model-strategy-PJ26VXEA.js.map +1 -0
  22. package/dist/index.cjs +1903 -384
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +798 -185
  25. package/dist/index.d.ts +798 -185
  26. package/dist/index.js +148 -24
  27. package/dist/index.js.map +1 -1
  28. package/dist/{orchestration-embedding-model-strategy-JO3QH5MR.js → orchestration-embedding-model-strategy-AZ76XLMD.js} +6 -5
  29. package/dist/{orchestration-embedding-model-strategy-JO3QH5MR.js.map → orchestration-embedding-model-strategy-AZ76XLMD.js.map} +1 -1
  30. package/dist/{orchestration-language-model-strategy-MBVA7BYX.js → orchestration-language-model-strategy-CT6RHCYO.js} +57 -19
  31. package/dist/orchestration-language-model-strategy-CT6RHCYO.js.map +1 -0
  32. package/dist/responses-language-model-strategy-UYTV6TPM.js +738 -0
  33. package/dist/responses-language-model-strategy-UYTV6TPM.js.map +1 -0
  34. package/dist/sap-ai-error-UPKYWPSS.js +16 -0
  35. package/dist/sap-ai-error-UPKYWPSS.js.map +1 -0
  36. package/package.json +79 -39
  37. package/dist/chunk-77JSAAPE.js.map +0 -1
  38. package/dist/chunk-LEME2MFD.js.map +0 -1
  39. package/dist/chunk-NLMWIVG7.js.map +0 -1
  40. package/dist/chunk-QZOZ3PZT.js.map +0 -1
  41. package/dist/chunk-U6WJSLR7.js.map +0 -1
  42. package/dist/chunk-YP3AADWD.js.map +0 -1
  43. package/dist/foundation-models-language-model-strategy-6U6KK6KH.js.map +0 -1
  44. package/dist/orchestration-language-model-strategy-MBVA7BYX.js.map +0 -1
@@ -1,29 +1,44 @@
1
1
  import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
2
  import {
3
3
  convertToSAPMessages
4
- } from "./chunk-YP3AADWD.js";
4
+ } from "./chunk-FKHOJ3ZC.js";
5
5
  import {
6
6
  buildAnthropicCacheMetadata,
7
7
  buildGenerateResult,
8
8
  buildModelParams,
9
+ buildOrchestrationReasoningMetadata,
9
10
  createAISDKRequestBodySummary,
11
+ createAbortError,
10
12
  extractCompletionMetadata,
11
13
  extractResponseMetadata,
14
+ getProviderFinishReason,
12
15
  mapFinishReason,
13
16
  mapTokenUsage,
14
17
  mapToolChoice,
15
18
  mergeRequestConfig,
16
- sanitizeAsJSONArray
17
- } from "./chunk-LEME2MFD.js";
19
+ parseProviderSpecificFields,
20
+ sanitizeAsJSONArray,
21
+ throwIfAborted,
22
+ waitWithAbort
23
+ } from "./chunk-DLGBK3C3.js";
18
24
  import {
19
25
  VERSION,
20
- convertToAISDKError,
21
26
  getProviderName,
27
+ orchestrationReasoningBlockSchema
28
+ } from "./chunk-BHA5MIN6.js";
29
+ import {
30
+ convertToAISDKError,
22
31
  normalizeHeaders
23
- } from "./chunk-77JSAAPE.js";
32
+ } from "./chunk-QFMHNGLB.js";
24
33
 
25
34
  // src/stream-transformer.ts
26
35
  var StreamIdGenerator = class {
36
+ /**
37
+ * @returns A UUID string for identifying a native reasoning block.
38
+ */
39
+ generateReasoningBlockId() {
40
+ return crypto.randomUUID();
41
+ }
27
42
  /**
28
43
  * @returns A UUID string for identifying the response.
29
44
  */
@@ -43,11 +58,6 @@ var StreamIdGenerator = class {
43
58
  return crypto.randomUUID();
44
59
  }
45
60
  };
46
- function createAbortError(reason) {
47
- const error = new Error("The operation was aborted.", { cause: reason });
48
- error.name = "AbortError";
49
- return error;
50
- }
51
61
  function createInitialStreamState() {
52
62
  return {
53
63
  activeText: false,
@@ -76,6 +86,8 @@ function createStreamTransformer(config) {
76
86
  cancel,
77
87
  convertToAISDKError: convertToAISDKError2,
78
88
  extractChunkMetadata,
89
+ extractProviderSpecificFields,
90
+ extractReasoningBlocks,
79
91
  idGenerator,
80
92
  includeRawChunks,
81
93
  modelId,
@@ -98,6 +110,47 @@ function createStreamTransformer(config) {
98
110
  let resolvedRequestId = requestId;
99
111
  let tokenUsage;
100
112
  let citations;
113
+ let providerSpecificFields;
114
+ let providerFinishReason;
115
+ let reasoningBlocks;
116
+ function collectReasoningBlocks(incoming, controller) {
117
+ if (incoming === void 0) return true;
118
+ if (!Array.isArray(incoming)) {
119
+ handleStreamError(
120
+ new TypeError("Invalid Orchestration reasoning_content: expected an array."),
121
+ controller,
122
+ convertToAISDKError2,
123
+ options,
124
+ modelId,
125
+ url
126
+ );
127
+ return false;
128
+ }
129
+ const blocks = incoming;
130
+ if (blocks.length === 0) return true;
131
+ reasoningBlocks ??= [];
132
+ for (const [index, value] of blocks.entries()) {
133
+ const parsed = orchestrationReasoningBlockSchema.safeParse(value);
134
+ if (!parsed.success) {
135
+ handleStreamError(parsed.error, controller, convertToAISDKError2, options, modelId, url);
136
+ return false;
137
+ }
138
+ const block = parsed.data;
139
+ let state = reasoningBlocks[index];
140
+ if (state) {
141
+ state.block.content = (state.block.content ?? "") + (block.content ?? "");
142
+ if (block.signature) state.block.signature = block.signature;
143
+ } else {
144
+ state = { block, id: idGenerator.generateReasoningBlockId() };
145
+ reasoningBlocks.push(state);
146
+ controller.enqueue({ id: state.id, type: "reasoning-start" });
147
+ }
148
+ if (block.content) {
149
+ controller.enqueue({ delta: block.content, id: state.id, type: "reasoning-delta" });
150
+ }
151
+ }
152
+ return true;
153
+ }
101
154
  function collectCitations(incoming) {
102
155
  if (!incoming?.length) return;
103
156
  citations ??= /* @__PURE__ */ new Map();
@@ -174,6 +227,13 @@ function createStreamTransformer(config) {
174
227
  );
175
228
  return;
176
229
  }
230
+ for (const state of reasoningBlocks ?? []) {
231
+ controller.enqueue({
232
+ id: state.id,
233
+ providerMetadata: buildOrchestrationReasoningMetadata(state.block, providerName),
234
+ type: "reasoning-end"
235
+ });
236
+ }
177
237
  const didEmitAnyToolCalls = finalizeToolCalls(
178
238
  controller,
179
239
  toolCallsInProgress,
@@ -185,13 +245,16 @@ function createStreamTransformer(config) {
185
245
  }
186
246
  const finalFinishReason = streamResponseGetFinishReason();
187
247
  if (finalFinishReason) {
188
- streamState.finishReason = mapFinishReason(finalFinishReason);
248
+ streamState.finishReason = mapFinishReason(finalFinishReason, providerFinishReason);
189
249
  } else if (didEmitAnyToolCalls) {
190
250
  streamState.finishReason = {
191
- raw: void 0,
251
+ raw: providerFinishReason,
192
252
  unified: "tool-calls"
193
253
  };
194
254
  }
255
+ if (providerFinishReason !== void 0) {
256
+ streamState.finishReason = { ...streamState.finishReason, raw: providerFinishReason };
257
+ }
195
258
  streamState.usage = mapTokenUsage(tokenUsage);
196
259
  collectCitations(streamResponseGetCitations?.());
197
260
  if (citations) {
@@ -213,6 +276,7 @@ function createStreamTransformer(config) {
213
276
  ...buildAnthropicCacheMetadata(tokenUsage),
214
277
  finishReason: streamState.finishReason.raw ?? "unknown",
215
278
  finishReasonMapped: streamState.finishReason,
279
+ ...providerSpecificFields && { providerSpecificFields },
216
280
  ...streamIntermediateFailures?.length ? {
217
281
  intermediateFailures: sanitizeAsJSONArray(streamIntermediateFailures)
218
282
  } : {},
@@ -252,6 +316,14 @@ function createStreamTransformer(config) {
252
316
  Object.assign(resolvedResponseMetadata, incomingMetadata);
253
317
  collectUsage(chunk.getTokenUsage?.());
254
318
  collectCitations(chunk.getCitations?.());
319
+ const incomingProviderFields = parseProviderSpecificFields(
320
+ extractProviderSpecificFields?.(chunk)
321
+ );
322
+ if (incomingProviderFields) {
323
+ providerSpecificFields = { ...providerSpecificFields, ...incomingProviderFields };
324
+ providerFinishReason = getProviderFinishReason(incomingProviderFields) ?? providerFinishReason;
325
+ }
326
+ if (!collectReasoningBlocks(extractReasoningBlocks?.(chunk), controller)) return;
255
327
  if (streamState.isFirstChunk || metadataChanged) {
256
328
  streamState.isFirstChunk = false;
257
329
  controller.enqueue({
@@ -281,7 +353,7 @@ function createStreamTransformer(config) {
281
353
  }
282
354
  const chunkFinishReason = chunk.getFinishReason();
283
355
  if (chunkFinishReason) {
284
- streamState.finishReason = mapFinishReason(chunkFinishReason);
356
+ streamState.finishReason = mapFinishReason(chunkFinishReason, providerFinishReason);
285
357
  if (streamState.finishReason.unified === "tool-calls") {
286
358
  finalizeToolCalls(controller, toolCallsInProgress, idGenerator, emitToolInputStart);
287
359
  if (streamState.activeText && textBlockId) {
@@ -427,15 +499,19 @@ var BaseLanguageModelStrategy = class {
427
499
  ];
428
500
  async doGenerate(config, settings, options) {
429
501
  try {
430
- if (options.abortSignal?.aborted) throw createAbortError(options.abortSignal.reason);
502
+ throwIfAborted(options.abortSignal);
431
503
  const commonParts = this.buildCommonParts(config, settings, options);
432
504
  const { request, warnings } = this.buildRequest(config, settings, options, commonParts);
433
505
  const client = this.createClient(config, settings, commonParts);
434
- const response = await this.executeApiCall(
435
- client,
436
- request,
437
- mergeRequestConfig(config.requestConfig, options.abortSignal, options.headers)
506
+ const response = await waitWithAbort(
507
+ this.executeApiCall(
508
+ client,
509
+ request,
510
+ mergeRequestConfig(config.requestConfig, options.abortSignal, options.headers)
511
+ ),
512
+ options.abortSignal
438
513
  );
514
+ throwIfAborted(options.abortSignal);
439
515
  return buildGenerateResult({
440
516
  providerName: commonParts.providerName,
441
517
  requestBody: request,
@@ -457,7 +533,7 @@ var BaseLanguageModelStrategy = class {
457
533
  }
458
534
  async doStream(config, settings, options) {
459
535
  try {
460
- if (options.abortSignal?.aborted) throw createAbortError(options.abortSignal.reason);
536
+ throwIfAborted(options.abortSignal);
461
537
  const commonParts = this.buildCommonParts(config, settings, options);
462
538
  const { request, warnings } = this.buildRequest(config, settings, options, commonParts);
463
539
  const client = this.createClient(config, settings, commonParts);
@@ -466,14 +542,24 @@ var BaseLanguageModelStrategy = class {
466
542
  request,
467
543
  options.abortSignal ?? void 0,
468
544
  settings,
469
- mergeRequestConfig(config.requestConfig, void 0, options.headers)
545
+ mergeRequestConfig(config.requestConfig, void 0, options.headers),
546
+ commonParts
470
547
  );
548
+ if (options.abortSignal?.aborted) {
549
+ try {
550
+ streamResponse.cancel();
551
+ } finally {
552
+ throwIfAborted(options.abortSignal);
553
+ }
554
+ }
471
555
  const idGenerator = new StreamIdGenerator();
472
556
  const streamWarnings = this.collectStreamWarnings(settings, commonParts.sapOptions);
473
557
  const transformedStream = createStreamTransformer({
474
558
  cancel: streamResponse.cancel,
475
559
  convertToAISDKError,
476
560
  extractChunkMetadata: (chunk) => this.extractMetadata(chunk),
561
+ extractProviderSpecificFields: streamResponse.extractProviderSpecificFields,
562
+ extractReasoningBlocks: streamResponse.extractReasoningBlocks,
477
563
  idGenerator,
478
564
  includeRawChunks: options.includeRawChunks ?? false,
479
565
  modelId: config.modelId,
@@ -533,6 +619,7 @@ var BaseLanguageModelStrategy = class {
533
619
  const messages = convertToSAPMessages(options.prompt, {
534
620
  escapeTemplatePlaceholders: this.getEscapeTemplatePlaceholders(sapOptions, settings),
535
621
  includeReasoning: this.getIncludeReasoning(sapOptions, settings),
622
+ nativeReasoningProviderName: this.getNativeReasoningProviderName(providerName),
536
623
  parsePartProviderOptions: this.getPartProviderOptionsParser(),
537
624
  warnings
538
625
  });
@@ -597,7 +684,16 @@ var BaseLanguageModelStrategy = class {
597
684
  * @internal
598
685
  */
599
686
  getIncludeReasoning(sapOptions, settings) {
600
- return sapOptions?.includeReasoning ?? settings.includeReasoning ?? false;
687
+ return sapOptions?.includeReasoning ?? ("includeReasoning" in settings ? settings.includeReasoning : false) ?? false;
688
+ }
689
+ /**
690
+ * Enables native reasoning history only for strategies supporting the Orchestration wire format.
691
+ * @param _providerName - Configured provider namespace.
692
+ * @returns The native reasoning namespace, or undefined for legacy text-only history.
693
+ * @internal
694
+ */
695
+ getNativeReasoningProviderName(_providerName) {
696
+ return void 0;
601
697
  }
602
698
  /**
603
699
  * Returns a parser for per-message-part `providerOptions['sap-ai']`.
@@ -631,4 +727,4 @@ var BaseLanguageModelStrategy = class {
631
727
  export {
632
728
  BaseLanguageModelStrategy
633
729
  };
634
- //# sourceMappingURL=chunk-QZOZ3PZT.js.map
730
+ //# sourceMappingURL=chunk-ZOBD7PXJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stream-transformer.ts","../src/base-language-model-strategy.ts"],"sourcesContent":["/**\n * Stream transformer for converting SAP AI SDK streaming responses\n * into Vercel AI SDK LanguageModelV3StreamPart events.\n */\nimport type {\n JSONObject,\n LanguageModelV3CallOptions,\n LanguageModelV3FinishReason,\n LanguageModelV3ResponseMetadata,\n LanguageModelV3StreamPart,\n LanguageModelV3Usage,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport type { ReasoningBlock } from \"@sap-ai-sdk/orchestration\";\n\nimport type {\n SDKCitation,\n SDKDeltaToolCall,\n SDKStreamChunk,\n SDKTokenUsage,\n} from \"./strategy-utils.js\";\n\nimport { createAbortError } from \"./abort-utils.js\";\nimport { orchestrationReasoningBlockSchema } from \"./sap-ai-provider-options.js\";\nimport {\n buildAnthropicCacheMetadata,\n buildOrchestrationReasoningMetadata,\n createAISDKRequestBodySummary,\n getProviderFinishReason,\n mapFinishReason,\n mapTokenUsage,\n parseProviderSpecificFields,\n sanitizeAsJSONArray,\n} from \"./strategy-utils.js\";\n\n/**\n * @internal\n */\nexport interface StreamState {\n activeText: boolean;\n finishReason: LanguageModelV3FinishReason;\n isFirstChunk: boolean;\n usage: LanguageModelV3Usage;\n}\n\n/**\n * @internal\n */\nexport interface StreamTransformerConfig {\n readonly cancel: () => void;\n readonly convertToAISDKError: (\n error: unknown,\n context: {\n modelId: string;\n modelType: \"languageModel\";\n operation: string;\n requestBody: unknown;\n url: string;\n },\n ) => unknown;\n readonly extractChunkMetadata: (chunk: SDKStreamChunk) => {\n requestId?: string;\n responseMetadata: LanguageModelV3ResponseMetadata;\n };\n readonly extractProviderSpecificFields?: (chunk: SDKStreamChunk) => unknown;\n readonly extractReasoningBlocks?: (chunk: SDKStreamChunk) => unknown;\n readonly idGenerator: StreamIdGenerator;\n readonly includeRawChunks: boolean;\n readonly modelId: string;\n readonly options: LanguageModelV3CallOptions;\n readonly providerName: string;\n /** SAP-pipeline request id resolved by `extractResponseMetadata`. */\n readonly requestId?: string;\n readonly responseMetadata: LanguageModelV3ResponseMetadata & { id: string };\n readonly sdkStream: AsyncIterable<SDKStreamChunk>;\n readonly streamResponseGetCitations?: () => SDKCitation[] | undefined;\n readonly streamResponseGetFinishReason: () => null | string | undefined;\n readonly streamResponseGetIntermediateFailures?: () => undefined | unknown[];\n readonly url: string;\n readonly version: string;\n readonly warnings: readonly SharedV3Warning[];\n}\n\n/**\n * @internal\n */\nexport interface ToolCallInProgress {\n arguments: string;\n didEmitCall: boolean;\n didEmitInputStart: boolean;\n id: string | undefined;\n toolName?: string;\n}\n\n/**\n * @internal\n */\nexport class StreamIdGenerator {\n /**\n * @returns A UUID string for identifying a native reasoning block.\n */\n generateReasoningBlockId(): string {\n return crypto.randomUUID();\n }\n\n /**\n * @returns A UUID string for identifying the response.\n */\n generateResponseId(): string {\n return crypto.randomUUID();\n }\n\n /**\n * @returns A UUID string for identifying a text block.\n */\n generateTextBlockId(): string {\n return crypto.randomUUID();\n }\n\n /**\n * @returns A UUID string for identifying a tool call when the API does not provide one.\n */\n generateToolCallId(): string {\n return crypto.randomUUID();\n }\n}\n\n/**\n * Creates the initial stream state for processing streaming responses.\n * @returns The initial stream state object.\n * @internal\n */\nexport function createInitialStreamState(): StreamState {\n return {\n activeText: false,\n finishReason: {\n raw: undefined,\n unified: \"other\" as const,\n },\n isFirstChunk: true,\n usage: {\n inputTokens: {\n cacheRead: undefined,\n cacheWrite: undefined,\n noCache: undefined,\n total: undefined,\n },\n outputTokens: {\n reasoning: undefined,\n text: undefined,\n total: undefined,\n },\n },\n };\n}\n\n/**\n * Creates a ReadableStream that transforms SAP AI SDK streaming responses\n * into Vercel AI SDK LanguageModelV3StreamPart events.\n * @param config - The stream transformer configuration containing all dependencies.\n * @returns A ReadableStream of LanguageModelV3StreamPart events.\n * @internal\n */\nexport function createStreamTransformer(\n config: StreamTransformerConfig,\n): ReadableStream<LanguageModelV3StreamPart> {\n const {\n cancel,\n convertToAISDKError,\n extractChunkMetadata,\n extractProviderSpecificFields,\n extractReasoningBlocks,\n idGenerator,\n includeRawChunks,\n modelId,\n options,\n providerName,\n requestId,\n responseMetadata,\n sdkStream,\n streamResponseGetCitations,\n streamResponseGetFinishReason,\n streamResponseGetIntermediateFailures,\n url,\n version,\n warnings,\n } = config;\n\n let textBlockId: null | string = null;\n const streamState = createInitialStreamState();\n const toolCallsInProgress = new Map<number, ToolCallInProgress>();\n const resolvedResponseMetadata = { ...responseMetadata };\n let resolvedRequestId = requestId;\n let tokenUsage: SDKTokenUsage | undefined;\n let citations: Map<string, SDKCitation> | undefined;\n let providerSpecificFields: JSONObject | undefined;\n let providerFinishReason: string | undefined;\n let reasoningBlocks: undefined | { block: ReasoningBlock; id: string }[];\n\n /**\n * Retains SAP's positional reasoning blocks until EOF, including late signature updates.\n * @param incoming - Unvalidated native reasoning collection from the SDK.\n * @param controller - Output event controller.\n * @returns False after emitting a terminal validation error; true otherwise.\n */\n function collectReasoningBlocks(\n incoming: unknown,\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n ): boolean {\n if (incoming === undefined) return true;\n if (!Array.isArray(incoming)) {\n handleStreamError(\n new TypeError(\"Invalid Orchestration reasoning_content: expected an array.\"),\n controller,\n convertToAISDKError,\n options,\n modelId,\n url,\n );\n return false;\n }\n const blocks: unknown[] = incoming;\n if (blocks.length === 0) return true;\n reasoningBlocks ??= [];\n for (const [index, value] of blocks.entries()) {\n const parsed = orchestrationReasoningBlockSchema.safeParse(value);\n if (!parsed.success) {\n handleStreamError(parsed.error, controller, convertToAISDKError, options, modelId, url);\n return false;\n }\n const block = parsed.data;\n let state = reasoningBlocks[index];\n if (state) {\n state.block.content = (state.block.content ?? \"\") + (block.content ?? \"\");\n if (block.signature) state.block.signature = block.signature;\n } else {\n state = { block, id: idGenerator.generateReasoningBlockId() };\n reasoningBlocks.push(state);\n controller.enqueue({ id: state.id, type: \"reasoning-start\" });\n }\n if (block.content) {\n controller.enqueue({ delta: block.content, id: state.id, type: \"reasoning-delta\" });\n }\n }\n return true;\n }\n\n /**\n * Retains sources from early chunks when later SDK snapshots omit them.\n * @param incoming - Citations in a chunk or final response.\n */\n function collectCitations(incoming: SDKCitation[] | undefined): void {\n if (!incoming?.length) return;\n citations ??= new Map();\n for (const citation of incoming) {\n citations.set(String(citation.ref_id ?? citation.url), citation);\n }\n }\n\n /**\n * Combines usage snapshots without losing details omitted by later chunks.\n * @param incoming - Usage in the incoming chunk.\n */\n function collectUsage(incoming: null | SDKTokenUsage | undefined): void {\n if (!incoming) return;\n const promptDetails = tokenUsage?.prompt_tokens_details;\n const incomingPromptDetails = incoming.prompt_tokens_details;\n const completionDetails = tokenUsage?.completion_tokens_details;\n const incomingCompletionDetails = incoming.completion_tokens_details;\n const cacheDetails = promptDetails?.cache_creation_token_details;\n const incomingCacheDetails = incomingPromptDetails?.cache_creation_token_details;\n tokenUsage = {\n ...tokenUsage,\n ...incoming,\n ...(promptDetails || incomingPromptDetails\n ? {\n prompt_tokens_details: {\n ...promptDetails,\n ...incomingPromptDetails,\n ...(cacheDetails || incomingCacheDetails\n ? {\n cache_creation_token_details: { ...cacheDetails, ...incomingCacheDetails },\n }\n : {}),\n },\n }\n : {}),\n ...(completionDetails || incomingCompletionDetails\n ? {\n completion_tokens_details: { ...completionDetails, ...incomingCompletionDetails },\n }\n : {}),\n };\n }\n\n /**\n * Emits tool-input-start and replays any buffered arguments as a delta.\n * @param tc - The in-progress tool call state.\n * @param controller - The transform stream controller to enqueue events into.\n */\n function emitToolInputStart(\n tc: ToolCallInProgress,\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n ): void {\n if (tc.didEmitInputStart || tc.id == null) return;\n tc.didEmitInputStart = true;\n controller.enqueue({\n id: tc.id,\n toolName: tc.toolName ?? \"\",\n type: \"tool-input-start\",\n });\n if (tc.arguments.length > 0) {\n controller.enqueue({\n delta: tc.arguments,\n id: tc.id,\n type: \"tool-input-delta\",\n });\n }\n }\n\n const iterator = safeIterate(sdkStream, options.abortSignal)[Symbol.asyncIterator]();\n let canceled = false;\n return new ReadableStream<Error | SDKStreamChunk>({\n async cancel() {\n canceled = true;\n // Abort transport before return(): an async iterator can be waiting on the next chunk.\n cancel();\n await iterator.return(undefined);\n },\n async pull(controller) {\n const { done, value } = await iterator.next();\n if (canceled) return;\n if (done) controller.close();\n else controller.enqueue(value);\n },\n }).pipeThrough(\n new TransformStream<Error | SDKStreamChunk, LanguageModelV3StreamPart>({\n flush(controller) {\n if (options.abortSignal?.aborted) {\n handleStreamError(\n createAbortError(options.abortSignal.reason),\n controller,\n convertToAISDKError,\n options,\n modelId,\n url,\n );\n return;\n }\n\n for (const state of reasoningBlocks ?? []) {\n controller.enqueue({\n id: state.id,\n providerMetadata: buildOrchestrationReasoningMetadata(state.block, providerName),\n type: \"reasoning-end\",\n });\n }\n\n const didEmitAnyToolCalls = finalizeToolCalls(\n controller,\n toolCallsInProgress,\n idGenerator,\n emitToolInputStart,\n );\n\n if (streamState.activeText && textBlockId) {\n controller.enqueue({ id: textBlockId, type: \"text-end\" });\n }\n\n const finalFinishReason = streamResponseGetFinishReason();\n if (finalFinishReason) {\n streamState.finishReason = mapFinishReason(finalFinishReason, providerFinishReason);\n } else if (didEmitAnyToolCalls) {\n streamState.finishReason = {\n raw: providerFinishReason,\n unified: \"tool-calls\",\n };\n }\n if (providerFinishReason !== undefined) {\n streamState.finishReason = { ...streamState.finishReason, raw: providerFinishReason };\n }\n\n // Use wire usage snapshots; SAP final aggregation can invent zero totals.\n streamState.usage = mapTokenUsage(tokenUsage);\n\n collectCitations(streamResponseGetCitations?.());\n if (citations) {\n for (const citation of citations.values()) {\n controller.enqueue({\n id: String(citation.ref_id ?? citation.url),\n sourceType: \"url\" as const,\n title: citation.title,\n type: \"source\",\n url: citation.url,\n });\n }\n }\n\n const streamIntermediateFailures = streamResponseGetIntermediateFailures?.();\n\n controller.enqueue({\n finishReason: streamState.finishReason,\n providerMetadata: {\n [providerName]: {\n ...buildAnthropicCacheMetadata(tokenUsage),\n finishReason: streamState.finishReason.raw ?? \"unknown\",\n finishReasonMapped: streamState.finishReason,\n ...(providerSpecificFields && { providerSpecificFields }),\n ...(streamIntermediateFailures?.length\n ? {\n intermediateFailures: sanitizeAsJSONArray(streamIntermediateFailures),\n }\n : {}),\n ...(resolvedRequestId ? { requestId: resolvedRequestId } : {}),\n responseId: resolvedResponseMetadata.id,\n version,\n },\n },\n type: \"finish\",\n usage: streamState.usage,\n });\n },\n\n start(controller) {\n controller.enqueue({\n type: \"stream-start\",\n warnings: [...warnings],\n });\n },\n\n transform(chunk, controller) {\n if (options.abortSignal?.aborted && !(chunk instanceof Error)) {\n chunk = createAbortError(options.abortSignal.reason);\n }\n if (chunk instanceof Error) {\n handleStreamError(chunk, controller, convertToAISDKError, options, modelId, url);\n return;\n }\n\n if (includeRawChunks) {\n controller.enqueue({\n rawValue: (chunk as { _data?: unknown })._data ?? chunk,\n type: \"raw\",\n });\n }\n\n const metadata = extractChunkMetadata(chunk);\n if (metadata.requestId) resolvedRequestId = metadata.requestId;\n const incomingMetadata = metadata.responseMetadata;\n const metadataChanged =\n (incomingMetadata.id !== undefined &&\n incomingMetadata.id !== resolvedResponseMetadata.id) ||\n (incomingMetadata.modelId !== undefined &&\n incomingMetadata.modelId !== resolvedResponseMetadata.modelId) ||\n (incomingMetadata.timestamp !== undefined &&\n incomingMetadata.timestamp.getTime() !== resolvedResponseMetadata.timestamp?.getTime());\n Object.assign(resolvedResponseMetadata, incomingMetadata);\n collectUsage(chunk.getTokenUsage?.());\n collectCitations(chunk.getCitations?.());\n const incomingProviderFields = parseProviderSpecificFields(\n extractProviderSpecificFields?.(chunk),\n );\n if (incomingProviderFields) {\n providerSpecificFields = { ...providerSpecificFields, ...incomingProviderFields };\n providerFinishReason =\n getProviderFinishReason(incomingProviderFields) ?? providerFinishReason;\n }\n if (!collectReasoningBlocks(extractReasoningBlocks?.(chunk), controller)) return;\n\n if (streamState.isFirstChunk || metadataChanged) {\n streamState.isFirstChunk = false;\n controller.enqueue({\n ...resolvedResponseMetadata,\n type: \"response-metadata\",\n });\n }\n\n const deltaToolCalls = chunk.getDeltaToolCalls();\n if (Array.isArray(deltaToolCalls) && deltaToolCalls.length > 0) {\n streamState.finishReason = {\n raw: undefined,\n unified: \"tool-calls\",\n };\n }\n\n const deltaContent = chunk.getDeltaContent();\n if (typeof deltaContent === \"string\" && deltaContent.length > 0) {\n textBlockId = handleTextDelta(\n deltaContent,\n controller,\n streamState,\n textBlockId,\n idGenerator,\n );\n }\n\n if (Array.isArray(deltaToolCalls) && deltaToolCalls.length > 0) {\n handleToolCallDeltas(deltaToolCalls, controller, toolCallsInProgress, emitToolInputStart);\n }\n\n const chunkFinishReason = chunk.getFinishReason();\n if (chunkFinishReason) {\n streamState.finishReason = mapFinishReason(chunkFinishReason, providerFinishReason);\n\n if (streamState.finishReason.unified === \"tool-calls\") {\n finalizeToolCalls(controller, toolCallsInProgress, idGenerator, emitToolInputStart);\n\n if (streamState.activeText && textBlockId) {\n controller.enqueue({ id: textBlockId, type: \"text-end\" });\n streamState.activeText = false;\n }\n }\n }\n },\n }),\n );\n}\n\n/**\n * Finalizes pending tool calls by emitting tool-input-end and tool-call events.\n * @param controller - The transform stream controller.\n * @param toolCallsInProgress - Map of in-progress tool calls.\n * @param idGenerator - ID generator for tool calls without IDs.\n * @param emitToolInputStart - Function to emit tool-input-start events.\n * @returns Whether any tool calls were finalized.\n * @internal\n */\nfunction finalizeToolCalls(\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n toolCallsInProgress: Map<number, ToolCallInProgress>,\n idGenerator: StreamIdGenerator,\n emitToolInputStart: (\n tc: ToolCallInProgress,\n ctrl: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n ) => void,\n): boolean {\n let didEmitAnyToolCalls = false;\n\n for (const tc of toolCallsInProgress.values()) {\n if (tc.didEmitCall) {\n continue;\n }\n\n tc.id ??= idGenerator.generateToolCallId();\n emitToolInputStart(tc, controller);\n\n didEmitAnyToolCalls = true;\n tc.didEmitCall = true;\n controller.enqueue({ id: tc.id, type: \"tool-input-end\" });\n controller.enqueue({\n input: tc.arguments,\n toolCallId: tc.id,\n toolName: tc.toolName ?? \"\",\n type: \"tool-call\",\n });\n }\n\n return didEmitAnyToolCalls;\n}\n\n/**\n * Handles a stream error by converting it and enqueuing an error event.\n * @param error - The error from the stream iteration.\n * @param controller - The transform stream controller.\n * @param convertToAISDKError - Error conversion function.\n * @param options - Language model call options for context.\n * @param modelId - Model identifier for error classification.\n * @param url - The request URL for error context.\n * @internal\n */\nfunction handleStreamError(\n error: Error,\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n convertToAISDKError: StreamTransformerConfig[\"convertToAISDKError\"],\n options: LanguageModelV3CallOptions,\n modelId: string,\n url: string,\n): void {\n const aiError = convertToAISDKError(error, {\n modelId,\n modelType: \"languageModel\",\n operation: \"doStream\",\n requestBody: createAISDKRequestBodySummary(options),\n url,\n });\n controller.enqueue({\n error: aiError instanceof Error ? aiError : new Error(String(aiError)),\n type: \"error\",\n });\n controller.terminate();\n}\n\n/**\n * Handles a text delta by managing text block lifecycle.\n * @param deltaContent - The text delta content.\n * @param controller - The transform stream controller.\n * @param streamState - The current stream state.\n * @param currentTextBlockId - The current text block ID (or null).\n * @param idGenerator - ID generator for new text blocks.\n * @returns The current text block ID (may be newly created).\n * @internal\n */\nfunction handleTextDelta(\n deltaContent: string,\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n streamState: StreamState,\n currentTextBlockId: null | string,\n idGenerator: StreamIdGenerator,\n): string {\n let textBlockId = currentTextBlockId;\n if (!streamState.activeText) {\n textBlockId = idGenerator.generateTextBlockId();\n controller.enqueue({ id: textBlockId, type: \"text-start\" });\n streamState.activeText = true;\n }\n if (textBlockId) {\n controller.enqueue({\n delta: deltaContent,\n id: textBlockId,\n type: \"text-delta\",\n });\n return textBlockId;\n }\n return currentTextBlockId ?? idGenerator.generateTextBlockId();\n}\n\n/**\n * Handles tool call delta chunks by assembling tool calls progressively.\n * @param deltaToolCalls - The tool call delta chunks from the stream.\n * @param controller - The transform stream controller.\n * @param toolCallsInProgress - Map of in-progress tool calls by index.\n * @param emitToolInputStart - Function to emit tool-input-start events.\n * @internal\n */\nfunction handleToolCallDeltas(\n deltaToolCalls: SDKDeltaToolCall[],\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n toolCallsInProgress: Map<number, ToolCallInProgress>,\n emitToolInputStart: (\n tc: ToolCallInProgress,\n ctrl: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n ) => void,\n): void {\n for (const toolCallChunk of deltaToolCalls) {\n const index = toolCallChunk.index;\n if (typeof index !== \"number\" || !Number.isFinite(index)) {\n continue;\n }\n\n if (!toolCallsInProgress.has(index)) {\n toolCallsInProgress.set(index, {\n arguments: \"\",\n didEmitCall: false,\n didEmitInputStart: false,\n id:\n typeof toolCallChunk.id === \"string\" && toolCallChunk.id.length > 0\n ? toolCallChunk.id\n : undefined,\n toolName: toolCallChunk.function?.name,\n });\n }\n\n const tc = toolCallsInProgress.get(index);\n if (!tc) continue;\n\n if (\n typeof toolCallChunk.id === \"string\" &&\n toolCallChunk.id.length > 0 &&\n tc.id === undefined\n ) {\n tc.id = toolCallChunk.id;\n }\n\n const nextToolName = toolCallChunk.function?.name;\n if (typeof nextToolName === \"string\" && nextToolName.length > 0) {\n tc.toolName = nextToolName;\n }\n\n if (!tc.didEmitInputStart && tc.toolName != null && tc.id != null) {\n emitToolInputStart(tc, controller);\n }\n\n const argumentsDelta = toolCallChunk.function?.arguments;\n if (typeof argumentsDelta === \"string\" && argumentsDelta.length > 0) {\n tc.arguments += argumentsDelta;\n\n if (tc.didEmitInputStart && tc.id != null) {\n controller.enqueue({\n delta: argumentsDelta,\n id: tc.id,\n type: \"tool-input-delta\",\n });\n }\n }\n }\n}\n\n/**\n * Wraps an async iterable to catch iteration errors and yield them as values.\n *\n * After the first error, the transformer emits an error event and terminates without\n * a successful finish event.\n * @param iterable - The async iterable to wrap.\n * @param abortSignal - Caller cancellation, which the SAP iterator can otherwise swallow.\n * @yields {Error | T} Original values or Error instances for caught exceptions.\n * @internal\n */\nasync function* safeIterate<T>(\n iterable: AsyncIterable<T>,\n abortSignal: AbortSignal | undefined,\n): AsyncGenerator<Error | T, void> {\n try {\n for await (const chunk of iterable) {\n abortSignal?.throwIfAborted();\n yield chunk;\n }\n abortSignal?.throwIfAborted();\n } catch (error) {\n if (abortSignal?.aborted) {\n yield createAbortError(abortSignal.reason);\n } else {\n yield error instanceof Error ? error : new Error(String(error));\n }\n }\n}\n","/** Base class for language model strategies using the Template Method pattern. */\nimport type {\n LanguageModelV3CallOptions,\n LanguageModelV3GenerateResult,\n LanguageModelV3ResponseMetadata,\n LanguageModelV3StreamResult,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport type { CustomRequestConfig } from \"@sap-ai-sdk/core\";\nimport type { ChatMessage } from \"@sap-ai-sdk/orchestration\";\n\nimport type { ParsePartProviderOptions } from \"./sap-ai-provider-options.js\";\nimport type { SAPAIModelSettings } from \"./sap-ai-settings.js\";\nimport type { LanguageModelAPIStrategy, LanguageModelStrategyConfig } from \"./sap-ai-strategy.js\";\n\nimport { throwIfAborted, waitWithAbort } from \"./abort-utils.js\";\nimport { convertToSAPMessages } from \"./convert-to-sap-messages.js\";\nimport { convertToAISDKError, normalizeHeaders } from \"./sap-ai-error.js\";\nimport { getProviderName } from \"./sap-ai-provider-options.js\";\nimport {\n buildGenerateResult,\n buildModelParams,\n createAISDKRequestBodySummary,\n extractCompletionMetadata,\n extractResponseMetadata,\n mapToolChoice,\n mergeRequestConfig,\n type ParamMapping,\n type SAPToolChoice,\n type SDKCitation,\n type SDKResponse,\n type SDKStreamChunk,\n} from \"./strategy-utils.js\";\nimport { createStreamTransformer, StreamIdGenerator } from \"./stream-transformer.js\";\nimport { VERSION } from \"./version.js\";\n\n/**\n * Result of building common parts for a language model request.\n * @template TMessages - The message array type (e.g., `ChatMessage[]`, `AzureOpenAiChatCompletionRequestMessage[]`)\n * @template TToolChoice - The tool choice type (e.g., `SAPToolChoice`)\n * @internal\n */\nexport interface CommonBuildResult<TMessages extends unknown[] = unknown[], TToolChoice = unknown> {\n readonly messages: TMessages;\n readonly modelParams: Record<string, unknown>;\n readonly providerName: string;\n readonly resolvedState?: unknown;\n readonly sapOptions: Record<string, unknown> | undefined;\n readonly toolChoice: TToolChoice;\n readonly warnings: SharedV3Warning[];\n}\n\n/**\n * Stream response shape returned by executeStreamCall.\n * @internal\n */\nexport interface StreamCallResponse {\n readonly cancel: () => void;\n readonly extractProviderSpecificFields?: (chunk: SDKStreamChunk) => unknown;\n readonly extractReasoningBlocks?: (chunk: SDKStreamChunk) => unknown;\n readonly getCitations?: () => SDKCitation[] | undefined;\n readonly getFinishReason: () => null | string | undefined;\n readonly getIntermediateFailures?: () => undefined | unknown[];\n /** SAP-pipeline request id resolved by `extractResponseMetadata`. */\n readonly requestId?: string;\n readonly responseHeaders?: Record<string, string>;\n readonly responseMetadata?: LanguageModelV3ResponseMetadata;\n readonly stream: AsyncIterable<SDKStreamChunk>;\n}\n\n/**\n * Abstract base class for language model strategies using the Template Method pattern.\n * @template TClient - The SDK client type (e.g., AzureOpenAiChatClient, OrchestrationClient).\n * @template TRequest - The API request type (e.g., AzureOpenAiChatCompletionParameters).\n * @template TSettings - The model settings type extending SAPAIModelSettings.\n * @internal\n */\nexport abstract class BaseLanguageModelStrategy<\n TClient,\n TRequest,\n TSettings extends SAPAIModelSettings = SAPAIModelSettings,\n> implements LanguageModelAPIStrategy<TSettings> {\n /**\n * Common parameter mappings for language model APIs.\n * @internal\n */\n static readonly COMMON_PARAM_MAPPINGS: readonly ParamMapping[] = [\n { camelCaseKey: \"maxTokens\", optionKey: \"maxOutputTokens\", outputKey: \"max_completion_tokens\" },\n { camelCaseKey: \"temperature\", optionKey: \"temperature\", outputKey: \"temperature\" },\n { camelCaseKey: \"topP\", optionKey: \"topP\", outputKey: \"top_p\" },\n {\n camelCaseKey: \"frequencyPenalty\",\n optionKey: \"frequencyPenalty\",\n outputKey: \"frequency_penalty\",\n },\n {\n camelCaseKey: \"presencePenalty\",\n optionKey: \"presencePenalty\",\n outputKey: \"presence_penalty\",\n },\n { camelCaseKey: \"seed\", optionKey: \"seed\", outputKey: \"seed\" },\n { optionKey: \"reasoning\", outputKey: \"reasoning_effort\" },\n { camelCaseKey: \"parallel_tool_calls\", outputKey: \"parallel_tool_calls\" },\n ] as const;\n\n async doGenerate(\n config: LanguageModelStrategyConfig,\n settings: TSettings,\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3GenerateResult> {\n try {\n throwIfAborted(options.abortSignal);\n const commonParts = this.buildCommonParts(config, settings, options);\n const { request, warnings } = this.buildRequest(config, settings, options, commonParts);\n\n const client = this.createClient(config, settings, commonParts);\n\n const response = await waitWithAbort(\n this.executeApiCall(\n client,\n request,\n mergeRequestConfig(config.requestConfig, options.abortSignal, options.headers),\n ),\n options.abortSignal,\n );\n throwIfAborted(options.abortSignal);\n\n return buildGenerateResult({\n providerName: commonParts.providerName,\n requestBody: request,\n requestId: response.requestId,\n response,\n responseHeaders: normalizeHeaders(response.rawResponse.headers),\n version: VERSION,\n warnings: [...commonParts.warnings, ...warnings],\n });\n } catch (error) {\n throw convertToAISDKError(error, {\n modelId: config.modelId,\n modelType: \"languageModel\",\n operation: \"doGenerate\",\n requestBody: createAISDKRequestBodySummary(options),\n url: this.getUrl(),\n });\n }\n }\n\n async doStream(\n config: LanguageModelStrategyConfig,\n settings: TSettings,\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n try {\n throwIfAborted(options.abortSignal);\n const commonParts = this.buildCommonParts(config, settings, options);\n const { request, warnings } = this.buildRequest(config, settings, options, commonParts);\n\n const client = this.createClient(config, settings, commonParts);\n\n const streamResponse = await this.executeStreamCall(\n client,\n request,\n options.abortSignal ?? undefined,\n settings,\n mergeRequestConfig(config.requestConfig, undefined, options.headers),\n commonParts,\n );\n if (options.abortSignal?.aborted) {\n try {\n streamResponse.cancel();\n } finally {\n throwIfAborted(options.abortSignal);\n }\n }\n\n const idGenerator = new StreamIdGenerator();\n\n const streamWarnings = this.collectStreamWarnings(settings, commonParts.sapOptions);\n\n const transformedStream = createStreamTransformer({\n cancel: streamResponse.cancel,\n convertToAISDKError,\n extractChunkMetadata: (chunk) => this.extractMetadata(chunk),\n extractProviderSpecificFields: streamResponse.extractProviderSpecificFields,\n extractReasoningBlocks: streamResponse.extractReasoningBlocks,\n idGenerator,\n includeRawChunks: options.includeRawChunks ?? false,\n modelId: config.modelId,\n options,\n providerName: commonParts.providerName,\n requestId: streamResponse.requestId,\n responseMetadata: {\n ...streamResponse.responseMetadata,\n id: streamResponse.responseMetadata?.id ?? idGenerator.generateResponseId(),\n },\n sdkStream: streamResponse.stream,\n streamResponseGetCitations: streamResponse.getCitations,\n streamResponseGetFinishReason: streamResponse.getFinishReason,\n streamResponseGetIntermediateFailures: streamResponse.getIntermediateFailures,\n url: this.getUrl(),\n version: VERSION,\n warnings: [...commonParts.warnings, ...warnings, ...streamWarnings],\n });\n\n return {\n request: {\n body: request,\n },\n response: {\n headers: streamResponse.responseHeaders,\n },\n stream: transformedStream,\n };\n } catch (error) {\n throw convertToAISDKError(error, {\n modelId: config.modelId,\n modelType: \"languageModel\",\n operation: \"doStream\",\n requestBody: createAISDKRequestBodySummary(options),\n url: this.getUrl(),\n });\n }\n }\n\n /**\n * Builds common parts shared between doGenerate and doStream.\n * @param config - Strategy configuration.\n * @param settings - Model settings.\n * @param options - AI SDK call options.\n * @returns Common build result with typed messages and tool choice.\n * @internal\n */\n protected buildCommonParts(\n config: LanguageModelStrategyConfig,\n settings: TSettings,\n options: LanguageModelV3CallOptions,\n ): CommonBuildResult<ChatMessage[], SAPToolChoice | undefined> {\n const providerName = getProviderName(config.provider);\n\n const sapOptions = config.parsedProviderOptions;\n\n const warnings: SharedV3Warning[] = [];\n\n const resolvedState = this.resolveAdditionalState(\n config,\n settings,\n sapOptions,\n options,\n warnings,\n );\n\n const messages = convertToSAPMessages(options.prompt, {\n escapeTemplatePlaceholders: this.getEscapeTemplatePlaceholders(sapOptions, settings),\n includeReasoning: this.getIncludeReasoning(sapOptions, settings),\n nativeReasoningProviderName: this.getNativeReasoningProviderName(providerName),\n parsePartProviderOptions: this.getPartProviderOptionsParser(),\n warnings,\n });\n\n const { modelParams, warnings: paramWarnings } = buildModelParams({\n options,\n paramMappings: this.getParamMappings(),\n providerModelParams: sapOptions?.modelParams,\n settingsModelParams: settings.modelParams,\n });\n warnings.push(...paramWarnings);\n\n const toolChoice = mapToolChoice(options.toolChoice);\n\n return {\n messages,\n modelParams,\n providerName,\n resolvedState,\n sapOptions,\n toolChoice,\n warnings,\n };\n }\n\n /**\n * Builds the API-specific request body.\n * @param config - Strategy configuration.\n * @param settings - Model settings.\n * @param options - AI SDK call options.\n * @param commonParts - Common build result from base class.\n * @returns Request body and accumulated warnings.\n * @internal\n */\n protected abstract buildRequest(\n config: LanguageModelStrategyConfig,\n settings: TSettings,\n options: LanguageModelV3CallOptions,\n commonParts: CommonBuildResult<ChatMessage[], SAPToolChoice | undefined>,\n ): { readonly request: TRequest; readonly warnings: SharedV3Warning[] };\n\n /**\n * Collects stream-specific warnings.\n * Override in subclasses to add API-specific streaming warnings.\n * @param _settings - Model settings (unused in base implementation).\n * @param _sapOptions - Provider options (unused in base implementation).\n * @returns Array of warnings for streaming operations.\n * @internal\n */\n protected collectStreamWarnings(\n _settings: TSettings,\n _sapOptions?: Record<string, unknown>,\n ): SharedV3Warning[] {\n return [];\n }\n\n /**\n * Creates the appropriate SDK client for this API.\n * @param config - Strategy configuration.\n * @param settings - Model settings.\n * @param commonParts - Common build result (messages, options, etc.).\n * @returns SDK client instance.\n * @internal\n */\n protected abstract createClient(\n config: LanguageModelStrategyConfig,\n settings: TSettings,\n commonParts: CommonBuildResult<ChatMessage[], SAPToolChoice | undefined>,\n ): TClient;\n\n /**\n * Executes the non-streaming API call.\n * @param client - SDK client instance.\n * @param request - Request body.\n * @param requestConfig - Optional custom request configuration (e.g. custom headers).\n * @returns SDK response.\n * @internal\n */\n protected abstract executeApiCall(\n client: TClient,\n request: TRequest,\n requestConfig: CustomRequestConfig | undefined,\n ): Promise<SDKResponse>;\n\n /**\n * Executes the streaming API call.\n * @param client - SDK client instance.\n * @param request - Request body.\n * @param abortSignal - Optional abort signal.\n * @param settings - Model settings for API-specific stream options.\n * @param requestConfig - Optional custom request configuration (e.g. custom headers).\n * @param commonParts - Common build result (resolved state, provider options, etc.).\n * @returns Stream response with accessors.\n * @internal\n */\n protected abstract executeStreamCall(\n client: TClient,\n request: TRequest,\n abortSignal: AbortSignal | undefined,\n settings: TSettings,\n requestConfig: CustomRequestConfig | undefined,\n commonParts: CommonBuildResult<ChatMessage[], SAPToolChoice | undefined>,\n ): Promise<StreamCallResponse>;\n\n /**\n * Resolves completion metadata, request ID, and normalised headers from an SDK response.\n * @param response - Raw SDK response or stream response.\n * @returns Combined metadata fragment.\n * @internal\n */\n protected extractMetadata(response: unknown): {\n requestId?: string;\n responseHeaders?: Record<string, string>;\n responseMetadata: LanguageModelV3ResponseMetadata;\n } {\n const responseMetadata = extractCompletionMetadata(\n response as { _data?: unknown; getRequestId?: () => string | undefined },\n this.getCompletionDataPath(),\n );\n const { headers, requestId } = extractResponseMetadata(response, \"rawResponse\");\n return { requestId, responseHeaders: headers, responseMetadata };\n }\n\n /**\n * Returns the API-specific path to the completion object in an SDK payload.\n * @returns Completion path (`[\"final_result\"]` for orchestration, `[]` for Foundation Models).\n * @internal\n */\n protected abstract getCompletionDataPath(): readonly string[];\n\n /**\n * Returns whether to escape template placeholders for this API.\n * @param _sapOptions - Parsed provider options (unused in base implementation).\n * @param _settings - Model settings (unused in base implementation).\n * @returns false by default; the Orchestration override defaults to true unless disabled.\n * @internal\n */\n protected getEscapeTemplatePlaceholders(\n _sapOptions: Record<string, unknown> | undefined,\n _settings: TSettings,\n ): boolean {\n return false;\n }\n\n /**\n * Returns whether assistant reasoning in the input history is forwarded as text.\n * @param sapOptions - Parsed provider options.\n * @param settings - Model settings.\n * @returns Whether to forward input reasoning (checks sapOptions then settings, defaults to false).\n * @internal\n */\n protected getIncludeReasoning(\n sapOptions: Record<string, unknown> | undefined,\n settings: TSettings,\n ): boolean {\n return (\n (sapOptions?.includeReasoning as boolean | undefined) ??\n (\"includeReasoning\" in settings ? settings.includeReasoning : false) ??\n false\n );\n }\n\n /**\n * Enables native reasoning history only for strategies supporting the Orchestration wire format.\n * @param _providerName - Configured provider namespace.\n * @returns The native reasoning namespace, or undefined for legacy text-only history.\n * @internal\n */\n protected getNativeReasoningProviderName(_providerName: string): string | undefined {\n return undefined;\n }\n\n /**\n * Returns the parameter mappings specific to this API strategy.\n * @returns Array of parameter mappings.\n * @internal\n */\n protected abstract getParamMappings(): readonly ParamMapping[];\n\n /**\n * Returns a parser for per-message-part `providerOptions['sap-ai']`.\n *\n * Default returns `undefined`; strategies honouring part-level directives\n * (e.g. Anthropic `cacheControl` on orchestration) override to return a parser.\n * @returns Parser callback, or undefined to disable per-part plumbing.\n * @internal\n */\n protected getPartProviderOptionsParser(): ParsePartProviderOptions | undefined {\n return undefined;\n }\n\n /**\n * Returns the URL identifier for this API (used in error messages).\n * @returns URL string identifier.\n * @internal\n */\n protected abstract getUrl(): string;\n\n /**\n * Resolves API-specific extra state shared between doGenerate and doStream\n * (e.g. orchestration `configRef` / `promptTemplateRef` / `tools`). Override\n * to add API-specific deprecation checks or pre-resolve auxiliary inputs.\n * Pushed warnings flow into the shared sink.\n * @param _config - Strategy configuration.\n * @param _settings - Model settings.\n * @param _sapOptions - Parsed provider options, or `undefined`.\n * @param _options - AI SDK call options.\n * @param _warnings - Shared warnings sink for the current call.\n * @returns Strategy-specific resolved state, or `undefined` (default).\n * @internal\n */\n protected resolveAdditionalState(\n _config: LanguageModelStrategyConfig,\n _settings: TSettings,\n _sapOptions: Record<string, unknown> | undefined,\n _options: LanguageModelV3CallOptions,\n _warnings: SharedV3Warning[],\n ): unknown {\n return undefined;\n }\n}\n"],"mappings":"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","names":["convertToAISDKError"]}
@@ -1,14 +1,15 @@
1
1
  import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
2
  import {
3
3
  BaseEmbeddingModelStrategy
4
- } from "./chunk-U6WJSLR7.js";
4
+ } from "./chunk-QQQYMQPU.js";
5
5
  import {
6
6
  buildModelDeployment,
7
7
  extractResponseMetadata,
8
8
  hasKeys,
9
9
  normalizeEmbedding
10
- } from "./chunk-LEME2MFD.js";
11
- import "./chunk-77JSAAPE.js";
10
+ } from "./chunk-DLGBK3C3.js";
11
+ import "./chunk-BHA5MIN6.js";
12
+ import "./chunk-QFMHNGLB.js";
12
13
 
13
14
  // src/foundation-models-embedding-model-strategy.ts
14
15
  var FoundationModelsEmbeddingModelStrategy = class extends BaseEmbeddingModelStrategy {
@@ -55,4 +56,4 @@ var FoundationModelsEmbeddingModelStrategy = class extends BaseEmbeddingModelStr
55
56
  export {
56
57
  FoundationModelsEmbeddingModelStrategy
57
58
  };
58
- //# sourceMappingURL=foundation-models-embedding-model-strategy-A3WDDAYK.js.map
59
+ //# sourceMappingURL=foundation-models-embedding-model-strategy-3WAKJXBY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/foundation-models-embedding-model-strategy.ts"],"sourcesContent":["/** Foundation Models embedding model strategy using `@sap-ai-sdk/foundation-models`. */\nimport type { EmbeddingModelV3Embedding } from \"@ai-sdk/provider\";\nimport type { CustomRequestConfig } from \"@sap-ai-sdk/core\";\nimport type {\n AzureOpenAiEmbeddingClient,\n AzureOpenAiEmbeddingParameters,\n AzureOpenAiEmbeddingResponse,\n} from \"@sap-ai-sdk/foundation-models\";\n\nimport type { SAPAIEmbeddingSettings } from \"./sap-ai-settings.js\";\nimport type { EmbeddingModelStrategyConfig } from \"./sap-ai-strategy.js\";\nimport type { EmbeddingProviderOptions, ResponseMetadata } from \"./strategy-utils.js\";\n\nimport { BaseEmbeddingModelStrategy } from \"./base-embedding-model-strategy.js\";\nimport {\n buildModelDeployment,\n extractResponseMetadata,\n hasKeys,\n normalizeEmbedding,\n} from \"./strategy-utils.js\";\n\n/**\n * Client with pre-merged params for thread-safe concurrent requests.\n * @internal\n */\ninterface FMEmbeddingClientWithContext {\n client: AzureOpenAiEmbeddingClient;\n mergedParams: Record<string, unknown> | undefined;\n}\n\n/** @internal */\ntype FoundationModelsEmbeddingClientClass = typeof AzureOpenAiEmbeddingClient;\n\n/**\n * Embedding model strategy for the Foundation Models API.\n *\n * Provides direct access to Azure OpenAI embedding models.\n * @internal\n */\nexport class FoundationModelsEmbeddingModelStrategy extends BaseEmbeddingModelStrategy<\n FMEmbeddingClientWithContext,\n AzureOpenAiEmbeddingResponse\n> {\n private readonly ClientClass: FoundationModelsEmbeddingClientClass;\n\n constructor(ClientClass: FoundationModelsEmbeddingClientClass) {\n super();\n this.ClientClass = ClientClass;\n }\n\n protected createClient(\n config: EmbeddingModelStrategyConfig,\n settings: SAPAIEmbeddingSettings,\n embeddingOptions: EmbeddingProviderOptions | undefined,\n ): FMEmbeddingClientWithContext {\n const mergedParams = this.mergeModelParams(settings, embeddingOptions);\n\n return {\n client: new this.ClientClass(\n buildModelDeployment(config, settings.modelVersion),\n config.destination,\n ),\n mergedParams: hasKeys(mergedParams) ? mergedParams : undefined,\n };\n }\n\n protected async executeCall(\n clientWithContext: FMEmbeddingClientWithContext,\n values: string[],\n _embeddingType: unknown,\n requestConfig: CustomRequestConfig | undefined,\n ): Promise<AzureOpenAiEmbeddingResponse> {\n const request = this.buildRequest(values, clientWithContext.mergedParams);\n return clientWithContext.client.run(request, requestConfig);\n }\n\n protected extractEmbeddings(response: AzureOpenAiEmbeddingResponse): EmbeddingModelV3Embedding[] {\n // SDK types include `& Record<string, any>` which requires explicit extraction\n const embeddingData = response._data.data;\n const sortedEmbeddings = embeddingData.slice().sort((a, b) => a.index - b.index);\n return sortedEmbeddings.map((item) => normalizeEmbedding(item.embedding as number[]));\n }\n\n protected override extractResponseMetadata(\n response: AzureOpenAiEmbeddingResponse,\n ): ResponseMetadata {\n return extractResponseMetadata(response, \"rawResponse\");\n }\n\n protected extractTokenCount(response: AzureOpenAiEmbeddingResponse): number {\n return response._data.usage.total_tokens;\n }\n\n protected getUrl(): string {\n return \"sap-ai:foundation-models/embeddings\";\n }\n\n private buildRequest(\n values: string[],\n mergedParams: Record<string, unknown> | undefined,\n ): AzureOpenAiEmbeddingParameters {\n return {\n ...(mergedParams ?? {}),\n input: values,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAuCO,IAAM,yCAAN,cAAqD,2BAG1D;AAAA,EACiB;AAAA,EAEjB,YAAY,aAAmD;AAC7D,UAAM;AACN,SAAK,cAAc;AAAA,EACrB;AAAA,EAEU,aACR,QACA,UACA,kBAC8B;AAC9B,UAAM,eAAe,KAAK,iBAAiB,UAAU,gBAAgB;AAErE,WAAO;AAAA,MACL,QAAQ,IAAI,KAAK;AAAA,QACf,qBAAqB,QAAQ,SAAS,YAAY;AAAA,QAClD,OAAO;AAAA,MACT;AAAA,MACA,cAAc,QAAQ,YAAY,IAAI,eAAe;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,MAAgB,YACd,mBACA,QACA,gBACA,eACuC;AACvC,UAAM,UAAU,KAAK,aAAa,QAAQ,kBAAkB,YAAY;AACxE,WAAO,kBAAkB,OAAO,IAAI,SAAS,aAAa;AAAA,EAC5D;AAAA,EAEU,kBAAkB,UAAqE;AAE/F,UAAM,gBAAgB,SAAS,MAAM;AACrC,UAAM,mBAAmB,cAAc,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC/E,WAAO,iBAAiB,IAAI,CAAC,SAAS,mBAAmB,KAAK,SAAqB,CAAC;AAAA,EACtF;AAAA,EAEmB,wBACjB,UACkB;AAClB,WAAO,wBAAwB,UAAU,aAAa;AAAA,EACxD;AAAA,EAEU,kBAAkB,UAAgD;AAC1E,WAAO,SAAS,MAAM,MAAM;AAAA,EAC9B;AAAA,EAEU,SAAiB;AACzB,WAAO;AAAA,EACT;AAAA,EAEQ,aACN,QACA,cACgC;AAChC,WAAO;AAAA,MACL,GAAI,gBAAgB,CAAC;AAAA,MACrB,OAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/foundation-models-embedding-model-strategy.ts"],"sourcesContent":["/** Foundation Models embedding model strategy using `@sap-ai-sdk/foundation-models`. */\nimport type { EmbeddingModelV3Embedding } from \"@ai-sdk/provider\";\nimport type { CustomRequestConfig } from \"@sap-ai-sdk/core\";\nimport type {\n AzureOpenAiEmbeddingClient,\n AzureOpenAiEmbeddingParameters,\n AzureOpenAiEmbeddingResponse,\n} from \"@sap-ai-sdk/foundation-models\";\n\nimport type { SAPAIEmbeddingSettings } from \"./sap-ai-settings.js\";\nimport type { EmbeddingModelStrategyConfig } from \"./sap-ai-strategy.js\";\nimport type { EmbeddingProviderOptions, ResponseMetadata } from \"./strategy-utils.js\";\n\nimport { BaseEmbeddingModelStrategy } from \"./base-embedding-model-strategy.js\";\nimport {\n buildModelDeployment,\n extractResponseMetadata,\n hasKeys,\n normalizeEmbedding,\n} from \"./strategy-utils.js\";\n\n/**\n * Client with pre-merged params for thread-safe concurrent requests.\n * @internal\n */\ninterface FMEmbeddingClientWithContext {\n client: AzureOpenAiEmbeddingClient;\n mergedParams: Record<string, unknown> | undefined;\n}\n\n/** @internal */\ntype FoundationModelsEmbeddingClientClass = typeof AzureOpenAiEmbeddingClient;\n\n/**\n * Embedding model strategy for the Foundation Models API.\n *\n * Provides direct access to Azure OpenAI embedding models.\n * @internal\n */\nexport class FoundationModelsEmbeddingModelStrategy extends BaseEmbeddingModelStrategy<\n FMEmbeddingClientWithContext,\n AzureOpenAiEmbeddingResponse\n> {\n private readonly ClientClass: FoundationModelsEmbeddingClientClass;\n\n constructor(ClientClass: FoundationModelsEmbeddingClientClass) {\n super();\n this.ClientClass = ClientClass;\n }\n\n protected createClient(\n config: EmbeddingModelStrategyConfig,\n settings: SAPAIEmbeddingSettings,\n embeddingOptions: EmbeddingProviderOptions | undefined,\n ): FMEmbeddingClientWithContext {\n const mergedParams = this.mergeModelParams(settings, embeddingOptions);\n\n return {\n client: new this.ClientClass(\n buildModelDeployment(config, settings.modelVersion),\n config.destination,\n ),\n mergedParams: hasKeys(mergedParams) ? mergedParams : undefined,\n };\n }\n\n protected async executeCall(\n clientWithContext: FMEmbeddingClientWithContext,\n values: string[],\n _embeddingType: unknown,\n requestConfig: CustomRequestConfig | undefined,\n ): Promise<AzureOpenAiEmbeddingResponse> {\n const request = this.buildRequest(values, clientWithContext.mergedParams);\n return clientWithContext.client.run(request, requestConfig);\n }\n\n protected extractEmbeddings(response: AzureOpenAiEmbeddingResponse): EmbeddingModelV3Embedding[] {\n // SDK types include `& Record<string, any>` which requires explicit extraction\n const embeddingData = response._data.data;\n const sortedEmbeddings = embeddingData.slice().sort((a, b) => a.index - b.index);\n return sortedEmbeddings.map((item) => normalizeEmbedding(item.embedding as number[]));\n }\n\n protected override extractResponseMetadata(\n response: AzureOpenAiEmbeddingResponse,\n ): ResponseMetadata {\n return extractResponseMetadata(response, \"rawResponse\");\n }\n\n protected extractTokenCount(response: AzureOpenAiEmbeddingResponse): number {\n return response._data.usage.total_tokens;\n }\n\n protected getUrl(): string {\n return \"sap-ai:foundation-models/embeddings\";\n }\n\n private buildRequest(\n values: string[],\n mergedParams: Record<string, unknown> | undefined,\n ): AzureOpenAiEmbeddingParameters {\n return {\n ...(mergedParams ?? {}),\n input: values,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAuCO,IAAM,yCAAN,cAAqD,2BAG1D;AAAA,EACiB;AAAA,EAEjB,YAAY,aAAmD;AAC7D,UAAM;AACN,SAAK,cAAc;AAAA,EACrB;AAAA,EAEU,aACR,QACA,UACA,kBAC8B;AAC9B,UAAM,eAAe,KAAK,iBAAiB,UAAU,gBAAgB;AAErE,WAAO;AAAA,MACL,QAAQ,IAAI,KAAK;AAAA,QACf,qBAAqB,QAAQ,SAAS,YAAY;AAAA,QAClD,OAAO;AAAA,MACT;AAAA,MACA,cAAc,QAAQ,YAAY,IAAI,eAAe;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,MAAgB,YACd,mBACA,QACA,gBACA,eACuC;AACvC,UAAM,UAAU,KAAK,aAAa,QAAQ,kBAAkB,YAAY;AACxE,WAAO,kBAAkB,OAAO,IAAI,SAAS,aAAa;AAAA,EAC5D;AAAA,EAEU,kBAAkB,UAAqE;AAE/F,UAAM,gBAAgB,SAAS,MAAM;AACrC,UAAM,mBAAmB,cAAc,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC/E,WAAO,iBAAiB,IAAI,CAAC,SAAS,mBAAmB,KAAK,SAAqB,CAAC;AAAA,EACtF;AAAA,EAEmB,wBACjB,UACkB;AAClB,WAAO,wBAAwB,UAAU,aAAa;AAAA,EACxD;AAAA,EAEU,kBAAkB,UAAgD;AAC1E,WAAO,SAAS,MAAM,MAAM;AAAA,EAC9B;AAAA,EAEU,SAAiB;AACzB,WAAO;AAAA,EACT;AAAA,EAEQ,aACN,QACA,cACgC;AAChC,WAAO;AAAA,MACL,GAAI,gBAAgB,CAAC;AAAA,MACrB,OAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -1,14 +1,20 @@
1
1
  import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
2
  import {
3
3
  BaseLanguageModelStrategy
4
- } from "./chunk-QZOZ3PZT.js";
5
- import "./chunk-YP3AADWD.js";
4
+ } from "./chunk-ZOBD7PXJ.js";
5
+ import {
6
+ disposeSapStream,
7
+ executeSapStream,
8
+ withSapStreamCleanup
9
+ } from "./chunk-4ILJD6PI.js";
10
+ import "./chunk-FKHOJ3ZC.js";
6
11
  import {
7
12
  buildModelDeployment,
8
13
  convertResponseFormat,
9
14
  convertToolsToSAPFormat
10
- } from "./chunk-LEME2MFD.js";
11
- import "./chunk-77JSAAPE.js";
15
+ } from "./chunk-DLGBK3C3.js";
16
+ import "./chunk-BHA5MIN6.js";
17
+ import "./chunk-QFMHNGLB.js";
12
18
 
13
19
  // src/foundation-models-language-model-strategy.ts
14
20
  var FOUNDATION_MODELS_PARAM_MAPPINGS = [
@@ -67,18 +73,25 @@ var FoundationModelsLanguageModelStrategy = class extends BaseLanguageModelStrat
67
73
  responseMetadata
68
74
  };
69
75
  }
70
- async executeStreamCall(client, request, abortSignal, _settings, requestConfig) {
71
- const streamResponse = await client.stream(request, abortSignal, requestConfig);
76
+ async executeStreamCall(client, request, abortSignal, _settings, requestConfig, _commonParts) {
77
+ const streamResponse = await executeSapStream(
78
+ (streamRequestConfig) => client.stream(request, abortSignal, streamRequestConfig),
79
+ abortSignal,
80
+ requestConfig
81
+ );
72
82
  const { requestId, responseHeaders, responseMetadata } = this.extractMetadata(streamResponse);
73
83
  return {
74
84
  cancel: () => {
75
- streamResponse.stream.controller.abort();
85
+ disposeSapStream(streamResponse);
76
86
  },
77
87
  getFinishReason: () => streamResponse.getFinishReason(),
78
88
  requestId,
79
89
  responseHeaders,
80
90
  responseMetadata,
81
- stream: streamResponse.stream
91
+ stream: withSapStreamCleanup(
92
+ streamResponse,
93
+ streamResponse.stream
94
+ )
82
95
  };
83
96
  }
84
97
  getCompletionDataPath() {
@@ -94,4 +107,4 @@ var FoundationModelsLanguageModelStrategy = class extends BaseLanguageModelStrat
94
107
  export {
95
108
  FoundationModelsLanguageModelStrategy
96
109
  };
97
- //# sourceMappingURL=foundation-models-language-model-strategy-6U6KK6KH.js.map
110
+ //# sourceMappingURL=foundation-models-language-model-strategy-PJ26VXEA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/foundation-models-language-model-strategy.ts"],"sourcesContent":["/** Foundation Models language model strategy using `@sap-ai-sdk/foundation-models`. */\nimport type { LanguageModelV3CallOptions, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { CustomRequestConfig } from \"@sap-ai-sdk/core\";\nimport type {\n AzureOpenAiChatClient,\n AzureOpenAiChatCompletionParameters,\n AzureOpenAiChatCompletionTool,\n} from \"@sap-ai-sdk/foundation-models\";\nimport type { ChatMessage } from \"@sap-ai-sdk/orchestration\";\n\nimport type { FoundationModelsModelSettings } from \"./sap-ai-settings.js\";\nimport type { LanguageModelStrategyConfig } from \"./sap-ai-strategy.js\";\n\nimport {\n BaseLanguageModelStrategy,\n type CommonBuildResult,\n type StreamCallResponse,\n} from \"./base-language-model-strategy.js\";\nimport { disposeSapStream, executeSapStream, withSapStreamCleanup } from \"./sap-http-stream.js\";\nimport {\n buildModelDeployment,\n convertResponseFormat,\n convertToolsToSAPFormat,\n type ParamMapping,\n type SAPToolChoice,\n type SDKResponse,\n type SDKStreamChunk,\n} from \"./strategy-utils.js\";\n\n/** @internal */\ntype FoundationModelsClient = InstanceType<typeof AzureOpenAiChatClient>;\n\n/**\n * Foundation Models API parameter mappings.\n * @internal\n */\nconst FOUNDATION_MODELS_PARAM_MAPPINGS: readonly ParamMapping[] = [\n ...BaseLanguageModelStrategy.COMMON_PARAM_MAPPINGS,\n { camelCaseKey: \"logprobs\", outputKey: \"logprobs\" },\n { camelCaseKey: \"topLogprobs\", outputKey: \"top_logprobs\" },\n { camelCaseKey: \"logitBias\", outputKey: \"logit_bias\" },\n { camelCaseKey: \"user\", outputKey: \"user\" },\n { camelCaseKey: \"n\", outputKey: \"n\" },\n] as const;\n\n/**\n * Language model strategy for the Foundation Models API.\n *\n * Provides direct access to Azure OpenAI models with parameters like:\n * - logprobs\n * - seed\n * - dataSources (On Your Data)\n * @internal\n */\nexport class FoundationModelsLanguageModelStrategy extends BaseLanguageModelStrategy<\n FoundationModelsClient,\n AzureOpenAiChatCompletionParameters,\n FoundationModelsModelSettings\n> {\n private readonly ClientClass: typeof AzureOpenAiChatClient;\n\n constructor(ClientClass: typeof AzureOpenAiChatClient) {\n super();\n this.ClientClass = ClientClass;\n }\n\n protected buildRequest(\n _config: LanguageModelStrategyConfig,\n settings: FoundationModelsModelSettings,\n options: LanguageModelV3CallOptions,\n commonParts: CommonBuildResult<ChatMessage[], SAPToolChoice | undefined>,\n ): {\n readonly request: AzureOpenAiChatCompletionParameters;\n readonly warnings: SharedV3Warning[];\n } {\n const warnings: SharedV3Warning[] = [];\n\n const toolsResult = convertToolsToSAPFormat<AzureOpenAiChatCompletionTool>(options.tools);\n warnings.push(...toolsResult.warnings);\n\n const { responseFormat, warning: responseFormatWarning } = convertResponseFormat(\n options.responseFormat,\n settings.responseFormat,\n );\n if (responseFormatWarning) {\n warnings.push(responseFormatWarning);\n }\n\n const { toolChoice } = commonParts;\n\n const request: AzureOpenAiChatCompletionParameters = {\n messages: commonParts.messages as AzureOpenAiChatCompletionParameters[\"messages\"],\n ...(commonParts.modelParams as Partial<AzureOpenAiChatCompletionParameters>),\n ...(toolsResult.tools?.length ? { tools: toolsResult.tools } : {}),\n ...(toolChoice ? { tool_choice: toolChoice } : {}),\n ...(responseFormat ? { response_format: responseFormat } : {}),\n ...(settings.dataSources?.length\n ? {\n data_sources: settings.dataSources,\n }\n : {}),\n };\n\n return { request, warnings };\n }\n\n protected createClient(\n config: LanguageModelStrategyConfig,\n settings: FoundationModelsModelSettings,\n _commonParts: CommonBuildResult<ChatMessage[], SAPToolChoice | undefined>,\n ): FoundationModelsClient {\n const modelDeployment = buildModelDeployment(config, settings.modelVersion);\n return new this.ClientClass(modelDeployment, config.destination);\n }\n\n protected async executeApiCall(\n client: FoundationModelsClient,\n request: AzureOpenAiChatCompletionParameters,\n requestConfig: CustomRequestConfig | undefined,\n ): Promise<SDKResponse> {\n const response = await client.run(request, requestConfig);\n\n const { requestId, responseMetadata } = this.extractMetadata(response);\n\n return {\n getContent: () => response.getContent(),\n getFinishReason: () => response.getFinishReason(),\n getTokenUsage: () => response.getTokenUsage(),\n getToolCalls: () => response.getToolCalls(),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- SAP SDK types headers as any\n rawResponse: { headers: response.rawResponse.headers },\n requestId,\n responseMetadata,\n };\n }\n\n protected async executeStreamCall(\n client: FoundationModelsClient,\n request: AzureOpenAiChatCompletionParameters,\n abortSignal: AbortSignal | undefined,\n _settings: FoundationModelsModelSettings,\n requestConfig: CustomRequestConfig | undefined,\n _commonParts: CommonBuildResult<ChatMessage[], SAPToolChoice | undefined>,\n ): Promise<StreamCallResponse> {\n const streamResponse = await executeSapStream(\n (streamRequestConfig) => client.stream(request, abortSignal, streamRequestConfig),\n abortSignal,\n requestConfig,\n );\n\n const { requestId, responseHeaders, responseMetadata } = this.extractMetadata(streamResponse);\n\n return {\n cancel: () => {\n disposeSapStream(streamResponse);\n },\n getFinishReason: () => streamResponse.getFinishReason(),\n requestId,\n responseHeaders,\n responseMetadata,\n stream: withSapStreamCleanup(\n streamResponse,\n streamResponse.stream as AsyncIterable<SDKStreamChunk>,\n ),\n };\n }\n\n protected getCompletionDataPath(): readonly string[] {\n return [];\n }\n\n protected getParamMappings(): readonly ParamMapping[] {\n return FOUNDATION_MODELS_PARAM_MAPPINGS;\n }\n\n protected getUrl(): string {\n return \"sap-ai:foundation-models\";\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoCA,IAAM,mCAA4D;AAAA,EAChE,GAAG,0BAA0B;AAAA,EAC7B,EAAE,cAAc,YAAY,WAAW,WAAW;AAAA,EAClD,EAAE,cAAc,eAAe,WAAW,eAAe;AAAA,EACzD,EAAE,cAAc,aAAa,WAAW,aAAa;AAAA,EACrD,EAAE,cAAc,QAAQ,WAAW,OAAO;AAAA,EAC1C,EAAE,cAAc,KAAK,WAAW,IAAI;AACtC;AAWO,IAAM,wCAAN,cAAoD,0BAIzD;AAAA,EACiB;AAAA,EAEjB,YAAY,aAA2C;AACrD,UAAM;AACN,SAAK,cAAc;AAAA,EACrB;AAAA,EAEU,aACR,SACA,UACA,SACA,aAIA;AACA,UAAM,WAA8B,CAAC;AAErC,UAAM,cAAc,wBAAuD,QAAQ,KAAK;AACxF,aAAS,KAAK,GAAG,YAAY,QAAQ;AAErC,UAAM,EAAE,gBAAgB,SAAS,sBAAsB,IAAI;AAAA,MACzD,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AACA,QAAI,uBAAuB;AACzB,eAAS,KAAK,qBAAqB;AAAA,IACrC;AAEA,UAAM,EAAE,WAAW,IAAI;AAEvB,UAAM,UAA+C;AAAA,MACnD,UAAU,YAAY;AAAA,MACtB,GAAI,YAAY;AAAA,MAChB,GAAI,YAAY,OAAO,SAAS,EAAE,OAAO,YAAY,MAAM,IAAI,CAAC;AAAA,MAChE,GAAI,aAAa,EAAE,aAAa,WAAW,IAAI,CAAC;AAAA,MAChD,GAAI,iBAAiB,EAAE,iBAAiB,eAAe,IAAI,CAAC;AAAA,MAC5D,GAAI,SAAS,aAAa,SACtB;AAAA,QACE,cAAc,SAAS;AAAA,MACzB,IACA,CAAC;AAAA,IACP;AAEA,WAAO,EAAE,SAAS,SAAS;AAAA,EAC7B;AAAA,EAEU,aACR,QACA,UACA,cACwB;AACxB,UAAM,kBAAkB,qBAAqB,QAAQ,SAAS,YAAY;AAC1E,WAAO,IAAI,KAAK,YAAY,iBAAiB,OAAO,WAAW;AAAA,EACjE;AAAA,EAEA,MAAgB,eACd,QACA,SACA,eACsB;AACtB,UAAM,WAAW,MAAM,OAAO,IAAI,SAAS,aAAa;AAExD,UAAM,EAAE,WAAW,iBAAiB,IAAI,KAAK,gBAAgB,QAAQ;AAErE,WAAO;AAAA,MACL,YAAY,MAAM,SAAS,WAAW;AAAA,MACtC,iBAAiB,MAAM,SAAS,gBAAgB;AAAA,MAChD,eAAe,MAAM,SAAS,cAAc;AAAA,MAC5C,cAAc,MAAM,SAAS,aAAa;AAAA;AAAA,MAE1C,aAAa,EAAE,SAAS,SAAS,YAAY,QAAQ;AAAA,MACrD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAgB,kBACd,QACA,SACA,aACA,WACA,eACA,cAC6B;AAC7B,UAAM,iBAAiB,MAAM;AAAA,MAC3B,CAAC,wBAAwB,OAAO,OAAO,SAAS,aAAa,mBAAmB;AAAA,MAChF;AAAA,MACA;AAAA,IACF;AAEA,UAAM,EAAE,WAAW,iBAAiB,iBAAiB,IAAI,KAAK,gBAAgB,cAAc;AAE5F,WAAO;AAAA,MACL,QAAQ,MAAM;AACZ,yBAAiB,cAAc;AAAA,MACjC;AAAA,MACA,iBAAiB,MAAM,eAAe,gBAAgB;AAAA,MACtD;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,QACN;AAAA,QACA,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAAA,EAEU,wBAA2C;AACnD,WAAO,CAAC;AAAA,EACV;AAAA,EAEU,mBAA4C;AACpD,WAAO;AAAA,EACT;AAAA,EAEU,SAAiB;AACzB,WAAO;AAAA,EACT;AACF;","names":[]}