@tanstack/ai 0.0.2 → 0.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 (147) hide show
  1. package/README.md +26 -0
  2. package/dist/esm/activities/chat/adapter.d.ts +100 -0
  3. package/dist/esm/activities/chat/adapter.js +14 -0
  4. package/dist/esm/activities/chat/adapter.js.map +1 -0
  5. package/dist/esm/{utilities → activities/chat}/agent-loop-strategies.d.ts +4 -4
  6. package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -0
  7. package/dist/esm/activities/chat/index.d.ts +165 -0
  8. package/dist/esm/{core/chat.js → activities/chat/index.js} +131 -33
  9. package/dist/esm/activities/chat/index.js.map +1 -0
  10. package/dist/esm/{message-converters.d.ts → activities/chat/messages.d.ts} +1 -1
  11. package/dist/esm/{message-converters.js → activities/chat/messages.js} +7 -7
  12. package/dist/esm/activities/chat/messages.js.map +1 -0
  13. package/dist/esm/activities/chat/stream/json-parser.js.map +1 -0
  14. package/dist/esm/{stream → activities/chat/stream}/message-updaters.d.ts +1 -1
  15. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -0
  16. package/dist/esm/{stream → activities/chat/stream}/processor.d.ts +1 -1
  17. package/dist/esm/{stream → activities/chat/stream}/processor.js +1 -1
  18. package/dist/esm/activities/chat/stream/processor.js.map +1 -0
  19. package/dist/esm/activities/chat/stream/strategies.js.map +1 -0
  20. package/dist/esm/{stream → activities/chat/stream}/types.d.ts +2 -9
  21. package/dist/esm/{tools → activities/chat/tools}/tool-calls.d.ts +1 -1
  22. package/dist/esm/{tools → activities/chat/tools}/tool-calls.js +9 -5
  23. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -0
  24. package/dist/esm/{tools → activities/chat/tools}/tool-definition.d.ts +14 -14
  25. package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -0
  26. package/dist/esm/activities/chat/tools/zod-converter.d.ts +69 -0
  27. package/dist/esm/activities/chat/tools/zod-converter.js +99 -0
  28. package/dist/esm/activities/chat/tools/zod-converter.js.map +1 -0
  29. package/dist/esm/activities/generateImage/adapter.d.ts +68 -0
  30. package/dist/esm/activities/generateImage/adapter.js +14 -0
  31. package/dist/esm/activities/generateImage/adapter.js.map +1 -0
  32. package/dist/esm/activities/generateImage/index.d.ts +89 -0
  33. package/dist/esm/activities/generateImage/index.js +15 -0
  34. package/dist/esm/activities/generateImage/index.js.map +1 -0
  35. package/dist/esm/activities/generateSpeech/adapter.d.ts +62 -0
  36. package/dist/esm/activities/generateSpeech/adapter.js +14 -0
  37. package/dist/esm/activities/generateSpeech/adapter.js.map +1 -0
  38. package/dist/esm/activities/generateSpeech/index.d.ts +69 -0
  39. package/dist/esm/activities/generateSpeech/index.js +15 -0
  40. package/dist/esm/activities/generateSpeech/index.js.map +1 -0
  41. package/dist/esm/activities/generateTranscription/adapter.d.ts +62 -0
  42. package/dist/esm/activities/generateTranscription/adapter.js +14 -0
  43. package/dist/esm/activities/generateTranscription/adapter.js.map +1 -0
  44. package/dist/esm/activities/generateTranscription/index.d.ts +71 -0
  45. package/dist/esm/activities/generateTranscription/index.js +15 -0
  46. package/dist/esm/activities/generateTranscription/index.js.map +1 -0
  47. package/dist/esm/activities/generateVideo/adapter.d.ts +80 -0
  48. package/dist/esm/activities/generateVideo/adapter.js +14 -0
  49. package/dist/esm/activities/generateVideo/adapter.js.map +1 -0
  50. package/dist/esm/activities/generateVideo/index.d.ts +136 -0
  51. package/dist/esm/activities/generateVideo/index.js +47 -0
  52. package/dist/esm/activities/generateVideo/index.js.map +1 -0
  53. package/dist/esm/activities/index.d.ts +22 -0
  54. package/dist/esm/activities/index.js +34 -0
  55. package/dist/esm/activities/index.js.map +1 -0
  56. package/dist/esm/activities/summarize/adapter.d.ts +74 -0
  57. package/dist/esm/activities/summarize/adapter.js +14 -0
  58. package/dist/esm/activities/summarize/adapter.js.map +1 -0
  59. package/dist/esm/activities/summarize/index.d.ts +100 -0
  60. package/dist/esm/activities/summarize/index.js +90 -0
  61. package/dist/esm/activities/summarize/index.js.map +1 -0
  62. package/dist/esm/event-client.d.ts +4 -45
  63. package/dist/esm/event-client.js +0 -49
  64. package/dist/esm/event-client.js.map +1 -1
  65. package/dist/esm/index.d.ts +16 -14
  66. package/dist/esm/index.js +28 -19
  67. package/dist/esm/stream-to-response.d.ts +95 -0
  68. package/dist/esm/stream-to-response.js +118 -0
  69. package/dist/esm/stream-to-response.js.map +1 -0
  70. package/dist/esm/types.d.ts +347 -129
  71. package/package.json +6 -2
  72. package/src/activities/chat/adapter.ts +150 -0
  73. package/src/{utilities → activities/chat}/agent-loop-strategies.ts +4 -4
  74. package/src/{core/chat.ts → activities/chat/index.ts} +427 -79
  75. package/src/{message-converters.ts → activities/chat/messages.ts} +10 -13
  76. package/src/{stream → activities/chat/stream}/message-updaters.ts +1 -1
  77. package/src/{stream → activities/chat/stream}/processor.ts +2 -5
  78. package/src/{stream → activities/chat/stream}/types.ts +8 -18
  79. package/src/{tools → activities/chat/tools}/tool-calls.ts +36 -11
  80. package/src/{tools → activities/chat/tools}/tool-definition.ts +36 -27
  81. package/src/activities/chat/tools/zod-converter.ts +235 -0
  82. package/src/activities/generateImage/adapter.ts +104 -0
  83. package/src/activities/generateImage/index.ts +162 -0
  84. package/src/activities/generateSpeech/adapter.ts +87 -0
  85. package/src/activities/generateSpeech/index.ts +122 -0
  86. package/src/activities/generateTranscription/adapter.ts +89 -0
  87. package/src/activities/generateTranscription/index.ts +132 -0
  88. package/src/activities/generateVideo/adapter.ts +116 -0
  89. package/src/activities/generateVideo/index.ts +261 -0
  90. package/src/activities/index.ts +164 -0
  91. package/src/activities/summarize/adapter.ts +107 -0
  92. package/src/activities/summarize/index.ts +287 -0
  93. package/src/event-client.ts +5 -101
  94. package/src/index.ts +58 -15
  95. package/src/stream-to-response.ts +237 -0
  96. package/src/types.ts +404 -280
  97. package/dist/esm/base-adapter.d.ts +0 -36
  98. package/dist/esm/base-adapter.js +0 -12
  99. package/dist/esm/base-adapter.js.map +0 -1
  100. package/dist/esm/core/chat-common-options.d.ts +0 -52
  101. package/dist/esm/core/chat.d.ts +0 -30
  102. package/dist/esm/core/chat.js.map +0 -1
  103. package/dist/esm/core/embedding.d.ts +0 -8
  104. package/dist/esm/core/embedding.js +0 -33
  105. package/dist/esm/core/embedding.js.map +0 -1
  106. package/dist/esm/core/summarize.d.ts +0 -9
  107. package/dist/esm/core/summarize.js +0 -36
  108. package/dist/esm/core/summarize.js.map +0 -1
  109. package/dist/esm/message-converters.js.map +0 -1
  110. package/dist/esm/stream/json-parser.js.map +0 -1
  111. package/dist/esm/stream/message-updaters.js.map +0 -1
  112. package/dist/esm/stream/processor.js.map +0 -1
  113. package/dist/esm/stream/strategies.js.map +0 -1
  114. package/dist/esm/tools/tool-calls.js.map +0 -1
  115. package/dist/esm/tools/tool-definition.js.map +0 -1
  116. package/dist/esm/tools/zod-converter.d.ts +0 -30
  117. package/dist/esm/tools/zod-converter.js +0 -36
  118. package/dist/esm/tools/zod-converter.js.map +0 -1
  119. package/dist/esm/utilities/agent-loop-strategies.js.map +0 -1
  120. package/dist/esm/utilities/chat-options.d.ts +0 -6
  121. package/dist/esm/utilities/chat-options.js +0 -7
  122. package/dist/esm/utilities/chat-options.js.map +0 -1
  123. package/dist/esm/utilities/messages.d.ts +0 -30
  124. package/dist/esm/utilities/messages.js +0 -7
  125. package/dist/esm/utilities/messages.js.map +0 -1
  126. package/dist/esm/utilities/stream-to-response.d.ts +0 -48
  127. package/dist/esm/utilities/stream-to-response.js +0 -62
  128. package/dist/esm/utilities/stream-to-response.js.map +0 -1
  129. package/src/base-adapter.ts +0 -86
  130. package/src/core/chat-common-options.ts +0 -55
  131. package/src/core/embedding.ts +0 -54
  132. package/src/core/summarize.ts +0 -56
  133. package/src/tools/zod-converter.ts +0 -85
  134. package/src/utilities/chat-options.ts +0 -35
  135. package/src/utilities/messages.ts +0 -63
  136. package/src/utilities/stream-to-response.ts +0 -116
  137. /package/dist/esm/{utilities → activities/chat}/agent-loop-strategies.js +0 -0
  138. /package/dist/esm/{stream → activities/chat/stream}/index.d.ts +0 -0
  139. /package/dist/esm/{stream → activities/chat/stream}/json-parser.d.ts +0 -0
  140. /package/dist/esm/{stream → activities/chat/stream}/json-parser.js +0 -0
  141. /package/dist/esm/{stream → activities/chat/stream}/message-updaters.js +0 -0
  142. /package/dist/esm/{stream → activities/chat/stream}/strategies.d.ts +0 -0
  143. /package/dist/esm/{stream → activities/chat/stream}/strategies.js +0 -0
  144. /package/dist/esm/{tools → activities/chat/tools}/tool-definition.js +0 -0
  145. /package/src/{stream → activities/chat/stream}/index.ts +0 -0
  146. /package/src/{stream → activities/chat/stream}/json-parser.ts +0 -0
  147. /package/src/{stream → activities/chat/stream}/strategies.ts +0 -0
@@ -1,36 +0,0 @@
1
- import { toJSONSchema } from "zod";
2
- function convertZodToJsonSchema(schema) {
3
- if (!schema) return void 0;
4
- const jsonSchema = toJSONSchema(schema, {
5
- target: "openapi-3.0",
6
- reused: "ref"
7
- });
8
- let result = jsonSchema;
9
- if (typeof result === "object" && "$schema" in result) {
10
- const { $schema, ...rest } = result;
11
- result = rest;
12
- }
13
- if (typeof result === "object") {
14
- const isZodObject = typeof schema === "object" && "def" in schema && schema.def.type === "object";
15
- if (isZodObject && !result.type) {
16
- result.type = "object";
17
- }
18
- if (Object.keys(result).length === 0) {
19
- result.type = "object";
20
- }
21
- if ("properties" in result && !result.type) {
22
- result.type = "object";
23
- }
24
- if (result.type === "object" && !("properties" in result)) {
25
- result.properties = {};
26
- }
27
- if (result.type === "object" && !("required" in result)) {
28
- result.required = [];
29
- }
30
- }
31
- return result;
32
- }
33
- export {
34
- convertZodToJsonSchema
35
- };
36
- //# sourceMappingURL=zod-converter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"zod-converter.js","sources":["../../../src/tools/zod-converter.ts"],"sourcesContent":["import { toJSONSchema } from 'zod'\nimport type { z } from 'zod'\n/**\n * Converts a Zod schema to JSON Schema format compatible with LLM providers.\n *\n *\n * @param schema - Zod schema to convert\n * @returns JSON Schema object that can be sent to LLM providers\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * location: z.string().describe('City name'),\n * unit: z.enum(['celsius', 'fahrenheit']).optional()\n * });\n *\n * const jsonSchema = convertZodToJsonSchema(schema);\n * // Returns:\n * // {\n * // type: 'object',\n * // properties: {\n * // location: { type: 'string', description: 'City name' },\n * // unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }\n * // },\n * // required: ['location']\n * // }\n * ```\n */\nexport function convertZodToJsonSchema(\n schema: z.ZodType | undefined,\n): Record<string, any> | undefined {\n if (!schema) return undefined\n\n // Use Alcyone Labs fork which is compatible with Zod v4\n const jsonSchema = toJSONSchema(schema, {\n target: 'openapi-3.0',\n reused: 'ref',\n })\n\n // Remove $schema property as it's not needed for LLM providers\n let result = jsonSchema\n if (typeof result === 'object' && '$schema' in result) {\n const { $schema, ...rest } = result\n result = rest\n }\n\n // Ensure object schemas always have type: \"object\"\n // This fixes cases where zod-to-json-schema doesn't set type for empty objects\n if (typeof result === 'object') {\n // Check if the input schema is a ZodObject by inspecting its internal structure\n const isZodObject =\n typeof schema === 'object' &&\n 'def' in schema &&\n schema.def.type === 'object'\n\n // If we know it's a ZodObject but result doesn't have type, set it\n if (isZodObject && !result.type) {\n result.type = 'object'\n }\n\n // If result is completely empty (no keys), it's likely an empty object schema\n if (Object.keys(result).length === 0) {\n result.type = 'object'\n }\n\n // If it has properties (even empty), it should be an object type\n if ('properties' in result && !result.type) {\n result.type = 'object'\n }\n\n // Ensure properties exists for object types (even if empty)\n if (result.type === 'object' && !('properties' in result)) {\n result.properties = {}\n }\n\n // Ensure required exists for object types (even if empty array)\n if (result.type === 'object' && !('required' in result)) {\n result.required = []\n }\n }\n\n return result\n}\n"],"names":[],"mappings":";AA8BO,SAAS,uBACd,QACiC;AACjC,MAAI,CAAC,OAAQ,QAAO;AAGpB,QAAM,aAAa,aAAa,QAAQ;AAAA,IACtC,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA,CACT;AAGD,MAAI,SAAS;AACb,MAAI,OAAO,WAAW,YAAY,aAAa,QAAQ;AACrD,UAAM,EAAE,SAAS,GAAG,KAAA,IAAS;AAC7B,aAAS;AAAA,EACX;AAIA,MAAI,OAAO,WAAW,UAAU;AAE9B,UAAM,cACJ,OAAO,WAAW,YAClB,SAAS,UACT,OAAO,IAAI,SAAS;AAGtB,QAAI,eAAe,CAAC,OAAO,MAAM;AAC/B,aAAO,OAAO;AAAA,IAChB;AAGA,QAAI,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AACpC,aAAO,OAAO;AAAA,IAChB;AAGA,QAAI,gBAAgB,UAAU,CAAC,OAAO,MAAM;AAC1C,aAAO,OAAO;AAAA,IAChB;AAGA,QAAI,OAAO,SAAS,YAAY,EAAE,gBAAgB,SAAS;AACzD,aAAO,aAAa,CAAA;AAAA,IACtB;AAGA,QAAI,OAAO,SAAS,YAAY,EAAE,cAAc,SAAS;AACvD,aAAO,WAAW,CAAA;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AACT;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-loop-strategies.js","sources":["../../../src/utilities/agent-loop-strategies.ts"],"sourcesContent":["import type { AgentLoopStrategy } from '../types'\n\n/**\n * Creates a strategy that continues for a maximum number of iterations\n *\n * @param max - Maximum number of iterations to allow\n * @returns AgentLoopStrategy that stops after max iterations\n *\n * @example\n * ```typescript\n * const stream = chat({\n * adapter: openai(),\n * model: \"gpt-4o\",\n * messages: [...],\n * tools: [weatherTool],\n * agentLoopStrategy: maxIterations(3), // Max 3 iterations\n * });\n * ```\n */\nexport function maxIterations(max: number): AgentLoopStrategy {\n return ({ iterationCount }) => iterationCount < max\n}\n\n/**\n * Creates a strategy that continues until a specific finish reason is encountered\n *\n * @param stopReasons - Finish reasons that should stop the loop\n * @returns AgentLoopStrategy that stops on specific finish reasons\n *\n * @example\n * ```typescript\n * const stream = chat({\n * adapter: openai(),\n * model: \"gpt-4o\",\n * messages: [...],\n * tools: [weatherTool],\n * agentLoopStrategy: untilFinishReason([\"stop\", \"length\"]),\n * });\n * ```\n */\nexport function untilFinishReason(\n stopReasons: Array<string>,\n): AgentLoopStrategy {\n return ({ finishReason, iterationCount }) => {\n // Always allow at least one iteration\n if (iterationCount === 0) return true\n\n // Stop if we hit a stop reason\n if (finishReason && stopReasons.includes(finishReason)) {\n return false\n }\n\n // Otherwise continue\n return true\n }\n}\n\n/**\n * Creates a strategy that combines multiple strategies with AND logic\n * All strategies must return true to continue\n *\n * @param strategies - Array of strategies to combine\n * @returns AgentLoopStrategy that continues only if all strategies return true\n *\n * @example\n * ```typescript\n * const stream = chat({\n * adapter: openai(),\n * model: \"gpt-4o\",\n * messages: [...],\n * tools: [weatherTool],\n * agentLoopStrategy: combineStrategies([\n * maxIterations(10),\n * ({ messages }) => messages.length < 100,\n * ]),\n * });\n * ```\n */\nexport function combineStrategies(\n strategies: Array<AgentLoopStrategy>,\n): AgentLoopStrategy {\n return (state) => {\n return strategies.every((strategy) => strategy(state))\n }\n}\n"],"names":[],"mappings":"AAmBO,SAAS,cAAc,KAAgC;AAC5D,SAAO,CAAC,EAAE,qBAAqB,iBAAiB;AAClD;AAmBO,SAAS,kBACd,aACmB;AACnB,SAAO,CAAC,EAAE,cAAc,qBAAqB;AAE3C,QAAI,mBAAmB,EAAG,QAAO;AAGjC,QAAI,gBAAgB,YAAY,SAAS,YAAY,GAAG;AACtD,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AACF;AAuBO,SAAS,kBACd,YACmB;AACnB,SAAO,CAAC,UAAU;AAChB,WAAO,WAAW,MAAM,CAAC,aAAa,SAAS,KAAK,CAAC;AAAA,EACvD;AACF;"}
@@ -1,6 +0,0 @@
1
- import { AIAdapter, ChatStreamOptionsUnion } from '../types.js';
2
- export declare function chatOptions<TAdapter extends AIAdapter<any, any, any, any, any>, const TModel extends TAdapter extends AIAdapter<infer Models, any, any, any, any> ? Models[number] : string>(options: Omit<ChatStreamOptionsUnion<TAdapter>, 'providerOptions' | 'model' | 'messages' | 'abortController'> & {
3
- adapter: TAdapter;
4
- model: TModel;
5
- providerOptions?: TAdapter extends AIAdapter<any, any, any, any, infer ModelProviderOptions> ? TModel extends keyof ModelProviderOptions ? ModelProviderOptions[TModel] : never : never;
6
- }): typeof options;
@@ -1,7 +0,0 @@
1
- function chatOptions(options) {
2
- return options;
3
- }
4
- export {
5
- chatOptions
6
- };
7
- //# sourceMappingURL=chat-options.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat-options.js","sources":["../../../src/utilities/chat-options.ts"],"sourcesContent":["import type { AIAdapter, ChatStreamOptionsUnion } from '../types'\n\nexport function chatOptions<\n TAdapter extends AIAdapter<any, any, any, any, any>,\n const TModel extends TAdapter extends AIAdapter<\n infer Models,\n any,\n any,\n any,\n any\n >\n ? Models[number]\n : string,\n>(\n options: Omit<\n ChatStreamOptionsUnion<TAdapter>,\n 'providerOptions' | 'model' | 'messages' | 'abortController'\n > & {\n adapter: TAdapter\n model: TModel\n providerOptions?: TAdapter extends AIAdapter<\n any,\n any,\n any,\n any,\n infer ModelProviderOptions\n >\n ? TModel extends keyof ModelProviderOptions\n ? ModelProviderOptions[TModel]\n : never\n : never\n },\n): typeof options {\n return options\n}\n"],"names":[],"mappings":"AAEO,SAAS,YAYd,SAkBgB;AAChB,SAAO;AACT;"}
@@ -1,30 +0,0 @@
1
- import { AIAdapter, ConstrainedModelMessage, Modality, ModelMessage } from '../types.js';
2
- /**
3
- * Type-safe helper to create a messages array constrained by a model's supported modalities.
4
- *
5
- * This function provides compile-time checking that your messages only contain
6
- * content types supported by the specified model. It's particularly useful when
7
- * combining typed messages with untyped data (like from request.json()).
8
- *
9
- * @example
10
- * ```typescript
11
- * import { messages, chat } from '@tanstack/ai'
12
- * import { openai } from '@tanstack/ai-openai'
13
- *
14
- * const adapter = openai()
15
- *
16
- * // This will error at compile time because gpt-4o only supports text+image
17
- * const msgs = messages({ adapter, model: 'gpt-4o' }, [
18
- * {
19
- * role: 'user',
20
- * content: [
21
- * { type: 'video', source: { type: 'url', value: '...' } } // Error!
22
- * ]
23
- * }
24
- * ])
25
- * ```
26
- */
27
- export declare function messages<TAdapter extends AIAdapter<any, any, any, any, any, any>, const TModel extends TAdapter extends AIAdapter<infer Models, any, any, any, any, any> ? Models[number] : string>(_options: {
28
- adapter: TAdapter;
29
- model: TModel;
30
- }, msgs: TAdapter extends AIAdapter<any, any, any, any, any, infer ModelInputModalities> ? TModel extends keyof ModelInputModalities ? ModelInputModalities[TModel] extends ReadonlyArray<Modality> ? Array<ConstrainedModelMessage<ModelInputModalities[TModel]>> : Array<ModelMessage> : Array<ModelMessage> : Array<ModelMessage>): typeof msgs;
@@ -1,7 +0,0 @@
1
- function messages(_options, msgs) {
2
- return msgs;
3
- }
4
- export {
5
- messages
6
- };
7
- //# sourceMappingURL=messages.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"messages.js","sources":["../../../src/utilities/messages.ts"],"sourcesContent":["import type {\n AIAdapter,\n ConstrainedModelMessage,\n Modality,\n ModelMessage,\n} from '../types'\n\n/**\n * Type-safe helper to create a messages array constrained by a model's supported modalities.\n *\n * This function provides compile-time checking that your messages only contain\n * content types supported by the specified model. It's particularly useful when\n * combining typed messages with untyped data (like from request.json()).\n *\n * @example\n * ```typescript\n * import { messages, chat } from '@tanstack/ai'\n * import { openai } from '@tanstack/ai-openai'\n *\n * const adapter = openai()\n *\n * // This will error at compile time because gpt-4o only supports text+image\n * const msgs = messages({ adapter, model: 'gpt-4o' }, [\n * {\n * role: 'user',\n * content: [\n * { type: 'video', source: { type: 'url', value: '...' } } // Error!\n * ]\n * }\n * ])\n * ```\n */\nexport function messages<\n TAdapter extends AIAdapter<any, any, any, any, any, any>,\n const TModel extends TAdapter extends AIAdapter<\n infer Models,\n any,\n any,\n any,\n any,\n any\n >\n ? Models[number]\n : string,\n>(\n _options: { adapter: TAdapter; model: TModel },\n msgs: TAdapter extends AIAdapter<\n any,\n any,\n any,\n any,\n any,\n infer ModelInputModalities\n >\n ? TModel extends keyof ModelInputModalities\n ? ModelInputModalities[TModel] extends ReadonlyArray<Modality>\n ? Array<ConstrainedModelMessage<ModelInputModalities[TModel]>>\n : Array<ModelMessage>\n : Array<ModelMessage>\n : Array<ModelMessage>,\n): typeof msgs {\n return msgs\n}\n"],"names":[],"mappings":"AAgCO,SAAS,SAad,UACA,MAca;AACb,SAAO;AACT;"}
@@ -1,48 +0,0 @@
1
- import { StreamChunk } from '../types.js';
2
- /**
3
- * Convert a StreamChunk async iterable to a ReadableStream in Server-Sent Events format
4
- *
5
- * This creates a ReadableStream that emits chunks in SSE format:
6
- * - Each chunk is prefixed with "data: "
7
- * - Each chunk is followed by "\n\n"
8
- * - Stream ends with "data: [DONE]\n\n"
9
- *
10
- * @param stream - AsyncIterable of StreamChunks from chat()
11
- * @param abortController - Optional AbortController to abort when stream is cancelled
12
- * @returns ReadableStream in Server-Sent Events format
13
- *
14
- * @example
15
- * ```typescript
16
- * const stream = chat({ adapter: openai(), model: "gpt-4o", messages: [...] });
17
- * const readableStream = toServerSentEventsStream(stream);
18
- * // Use with Response, or any API that accepts ReadableStream
19
- * ```
20
- */
21
- export declare function toServerSentEventsStream(stream: AsyncIterable<StreamChunk>, abortController?: AbortController): ReadableStream<Uint8Array>;
22
- /**
23
- * Create a streaming HTTP response from a StreamChunk async iterable
24
- * Includes proper headers for Server-Sent Events
25
- *
26
- * @param stream - AsyncIterable of StreamChunks from chat()
27
- * @param init - Optional Response initialization options
28
- * @param abortController - Optional AbortController to abort when client disconnects
29
- * @returns Response object with SSE headers and streaming body
30
- *
31
- * @example
32
- * ```typescript
33
- * export async function POST(request: Request) {
34
- * const { messages } = await request.json();
35
- * const abortController = new AbortController();
36
- * const stream = chat({
37
- * adapter: openai(),
38
- * model: "gpt-4o",
39
- * messages,
40
- * options: { abortSignal: abortController.signal }
41
- * });
42
- * return toStreamResponse(stream, undefined, abortController);
43
- * }
44
- * ```
45
- */
46
- export declare function toStreamResponse(stream: AsyncIterable<StreamChunk>, init?: ResponseInit & {
47
- abortController?: AbortController;
48
- }): Response;
@@ -1,62 +0,0 @@
1
- function toServerSentEventsStream(stream, abortController) {
2
- const encoder = new TextEncoder();
3
- return new ReadableStream({
4
- async start(controller) {
5
- try {
6
- for await (const chunk of stream) {
7
- if (abortController?.signal.aborted) {
8
- break;
9
- }
10
- controller.enqueue(
11
- encoder.encode(`data: ${JSON.stringify(chunk)}
12
-
13
- `)
14
- );
15
- }
16
- controller.enqueue(encoder.encode("data: [DONE]\n\n"));
17
- controller.close();
18
- } catch (error) {
19
- if (abortController?.signal.aborted) {
20
- controller.close();
21
- return;
22
- }
23
- controller.enqueue(
24
- encoder.encode(
25
- `data: ${JSON.stringify({
26
- type: "error",
27
- error: {
28
- message: error.message || "Unknown error occurred",
29
- code: error.code
30
- }
31
- })}
32
-
33
- `
34
- )
35
- );
36
- controller.close();
37
- }
38
- },
39
- cancel() {
40
- if (abortController) {
41
- abortController.abort();
42
- }
43
- }
44
- });
45
- }
46
- function toStreamResponse(stream, init) {
47
- const { headers, abortController, ...responseInit } = init ?? {};
48
- return new Response(toServerSentEventsStream(stream, abortController), {
49
- ...responseInit,
50
- headers: {
51
- "Content-Type": "text/event-stream",
52
- "Cache-Control": "no-cache",
53
- Connection: "keep-alive",
54
- ...headers || {}
55
- }
56
- });
57
- }
58
- export {
59
- toServerSentEventsStream,
60
- toStreamResponse
61
- };
62
- //# sourceMappingURL=stream-to-response.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-to-response.js","sources":["../../../src/utilities/stream-to-response.ts"],"sourcesContent":["import type { StreamChunk } from '../types'\n\n/**\n * Convert a StreamChunk async iterable to a ReadableStream in Server-Sent Events format\n *\n * This creates a ReadableStream that emits chunks in SSE format:\n * - Each chunk is prefixed with \"data: \"\n * - Each chunk is followed by \"\\n\\n\"\n * - Stream ends with \"data: [DONE]\\n\\n\"\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param abortController - Optional AbortController to abort when stream is cancelled\n * @returns ReadableStream in Server-Sent Events format\n *\n * @example\n * ```typescript\n * const stream = chat({ adapter: openai(), model: \"gpt-4o\", messages: [...] });\n * const readableStream = toServerSentEventsStream(stream);\n * // Use with Response, or any API that accepts ReadableStream\n * ```\n */\nexport function toServerSentEventsStream(\n stream: AsyncIterable<StreamChunk>,\n abortController?: AbortController,\n): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder()\n\n return new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Check if stream was cancelled/aborted\n if (abortController?.signal.aborted) {\n break\n }\n\n // Send each chunk as Server-Sent Events format\n controller.enqueue(\n encoder.encode(`data: ${JSON.stringify(chunk)}\\n\\n`),\n )\n }\n\n // Send completion marker\n controller.enqueue(encoder.encode('data: [DONE]\\n\\n'))\n controller.close()\n } catch (error: any) {\n // Don't send error if aborted\n if (abortController?.signal.aborted) {\n controller.close()\n return\n }\n\n // Send error chunk\n controller.enqueue(\n encoder.encode(\n `data: ${JSON.stringify({\n type: 'error',\n error: {\n message: error.message || 'Unknown error occurred',\n code: error.code,\n },\n })}\\n\\n`,\n ),\n )\n controller.close()\n }\n },\n cancel() {\n // When the ReadableStream is cancelled (e.g., client disconnects),\n // abort the underlying stream\n if (abortController) {\n abortController.abort()\n }\n },\n })\n}\n\n/**\n * Create a streaming HTTP response from a StreamChunk async iterable\n * Includes proper headers for Server-Sent Events\n *\n * @param stream - AsyncIterable of StreamChunks from chat()\n * @param init - Optional Response initialization options\n * @param abortController - Optional AbortController to abort when client disconnects\n * @returns Response object with SSE headers and streaming body\n *\n * @example\n * ```typescript\n * export async function POST(request: Request) {\n * const { messages } = await request.json();\n * const abortController = new AbortController();\n * const stream = chat({\n * adapter: openai(),\n * model: \"gpt-4o\",\n * messages,\n * options: { abortSignal: abortController.signal }\n * });\n * return toStreamResponse(stream, undefined, abortController);\n * }\n * ```\n */\nexport function toStreamResponse(\n stream: AsyncIterable<StreamChunk>,\n init?: ResponseInit & { abortController?: AbortController },\n): Response {\n const { headers, abortController, ...responseInit } = init ?? {}\n return new Response(toServerSentEventsStream(stream, abortController), {\n ...responseInit,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n ...(headers || {}),\n },\n })\n}\n"],"names":[],"mappings":"AAqBO,SAAS,yBACd,QACA,iBAC4B;AAC5B,QAAM,UAAU,IAAI,YAAA;AAEpB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,MAAM,YAAY;AACtB,UAAI;AACF,yBAAiB,SAAS,QAAQ;AAEhC,cAAI,iBAAiB,OAAO,SAAS;AACnC;AAAA,UACF;AAGA,qBAAW;AAAA,YACT,QAAQ,OAAO,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA,CAAM;AAAA,UAAA;AAAA,QAEvD;AAGA,mBAAW,QAAQ,QAAQ,OAAO,kBAAkB,CAAC;AACrD,mBAAW,MAAA;AAAA,MACb,SAAS,OAAY;AAEnB,YAAI,iBAAiB,OAAO,SAAS;AACnC,qBAAW,MAAA;AACX;AAAA,QACF;AAGA,mBAAW;AAAA,UACT,QAAQ;AAAA,YACN,SAAS,KAAK,UAAU;AAAA,cACtB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,SAAS,MAAM,WAAW;AAAA,gBAC1B,MAAM,MAAM;AAAA,cAAA;AAAA,YACd,CACD,CAAC;AAAA;AAAA;AAAA,UAAA;AAAA,QACJ;AAEF,mBAAW,MAAA;AAAA,MACb;AAAA,IACF;AAAA,IACA,SAAS;AAGP,UAAI,iBAAiB;AACnB,wBAAgB,MAAA;AAAA,MAClB;AAAA,IACF;AAAA,EAAA,CACD;AACH;AA0BO,SAAS,iBACd,QACA,MACU;AACV,QAAM,EAAE,SAAS,iBAAiB,GAAG,aAAA,IAAiB,QAAQ,CAAA;AAC9D,SAAO,IAAI,SAAS,yBAAyB,QAAQ,eAAe,GAAG;AAAA,IACrE,GAAG;AAAA,IACH,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,YAAY;AAAA,MACZ,GAAI,WAAW,CAAA;AAAA,IAAC;AAAA,EAClB,CACD;AACH;"}
@@ -1,86 +0,0 @@
1
- import type {
2
- AIAdapter,
3
- AIAdapterConfig,
4
- ChatOptions,
5
- DefaultMessageMetadataByModality,
6
- EmbeddingOptions,
7
- EmbeddingResult,
8
- Modality,
9
- StreamChunk,
10
- SummarizationOptions,
11
- SummarizationResult,
12
- } from './types'
13
-
14
- /**
15
- * Base adapter class with support for endpoint-specific models and provider options.
16
- *
17
- * Generic parameters:
18
- * - TChatModels: Models that support chat/text completion
19
- * - TEmbeddingModels: Models that support embeddings
20
- * - TChatProviderOptions: Provider-specific options for chat endpoint
21
- * - TEmbeddingProviderOptions: Provider-specific options for embedding endpoint
22
- * - TModelProviderOptionsByName: Provider-specific options for model by name
23
- * - TModelInputModalitiesByName: Map from model name to its supported input modalities
24
- * - TMessageMetadataByModality: Map from modality type to adapter-specific metadata types
25
- */
26
- export abstract class BaseAdapter<
27
- TChatModels extends ReadonlyArray<string> = ReadonlyArray<string>,
28
- TEmbeddingModels extends ReadonlyArray<string> = ReadonlyArray<string>,
29
- TChatProviderOptions extends Record<string, any> = Record<string, any>,
30
- TEmbeddingProviderOptions extends Record<string, any> = Record<string, any>,
31
- TModelProviderOptionsByName extends Record<string, any> = Record<string, any>,
32
- TModelInputModalitiesByName extends Record<
33
- string,
34
- ReadonlyArray<Modality>
35
- > = Record<string, ReadonlyArray<Modality>>,
36
- TMessageMetadataByModality extends {
37
- text: unknown
38
- image: unknown
39
- audio: unknown
40
- video: unknown
41
- document: unknown
42
- } = DefaultMessageMetadataByModality,
43
- > implements
44
- AIAdapter<
45
- TChatModels,
46
- TEmbeddingModels,
47
- TChatProviderOptions,
48
- TEmbeddingProviderOptions,
49
- TModelProviderOptionsByName,
50
- TModelInputModalitiesByName,
51
- TMessageMetadataByModality
52
- >
53
- {
54
- abstract name: string
55
- abstract models: TChatModels
56
- embeddingModels?: TEmbeddingModels
57
- protected config: AIAdapterConfig
58
-
59
- // These properties are used for type inference only, never assigned at runtime
60
- _providerOptions?: TChatProviderOptions
61
- _chatProviderOptions?: TChatProviderOptions
62
- _embeddingProviderOptions?: TEmbeddingProviderOptions
63
- // Type-only map; concrete adapters should override this with a precise type
64
- _modelProviderOptionsByName!: TModelProviderOptionsByName
65
- // Type-only map for model input modalities; concrete adapters should override this
66
- _modelInputModalitiesByName?: TModelInputModalitiesByName
67
- // Type-only map for message metadata types; concrete adapters should override this
68
- _messageMetadataByModality?: TMessageMetadataByModality
69
-
70
- constructor(config: AIAdapterConfig = {}) {
71
- this.config = config
72
- }
73
-
74
- abstract chatStream(options: ChatOptions): AsyncIterable<StreamChunk>
75
-
76
- abstract summarize(
77
- options: SummarizationOptions,
78
- ): Promise<SummarizationResult>
79
- abstract createEmbeddings(options: EmbeddingOptions): Promise<EmbeddingResult>
80
-
81
- protected generateId(): string {
82
- return `${this.name}-${Date.now()}-${Math.random()
83
- .toString(36)
84
- .substring(7)}`
85
- }
86
- }
@@ -1,55 +0,0 @@
1
- /**
2
- * Common options shared across different AI provider implementations.
3
- * These options represent the standard parameters that work across OpenAI, Anthropic, and Gemini.
4
- */
5
- export interface CommonOptions {
6
- /**
7
- * Controls the randomness of the output.
8
- * Higher values (e.g., 0.8) make output more random, lower values (e.g., 0.2) make it more focused and deterministic.
9
- * Range: [0.0, 2.0]
10
- *
11
- * Note: Generally recommended to use either temperature or topP, but not both.
12
- *
13
- * Provider usage:
14
- * - OpenAI: `temperature` (number) - in text.top_p field
15
- * - Anthropic: `temperature` (number) - ranges from 0.0 to 1.0, default 1.0
16
- * - Gemini: `generationConfig.temperature` (number) - ranges from 0.0 to 2.0
17
- */
18
- temperature?: number
19
-
20
- /**
21
- * Nucleus sampling parameter. An alternative to temperature sampling.
22
- * The model considers the results of tokens with topP probability mass.
23
- * For example, 0.1 means only tokens comprising the top 10% probability mass are considered.
24
- *
25
- * Note: Generally recommended to use either temperature or topP, but not both.
26
- *
27
- * Provider usage:
28
- * - OpenAI: `text.top_p` (number)
29
- * - Anthropic: `top_p` (number | null)
30
- * - Gemini: `generationConfig.topP` (number)
31
- */
32
- topP?: number
33
-
34
- /**
35
- * The maximum number of tokens to generate in the response.
36
- *
37
- * Provider usage:
38
- * - OpenAI: `max_output_tokens` (number) - includes visible output and reasoning tokens
39
- * - Anthropic: `max_tokens` (number, required) - range x >= 1
40
- * - Gemini: `generationConfig.maxOutputTokens` (number)
41
- */
42
- maxTokens?: number
43
-
44
- /**
45
- * Additional metadata to attach to the request.
46
- * Can be used for tracking, debugging, or passing custom information.
47
- * Structure and constraints vary by provider.
48
- *
49
- * Provider usage:
50
- * - OpenAI: `metadata` (Record<string, string>) - max 16 key-value pairs, keys max 64 chars, values max 512 chars
51
- * - Anthropic: `metadata` (Record<string, any>) - includes optional user_id (max 256 chars)
52
- * - Gemini: Not directly available in TextProviderOptions
53
- */
54
- metadata?: Record<string, any>
55
- }
@@ -1,54 +0,0 @@
1
- import { aiEventClient } from '../event-client.js'
2
- import type {
3
- AIAdapter,
4
- EmbeddingOptions,
5
- EmbeddingResult,
6
- ExtractModelsFromAdapter,
7
- } from '../types'
8
-
9
- function createId(prefix: string): string {
10
- return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
11
- }
12
-
13
- /**
14
- * Standalone embedding function with type inference from adapter
15
- */
16
- export async function embedding<
17
- TAdapter extends AIAdapter<any, any, any, any, any>,
18
- >(
19
- options: Omit<EmbeddingOptions, 'model'> & {
20
- adapter: TAdapter
21
- model: ExtractModelsFromAdapter<TAdapter>
22
- },
23
- ): Promise<EmbeddingResult> {
24
- const { adapter, model, ...restOptions } = options
25
- const requestId = createId('embedding')
26
- const inputCount = Array.isArray(restOptions.input)
27
- ? restOptions.input.length
28
- : 1
29
- const startTime = Date.now()
30
-
31
- aiEventClient.emit('embedding:started', {
32
- requestId,
33
- model: model as string,
34
- inputCount,
35
- timestamp: startTime,
36
- })
37
-
38
- const result = await adapter.createEmbeddings({
39
- ...restOptions,
40
- model: model as string,
41
- })
42
-
43
- const duration = Date.now() - startTime
44
-
45
- aiEventClient.emit('embedding:completed', {
46
- requestId,
47
- model: model as string,
48
- inputCount,
49
- duration,
50
- timestamp: Date.now(),
51
- })
52
-
53
- return result
54
- }
@@ -1,56 +0,0 @@
1
- import { aiEventClient } from '../event-client.js'
2
- import type {
3
- AIAdapter,
4
- ExtractModelsFromAdapter,
5
- SummarizationOptions,
6
- SummarizationResult,
7
- } from '../types'
8
-
9
- function createId(prefix: string): string {
10
- return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
11
- }
12
-
13
- /**
14
- * Standalone summarize function with type inference from adapter
15
- */
16
- export async function summarize<
17
- TAdapter extends AIAdapter<any, any, any, any, any>,
18
- >(
19
- options: Omit<SummarizationOptions, 'model'> & {
20
- adapter: TAdapter
21
- model: ExtractModelsFromAdapter<TAdapter>
22
- text: string
23
- },
24
- ): Promise<SummarizationResult> {
25
- const { adapter, model, text, ...restOptions } = options
26
- const requestId = createId('summarize')
27
- const inputLength = text.length
28
- const startTime = Date.now()
29
-
30
- aiEventClient.emit('summarize:started', {
31
- requestId,
32
- model: model as string,
33
- inputLength,
34
- timestamp: startTime,
35
- })
36
-
37
- const result = await adapter.summarize({
38
- ...restOptions,
39
- text,
40
- model: model as string,
41
- })
42
-
43
- const duration = Date.now() - startTime
44
- const outputLength = result.summary.length
45
-
46
- aiEventClient.emit('summarize:completed', {
47
- requestId,
48
- model: model as string,
49
- inputLength,
50
- outputLength,
51
- duration,
52
- timestamp: Date.now(),
53
- })
54
-
55
- return result
56
- }
@@ -1,85 +0,0 @@
1
- import { toJSONSchema } from 'zod'
2
- import type { z } from 'zod'
3
- /**
4
- * Converts a Zod schema to JSON Schema format compatible with LLM providers.
5
- *
6
- *
7
- * @param schema - Zod schema to convert
8
- * @returns JSON Schema object that can be sent to LLM providers
9
- *
10
- * @example
11
- * ```typescript
12
- * import { z } from 'zod';
13
- *
14
- * const schema = z.object({
15
- * location: z.string().describe('City name'),
16
- * unit: z.enum(['celsius', 'fahrenheit']).optional()
17
- * });
18
- *
19
- * const jsonSchema = convertZodToJsonSchema(schema);
20
- * // Returns:
21
- * // {
22
- * // type: 'object',
23
- * // properties: {
24
- * // location: { type: 'string', description: 'City name' },
25
- * // unit: { type: 'string', enum: ['celsius', 'fahrenheit'] }
26
- * // },
27
- * // required: ['location']
28
- * // }
29
- * ```
30
- */
31
- export function convertZodToJsonSchema(
32
- schema: z.ZodType | undefined,
33
- ): Record<string, any> | undefined {
34
- if (!schema) return undefined
35
-
36
- // Use Alcyone Labs fork which is compatible with Zod v4
37
- const jsonSchema = toJSONSchema(schema, {
38
- target: 'openapi-3.0',
39
- reused: 'ref',
40
- })
41
-
42
- // Remove $schema property as it's not needed for LLM providers
43
- let result = jsonSchema
44
- if (typeof result === 'object' && '$schema' in result) {
45
- const { $schema, ...rest } = result
46
- result = rest
47
- }
48
-
49
- // Ensure object schemas always have type: "object"
50
- // This fixes cases where zod-to-json-schema doesn't set type for empty objects
51
- if (typeof result === 'object') {
52
- // Check if the input schema is a ZodObject by inspecting its internal structure
53
- const isZodObject =
54
- typeof schema === 'object' &&
55
- 'def' in schema &&
56
- schema.def.type === 'object'
57
-
58
- // If we know it's a ZodObject but result doesn't have type, set it
59
- if (isZodObject && !result.type) {
60
- result.type = 'object'
61
- }
62
-
63
- // If result is completely empty (no keys), it's likely an empty object schema
64
- if (Object.keys(result).length === 0) {
65
- result.type = 'object'
66
- }
67
-
68
- // If it has properties (even empty), it should be an object type
69
- if ('properties' in result && !result.type) {
70
- result.type = 'object'
71
- }
72
-
73
- // Ensure properties exists for object types (even if empty)
74
- if (result.type === 'object' && !('properties' in result)) {
75
- result.properties = {}
76
- }
77
-
78
- // Ensure required exists for object types (even if empty array)
79
- if (result.type === 'object' && !('required' in result)) {
80
- result.required = []
81
- }
82
- }
83
-
84
- return result
85
- }
@@ -1,35 +0,0 @@
1
- import type { AIAdapter, ChatStreamOptionsUnion } from '../types'
2
-
3
- export function chatOptions<
4
- TAdapter extends AIAdapter<any, any, any, any, any>,
5
- const TModel extends TAdapter extends AIAdapter<
6
- infer Models,
7
- any,
8
- any,
9
- any,
10
- any
11
- >
12
- ? Models[number]
13
- : string,
14
- >(
15
- options: Omit<
16
- ChatStreamOptionsUnion<TAdapter>,
17
- 'providerOptions' | 'model' | 'messages' | 'abortController'
18
- > & {
19
- adapter: TAdapter
20
- model: TModel
21
- providerOptions?: TAdapter extends AIAdapter<
22
- any,
23
- any,
24
- any,
25
- any,
26
- infer ModelProviderOptions
27
- >
28
- ? TModel extends keyof ModelProviderOptions
29
- ? ModelProviderOptions[TModel]
30
- : never
31
- : never
32
- },
33
- ): typeof options {
34
- return options
35
- }