@webiny/api-core 6.5.0-beta.6 → 6.5.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/features/ai/Ai.js CHANGED
@@ -4,6 +4,11 @@ import { Ai, AiConnectionFactory, AiModelRegistry, AiSdkFactory } from "./abstra
4
4
  import { mdbid } from "@webiny/utils/mdbid.js";
5
5
  import { EventPublisher } from "../eventPublisher/index.js";
6
6
  import { AiAfterGenerateTextEvent, AiBeforeGenerateTextEvent, AiBeforeStreamTextEvent, AiGenerateTextErrorEvent } from "./events.js";
7
+ const withSupportedOptions = (options, model)=>{
8
+ if (void 0 === options.temperature || model.supports?.temperature === true) return options;
9
+ const { temperature: _temperature, ...rest } = options;
10
+ return rest;
11
+ };
7
12
  class AiImpl {
8
13
  constructor(sdkFactories, connectionFactories, eventPublisher, modelRegistry){
9
14
  this.sdkFactories = sdkFactories;
@@ -14,8 +19,9 @@ class AiImpl {
14
19
  this.resolvedConnections = null;
15
20
  }
16
21
  async generateText(params) {
17
- const { model, connection, ...rest } = params;
18
- const resolvedModel = await this.resolveLanguageModel(model, connection);
22
+ const { model, connection, ...options } = params;
23
+ const { languageModel: resolvedModel, model: catalogModel } = await this.resolveLanguageModel(model, connection);
24
+ const rest = withSupportedOptions(options, catalogModel);
19
25
  const requestId = mdbid();
20
26
  await this.eventPublisher.publish(new AiBeforeGenerateTextEvent({
21
27
  requestId,
@@ -48,8 +54,9 @@ class AiImpl {
48
54
  }
49
55
  }
50
56
  async streamText(params) {
51
- const { model, connection, ...rest } = params;
52
- const resolvedModel = await this.resolveLanguageModel(model, connection);
57
+ const { model, connection, ...options } = params;
58
+ const { languageModel: resolvedModel, model: catalogModel } = await this.resolveLanguageModel(model, connection);
59
+ const rest = withSupportedOptions(options, catalogModel);
53
60
  await this.eventPublisher.publish(new AiBeforeStreamTextEvent({
54
61
  params
55
62
  }));
@@ -82,11 +89,14 @@ class AiImpl {
82
89
  const providerId = modelId.slice(0, slashIndex);
83
90
  const rawModelId = modelId.slice(slashIndex + 1);
84
91
  const models = await this.modelRegistry.listModels();
85
- const found = models.some((m)=>m.providerId === providerId && m.modelId === rawModelId);
92
+ const found = models.find((m)=>m.providerId === providerId && m.modelId === rawModelId);
86
93
  if (!found) throw new Error(`Model "${modelId}" is not available. Use listModels() to see available models.`);
87
94
  const conn = await this.resolveConnection(providerId, connection);
88
95
  const sdk = await this.getSdk(conn);
89
- return sdk.languageModel(rawModelId);
96
+ return {
97
+ languageModel: sdk.languageModel(rawModelId),
98
+ model: found
99
+ };
90
100
  }
91
101
  async getConnections() {
92
102
  if (!this.resolvedConnections) this.resolvedConnections = await Promise.all(this.connectionFactories.map((f)=>f.execute()));
@@ -1 +1 @@
1
- {"version":3,"file":"features/ai/Ai.js","sources":["../../../src/features/ai/Ai.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport { generateText } from \"ai\";\nimport { streamText } from \"ai\";\nimport { Ai as AiAbstraction } from \"./abstractions.js\";\nimport { AiSdkFactory } from \"./abstractions.js\";\nimport { AiConnectionFactory } from \"./abstractions.js\";\nimport { AiModelRegistry } from \"./abstractions.js\";\nimport type { AiGenerateTextParams, AiModel } from \"./abstractions.js\";\nimport type { AiStreamTextParams } from \"./abstractions.js\";\nimport type { IAiSdk } from \"./abstractions.js\";\nimport type { IAiConnection } from \"./abstractions.js\";\nimport type { IAiConnectionInline } from \"./abstractions.js\";\nimport type { LanguageModel } from \"ai\";\nimport { mdbid } from \"@webiny/utils/mdbid.js\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport {\n AiBeforeGenerateTextEvent,\n AiAfterGenerateTextEvent,\n AiGenerateTextErrorEvent,\n AiBeforeStreamTextEvent\n} from \"./events.js\";\n\nclass AiImpl implements AiAbstraction.Interface {\n private sdkCache = new Map<string, IAiSdk>();\n private resolvedConnections: IAiConnection[] | null = null;\n\n constructor(\n private readonly sdkFactories: AiSdkFactory.Interface[],\n private readonly connectionFactories: AiConnectionFactory.Interface[],\n private readonly eventPublisher: EventPublisher.Interface,\n private readonly modelRegistry: AiModelRegistry.Interface\n ) {}\n\n async generateText(params: AiGenerateTextParams): ReturnType<typeof generateText> {\n const { model, connection, ...rest } = params;\n const resolvedModel = await this.resolveLanguageModel(model, connection);\n const requestId = mdbid();\n\n await this.eventPublisher.publish(new AiBeforeGenerateTextEvent({ requestId, params }));\n\n const start = performance.now();\n\n try {\n const result = await generateText({ model: resolvedModel, ...rest } as Parameters<\n typeof generateText\n >[0]);\n\n const duration = performance.now() - start;\n\n await this.eventPublisher.publish(\n new AiAfterGenerateTextEvent({ requestId, params, result, duration })\n );\n\n return result;\n } catch (err) {\n const duration = performance.now() - start;\n const error = err instanceof Error ? err : new Error(String(err));\n\n await this.eventPublisher.publish(\n new AiGenerateTextErrorEvent({ requestId, params, error, duration })\n );\n\n throw err;\n }\n }\n\n async streamText(params: AiStreamTextParams): Promise<ReturnType<typeof streamText>> {\n const { model, connection, ...rest } = params;\n const resolvedModel = await this.resolveLanguageModel(model, connection);\n\n await this.eventPublisher.publish(new AiBeforeStreamTextEvent({ params }));\n\n // Cast required: spreading the discriminated Prompt union loses its narrowing.\n return streamText({ model: resolvedModel, ...rest } as Parameters<typeof streamText>[0]);\n }\n\n listModels(): Promise<AiModel[]> {\n return this.modelRegistry.listModels();\n }\n\n async listModelsByConnections(): Promise<AiModel[]> {\n const [connections, models] = await Promise.all([\n this.getConnections(),\n this.modelRegistry.listModels()\n ]);\n const connectedProviderIds = new Set(connections.map(c => c.sdkName));\n return models.filter(m => connectedProviderIds.has(m.providerId));\n }\n\n async listModelsByConnection(connection: string | IAiConnectionInline): Promise<AiModel[]> {\n const [conn, models] = await Promise.all([\n this.resolveConnection(undefined, connection),\n this.modelRegistry.listModels()\n ]);\n return models.filter(m => m.providerId === conn.sdkName);\n }\n\n private async resolveLanguageModel(\n modelId: string,\n connection?: string | IAiConnectionInline\n ): Promise<LanguageModel> {\n const slashIndex = modelId.indexOf(\"/\");\n if (slashIndex === -1) {\n throw new Error(\n `Invalid model ID \"${modelId}\". Expected format: \"<providerId>/<modelId>\" (e.g. \"openai/gpt-4o\").`\n );\n }\n\n const providerId = modelId.slice(0, slashIndex);\n const rawModelId = modelId.slice(slashIndex + 1);\n\n const models = await this.modelRegistry.listModels();\n const found = models.some(m => m.providerId === providerId && m.modelId === rawModelId);\n if (!found) {\n throw new Error(\n `Model \"${modelId}\" is not available. Use listModels() to see available models.`\n );\n }\n\n const conn = await this.resolveConnection(providerId, connection);\n const sdk = await this.getSdk(conn);\n return sdk.languageModel(rawModelId);\n }\n\n private async getConnections(): Promise<IAiConnection[]> {\n if (!this.resolvedConnections) {\n this.resolvedConnections = await Promise.all(\n this.connectionFactories.map(f => f.execute())\n );\n }\n return this.resolvedConnections;\n }\n\n private async resolveConnection(\n providerId: string | undefined,\n connection?: string | IAiConnectionInline\n ): Promise<IAiConnectionInline> {\n if (typeof connection === \"object\") {\n return connection;\n }\n\n const connections = await this.getConnections();\n\n if (typeof connection === \"string\") {\n const found = connections.find(c => c.id === connection);\n if (!found) {\n const known = connections.map(c => `\"${c.id}\"`).join(\", \");\n throw new Error(\n `Unknown AI connection \"${connection}\". Registered connections: ${known}.`\n );\n }\n return found;\n }\n\n const found = connections.find(c => c.sdkName === providerId);\n if (!found) {\n const known = connections.map(c => `\"${c.id}\" (${c.sdkName})`).join(\", \");\n throw new Error(\n `No AI connection found for provider \"${providerId}\". Registered connections: ${known}.`\n );\n }\n return found;\n }\n\n private async getSdk(connection: IAiConnectionInline): Promise<IAiSdk> {\n const cacheKey =\n \"id\" in connection\n ? (connection as IAiConnection).id\n : `${connection.sdkName}:${connection.apiKey ?? \"__env__\"}`;\n\n const cached = this.sdkCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const factory = this.sdkFactories.find(f => f.id === connection.sdkName);\n if (!factory) {\n const known = this.sdkFactories.map(f => `\"${f.id}\"`).join(\", \");\n throw new Error(\n `No AI SDK factory found for \"${connection.sdkName}\". Registered factories: ${known}.`\n );\n }\n\n const sdk = await factory.execute(connection.apiKey);\n this.sdkCache.set(cacheKey, sdk);\n return sdk;\n }\n}\n\nexport const Ai = createImplementation({\n abstraction: AiAbstraction,\n implementation: AiImpl,\n dependencies: [\n [AiSdkFactory, { multiple: true }],\n [AiConnectionFactory, { multiple: true }],\n EventPublisher,\n AiModelRegistry\n ]\n});\n"],"names":["AiImpl","sdkFactories","connectionFactories","eventPublisher","modelRegistry","Map","params","model","connection","rest","resolvedModel","requestId","mdbid","AiBeforeGenerateTextEvent","start","performance","result","generateText","duration","AiAfterGenerateTextEvent","err","error","Error","String","AiGenerateTextErrorEvent","AiBeforeStreamTextEvent","streamText","connections","models","Promise","connectedProviderIds","Set","c","m","conn","undefined","modelId","slashIndex","providerId","rawModelId","found","sdk","f","known","cacheKey","cached","factory","Ai","createImplementation","AiAbstraction","AiSdkFactory","AiConnectionFactory","EventPublisher","AiModelRegistry"],"mappings":"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"}
1
+ {"version":3,"file":"features/ai/Ai.js","sources":["../../../src/features/ai/Ai.ts"],"sourcesContent":["import { createImplementation } from \"@webiny/feature/api\";\nimport { generateText } from \"ai\";\nimport { streamText } from \"ai\";\nimport { Ai as AiAbstraction } from \"./abstractions.js\";\nimport { AiSdkFactory } from \"./abstractions.js\";\nimport { AiConnectionFactory } from \"./abstractions.js\";\nimport { AiModelRegistry } from \"./abstractions.js\";\nimport type { AiGenerateTextParams, AiModel } from \"./abstractions.js\";\nimport type { AiStreamTextParams } from \"./abstractions.js\";\nimport type { IAiSdk } from \"./abstractions.js\";\nimport type { IAiConnection } from \"./abstractions.js\";\nimport type { IAiConnectionInline } from \"./abstractions.js\";\nimport type { LanguageModel } from \"ai\";\nimport { mdbid } from \"@webiny/utils/mdbid.js\";\nimport { EventPublisher } from \"~/features/eventPublisher/index.js\";\nimport {\n AiBeforeGenerateTextEvent,\n AiAfterGenerateTextEvent,\n AiGenerateTextErrorEvent,\n AiBeforeStreamTextEvent\n} from \"./events.js\";\n\n/**\n * Drops call options the model doesn't accept. Several current models reject `temperature` outright\n * (a 400, not a warning), so it is only sent when the catalog says the model supports it. No\n * information counts as unsupported: leaving it out costs some determinism, sending it can fail the\n * whole request.\n */\nconst withSupportedOptions = <T extends { temperature?: number }>(\n options: T,\n model: AiModel\n): T => {\n if (options.temperature === undefined || model.supports?.temperature === true) {\n return options;\n }\n const { temperature: _temperature, ...rest } = options;\n return rest as T;\n};\n\nclass AiImpl implements AiAbstraction.Interface {\n private sdkCache = new Map<string, IAiSdk>();\n private resolvedConnections: IAiConnection[] | null = null;\n\n constructor(\n private readonly sdkFactories: AiSdkFactory.Interface[],\n private readonly connectionFactories: AiConnectionFactory.Interface[],\n private readonly eventPublisher: EventPublisher.Interface,\n private readonly modelRegistry: AiModelRegistry.Interface\n ) {}\n\n async generateText(params: AiGenerateTextParams): ReturnType<typeof generateText> {\n const { model, connection, ...options } = params;\n const { languageModel: resolvedModel, model: catalogModel } =\n await this.resolveLanguageModel(model, connection);\n const rest = withSupportedOptions(options, catalogModel);\n const requestId = mdbid();\n\n await this.eventPublisher.publish(new AiBeforeGenerateTextEvent({ requestId, params }));\n\n const start = performance.now();\n\n try {\n const result = await generateText({ model: resolvedModel, ...rest } as Parameters<\n typeof generateText\n >[0]);\n\n const duration = performance.now() - start;\n\n await this.eventPublisher.publish(\n new AiAfterGenerateTextEvent({ requestId, params, result, duration })\n );\n\n return result;\n } catch (err) {\n const duration = performance.now() - start;\n const error = err instanceof Error ? err : new Error(String(err));\n\n await this.eventPublisher.publish(\n new AiGenerateTextErrorEvent({ requestId, params, error, duration })\n );\n\n throw err;\n }\n }\n\n async streamText(params: AiStreamTextParams): Promise<ReturnType<typeof streamText>> {\n const { model, connection, ...options } = params;\n const { languageModel: resolvedModel, model: catalogModel } =\n await this.resolveLanguageModel(model, connection);\n const rest = withSupportedOptions(options, catalogModel);\n\n await this.eventPublisher.publish(new AiBeforeStreamTextEvent({ params }));\n\n // Cast required: spreading the discriminated Prompt union loses its narrowing.\n return streamText({ model: resolvedModel, ...rest } as Parameters<typeof streamText>[0]);\n }\n\n listModels(): Promise<AiModel[]> {\n return this.modelRegistry.listModels();\n }\n\n async listModelsByConnections(): Promise<AiModel[]> {\n const [connections, models] = await Promise.all([\n this.getConnections(),\n this.modelRegistry.listModels()\n ]);\n const connectedProviderIds = new Set(connections.map(c => c.sdkName));\n return models.filter(m => connectedProviderIds.has(m.providerId));\n }\n\n async listModelsByConnection(connection: string | IAiConnectionInline): Promise<AiModel[]> {\n const [conn, models] = await Promise.all([\n this.resolveConnection(undefined, connection),\n this.modelRegistry.listModels()\n ]);\n return models.filter(m => m.providerId === conn.sdkName);\n }\n\n private async resolveLanguageModel(\n modelId: string,\n connection?: string | IAiConnectionInline\n ): Promise<{ languageModel: LanguageModel; model: AiModel }> {\n const slashIndex = modelId.indexOf(\"/\");\n if (slashIndex === -1) {\n throw new Error(\n `Invalid model ID \"${modelId}\". Expected format: \"<providerId>/<modelId>\" (e.g. \"openai/gpt-4o\").`\n );\n }\n\n const providerId = modelId.slice(0, slashIndex);\n const rawModelId = modelId.slice(slashIndex + 1);\n\n const models = await this.modelRegistry.listModels();\n const found = models.find(m => m.providerId === providerId && m.modelId === rawModelId);\n if (!found) {\n throw new Error(\n `Model \"${modelId}\" is not available. Use listModels() to see available models.`\n );\n }\n\n const conn = await this.resolveConnection(providerId, connection);\n const sdk = await this.getSdk(conn);\n return { languageModel: sdk.languageModel(rawModelId), model: found };\n }\n\n private async getConnections(): Promise<IAiConnection[]> {\n if (!this.resolvedConnections) {\n this.resolvedConnections = await Promise.all(\n this.connectionFactories.map(f => f.execute())\n );\n }\n return this.resolvedConnections;\n }\n\n private async resolveConnection(\n providerId: string | undefined,\n connection?: string | IAiConnectionInline\n ): Promise<IAiConnectionInline> {\n if (typeof connection === \"object\") {\n return connection;\n }\n\n const connections = await this.getConnections();\n\n if (typeof connection === \"string\") {\n const found = connections.find(c => c.id === connection);\n if (!found) {\n const known = connections.map(c => `\"${c.id}\"`).join(\", \");\n throw new Error(\n `Unknown AI connection \"${connection}\". Registered connections: ${known}.`\n );\n }\n return found;\n }\n\n const found = connections.find(c => c.sdkName === providerId);\n if (!found) {\n const known = connections.map(c => `\"${c.id}\" (${c.sdkName})`).join(\", \");\n throw new Error(\n `No AI connection found for provider \"${providerId}\". Registered connections: ${known}.`\n );\n }\n return found;\n }\n\n private async getSdk(connection: IAiConnectionInline): Promise<IAiSdk> {\n const cacheKey =\n \"id\" in connection\n ? (connection as IAiConnection).id\n : `${connection.sdkName}:${connection.apiKey ?? \"__env__\"}`;\n\n const cached = this.sdkCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const factory = this.sdkFactories.find(f => f.id === connection.sdkName);\n if (!factory) {\n const known = this.sdkFactories.map(f => `\"${f.id}\"`).join(\", \");\n throw new Error(\n `No AI SDK factory found for \"${connection.sdkName}\". Registered factories: ${known}.`\n );\n }\n\n const sdk = await factory.execute(connection.apiKey);\n this.sdkCache.set(cacheKey, sdk);\n return sdk;\n }\n}\n\nexport const Ai = createImplementation({\n abstraction: AiAbstraction,\n implementation: AiImpl,\n dependencies: [\n [AiSdkFactory, { multiple: true }],\n [AiConnectionFactory, { multiple: true }],\n EventPublisher,\n AiModelRegistry\n ]\n});\n"],"names":["withSupportedOptions","options","model","undefined","_temperature","rest","AiImpl","sdkFactories","connectionFactories","eventPublisher","modelRegistry","Map","params","connection","resolvedModel","catalogModel","requestId","mdbid","AiBeforeGenerateTextEvent","start","performance","result","generateText","duration","AiAfterGenerateTextEvent","err","error","Error","String","AiGenerateTextErrorEvent","AiBeforeStreamTextEvent","streamText","connections","models","Promise","connectedProviderIds","Set","c","m","conn","modelId","slashIndex","providerId","rawModelId","found","sdk","f","known","cacheKey","cached","factory","Ai","createImplementation","AiAbstraction","AiSdkFactory","AiConnectionFactory","EventPublisher","AiModelRegistry"],"mappings":"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"}
@@ -16,7 +16,8 @@ class AiModelRegistryImpl {
16
16
  modelId: m.id,
17
17
  modelName: m.name,
18
18
  deprecated: m.deprecated,
19
- endOfLife: m.endOfLife
19
+ endOfLife: m.endOfLife,
20
+ supports: m.supports
20
21
  }));
21
22
  });
22
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"features/ai/AiModelRegistry.js","sources":["../../../src/features/ai/AiModelRegistry.ts"],"sourcesContent":["import { AiModelRegistry as AiModelRegistryAbstraction } from \"./abstractions.js\";\nimport { AiSdkFactory } from \"./abstractions.js\";\nimport { AiModelCatalog } from \"./abstractions.js\";\nimport type { AiModel } from \"./abstractions.js\";\n\nclass AiModelRegistryImpl implements AiModelRegistryAbstraction.Interface {\n constructor(\n private readonly sdkFactories: AiSdkFactory.Interface[],\n private readonly catalog: AiModelCatalog.Interface\n ) {}\n\n async listModels(): Promise<AiModel[]> {\n const providers = await this.catalog.listProviders();\n\n /*\n * A provider is only offered when an SDK factory can serve it. The catalog decides its\n * models; a factory the catalog doesn't know (a custom SDK), or an unreachable catalog,\n * falls back to the factory's own list.\n */\n return this.sdkFactories.flatMap(factory => {\n const provider = providers?.find(p => p.id === factory.id);\n const providerName = provider?.name ?? factory.name;\n const models = provider?.models ?? factory.models;\n\n return models.map(m => ({\n providerId: factory.id,\n providerName,\n modelId: m.id,\n modelName: m.name,\n deprecated: m.deprecated,\n endOfLife: m.endOfLife\n }));\n });\n }\n}\n\nexport const AiModelRegistry = AiModelRegistryAbstraction.createImplementation({\n implementation: AiModelRegistryImpl,\n dependencies: [[AiSdkFactory, { multiple: true }], AiModelCatalog]\n});\n"],"names":["AiModelRegistryImpl","sdkFactories","catalog","providers","factory","provider","p","providerName","models","m","AiModelRegistry","AiModelRegistryAbstraction","AiSdkFactory","AiModelCatalog"],"mappings":";AAKA,MAAMA;IACF,YACqBC,YAAsC,EACtCC,OAAiC,CACpD;aAFmBD,YAAY,GAAZA;aACAC,OAAO,GAAPA;IAClB;IAEH,MAAM,aAAiC;QACnC,MAAMC,YAAY,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa;QAOlD,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAACC,CAAAA;YAC7B,MAAMC,WAAWF,WAAW,KAAKG,CAAAA,IAAKA,EAAE,EAAE,KAAKF,QAAQ,EAAE;YACzD,MAAMG,eAAeF,UAAU,QAAQD,QAAQ,IAAI;YACnD,MAAMI,SAASH,UAAU,UAAUD,QAAQ,MAAM;YAEjD,OAAOI,OAAO,GAAG,CAACC,CAAAA,IAAM;oBACpB,YAAYL,QAAQ,EAAE;oBACtBG;oBACA,SAASE,EAAE,EAAE;oBACb,WAAWA,EAAE,IAAI;oBACjB,YAAYA,EAAE,UAAU;oBACxB,WAAWA,EAAE,SAAS;gBAC1B;QACJ;IACJ;AACJ;AAEO,MAAMC,kCAAkBC,gBAAAA,oBAA+C,CAAC;IAC3E,gBAAgBX;IAChB,cAAc;QAAC;YAACY;YAAc;gBAAE,UAAU;YAAK;SAAE;QAAEC;KAAe;AACtE"}
1
+ {"version":3,"file":"features/ai/AiModelRegistry.js","sources":["../../../src/features/ai/AiModelRegistry.ts"],"sourcesContent":["import { AiModelRegistry as AiModelRegistryAbstraction } from \"./abstractions.js\";\nimport { AiSdkFactory } from \"./abstractions.js\";\nimport { AiModelCatalog } from \"./abstractions.js\";\nimport type { AiModel } from \"./abstractions.js\";\n\nclass AiModelRegistryImpl implements AiModelRegistryAbstraction.Interface {\n constructor(\n private readonly sdkFactories: AiSdkFactory.Interface[],\n private readonly catalog: AiModelCatalog.Interface\n ) {}\n\n async listModels(): Promise<AiModel[]> {\n const providers = await this.catalog.listProviders();\n\n /*\n * A provider is only offered when an SDK factory can serve it. The catalog decides its\n * models; a factory the catalog doesn't know (a custom SDK), or an unreachable catalog,\n * falls back to the factory's own list.\n */\n return this.sdkFactories.flatMap(factory => {\n const provider = providers?.find(p => p.id === factory.id);\n const providerName = provider?.name ?? factory.name;\n const models = provider?.models ?? factory.models;\n\n return models.map(m => ({\n providerId: factory.id,\n providerName,\n modelId: m.id,\n modelName: m.name,\n deprecated: m.deprecated,\n endOfLife: m.endOfLife,\n supports: m.supports\n }));\n });\n }\n}\n\nexport const AiModelRegistry = AiModelRegistryAbstraction.createImplementation({\n implementation: AiModelRegistryImpl,\n dependencies: [[AiSdkFactory, { multiple: true }], AiModelCatalog]\n});\n"],"names":["AiModelRegistryImpl","sdkFactories","catalog","providers","factory","provider","p","providerName","models","m","AiModelRegistry","AiModelRegistryAbstraction","AiSdkFactory","AiModelCatalog"],"mappings":";AAKA,MAAMA;IACF,YACqBC,YAAsC,EACtCC,OAAiC,CACpD;aAFmBD,YAAY,GAAZA;aACAC,OAAO,GAAPA;IAClB;IAEH,MAAM,aAAiC;QACnC,MAAMC,YAAY,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa;QAOlD,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAACC,CAAAA;YAC7B,MAAMC,WAAWF,WAAW,KAAKG,CAAAA,IAAKA,EAAE,EAAE,KAAKF,QAAQ,EAAE;YACzD,MAAMG,eAAeF,UAAU,QAAQD,QAAQ,IAAI;YACnD,MAAMI,SAASH,UAAU,UAAUD,QAAQ,MAAM;YAEjD,OAAOI,OAAO,GAAG,CAACC,CAAAA,IAAM;oBACpB,YAAYL,QAAQ,EAAE;oBACtBG;oBACA,SAASE,EAAE,EAAE;oBACb,WAAWA,EAAE,IAAI;oBACjB,YAAYA,EAAE,UAAU;oBACxB,WAAWA,EAAE,SAAS;oBACtB,UAAUA,EAAE,QAAQ;gBACxB;QACJ;IACJ;AACJ;AAEO,MAAMC,kCAAkBC,gBAAAA,oBAA+C,CAAC;IAC3E,gBAAgBX;IAChB,cAAc;QAAC;YAACY;YAAc;gBAAE,UAAU;YAAK;SAAE;QAAEC;KAAe;AACtE"}
@@ -15,7 +15,7 @@ The catalog is cached for an hour per process. A failed load is retried after a
15
15
 
16
16
  So adding or deprecating a model for an existing provider is a catalog change and needs no release. The `*_MODELS` arrays below are the offline fallback; keep them roughly in sync.
17
17
 
18
- The catalog response looks like this. Dates are ISO strings, and fields the schema doesn't know (`api`, `supports`, ...) are dropped:
18
+ The catalog response looks like this. Dates are ISO strings. `supports` is kept (`tools`, `vision`, `temperature`), and fields the schema doesn't know (`api`, other `supports` keys, ...) are dropped:
19
19
 
20
20
  ```json
21
21
  {
@@ -24,7 +24,13 @@ The catalog response looks like this. Dates are ISO strings, and fields the sche
24
24
  "id": "openai",
25
25
  "name": "OpenAI",
26
26
  "models": [
27
- { "id": "o3", "name": "o3", "deprecated": "2026-06-11", "endOfLife": "2026-12-11" }
27
+ {
28
+ "id": "o3",
29
+ "name": "o3",
30
+ "deprecated": "2026-06-11",
31
+ "endOfLife": "2026-12-11",
32
+ "supports": { "tools": true, "vision": true, "temperature": false }
33
+ }
28
34
  ]
29
35
  }
30
36
  ]
@@ -33,6 +39,8 @@ The catalog response looks like this. Dates are ISO strings, and fields the sche
33
39
 
34
40
  A response that doesn't match the schema counts as a failed load, so one bad entry drops the whole catalog and every factory falls back to its own list.
35
41
 
42
+ `Ai.generateText()` and `Ai.streamText()` send `temperature` only to a model whose `supports.temperature` is `true`. A model that says `false`, or says nothing (no `supports`, or a factory's fallback list), gets the call without it. Several current models reject `temperature` with a 400, so callers can always pass it and leave the decision to `Ai`.
43
+
36
44
  ## Selection criteria
37
45
 
38
46
  Every model in the catalog or in a factory **must** support:
@@ -16,7 +16,12 @@ const catalogSchema = z.object({
16
16
  id: z.string(),
17
17
  name: z.string(),
18
18
  deprecated: optionalDate,
19
- endOfLife: optionalDate
19
+ endOfLife: optionalDate,
20
+ supports: z.object({
21
+ tools: z.boolean().optional(),
22
+ vision: z.boolean().optional(),
23
+ temperature: z.boolean().optional()
24
+ }).optional()
20
25
  }))
21
26
  }))
22
27
  });
@@ -1 +1 @@
1
- {"version":3,"file":"features/ai/RemoteAiModelCatalog.js","sources":["../../../src/features/ai/RemoteAiModelCatalog.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { createImplementation } from \"@webiny/feature/api\";\nimport { getWcpApiUrl } from \"@webiny/wcp\";\nimport { AiModelCatalog as AiModelCatalogAbstraction } from \"./abstractions.js\";\nimport type { AiCatalogProvider } from \"./abstractions.js\";\nimport { Logger } from \"~/features/logger/index.js\";\nimport { HttpClient } from \"~/features/httpClient/index.js\";\n\nconst FETCH_TIMEOUT_MS = 3000;\nconst SUCCESS_TTL_MS = 60 * 60 * 1000;\nconst FAILURE_TTL_MS = 60 * 1000;\n\nconst optionalDate = z.coerce.date().optional();\n\nconst catalogSchema = z.object({\n providers: z.array(\n z.object({\n id: z.string(),\n name: z.string(),\n models: z.array(\n z.object({\n id: z.string(),\n name: z.string(),\n deprecated: optionalDate,\n endOfLife: optionalDate\n })\n )\n })\n )\n});\n\ninterface CachedCatalog {\n expiresAt: number;\n providers: Promise<AiCatalogProvider[] | undefined>;\n}\n\n/*\n * Process-wide on purpose: the catalog is the same for every tenant and request, and\n * `Ai.resolveLanguageModel()` reads it on every call, so a warm Lambda should fetch it once.\n */\nlet cached: CachedCatalog | undefined;\n\nclass RemoteAiModelCatalogImpl implements AiModelCatalogAbstraction.Interface {\n constructor(\n private readonly httpClient: HttpClient.Interface,\n private readonly logger: Logger.Interface\n ) {}\n\n listProviders(): Promise<AiCatalogProvider[] | undefined> {\n if (cached && cached.expiresAt > Date.now()) {\n return cached.providers;\n }\n\n const entry: CachedCatalog = {\n expiresAt: Date.now() + SUCCESS_TTL_MS,\n providers: this.fetchProviders().then(providers => {\n if (!providers) {\n entry.expiresAt = Date.now() + FAILURE_TTL_MS;\n }\n return providers;\n })\n };\n cached = entry;\n\n return entry.providers;\n }\n\n private async fetchProviders(): Promise<AiCatalogProvider[] | undefined> {\n const url = getWcpApiUrl(\"/ai/models\");\n\n const response = await this.httpClient.requestJson({ url, timeoutMs: FETCH_TIMEOUT_MS });\n if (response.isFail()) {\n this.logger.warn({ url, error: response.error }, \"Failed to load AI models.\");\n return undefined;\n }\n\n const result = catalogSchema.safeParse(response.value);\n if (!result.success) {\n this.logger.warn({ url, error: result.error }, \"Received invalid AI models.\");\n return undefined;\n }\n\n return result.data.providers;\n }\n}\n\nexport const RemoteAiModelCatalog = createImplementation({\n abstraction: AiModelCatalogAbstraction,\n implementation: RemoteAiModelCatalogImpl,\n dependencies: [HttpClient, Logger]\n});\n"],"names":["FETCH_TIMEOUT_MS","SUCCESS_TTL_MS","FAILURE_TTL_MS","optionalDate","z","catalogSchema","cached","RemoteAiModelCatalogImpl","httpClient","logger","Date","entry","providers","url","getWcpApiUrl","response","result","RemoteAiModelCatalog","createImplementation","AiModelCatalogAbstraction","HttpClient","Logger"],"mappings":";;;;;;AAQA,MAAMA,mBAAmB;AACzB,MAAMC,iBAAiB;AACvB,MAAMC,iBAAiB;AAEvB,MAAMC,eAAeC,EAAE,MAAM,CAAC,IAAI,GAAG,QAAQ;AAE7C,MAAMC,gBAAgBD,EAAE,MAAM,CAAC;IAC3B,WAAWA,EAAE,KAAK,CACdA,EAAE,MAAM,CAAC;QACL,IAAIA,EAAE,MAAM;QACZ,MAAMA,EAAE,MAAM;QACd,QAAQA,EAAE,KAAK,CACXA,EAAE,MAAM,CAAC;YACL,IAAIA,EAAE,MAAM;YACZ,MAAMA,EAAE,MAAM;YACd,YAAYD;YACZ,WAAWA;QACf;IAER;AAER;AAWA,IAAIG;AAEJ,MAAMC;IACF,YACqBC,UAAgC,EAChCC,MAAwB,CAC3C;aAFmBD,UAAU,GAAVA;aACAC,MAAM,GAANA;IAClB;IAEH,gBAA0D;QACtD,IAAIH,UAAUA,OAAO,SAAS,GAAGI,KAAK,GAAG,IACrC,OAAOJ,OAAO,SAAS;QAG3B,MAAMK,QAAuB;YACzB,WAAWD,KAAK,GAAG,KAAKT;YACxB,WAAW,IAAI,CAAC,cAAc,GAAG,IAAI,CAACW,CAAAA;gBAClC,IAAI,CAACA,WACDD,MAAM,SAAS,GAAGD,KAAK,GAAG,KAAKR;gBAEnC,OAAOU;YACX;QACJ;QACAN,SAASK;QAET,OAAOA,MAAM,SAAS;IAC1B;IAEA,MAAc,iBAA2D;QACrE,MAAME,MAAMC,aAAa;QAEzB,MAAMC,WAAW,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YAAEF;YAAK,WAAWb;QAAiB;QACtF,IAAIe,SAAS,MAAM,IAAI,YACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAAEF;YAAK,OAAOE,SAAS,KAAK;QAAC,GAAG;QAIrD,MAAMC,SAASX,cAAc,SAAS,CAACU,SAAS,KAAK;QACrD,IAAI,CAACC,OAAO,OAAO,EAAE,YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAAEH;YAAK,OAAOG,OAAO,KAAK;QAAC,GAAG;QAInD,OAAOA,OAAO,IAAI,CAAC,SAAS;IAChC;AACJ;AAEO,MAAMC,uBAAuBC,qBAAqB;IACrD,aAAaC;IACb,gBAAgBZ;IAChB,cAAc;QAACa;QAAYC;KAAO;AACtC"}
1
+ {"version":3,"file":"features/ai/RemoteAiModelCatalog.js","sources":["../../../src/features/ai/RemoteAiModelCatalog.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { createImplementation } from \"@webiny/feature/api\";\nimport { getWcpApiUrl } from \"@webiny/wcp\";\nimport { AiModelCatalog as AiModelCatalogAbstraction } from \"./abstractions.js\";\nimport type { AiCatalogProvider } from \"./abstractions.js\";\nimport { Logger } from \"~/features/logger/index.js\";\nimport { HttpClient } from \"~/features/httpClient/index.js\";\n\nconst FETCH_TIMEOUT_MS = 3000;\nconst SUCCESS_TTL_MS = 60 * 60 * 1000;\nconst FAILURE_TTL_MS = 60 * 1000;\n\nconst optionalDate = z.coerce.date().optional();\n\nconst catalogSchema = z.object({\n providers: z.array(\n z.object({\n id: z.string(),\n name: z.string(),\n models: z.array(\n z.object({\n id: z.string(),\n name: z.string(),\n deprecated: optionalDate,\n endOfLife: optionalDate,\n // Capabilities the catalog adds later are dropped here, not rejected.\n supports: z\n .object({\n tools: z.boolean().optional(),\n vision: z.boolean().optional(),\n temperature: z.boolean().optional()\n })\n .optional()\n })\n )\n })\n )\n});\n\ninterface CachedCatalog {\n expiresAt: number;\n providers: Promise<AiCatalogProvider[] | undefined>;\n}\n\n/*\n * Process-wide on purpose: the catalog is the same for every tenant and request, and\n * `Ai.resolveLanguageModel()` reads it on every call, so a warm Lambda should fetch it once.\n */\nlet cached: CachedCatalog | undefined;\n\nclass RemoteAiModelCatalogImpl implements AiModelCatalogAbstraction.Interface {\n constructor(\n private readonly httpClient: HttpClient.Interface,\n private readonly logger: Logger.Interface\n ) {}\n\n listProviders(): Promise<AiCatalogProvider[] | undefined> {\n if (cached && cached.expiresAt > Date.now()) {\n return cached.providers;\n }\n\n const entry: CachedCatalog = {\n expiresAt: Date.now() + SUCCESS_TTL_MS,\n providers: this.fetchProviders().then(providers => {\n if (!providers) {\n entry.expiresAt = Date.now() + FAILURE_TTL_MS;\n }\n return providers;\n })\n };\n cached = entry;\n\n return entry.providers;\n }\n\n private async fetchProviders(): Promise<AiCatalogProvider[] | undefined> {\n const url = getWcpApiUrl(\"/ai/models\");\n\n const response = await this.httpClient.requestJson({ url, timeoutMs: FETCH_TIMEOUT_MS });\n if (response.isFail()) {\n this.logger.warn({ url, error: response.error }, \"Failed to load AI models.\");\n return undefined;\n }\n\n const result = catalogSchema.safeParse(response.value);\n if (!result.success) {\n this.logger.warn({ url, error: result.error }, \"Received invalid AI models.\");\n return undefined;\n }\n\n return result.data.providers;\n }\n}\n\nexport const RemoteAiModelCatalog = createImplementation({\n abstraction: AiModelCatalogAbstraction,\n implementation: RemoteAiModelCatalogImpl,\n dependencies: [HttpClient, Logger]\n});\n"],"names":["FETCH_TIMEOUT_MS","SUCCESS_TTL_MS","FAILURE_TTL_MS","optionalDate","z","catalogSchema","cached","RemoteAiModelCatalogImpl","httpClient","logger","Date","entry","providers","url","getWcpApiUrl","response","result","RemoteAiModelCatalog","createImplementation","AiModelCatalogAbstraction","HttpClient","Logger"],"mappings":";;;;;;AAQA,MAAMA,mBAAmB;AACzB,MAAMC,iBAAiB;AACvB,MAAMC,iBAAiB;AAEvB,MAAMC,eAAeC,EAAE,MAAM,CAAC,IAAI,GAAG,QAAQ;AAE7C,MAAMC,gBAAgBD,EAAE,MAAM,CAAC;IAC3B,WAAWA,EAAE,KAAK,CACdA,EAAE,MAAM,CAAC;QACL,IAAIA,EAAE,MAAM;QACZ,MAAMA,EAAE,MAAM;QACd,QAAQA,EAAE,KAAK,CACXA,EAAE,MAAM,CAAC;YACL,IAAIA,EAAE,MAAM;YACZ,MAAMA,EAAE,MAAM;YACd,YAAYD;YACZ,WAAWA;YAEX,UAAUC,EAAAA,MACC,CAAC;gBACJ,OAAOA,EAAE,OAAO,GAAG,QAAQ;gBAC3B,QAAQA,EAAE,OAAO,GAAG,QAAQ;gBAC5B,aAAaA,EAAE,OAAO,GAAG,QAAQ;YACrC,GACC,QAAQ;QACjB;IAER;AAER;AAWA,IAAIE;AAEJ,MAAMC;IACF,YACqBC,UAAgC,EAChCC,MAAwB,CAC3C;aAFmBD,UAAU,GAAVA;aACAC,MAAM,GAANA;IAClB;IAEH,gBAA0D;QACtD,IAAIH,UAAUA,OAAO,SAAS,GAAGI,KAAK,GAAG,IACrC,OAAOJ,OAAO,SAAS;QAG3B,MAAMK,QAAuB;YACzB,WAAWD,KAAK,GAAG,KAAKT;YACxB,WAAW,IAAI,CAAC,cAAc,GAAG,IAAI,CAACW,CAAAA;gBAClC,IAAI,CAACA,WACDD,MAAM,SAAS,GAAGD,KAAK,GAAG,KAAKR;gBAEnC,OAAOU;YACX;QACJ;QACAN,SAASK;QAET,OAAOA,MAAM,SAAS;IAC1B;IAEA,MAAc,iBAA2D;QACrE,MAAME,MAAMC,aAAa;QAEzB,MAAMC,WAAW,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YAAEF;YAAK,WAAWb;QAAiB;QACtF,IAAIe,SAAS,MAAM,IAAI,YACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAAEF;YAAK,OAAOE,SAAS,KAAK;QAAC,GAAG;QAIrD,MAAMC,SAASX,cAAc,SAAS,CAACU,SAAS,KAAK;QACrD,IAAI,CAACC,OAAO,OAAO,EAAE,YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAAEH;YAAK,OAAOG,OAAO,KAAK;QAAC,GAAG;QAInD,OAAOA,OAAO,IAAI,CAAC,SAAS;IAChC;AACJ;AAEO,MAAMC,uBAAuBC,qBAAqB;IACrD,aAAaC;IACb,gBAAgBZ;IAChB,cAAc;QAACa;QAAYC;KAAO;AACtC"}
@@ -2,11 +2,21 @@ import type { generateText } from "ai";
2
2
  import type { streamText } from "ai";
3
3
  import type { LanguageModel } from "ai";
4
4
  import type { FlexibleSchema, ToolSet } from "ai";
5
+ /**
6
+ * What a model accepts, as published in the model catalog. A capability that isn't listed is unknown,
7
+ * and unknown is treated as unsupported: a parameter the model may reject is not sent.
8
+ */
9
+ export interface IAiModelSupports {
10
+ tools?: boolean;
11
+ vision?: boolean;
12
+ temperature?: boolean;
13
+ }
5
14
  export interface IAiSdkModel {
6
15
  id: string;
7
16
  name: string;
8
17
  deprecated?: Date;
9
18
  endOfLife?: Date;
19
+ supports?: IAiModelSupports;
10
20
  }
11
21
  export interface IAiSdk {
12
22
  languageModel(modelId: string): LanguageModel;
@@ -59,6 +69,7 @@ export interface AiModel {
59
69
  modelName: string;
60
70
  deprecated: Date | undefined;
61
71
  endOfLife: Date | undefined;
72
+ supports: IAiModelSupports | undefined;
62
73
  }
63
74
  export interface IAi {
64
75
  generateText(params: AiGenerateTextParams): ReturnType<typeof generateText>;
@@ -1 +1 @@
1
- {"version":3,"file":"features/ai/abstractions.js","sources":["../../../src/features/ai/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { generateText } from \"ai\";\nimport type { streamText } from \"ai\";\nimport type { LanguageModel } from \"ai\";\nimport type { FlexibleSchema, ToolSet } from \"ai\";\n\n// AiSdk\n\nexport interface IAiSdkModel {\n id: string; // raw model id, e.g. \"claude-sonnet-4-5\"\n name: string; // human-friendly name, e.g. \"Claude Sonnet 4.5\"\n deprecated?: Date;\n endOfLife?: Date;\n}\n\nexport interface IAiSdk {\n languageModel(modelId: string): LanguageModel;\n}\n\n/** A single AI SDK instance (e.g. OpenAI, Anthropic) that resolves model instances. */\nexport const AiSdk = createAbstraction<IAiSdk>(\"AiSdk\");\n\nexport namespace AiSdk {\n export type Interface = IAiSdk;\n}\n\n// AiSdkFactory\n\nexport interface IAiSdkFactory {\n readonly id: string; // machine id, e.g. \"anthropic\"\n readonly name: string; // human-friendly name, e.g. \"Anthropic\"\n readonly models: readonly IAiSdkModel[]; // static model list, no API call needed\n execute(apiKey?: string): Promise<IAiSdk>;\n}\n\n/** Factory that asynchronously initialises an AI SDK. Register one per provider namespace. */\nexport const AiSdkFactory = createAbstraction<IAiSdkFactory>(\"AiSdkFactory\");\n\nexport namespace AiSdkFactory {\n export type Interface = IAiSdkFactory;\n}\n\n// AiConnection\n\nexport interface IAiConnectionInline {\n readonly sdkName: string;\n readonly apiKey?: string;\n}\n\nexport interface IAiConnection extends IAiConnectionInline {\n readonly id: string;\n}\n\n// AiConnectionFactory\n\nexport interface IAiConnectionFactory {\n execute(): Promise<IAiConnection>;\n}\n\n/** Factory that asynchronously produces an AiConnection. */\nexport const AiConnectionFactory = createAbstraction<IAiConnectionFactory>(\"AiConnectionFactory\");\n\nexport namespace AiConnectionFactory {\n export type Interface = IAiConnectionFactory;\n}\n\n// Ai\n\ntype SDKGenerateTextParams = Parameters<typeof generateText>[0];\ntype SDKStreamTextParams = Parameters<typeof streamText>[0];\n\nexport type AiGenerateTextParams = Omit<SDKGenerateTextParams, \"model\"> & {\n model: string;\n connection?: string | IAiConnectionInline;\n};\nexport type AiStreamTextParams = Omit<SDKStreamTextParams, \"model\"> & {\n model: string;\n connection?: string | IAiConnectionInline;\n};\n\nexport interface AiModel {\n providerId: string; // e.g. \"anthropic\"\n providerName: string; // e.g. \"Anthropic\"\n modelId: string; // e.g. \"claude-sonnet-4-5\"\n modelName: string; // e.g. \"Claude Sonnet 4.5\"\n deprecated: Date | undefined;\n endOfLife: Date | undefined;\n}\n\nexport interface IAi {\n generateText(params: AiGenerateTextParams): ReturnType<typeof generateText>;\n streamText(params: AiStreamTextParams): Promise<ReturnType<typeof streamText>>;\n listModels(): Promise<AiModel[]>;\n listModelsByConnections(): Promise<AiModel[]>;\n listModelsByConnection(connection: string | IAiConnectionInline): Promise<AiModel[]>;\n}\n\n/** Interact with AI language models using registered providers. */\nexport const Ai = createAbstraction<IAi>(\"Ai\");\n\nexport namespace Ai {\n export type Interface = IAi;\n export type GenerateTextParams = AiGenerateTextParams;\n export type StreamTextParams = AiStreamTextParams;\n}\n\n// AiModelRegistry\n\nexport interface IAiModelRegistry {\n listModels(): Promise<AiModel[]>;\n}\n\n/** Single source of truth for available AI models. Decoratable to restrict the model list. */\nexport const AiModelRegistry = createAbstraction<IAiModelRegistry>(\"AiModelRegistry\");\n\nexport namespace AiModelRegistry {\n export type Interface = IAiModelRegistry;\n}\n\n// AiModelCatalog\n\nexport interface AiCatalogProvider {\n id: string; // Matches `AiSdkFactory.id`, e.g. \"anthropic\".\n name: string; // Human-friendly name, e.g. \"Anthropic\".\n models: IAiSdkModel[];\n}\n\nexport interface IAiModelCatalog {\n /** Returns `undefined` when the catalog can't be loaded. */\n listProviders(): Promise<AiCatalogProvider[] | undefined>;\n}\n\n/** The published list of providers and models Webiny supports. SDK factories still gate what is offered. */\nexport const AiModelCatalog = createAbstraction<IAiModelCatalog>(\"AiModelCatalog\");\n\nexport namespace AiModelCatalog {\n export type Interface = IAiModelCatalog;\n}\n\n// AiSdkTool\n\nexport interface IAiSdkTool<TInput = any> {\n readonly name: string;\n readonly description: string;\n readonly inputSchema: FlexibleSchema<TInput>;\n execute(input: TInput): Promise<unknown>;\n}\n\n/** A single tool that can be provided to AI generateText/streamText calls. */\nexport const AiSdkTool = createAbstraction<IAiSdkTool>(\"AiSdkTool\");\n\nexport namespace AiSdkTool {\n export type Interface = IAiSdkTool;\n}\n\n// AiSdkTools\n\nexport interface IAiSdkTools {\n getToolSet(): ToolSet;\n}\n\n/** Collection of AI SDK tools. Returns a ready-to-use ToolSet for generateText/streamText. */\nexport const AiSdkTools = createAbstraction<IAiSdkTools>(\"AiSdkTools\");\n\nexport namespace AiSdkTools {\n export type Interface = IAiSdkTools;\n}\n"],"names":["AiSdk","createAbstraction","AiSdkFactory","AiConnectionFactory","Ai","AiModelRegistry","AiModelCatalog","AiSdkTool","AiSdkTools"],"mappings":";AAoBO,MAAMA,QAAQC,kBAA0B;AAgBxC,MAAMC,eAAeD,kBAAiC;AAwBtD,MAAME,sBAAsBF,kBAAwC;AAsCpE,MAAMG,KAAKH,kBAAuB;AAelC,MAAMI,kBAAkBJ,kBAAoC;AAoB5D,MAAMK,iBAAiBL,kBAAmC;AAgB1D,MAAMM,YAAYN,kBAA8B;AAahD,MAAMO,aAAaP,kBAA+B"}
1
+ {"version":3,"file":"features/ai/abstractions.js","sources":["../../../src/features/ai/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport type { generateText } from \"ai\";\nimport type { streamText } from \"ai\";\nimport type { LanguageModel } from \"ai\";\nimport type { FlexibleSchema, ToolSet } from \"ai\";\n\n// AiSdk\n\n/**\n * What a model accepts, as published in the model catalog. A capability that isn't listed is unknown,\n * and unknown is treated as unsupported: a parameter the model may reject is not sent.\n */\nexport interface IAiModelSupports {\n tools?: boolean;\n vision?: boolean;\n temperature?: boolean;\n}\n\nexport interface IAiSdkModel {\n id: string; // raw model id, e.g. \"claude-sonnet-4-5\"\n name: string; // human-friendly name, e.g. \"Claude Sonnet 4.5\"\n deprecated?: Date;\n endOfLife?: Date;\n supports?: IAiModelSupports;\n}\n\nexport interface IAiSdk {\n languageModel(modelId: string): LanguageModel;\n}\n\n/** A single AI SDK instance (e.g. OpenAI, Anthropic) that resolves model instances. */\nexport const AiSdk = createAbstraction<IAiSdk>(\"AiSdk\");\n\nexport namespace AiSdk {\n export type Interface = IAiSdk;\n}\n\n// AiSdkFactory\n\nexport interface IAiSdkFactory {\n readonly id: string; // machine id, e.g. \"anthropic\"\n readonly name: string; // human-friendly name, e.g. \"Anthropic\"\n readonly models: readonly IAiSdkModel[]; // static model list, no API call needed\n execute(apiKey?: string): Promise<IAiSdk>;\n}\n\n/** Factory that asynchronously initialises an AI SDK. Register one per provider namespace. */\nexport const AiSdkFactory = createAbstraction<IAiSdkFactory>(\"AiSdkFactory\");\n\nexport namespace AiSdkFactory {\n export type Interface = IAiSdkFactory;\n}\n\n// AiConnection\n\nexport interface IAiConnectionInline {\n readonly sdkName: string;\n readonly apiKey?: string;\n}\n\nexport interface IAiConnection extends IAiConnectionInline {\n readonly id: string;\n}\n\n// AiConnectionFactory\n\nexport interface IAiConnectionFactory {\n execute(): Promise<IAiConnection>;\n}\n\n/** Factory that asynchronously produces an AiConnection. */\nexport const AiConnectionFactory = createAbstraction<IAiConnectionFactory>(\"AiConnectionFactory\");\n\nexport namespace AiConnectionFactory {\n export type Interface = IAiConnectionFactory;\n}\n\n// Ai\n\ntype SDKGenerateTextParams = Parameters<typeof generateText>[0];\ntype SDKStreamTextParams = Parameters<typeof streamText>[0];\n\nexport type AiGenerateTextParams = Omit<SDKGenerateTextParams, \"model\"> & {\n model: string;\n connection?: string | IAiConnectionInline;\n};\nexport type AiStreamTextParams = Omit<SDKStreamTextParams, \"model\"> & {\n model: string;\n connection?: string | IAiConnectionInline;\n};\n\nexport interface AiModel {\n providerId: string; // e.g. \"anthropic\"\n providerName: string; // e.g. \"Anthropic\"\n modelId: string; // e.g. \"claude-sonnet-4-5\"\n modelName: string; // e.g. \"Claude Sonnet 4.5\"\n deprecated: Date | undefined;\n endOfLife: Date | undefined;\n supports: IAiModelSupports | undefined;\n}\n\nexport interface IAi {\n generateText(params: AiGenerateTextParams): ReturnType<typeof generateText>;\n streamText(params: AiStreamTextParams): Promise<ReturnType<typeof streamText>>;\n listModels(): Promise<AiModel[]>;\n listModelsByConnections(): Promise<AiModel[]>;\n listModelsByConnection(connection: string | IAiConnectionInline): Promise<AiModel[]>;\n}\n\n/** Interact with AI language models using registered providers. */\nexport const Ai = createAbstraction<IAi>(\"Ai\");\n\nexport namespace Ai {\n export type Interface = IAi;\n export type GenerateTextParams = AiGenerateTextParams;\n export type StreamTextParams = AiStreamTextParams;\n}\n\n// AiModelRegistry\n\nexport interface IAiModelRegistry {\n listModels(): Promise<AiModel[]>;\n}\n\n/** Single source of truth for available AI models. Decoratable to restrict the model list. */\nexport const AiModelRegistry = createAbstraction<IAiModelRegistry>(\"AiModelRegistry\");\n\nexport namespace AiModelRegistry {\n export type Interface = IAiModelRegistry;\n}\n\n// AiModelCatalog\n\nexport interface AiCatalogProvider {\n id: string; // Matches `AiSdkFactory.id`, e.g. \"anthropic\".\n name: string; // Human-friendly name, e.g. \"Anthropic\".\n models: IAiSdkModel[];\n}\n\nexport interface IAiModelCatalog {\n /** Returns `undefined` when the catalog can't be loaded. */\n listProviders(): Promise<AiCatalogProvider[] | undefined>;\n}\n\n/** The published list of providers and models Webiny supports. SDK factories still gate what is offered. */\nexport const AiModelCatalog = createAbstraction<IAiModelCatalog>(\"AiModelCatalog\");\n\nexport namespace AiModelCatalog {\n export type Interface = IAiModelCatalog;\n}\n\n// AiSdkTool\n\nexport interface IAiSdkTool<TInput = any> {\n readonly name: string;\n readonly description: string;\n readonly inputSchema: FlexibleSchema<TInput>;\n execute(input: TInput): Promise<unknown>;\n}\n\n/** A single tool that can be provided to AI generateText/streamText calls. */\nexport const AiSdkTool = createAbstraction<IAiSdkTool>(\"AiSdkTool\");\n\nexport namespace AiSdkTool {\n export type Interface = IAiSdkTool;\n}\n\n// AiSdkTools\n\nexport interface IAiSdkTools {\n getToolSet(): ToolSet;\n}\n\n/** Collection of AI SDK tools. Returns a ready-to-use ToolSet for generateText/streamText. */\nexport const AiSdkTools = createAbstraction<IAiSdkTools>(\"AiSdkTools\");\n\nexport namespace AiSdkTools {\n export type Interface = IAiSdkTools;\n}\n"],"names":["AiSdk","createAbstraction","AiSdkFactory","AiConnectionFactory","Ai","AiModelRegistry","AiModelCatalog","AiSdkTool","AiSdkTools"],"mappings":";AA+BO,MAAMA,QAAQC,kBAA0B;AAgBxC,MAAMC,eAAeD,kBAAiC;AAwBtD,MAAME,sBAAsBF,kBAAwC;AAuCpE,MAAMG,KAAKH,kBAAuB;AAelC,MAAMI,kBAAkBJ,kBAAoC;AAoB5D,MAAMK,iBAAiBL,kBAAmC;AAgB1D,MAAMM,YAAYN,kBAA8B;AAahD,MAAMO,aAAaP,kBAA+B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-core",
3
- "version": "6.5.0-beta.6",
3
+ "version": "6.5.0-beta.7",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,17 +17,17 @@
17
17
  "@ai-sdk/anthropic": "4.0.65",
18
18
  "@ai-sdk/google": "4.0.82",
19
19
  "@ai-sdk/openai": "4.0.78",
20
- "@webiny/api": "6.5.0-beta.6",
20
+ "@webiny/api": "6.5.0-beta.7",
21
21
  "@webiny/di": "1.1.0",
22
- "@webiny/error": "6.5.0-beta.6",
23
- "@webiny/feature": "6.5.0-beta.6",
24
- "@webiny/feature-flags": "6.5.0-beta.6",
25
- "@webiny/handler": "6.5.0-beta.6",
26
- "@webiny/handler-db": "6.5.0-beta.6",
27
- "@webiny/handler-graphql": "6.5.0-beta.6",
28
- "@webiny/plugins": "6.5.0-beta.6",
29
- "@webiny/utils": "6.5.0-beta.6",
30
- "@webiny/wcp": "6.5.0-beta.6",
22
+ "@webiny/error": "6.5.0-beta.7",
23
+ "@webiny/feature": "6.5.0-beta.7",
24
+ "@webiny/feature-flags": "6.5.0-beta.7",
25
+ "@webiny/handler": "6.5.0-beta.7",
26
+ "@webiny/handler-db": "6.5.0-beta.7",
27
+ "@webiny/handler-graphql": "6.5.0-beta.7",
28
+ "@webiny/plugins": "6.5.0-beta.7",
29
+ "@webiny/utils": "6.5.0-beta.7",
30
+ "@webiny/wcp": "6.5.0-beta.7",
31
31
  "ai": "7.0.118",
32
32
  "dataloader": "2.2.3",
33
33
  "jose": "6.2.12",
@@ -40,9 +40,9 @@
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/jsonwebtoken": "9.0.10",
43
- "@webiny/build-tools": "6.5.0-beta.6",
44
- "@webiny/handler-aws": "6.5.0-beta.6",
45
- "@webiny/project-utils": "6.5.0-beta.6",
43
+ "@webiny/build-tools": "6.5.0-beta.7",
44
+ "@webiny/handler-aws": "6.5.0-beta.7",
45
+ "@webiny/project-utils": "6.5.0-beta.7",
46
46
  "rimraf": "6.1.3",
47
47
  "typescript": "7.0.2",
48
48
  "vitest": "5.0.2"