@tanstack/openai-base 0.2.0 → 0.3.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 (79) hide show
  1. package/README.md +121 -0
  2. package/dist/esm/adapters/chat-completions-text.d.ts +49 -21
  3. package/dist/esm/adapters/chat-completions-text.js +476 -68
  4. package/dist/esm/adapters/chat-completions-text.js.map +1 -1
  5. package/dist/esm/adapters/chat-completions-tool-converter.d.ts +8 -4
  6. package/dist/esm/adapters/chat-completions-tool-converter.js.map +1 -1
  7. package/dist/esm/adapters/responses-text.d.ts +46 -33
  8. package/dist/esm/adapters/responses-text.js +657 -142
  9. package/dist/esm/adapters/responses-text.js.map +1 -1
  10. package/dist/esm/index.d.ts +2 -9
  11. package/dist/esm/index.js +4 -16
  12. package/dist/esm/index.js.map +1 -1
  13. package/dist/esm/tools/apply-patch-tool.d.ts +2 -2
  14. package/dist/esm/tools/apply-patch-tool.js.map +1 -1
  15. package/dist/esm/tools/code-interpreter-tool.d.ts +3 -2
  16. package/dist/esm/tools/code-interpreter-tool.js.map +1 -1
  17. package/dist/esm/tools/computer-use-tool.d.ts +2 -2
  18. package/dist/esm/tools/computer-use-tool.js.map +1 -1
  19. package/dist/esm/tools/custom-tool.d.ts +2 -2
  20. package/dist/esm/tools/custom-tool.js.map +1 -1
  21. package/dist/esm/tools/file-search-tool.d.ts +2 -2
  22. package/dist/esm/tools/file-search-tool.js.map +1 -1
  23. package/dist/esm/tools/function-tool.d.ts +2 -2
  24. package/dist/esm/tools/function-tool.js.map +1 -1
  25. package/dist/esm/tools/image-generation-tool.d.ts +3 -2
  26. package/dist/esm/tools/image-generation-tool.js.map +1 -1
  27. package/dist/esm/tools/local-shell-tool.d.ts +3 -2
  28. package/dist/esm/tools/local-shell-tool.js.map +1 -1
  29. package/dist/esm/tools/mcp-tool.d.ts +3 -2
  30. package/dist/esm/tools/mcp-tool.js.map +1 -1
  31. package/dist/esm/tools/shell-tool.d.ts +2 -2
  32. package/dist/esm/tools/shell-tool.js.map +1 -1
  33. package/dist/esm/tools/web-search-preview-tool.d.ts +2 -2
  34. package/dist/esm/tools/web-search-preview-tool.js.map +1 -1
  35. package/dist/esm/tools/web-search-tool.d.ts +2 -2
  36. package/dist/esm/tools/web-search-tool.js.map +1 -1
  37. package/package.json +6 -6
  38. package/src/adapters/chat-completions-text.ts +601 -117
  39. package/src/adapters/chat-completions-tool-converter.ts +9 -5
  40. package/src/adapters/responses-text.ts +865 -210
  41. package/src/index.ts +2 -12
  42. package/src/tools/apply-patch-tool.ts +2 -2
  43. package/src/tools/code-interpreter-tool.ts +4 -2
  44. package/src/tools/computer-use-tool.ts +2 -2
  45. package/src/tools/custom-tool.ts +2 -2
  46. package/src/tools/file-search-tool.ts +3 -3
  47. package/src/tools/function-tool.ts +2 -2
  48. package/src/tools/image-generation-tool.ts +4 -2
  49. package/src/tools/local-shell-tool.ts +4 -2
  50. package/src/tools/mcp-tool.ts +4 -2
  51. package/src/tools/shell-tool.ts +2 -2
  52. package/src/tools/web-search-preview-tool.ts +2 -2
  53. package/src/tools/web-search-tool.ts +2 -2
  54. package/dist/esm/adapters/image.d.ts +0 -32
  55. package/dist/esm/adapters/image.js +0 -89
  56. package/dist/esm/adapters/image.js.map +0 -1
  57. package/dist/esm/adapters/summarize.d.ts +0 -28
  58. package/dist/esm/adapters/summarize.js +0 -112
  59. package/dist/esm/adapters/summarize.js.map +0 -1
  60. package/dist/esm/adapters/transcription.d.ts +0 -34
  61. package/dist/esm/adapters/transcription.js +0 -131
  62. package/dist/esm/adapters/transcription.js.map +0 -1
  63. package/dist/esm/adapters/tts.d.ts +0 -26
  64. package/dist/esm/adapters/tts.js +0 -78
  65. package/dist/esm/adapters/tts.js.map +0 -1
  66. package/dist/esm/adapters/video.d.ts +0 -72
  67. package/dist/esm/adapters/video.js +0 -238
  68. package/dist/esm/adapters/video.js.map +0 -1
  69. package/dist/esm/types/config.d.ts +0 -4
  70. package/dist/esm/utils/client.d.ts +0 -3
  71. package/dist/esm/utils/client.js +0 -8
  72. package/dist/esm/utils/client.js.map +0 -1
  73. package/src/adapters/image.ts +0 -158
  74. package/src/adapters/summarize.ts +0 -174
  75. package/src/adapters/transcription.ts +0 -194
  76. package/src/adapters/tts.ts +0 -124
  77. package/src/adapters/video.ts +0 -385
  78. package/src/types/config.ts +0 -5
  79. package/src/utils/client.ts +0 -8
package/src/index.ts CHANGED
@@ -1,24 +1,14 @@
1
1
  export { makeStructuredOutputCompatible } from './utils/schema-converter'
2
- export { createOpenAICompatibleClient } from './utils/client'
3
- export type { OpenAICompatibleClientConfig } from './types/config'
4
2
  export * from './tools/index'
5
- export { OpenAICompatibleChatCompletionsTextAdapter } from './adapters/chat-completions-text'
3
+ export { OpenAIBaseChatCompletionsTextAdapter } from './adapters/chat-completions-text'
6
4
  export {
7
5
  convertFunctionToolToChatCompletionsFormat,
8
6
  convertToolsToChatCompletionsFormat,
9
7
  type ChatCompletionFunctionTool,
10
8
  } from './adapters/chat-completions-tool-converter'
11
- export { OpenAICompatibleResponsesTextAdapter } from './adapters/responses-text'
9
+ export { OpenAIBaseResponsesTextAdapter } from './adapters/responses-text'
12
10
  export {
13
11
  convertFunctionToolToResponsesFormat,
14
12
  convertToolsToResponsesFormat,
15
13
  type ResponsesFunctionTool,
16
14
  } from './adapters/responses-tool-converter'
17
- export { OpenAICompatibleImageAdapter } from './adapters/image'
18
- export {
19
- OpenAICompatibleSummarizeAdapter,
20
- type ChatStreamCapable,
21
- } from './adapters/summarize'
22
- export { OpenAICompatibleTranscriptionAdapter } from './adapters/transcription'
23
- export { OpenAICompatibleTTSAdapter } from './adapters/tts'
24
- export { OpenAICompatibleVideoAdapter } from './adapters/video'
@@ -1,7 +1,7 @@
1
- import type OpenAI from 'openai'
1
+ import type { ApplyPatchTool as ApplyPatchToolConfig } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type ApplyPatchToolConfig = OpenAI.Responses.ApplyPatchTool
4
+ export type { ApplyPatchToolConfig }
5
5
 
6
6
  /** @deprecated Renamed to `ApplyPatchToolConfig`. Will be removed in a future release. */
7
7
  export type ApplyPatchTool = ApplyPatchToolConfig
@@ -1,7 +1,9 @@
1
+ import type { Tool as SDKTool } from 'openai/resources/responses/responses'
1
2
  import type { Tool } from '@tanstack/ai'
2
- import type OpenAI from 'openai'
3
3
 
4
- export type CodeInterpreterToolConfig = OpenAI.Responses.Tool.CodeInterpreter
4
+ type CodeInterpreterToolConfig = SDKTool.CodeInterpreter
5
+
6
+ export type { CodeInterpreterToolConfig }
5
7
 
6
8
  /** @deprecated Renamed to `CodeInterpreterToolConfig`. Will be removed in a future release. */
7
9
  export type CodeInterpreterTool = CodeInterpreterToolConfig
@@ -1,7 +1,7 @@
1
- import type OpenAI from 'openai'
1
+ import type { ComputerTool as ComputerUseToolConfig } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type ComputerUseToolConfig = OpenAI.Responses.ComputerTool
4
+ export type { ComputerUseToolConfig }
5
5
 
6
6
  /** @deprecated Renamed to `ComputerUseToolConfig`. Will be removed in a future release. */
7
7
  export type ComputerUseTool = ComputerUseToolConfig
@@ -1,7 +1,7 @@
1
- import type OpenAI from 'openai'
1
+ import type { CustomTool as CustomToolConfig } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type CustomToolConfig = OpenAI.Responses.CustomTool
4
+ export type { CustomToolConfig }
5
5
 
6
6
  /** @deprecated Renamed to `CustomToolConfig`. Will be removed in a future release. */
7
7
  export type CustomTool = CustomToolConfig
@@ -1,6 +1,8 @@
1
- import type OpenAI from 'openai'
1
+ import type { FileSearchTool as FileSearchToolConfig } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
+ export type { FileSearchToolConfig }
5
+
4
6
  const validateMaxNumResults = (maxNumResults: number | undefined) => {
5
7
  if (
6
8
  maxNumResults !== undefined &&
@@ -10,8 +12,6 @@ const validateMaxNumResults = (maxNumResults: number | undefined) => {
10
12
  }
11
13
  }
12
14
 
13
- export type FileSearchToolConfig = OpenAI.Responses.FileSearchTool
14
-
15
15
  /** @deprecated Renamed to `FileSearchToolConfig`. Will be removed in a future release. */
16
16
  export type FileSearchTool = FileSearchToolConfig
17
17
 
@@ -1,8 +1,8 @@
1
1
  import { makeStructuredOutputCompatible } from '../utils/schema-converter'
2
+ import type { FunctionTool as FunctionToolConfig } from 'openai/resources/responses/responses'
2
3
  import type { JSONSchema, Tool } from '@tanstack/ai'
3
- import type OpenAI from 'openai'
4
4
 
5
- export type FunctionToolConfig = OpenAI.Responses.FunctionTool
5
+ export type { FunctionToolConfig }
6
6
 
7
7
  /** @deprecated Renamed to `FunctionToolConfig`. Will be removed in a future release. */
8
8
  export type FunctionTool = FunctionToolConfig
@@ -1,7 +1,9 @@
1
- import type OpenAI from 'openai'
1
+ import type { Tool as SDKTool } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type ImageGenerationToolConfig = OpenAI.Responses.Tool.ImageGeneration
4
+ type ImageGenerationToolConfig = SDKTool.ImageGeneration
5
+
6
+ export type { ImageGenerationToolConfig }
5
7
 
6
8
  /** @deprecated Renamed to `ImageGenerationToolConfig`. Will be removed in a future release. */
7
9
  export type ImageGenerationTool = ImageGenerationToolConfig
@@ -1,7 +1,9 @@
1
- import type OpenAI from 'openai'
1
+ import type { Tool as SDKTool } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type LocalShellToolConfig = OpenAI.Responses.Tool.LocalShell
4
+ type LocalShellToolConfig = SDKTool.LocalShell
5
+
6
+ export type { LocalShellToolConfig }
5
7
 
6
8
  /** @deprecated Renamed to `LocalShellToolConfig`. Will be removed in a future release. */
7
9
  export type LocalShellTool = LocalShellToolConfig
@@ -1,7 +1,9 @@
1
- import type OpenAI from 'openai'
1
+ import type { Tool as SDKTool } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type MCPToolConfig = OpenAI.Responses.Tool.Mcp
4
+ type MCPToolConfig = SDKTool.Mcp
5
+
6
+ export type { MCPToolConfig }
5
7
 
6
8
  /** @deprecated Renamed to `MCPToolConfig`. Will be removed in a future release. */
7
9
  export type MCPTool = MCPToolConfig
@@ -1,7 +1,7 @@
1
- import type OpenAI from 'openai'
1
+ import type { FunctionShellTool as ShellToolConfig } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type ShellToolConfig = OpenAI.Responses.FunctionShellTool
4
+ export type { ShellToolConfig }
5
5
 
6
6
  /** @deprecated Renamed to `ShellToolConfig`. Will be removed in a future release. */
7
7
  export type ShellTool = ShellToolConfig
@@ -1,7 +1,7 @@
1
- import type OpenAI from 'openai'
1
+ import type { WebSearchPreviewTool as WebSearchPreviewToolConfig } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type WebSearchPreviewToolConfig = OpenAI.Responses.WebSearchPreviewTool
4
+ export type { WebSearchPreviewToolConfig }
5
5
 
6
6
  /** @deprecated Renamed to `WebSearchPreviewToolConfig`. Will be removed in a future release. */
7
7
  export type WebSearchPreviewTool = WebSearchPreviewToolConfig
@@ -1,7 +1,7 @@
1
- import type OpenAI from 'openai'
1
+ import type { WebSearchTool as WebSearchToolConfig } from 'openai/resources/responses/responses'
2
2
  import type { Tool } from '@tanstack/ai'
3
3
 
4
- export type WebSearchToolConfig = OpenAI.Responses.WebSearchTool
4
+ export type { WebSearchToolConfig }
5
5
 
6
6
  /** @deprecated Renamed to `WebSearchToolConfig`. Will be removed in a future release. */
7
7
  export type WebSearchTool = WebSearchToolConfig
@@ -1,32 +0,0 @@
1
- import { BaseImageAdapter } from '@tanstack/ai/adapters';
2
- import { ImageGenerationOptions, ImageGenerationResult } from '@tanstack/ai';
3
- import { default as OpenAI_SDK } from 'openai';
4
- import { OpenAICompatibleClientConfig } from '../types/config.js';
5
- /**
6
- * OpenAI-Compatible Image Generation Adapter
7
- *
8
- * A generalized base class for providers that implement OpenAI-compatible image
9
- * generation APIs. Providers like OpenAI, Grok, and others can extend this class
10
- * and only need to:
11
- * - Set `baseURL` in the config
12
- * - Lock the generic type parameters to provider-specific types
13
- * - Override validation or request building methods for provider-specific constraints
14
- *
15
- * All methods that validate inputs, build requests, or transform responses are
16
- * `protected` so subclasses can override them.
17
- */
18
- export declare class OpenAICompatibleImageAdapter<TModel extends string, TProviderOptions extends object = Record<string, any>, TModelProviderOptionsByName extends Record<string, any> = Record<string, any>, TModelSizeByName extends Record<string, string> = Record<string, string>> extends BaseImageAdapter<TModel, TProviderOptions, TModelProviderOptionsByName, TModelSizeByName> {
19
- readonly kind: "image";
20
- readonly name: string;
21
- protected client: OpenAI_SDK;
22
- constructor(config: OpenAICompatibleClientConfig, model: TModel, name?: string);
23
- generateImages(options: ImageGenerationOptions<TProviderOptions>): Promise<ImageGenerationResult>;
24
- protected buildRequest(options: ImageGenerationOptions<TProviderOptions>): OpenAI_SDK.Images.ImageGenerateParams;
25
- protected transformResponse(model: string, response: OpenAI_SDK.Images.ImagesResponse): ImageGenerationResult;
26
- protected validatePrompt(options: {
27
- prompt: string;
28
- model: string;
29
- }): void;
30
- protected validateImageSize(_model: string, _size: string | undefined): void;
31
- protected validateNumberOfImages(_model: string, numberOfImages: number | undefined): void;
32
- }
@@ -1,89 +0,0 @@
1
- import { BaseImageAdapter } from "@tanstack/ai/adapters";
2
- import { toRunErrorPayload } from "@tanstack/ai/adapter-internals";
3
- import { generateId } from "@tanstack/ai-utils";
4
- import { createOpenAICompatibleClient } from "../utils/client.js";
5
- class OpenAICompatibleImageAdapter extends BaseImageAdapter {
6
- constructor(config, model, name = "openai-compatible") {
7
- super(model, {});
8
- this.kind = "image";
9
- this.name = name;
10
- this.client = createOpenAICompatibleClient(config);
11
- }
12
- async generateImages(options) {
13
- const { model, prompt, numberOfImages, size } = options;
14
- this.validatePrompt({ prompt, model });
15
- this.validateImageSize(model, size);
16
- this.validateNumberOfImages(model, numberOfImages);
17
- const request = this.buildRequest(options);
18
- try {
19
- options.logger.request(
20
- `activity=image provider=${this.name} model=${model} n=${request.n ?? 1} size=${request.size ?? "default"}`,
21
- { provider: this.name, model }
22
- );
23
- const response = await this.client.images.generate({
24
- ...request,
25
- stream: false
26
- });
27
- return this.transformResponse(model, response);
28
- } catch (error) {
29
- options.logger.errors(`${this.name}.generateImages fatal`, {
30
- error: toRunErrorPayload(error, `${this.name}.generateImages failed`),
31
- source: `${this.name}.generateImages`
32
- });
33
- throw error;
34
- }
35
- }
36
- buildRequest(options) {
37
- const { model, prompt, numberOfImages, size, modelOptions } = options;
38
- return {
39
- model,
40
- prompt,
41
- n: numberOfImages ?? 1,
42
- size,
43
- ...modelOptions
44
- };
45
- }
46
- transformResponse(model, response) {
47
- const images = (response.data ?? []).flatMap(
48
- (item) => {
49
- const revisedPrompt = item.revised_prompt;
50
- if (item.b64_json) {
51
- return [{ b64Json: item.b64_json, revisedPrompt }];
52
- }
53
- if (item.url) {
54
- return [{ url: item.url, revisedPrompt }];
55
- }
56
- return [];
57
- }
58
- );
59
- return {
60
- id: generateId(this.name),
61
- model,
62
- images,
63
- usage: response.usage ? {
64
- inputTokens: response.usage.input_tokens,
65
- outputTokens: response.usage.output_tokens,
66
- totalTokens: response.usage.total_tokens
67
- } : void 0
68
- };
69
- }
70
- validatePrompt(options) {
71
- if (options.prompt.length === 0) {
72
- throw new Error("Prompt cannot be empty.");
73
- }
74
- }
75
- validateImageSize(_model, _size) {
76
- }
77
- validateNumberOfImages(_model, numberOfImages) {
78
- if (numberOfImages === void 0) return;
79
- if (numberOfImages < 1) {
80
- throw new Error(
81
- `Number of images must be at least 1. Requested: ${numberOfImages}`
82
- );
83
- }
84
- }
85
- }
86
- export {
87
- OpenAICompatibleImageAdapter
88
- };
89
- //# sourceMappingURL=image.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"image.js","sources":["../../../src/adapters/image.ts"],"sourcesContent":["import { BaseImageAdapter } from '@tanstack/ai/adapters'\nimport { toRunErrorPayload } from '@tanstack/ai/adapter-internals'\nimport { generateId } from '@tanstack/ai-utils'\nimport { createOpenAICompatibleClient } from '../utils/client'\nimport type {\n GeneratedImage,\n ImageGenerationOptions,\n ImageGenerationResult,\n} from '@tanstack/ai'\nimport type OpenAI_SDK from 'openai'\nimport type { OpenAICompatibleClientConfig } from '../types/config'\n\n/**\n * OpenAI-Compatible Image Generation Adapter\n *\n * A generalized base class for providers that implement OpenAI-compatible image\n * generation APIs. Providers like OpenAI, Grok, and others can extend this class\n * and only need to:\n * - Set `baseURL` in the config\n * - Lock the generic type parameters to provider-specific types\n * - Override validation or request building methods for provider-specific constraints\n *\n * All methods that validate inputs, build requests, or transform responses are\n * `protected` so subclasses can override them.\n */\nexport class OpenAICompatibleImageAdapter<\n TModel extends string,\n TProviderOptions extends object = Record<string, any>,\n TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,\n TModelSizeByName extends Record<string, string> = Record<string, string>,\n> extends BaseImageAdapter<\n TModel,\n TProviderOptions,\n TModelProviderOptionsByName,\n TModelSizeByName\n> {\n readonly kind = 'image' as const\n readonly name: string\n\n protected client: OpenAI_SDK\n\n constructor(\n config: OpenAICompatibleClientConfig,\n model: TModel,\n name: string = 'openai-compatible',\n ) {\n super(model, {})\n this.name = name\n this.client = createOpenAICompatibleClient(config)\n }\n\n async generateImages(\n options: ImageGenerationOptions<TProviderOptions>,\n ): Promise<ImageGenerationResult> {\n const { model, prompt, numberOfImages, size } = options\n\n // Validate inputs\n this.validatePrompt({ prompt, model })\n this.validateImageSize(model, size)\n this.validateNumberOfImages(model, numberOfImages)\n\n // Build request based on model type\n const request = this.buildRequest(options)\n\n try {\n options.logger.request(\n `activity=image provider=${this.name} model=${model} n=${request.n ?? 1} size=${request.size ?? 'default'}`,\n { provider: this.name, model },\n )\n const response = await this.client.images.generate({\n ...request,\n stream: false,\n })\n\n return this.transformResponse(model, response)\n } catch (error: unknown) {\n // Narrow before logging: raw SDK errors can carry request metadata\n // (including auth headers) which we must never surface to user loggers.\n options.logger.errors(`${this.name}.generateImages fatal`, {\n error: toRunErrorPayload(error, `${this.name}.generateImages failed`),\n source: `${this.name}.generateImages`,\n })\n throw error\n }\n }\n\n protected buildRequest(\n options: ImageGenerationOptions<TProviderOptions>,\n ): OpenAI_SDK.Images.ImageGenerateParams {\n const { model, prompt, numberOfImages, size, modelOptions } = options\n\n return {\n model,\n prompt,\n n: numberOfImages ?? 1,\n size: size as OpenAI_SDK.Images.ImageGenerateParams['size'],\n ...modelOptions,\n }\n }\n\n protected transformResponse(\n model: string,\n response: OpenAI_SDK.Images.ImagesResponse,\n ): ImageGenerationResult {\n const images: Array<GeneratedImage> = (response.data ?? []).flatMap(\n (item): Array<GeneratedImage> => {\n const revisedPrompt = item.revised_prompt\n if (item.b64_json) {\n return [{ b64Json: item.b64_json, revisedPrompt }]\n }\n if (item.url) {\n return [{ url: item.url, revisedPrompt }]\n }\n return []\n },\n )\n\n return {\n id: generateId(this.name),\n model,\n images,\n usage: response.usage\n ? {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.total_tokens,\n }\n : undefined,\n }\n }\n\n protected validatePrompt(options: { prompt: string; model: string }): void {\n if (options.prompt.length === 0) {\n throw new Error('Prompt cannot be empty.')\n }\n }\n\n protected validateImageSize(_model: string, _size: string | undefined): void {\n // Default: no size validation — subclasses can override\n }\n\n protected validateNumberOfImages(\n _model: string,\n numberOfImages: number | undefined,\n ): void {\n if (numberOfImages === undefined) return\n\n // The base adapter only enforces \"must be at least 1\". Per-provider /\n // per-model upper bounds vary widely (some support 4, some 10, some\n // unlimited), so concrete adapter subclasses are expected to override\n // this method with a model-specific cap.\n if (numberOfImages < 1) {\n throw new Error(\n `Number of images must be at least 1. Requested: ${numberOfImages}`,\n )\n }\n }\n}\n"],"names":[],"mappings":";;;;AAyBO,MAAM,qCAKH,iBAKR;AAAA,EAMA,YACE,QACA,OACA,OAAe,qBACf;AACA,UAAM,OAAO,EAAE;AAVjB,SAAS,OAAO;AAWd,SAAK,OAAO;AACZ,SAAK,SAAS,6BAA6B,MAAM;AAAA,EACnD;AAAA,EAEA,MAAM,eACJ,SACgC;AAChC,UAAM,EAAE,OAAO,QAAQ,gBAAgB,SAAS;AAGhD,SAAK,eAAe,EAAE,QAAQ,MAAA,CAAO;AACrC,SAAK,kBAAkB,OAAO,IAAI;AAClC,SAAK,uBAAuB,OAAO,cAAc;AAGjD,UAAM,UAAU,KAAK,aAAa,OAAO;AAEzC,QAAI;AACF,cAAQ,OAAO;AAAA,QACb,2BAA2B,KAAK,IAAI,UAAU,KAAK,MAAM,QAAQ,KAAK,CAAC,SAAS,QAAQ,QAAQ,SAAS;AAAA,QACzG,EAAE,UAAU,KAAK,MAAM,MAAA;AAAA,MAAM;AAE/B,YAAM,WAAW,MAAM,KAAK,OAAO,OAAO,SAAS;AAAA,QACjD,GAAG;AAAA,QACH,QAAQ;AAAA,MAAA,CACT;AAED,aAAO,KAAK,kBAAkB,OAAO,QAAQ;AAAA,IAC/C,SAAS,OAAgB;AAGvB,cAAQ,OAAO,OAAO,GAAG,KAAK,IAAI,yBAAyB;AAAA,QACzD,OAAO,kBAAkB,OAAO,GAAG,KAAK,IAAI,wBAAwB;AAAA,QACpE,QAAQ,GAAG,KAAK,IAAI;AAAA,MAAA,CACrB;AACD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEU,aACR,SACuC;AACvC,UAAM,EAAE,OAAO,QAAQ,gBAAgB,MAAM,iBAAiB;AAE9D,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,GAAG,kBAAkB;AAAA,MACrB;AAAA,MACA,GAAG;AAAA,IAAA;AAAA,EAEP;AAAA,EAEU,kBACR,OACA,UACuB;AACvB,UAAM,UAAiC,SAAS,QAAQ,CAAA,GAAI;AAAA,MAC1D,CAAC,SAAgC;AAC/B,cAAM,gBAAgB,KAAK;AAC3B,YAAI,KAAK,UAAU;AACjB,iBAAO,CAAC,EAAE,SAAS,KAAK,UAAU,eAAe;AAAA,QACnD;AACA,YAAI,KAAK,KAAK;AACZ,iBAAO,CAAC,EAAE,KAAK,KAAK,KAAK,eAAe;AAAA,QAC1C;AACA,eAAO,CAAA;AAAA,MACT;AAAA,IAAA;AAGF,WAAO;AAAA,MACL,IAAI,WAAW,KAAK,IAAI;AAAA,MACxB;AAAA,MACA;AAAA,MACA,OAAO,SAAS,QACZ;AAAA,QACE,aAAa,SAAS,MAAM;AAAA,QAC5B,cAAc,SAAS,MAAM;AAAA,QAC7B,aAAa,SAAS,MAAM;AAAA,MAAA,IAE9B;AAAA,IAAA;AAAA,EAER;AAAA,EAEU,eAAe,SAAkD;AACzE,QAAI,QAAQ,OAAO,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAAA,EACF;AAAA,EAEU,kBAAkB,QAAgB,OAAiC;AAAA,EAE7E;AAAA,EAEU,uBACR,QACA,gBACM;AACN,QAAI,mBAAmB,OAAW;AAMlC,QAAI,iBAAiB,GAAG;AACtB,YAAM,IAAI;AAAA,QACR,mDAAmD,cAAc;AAAA,MAAA;AAAA,IAErE;AAAA,EACF;AACF;"}
@@ -1,28 +0,0 @@
1
- import { BaseSummarizeAdapter } from '@tanstack/ai/adapters';
2
- import { StreamChunk, SummarizationOptions, SummarizationResult, TextOptions } from '@tanstack/ai';
3
- /**
4
- * Minimal interface for a text adapter that supports chatStream.
5
- * This allows the summarize adapter to work with any OpenAI-compatible
6
- * text adapter without tight coupling to a specific implementation.
7
- */
8
- export interface ChatStreamCapable<TProviderOptions extends object> {
9
- chatStream: (options: TextOptions<TProviderOptions>) => AsyncIterable<StreamChunk>;
10
- }
11
- /**
12
- * OpenAI-Compatible Summarize Adapter
13
- *
14
- * A thin wrapper around a text adapter that adds summarization-specific prompting.
15
- * Delegates all API calls to the provided text adapter.
16
- *
17
- * Subclasses or instantiators provide a text adapter (or factory) at construction
18
- * time, allowing any OpenAI-compatible provider to get summarization for free by
19
- * reusing its text adapter.
20
- */
21
- export declare class OpenAICompatibleSummarizeAdapter<TModel extends string, TProviderOptions extends object = Record<string, any>> extends BaseSummarizeAdapter<TModel, TProviderOptions> {
22
- readonly name: string;
23
- private textAdapter;
24
- constructor(textAdapter: ChatStreamCapable<TProviderOptions>, model: TModel, name?: string);
25
- summarize(options: SummarizationOptions): Promise<SummarizationResult>;
26
- summarizeStream(options: SummarizationOptions): AsyncIterable<StreamChunk>;
27
- protected buildSummarizationPrompt(options: SummarizationOptions): string;
28
- }
@@ -1,112 +0,0 @@
1
- import { BaseSummarizeAdapter } from "@tanstack/ai/adapters";
2
- import { toRunErrorPayload } from "@tanstack/ai/adapter-internals";
3
- import { generateId } from "@tanstack/ai-utils";
4
- class OpenAICompatibleSummarizeAdapter extends BaseSummarizeAdapter {
5
- constructor(textAdapter, model, name = "openai-compatible") {
6
- super({}, model);
7
- this.name = name;
8
- this.textAdapter = textAdapter;
9
- }
10
- async summarize(options) {
11
- const systemPrompt = this.buildSummarizationPrompt(options);
12
- let summary = "";
13
- const id = generateId(this.name);
14
- let model = options.model;
15
- let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
16
- options.logger.request(
17
- `activity=summarize provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? "unset"}`,
18
- { provider: this.name, model: options.model }
19
- );
20
- try {
21
- for await (const chunk of this.textAdapter.chatStream({
22
- model: options.model,
23
- messages: [{ role: "user", content: options.text }],
24
- systemPrompts: [systemPrompt],
25
- maxTokens: options.maxLength,
26
- temperature: 0.3,
27
- logger: options.logger
28
- })) {
29
- if (chunk.type === "TEXT_MESSAGE_CONTENT") {
30
- if (chunk.content) {
31
- summary = chunk.content;
32
- } else if (chunk.delta) {
33
- summary += chunk.delta;
34
- }
35
- model = chunk.model || model;
36
- }
37
- if (chunk.type === "RUN_FINISHED") {
38
- if (chunk.usage) {
39
- usage = chunk.usage;
40
- }
41
- }
42
- if (chunk.type === "RUN_ERROR") {
43
- const message = (chunk.error && typeof chunk.error.message === "string" ? chunk.error.message : null) ?? "Summarization failed";
44
- const code = chunk.error && typeof chunk.error.code === "string" ? chunk.error.code : void 0;
45
- const err = new Error(message);
46
- if (code) {
47
- ;
48
- err.code = code;
49
- }
50
- throw err;
51
- }
52
- }
53
- } catch (error) {
54
- options.logger.errors(`${this.name}.summarize fatal`, {
55
- error: toRunErrorPayload(error, `${this.name}.summarize failed`),
56
- source: `${this.name}.summarize`
57
- });
58
- throw error;
59
- }
60
- return { id, model, summary, usage };
61
- }
62
- async *summarizeStream(options) {
63
- const systemPrompt = this.buildSummarizationPrompt(options);
64
- options.logger.request(
65
- `activity=summarizeStream provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? "unset"}`,
66
- { provider: this.name, model: options.model }
67
- );
68
- try {
69
- yield* this.textAdapter.chatStream({
70
- model: options.model,
71
- messages: [{ role: "user", content: options.text }],
72
- systemPrompts: [systemPrompt],
73
- maxTokens: options.maxLength,
74
- temperature: 0.3,
75
- logger: options.logger
76
- });
77
- } catch (error) {
78
- options.logger.errors(`${this.name}.summarizeStream fatal`, {
79
- error: toRunErrorPayload(error, `${this.name}.summarizeStream failed`),
80
- source: `${this.name}.summarizeStream`
81
- });
82
- throw error;
83
- }
84
- }
85
- buildSummarizationPrompt(options) {
86
- let prompt = "You are a professional summarizer. ";
87
- switch (options.style) {
88
- case "bullet-points":
89
- prompt += "Provide a summary in bullet point format. ";
90
- break;
91
- case "paragraph":
92
- prompt += "Provide a summary in paragraph format. ";
93
- break;
94
- case "concise":
95
- prompt += "Provide a very concise summary in 1-2 sentences. ";
96
- break;
97
- default:
98
- prompt += "Provide a clear and concise summary. ";
99
- }
100
- if (options.focus && options.focus.length > 0) {
101
- prompt += `Focus on the following aspects: ${options.focus.join(", ")}. `;
102
- }
103
- if (options.maxLength) {
104
- prompt += `Keep the summary under ${options.maxLength} tokens. `;
105
- }
106
- return prompt;
107
- }
108
- }
109
- export {
110
- OpenAICompatibleSummarizeAdapter
111
- };
112
- //# sourceMappingURL=summarize.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"summarize.js","sources":["../../../src/adapters/summarize.ts"],"sourcesContent":["import { BaseSummarizeAdapter } from '@tanstack/ai/adapters'\nimport { toRunErrorPayload } from '@tanstack/ai/adapter-internals'\nimport { generateId } from '@tanstack/ai-utils'\nimport type {\n StreamChunk,\n SummarizationOptions,\n SummarizationResult,\n TextOptions,\n} from '@tanstack/ai'\n\n/**\n * Minimal interface for a text adapter that supports chatStream.\n * This allows the summarize adapter to work with any OpenAI-compatible\n * text adapter without tight coupling to a specific implementation.\n */\nexport interface ChatStreamCapable<TProviderOptions extends object> {\n chatStream: (\n options: TextOptions<TProviderOptions>,\n ) => AsyncIterable<StreamChunk>\n}\n\n/**\n * OpenAI-Compatible Summarize Adapter\n *\n * A thin wrapper around a text adapter that adds summarization-specific prompting.\n * Delegates all API calls to the provided text adapter.\n *\n * Subclasses or instantiators provide a text adapter (or factory) at construction\n * time, allowing any OpenAI-compatible provider to get summarization for free by\n * reusing its text adapter.\n */\nexport class OpenAICompatibleSummarizeAdapter<\n TModel extends string,\n TProviderOptions extends object = Record<string, any>,\n> extends BaseSummarizeAdapter<TModel, TProviderOptions> {\n readonly name: string\n\n private textAdapter: ChatStreamCapable<TProviderOptions>\n\n constructor(\n textAdapter: ChatStreamCapable<TProviderOptions>,\n model: TModel,\n name: string = 'openai-compatible',\n ) {\n super({}, model)\n this.name = name\n this.textAdapter = textAdapter\n }\n\n async summarize(options: SummarizationOptions): Promise<SummarizationResult> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n let summary = ''\n const id = generateId(this.name)\n let model = options.model\n let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 }\n\n options.logger.request(\n `activity=summarize provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,\n { provider: this.name, model: options.model },\n )\n\n try {\n for await (const chunk of this.textAdapter.chatStream({\n model: options.model,\n messages: [{ role: 'user', content: options.text }],\n systemPrompts: [systemPrompt],\n maxTokens: options.maxLength,\n temperature: 0.3,\n logger: options.logger,\n } satisfies TextOptions<TProviderOptions>)) {\n if (chunk.type === 'TEXT_MESSAGE_CONTENT') {\n if (chunk.content) {\n summary = chunk.content\n } else if (chunk.delta) {\n // Append delta only when present — a content-less chunk with no\n // delta would otherwise concat literal `'undefined'`.\n summary += chunk.delta\n }\n model = chunk.model || model\n }\n if (chunk.type === 'RUN_FINISHED') {\n if (chunk.usage) {\n usage = chunk.usage\n }\n }\n // Surface failures: the underlying chatStream emits RUN_ERROR instead\n // of throwing, so without this branch summarize() would return an\n // empty summary and pretend a failed run succeeded.\n if (chunk.type === 'RUN_ERROR') {\n const message =\n (chunk.error && typeof chunk.error.message === 'string'\n ? chunk.error.message\n : null) ?? 'Summarization failed'\n const code =\n chunk.error && typeof chunk.error.code === 'string'\n ? chunk.error.code\n : undefined\n const err = new Error(message)\n if (code) {\n ;(err as Error & { code?: string }).code = code\n }\n throw err\n }\n }\n } catch (error: unknown) {\n // Narrow before logging: raw SDK errors can carry request metadata\n // (including auth headers) which we must never surface to user loggers.\n options.logger.errors(`${this.name}.summarize fatal`, {\n error: toRunErrorPayload(error, `${this.name}.summarize failed`),\n source: `${this.name}.summarize`,\n })\n throw error\n }\n\n return { id, model, summary, usage }\n }\n\n async *summarizeStream(\n options: SummarizationOptions,\n ): AsyncIterable<StreamChunk> {\n const systemPrompt = this.buildSummarizationPrompt(options)\n\n options.logger.request(\n `activity=summarizeStream provider=${this.name} model=${options.model} text-length=${options.text.length} maxLength=${options.maxLength ?? 'unset'}`,\n { provider: this.name, model: options.model },\n )\n\n try {\n yield* this.textAdapter.chatStream({\n model: options.model,\n messages: [{ role: 'user', content: options.text }],\n systemPrompts: [systemPrompt],\n maxTokens: options.maxLength,\n temperature: 0.3,\n logger: options.logger,\n } satisfies TextOptions<TProviderOptions>)\n } catch (error: unknown) {\n options.logger.errors(`${this.name}.summarizeStream fatal`, {\n error: toRunErrorPayload(error, `${this.name}.summarizeStream failed`),\n source: `${this.name}.summarizeStream`,\n })\n throw error\n }\n }\n\n protected buildSummarizationPrompt(options: SummarizationOptions): string {\n let prompt = 'You are a professional summarizer. '\n\n switch (options.style) {\n case 'bullet-points':\n prompt += 'Provide a summary in bullet point format. '\n break\n case 'paragraph':\n prompt += 'Provide a summary in paragraph format. '\n break\n case 'concise':\n prompt += 'Provide a very concise summary in 1-2 sentences. '\n break\n default:\n prompt += 'Provide a clear and concise summary. '\n }\n\n if (options.focus && options.focus.length > 0) {\n prompt += `Focus on the following aspects: ${options.focus.join(', ')}. `\n }\n\n if (options.maxLength) {\n prompt += `Keep the summary under ${options.maxLength} tokens. `\n }\n\n return prompt\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,34 +0,0 @@
1
- import { BaseTranscriptionAdapter } from '@tanstack/ai/adapters';
2
- import { TranscriptionOptions, TranscriptionResult } from '@tanstack/ai';
3
- import { default as OpenAI_SDK } from 'openai';
4
- import { OpenAICompatibleClientConfig } from '../types/config.js';
5
- /**
6
- * OpenAI-Compatible Transcription (Speech-to-Text) Adapter
7
- *
8
- * A generalized base class for providers that implement OpenAI-compatible audio
9
- * transcription APIs. Providers can extend this class and only need to:
10
- * - Set `baseURL` in the config
11
- * - Lock the generic type parameters to provider-specific types
12
- * - Override audio handling or response mapping methods as needed
13
- *
14
- * All methods that handle audio input or map response formats are `protected`
15
- * so subclasses can override them.
16
- */
17
- export declare class OpenAICompatibleTranscriptionAdapter<TModel extends string, TProviderOptions extends object = Record<string, any>> extends BaseTranscriptionAdapter<TModel, TProviderOptions> {
18
- readonly name: string;
19
- protected client: OpenAI_SDK;
20
- constructor(config: OpenAICompatibleClientConfig, model: TModel, name?: string);
21
- transcribe(options: TranscriptionOptions<TProviderOptions>): Promise<TranscriptionResult>;
22
- protected prepareAudioFile(audio: string | File | Blob | ArrayBuffer): File;
23
- /**
24
- * Checks that the global `File` constructor is available.
25
- * Throws a descriptive error in environments that lack it (e.g. Node < 20).
26
- */
27
- private ensureFileSupport;
28
- /**
29
- * Whether the adapter should default to verbose_json when no response format is specified.
30
- * Override in provider-specific subclasses for model-specific behavior.
31
- */
32
- protected shouldDefaultToVerbose(_model: string): boolean;
33
- protected mapResponseFormat(format?: 'json' | 'text' | 'srt' | 'verbose_json' | 'vtt'): OpenAI_SDK.Audio.TranscriptionCreateParams['response_format'];
34
- }
@@ -1,131 +0,0 @@
1
- import { BaseTranscriptionAdapter } from "@tanstack/ai/adapters";
2
- import { toRunErrorPayload } from "@tanstack/ai/adapter-internals";
3
- import { generateId, base64ToArrayBuffer } from "@tanstack/ai-utils";
4
- import { createOpenAICompatibleClient } from "../utils/client.js";
5
- class OpenAICompatibleTranscriptionAdapter extends BaseTranscriptionAdapter {
6
- constructor(config, model, name = "openai-compatible") {
7
- super(model, {});
8
- this.name = name;
9
- this.client = createOpenAICompatibleClient(config);
10
- }
11
- async transcribe(options) {
12
- const { model, audio, language, prompt, responseFormat, modelOptions } = options;
13
- const file = this.prepareAudioFile(audio);
14
- const request = {
15
- model,
16
- file,
17
- language,
18
- prompt,
19
- response_format: this.mapResponseFormat(responseFormat),
20
- ...modelOptions
21
- };
22
- const useVerbose = responseFormat === "verbose_json" || !responseFormat && this.shouldDefaultToVerbose(model);
23
- try {
24
- options.logger.request(
25
- `activity=transcription provider=${this.name} model=${model} verbose=${useVerbose}`,
26
- { provider: this.name, model }
27
- );
28
- if (useVerbose) {
29
- const response = await this.client.audio.transcriptions.create({
30
- ...request,
31
- response_format: "verbose_json"
32
- });
33
- return {
34
- id: generateId(this.name),
35
- model,
36
- text: response.text,
37
- language: response.language,
38
- duration: response.duration,
39
- segments: response.segments?.map(
40
- (seg) => ({
41
- id: seg.id,
42
- start: seg.start,
43
- end: seg.end,
44
- text: seg.text,
45
- // The OpenAI SDK types `avg_logprob` as `number`, so call Math.exp
46
- // directly. Previously this was guarded with `seg.avg_logprob ?`
47
- // which treated `0` (perfect-confidence) as missing.
48
- confidence: Math.exp(seg.avg_logprob)
49
- })
50
- ),
51
- words: response.words?.map((w) => ({
52
- word: w.word,
53
- start: w.start,
54
- end: w.end
55
- }))
56
- };
57
- } else {
58
- const response = await this.client.audio.transcriptions.create(request);
59
- return {
60
- id: generateId(this.name),
61
- model,
62
- text: typeof response === "string" ? response : response.text,
63
- language
64
- };
65
- }
66
- } catch (error) {
67
- options.logger.errors(`${this.name}.transcribe fatal`, {
68
- error: toRunErrorPayload(error, `${this.name}.transcribe failed`),
69
- source: `${this.name}.transcribe`
70
- });
71
- throw error;
72
- }
73
- }
74
- prepareAudioFile(audio) {
75
- if (typeof File !== "undefined" && audio instanceof File) {
76
- return audio;
77
- }
78
- if (typeof Blob !== "undefined" && audio instanceof Blob) {
79
- this.ensureFileSupport();
80
- return new File([audio], "audio.mp3", {
81
- type: audio.type || "audio/mpeg"
82
- });
83
- }
84
- if (typeof ArrayBuffer !== "undefined" && audio instanceof ArrayBuffer) {
85
- this.ensureFileSupport();
86
- return new File([audio], "audio.mp3", { type: "audio/mpeg" });
87
- }
88
- if (typeof audio === "string") {
89
- this.ensureFileSupport();
90
- if (audio.startsWith("data:")) {
91
- const parts = audio.split(",");
92
- const header = parts[0];
93
- const base64Data = parts[1] || "";
94
- const mimeMatch = header?.match(/data:([^;]+)/);
95
- const mimeType = mimeMatch?.[1] || "audio/mpeg";
96
- const bytes2 = base64ToArrayBuffer(base64Data);
97
- const extension = mimeType.split("/")[1] || "mp3";
98
- return new File([bytes2], `audio.${extension}`, { type: mimeType });
99
- }
100
- const bytes = base64ToArrayBuffer(audio);
101
- return new File([bytes], "audio.mp3", { type: "audio/mpeg" });
102
- }
103
- throw new Error("Invalid audio input type");
104
- }
105
- /**
106
- * Checks that the global `File` constructor is available.
107
- * Throws a descriptive error in environments that lack it (e.g. Node < 20).
108
- */
109
- ensureFileSupport() {
110
- if (typeof File === "undefined") {
111
- throw new Error(
112
- "`File` is not available in this environment. Use Node.js 20 or newer, or pass a File object directly."
113
- );
114
- }
115
- }
116
- /**
117
- * Whether the adapter should default to verbose_json when no response format is specified.
118
- * Override in provider-specific subclasses for model-specific behavior.
119
- */
120
- shouldDefaultToVerbose(_model) {
121
- return false;
122
- }
123
- mapResponseFormat(format) {
124
- if (!format) return "json";
125
- return format;
126
- }
127
- }
128
- export {
129
- OpenAICompatibleTranscriptionAdapter
130
- };
131
- //# sourceMappingURL=transcription.js.map