@open-mercato/core 0.6.1-develop.3191.1.2511ae315f → 0.6.1-develop.3198.1.aa979623f0
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { generateObject } from "ai";
|
|
2
2
|
import { createContainer } from "awilix";
|
|
3
3
|
import {
|
|
4
|
+
resolveAiProviderIdFromEnv,
|
|
4
5
|
resolveFirstConfiguredOpenCodeProvider,
|
|
5
6
|
resolveOpenCodeModel,
|
|
6
7
|
requireOpenCodeProviderApiKey,
|
|
@@ -15,9 +16,9 @@ function asAiModel(model) {
|
|
|
15
16
|
return model;
|
|
16
17
|
}
|
|
17
18
|
function resolveExtractionProviderId() {
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
return
|
|
19
|
+
const explicit = (process.env.OM_AI_PROVIDER ?? process.env.OPENCODE_PROVIDER ?? "").trim();
|
|
20
|
+
if (explicit.length > 0) {
|
|
21
|
+
return resolveAiProviderIdFromEnv(process.env);
|
|
21
22
|
}
|
|
22
23
|
const firstConfiguredProvider = resolveFirstConfiguredOpenCodeProvider();
|
|
23
24
|
if (firstConfiguredProvider) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/inbox_ops/lib/llmProvider.ts"],
|
|
4
|
-
"sourcesContent": ["import { generateObject } from 'ai'\nimport type { AwilixContainer } from 'awilix'\nimport { createContainer } from 'awilix'\nimport {\n resolveFirstConfiguredOpenCodeProvider,\n resolveOpenCodeModel,\n requireOpenCodeProviderApiKey,\n resolveOpenCodeProviderId,\n type OpenCodeProviderId,\n} from '@open-mercato/shared/lib/ai/opencode-provider'\nimport {\n AiModelFactoryError,\n createModelFactory,\n type AiModelFactory,\n} from '@open-mercato/ai-assistant/modules/ai_assistant/lib/model-factory'\nimport { extractionOutputSchema } from '../data/validators'\n\n// Vercel AI SDK provider factories return LanguageModelV1 but generateObject()\n// expects a narrower LanguageModel union. The types are structurally compatible\n// at runtime; the cast is required until the AI SDK unifies its model types.\ntype AiModel = Parameters<typeof generateObject>[0]['model']\nfunction asAiModel(model: unknown): AiModel {\n return model as AiModel\n}\n\n/**\n * Step 5.1 \u2014 thin backward-compatibility shim. The public surface of this\n * module (`resolveExtractionProviderId`, `createStructuredModel`,\n * `withTimeout`, `runExtractionWithConfiguredProvider`) is unchanged so\n * `ai-tools.ts`, `translationProvider.ts`, and `extractionWorker.ts` continue\n * to compile and pass their existing tests.\n *\n * The model-instantiation path inside {@link runExtractionWithConfiguredProvider}\n * now delegates to the shared {@link createModelFactory} so every\n * AI-runtime caller shares one resolution order. The legacy\n * `OPENCODE_MODEL` / `OPENCODE_PROVIDER` envs remain honored via\n * {@link resolveExtractionProviderId} and {@link resolveOpenCodeModel} so\n * inbox_ops deployments do not see a behavior change \u2014 the factory is\n * consulted first (honoring `INBOX_OPS_AI_MODEL` + `input.modelOverride`),\n * with the legacy path as the fallback when no registry provider is\n * configured (preserving the historical error messages).\n */\n\nexport function resolveExtractionProviderId(): OpenCodeProviderId {\n const
|
|
5
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAE/B,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,8BAA8B;AAMvC,SAAS,UAAU,OAAyB;AAC1C,SAAO;AACT;AAoBO,SAAS,8BAAkD;
|
|
4
|
+
"sourcesContent": ["import { generateObject } from 'ai'\nimport type { AwilixContainer } from 'awilix'\nimport { createContainer } from 'awilix'\nimport {\n resolveAiProviderIdFromEnv,\n resolveFirstConfiguredOpenCodeProvider,\n resolveOpenCodeModel,\n requireOpenCodeProviderApiKey,\n resolveOpenCodeProviderId,\n type OpenCodeProviderId,\n} from '@open-mercato/shared/lib/ai/opencode-provider'\nimport {\n AiModelFactoryError,\n createModelFactory,\n type AiModelFactory,\n} from '@open-mercato/ai-assistant/modules/ai_assistant/lib/model-factory'\nimport { extractionOutputSchema } from '../data/validators'\n\n// Vercel AI SDK provider factories return LanguageModelV1 but generateObject()\n// expects a narrower LanguageModel union. The types are structurally compatible\n// at runtime; the cast is required until the AI SDK unifies its model types.\ntype AiModel = Parameters<typeof generateObject>[0]['model']\nfunction asAiModel(model: unknown): AiModel {\n return model as AiModel\n}\n\n/**\n * Step 5.1 \u2014 thin backward-compatibility shim. The public surface of this\n * module (`resolveExtractionProviderId`, `createStructuredModel`,\n * `withTimeout`, `runExtractionWithConfiguredProvider`) is unchanged so\n * `ai-tools.ts`, `translationProvider.ts`, and `extractionWorker.ts` continue\n * to compile and pass their existing tests.\n *\n * The model-instantiation path inside {@link runExtractionWithConfiguredProvider}\n * now delegates to the shared {@link createModelFactory} so every\n * AI-runtime caller shares one resolution order. The legacy\n * `OPENCODE_MODEL` / `OPENCODE_PROVIDER` envs remain honored via\n * {@link resolveExtractionProviderId} and {@link resolveOpenCodeModel} so\n * inbox_ops deployments do not see a behavior change \u2014 the factory is\n * consulted first (honoring `OM_AI_INBOX_OPS_MODEL` \u2014 legacy `INBOX_OPS_AI_MODEL` \u2014 + `input.modelOverride`),\n * with the legacy path as the fallback when no registry provider is\n * configured (preserving the historical error messages).\n */\n\nexport function resolveExtractionProviderId(): OpenCodeProviderId {\n // Honors OM_AI_PROVIDER first, then the legacy OPENCODE_PROVIDER, then the\n // first configured provider from `OPEN_CODE_PROVIDER_IDS`, then the unified\n // default (currently `openai`). Mirrors the precedence applied by the\n // shared model factory so the BC fallback path stays consistent.\n const explicit = (process.env.OM_AI_PROVIDER ?? process.env.OPENCODE_PROVIDER ?? '').trim()\n if (explicit.length > 0) {\n return resolveAiProviderIdFromEnv(process.env)\n }\n\n const firstConfiguredProvider = resolveFirstConfiguredOpenCodeProvider()\n if (firstConfiguredProvider) {\n return firstConfiguredProvider\n }\n\n return resolveOpenCodeProviderId(undefined)\n}\n\nexport async function createStructuredModel(\n providerId: OpenCodeProviderId,\n apiKey: string,\n modelId: string,\n): Promise<AiModel> {\n switch (providerId) {\n case 'anthropic': {\n const { createAnthropic } = await import('@ai-sdk/anthropic')\n return asAiModel(createAnthropic({ apiKey })(modelId))\n }\n case 'openai': {\n const { createOpenAI } = await import('@ai-sdk/openai')\n return asAiModel(createOpenAI({ apiKey })(modelId))\n }\n case 'google': {\n const { createGoogleGenerativeAI } = await import('@ai-sdk/google')\n return asAiModel(createGoogleGenerativeAI({ apiKey })(modelId))\n }\n default:\n throw new Error(`Unsupported provider: ${providerId}`)\n }\n}\n\nexport async function withTimeout<T>(\n operation: Promise<T>,\n timeoutMs: number,\n timeoutMessage: string,\n): Promise<T> {\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs)\n })\n\n try {\n return await Promise.race([operation, timeoutPromise])\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle)\n }\n }\n}\n\n/**\n * Test-only seam for the factory-delegation regression suite. Production\n * callers MUST use {@link runExtractionWithConfiguredProvider} directly; the\n * suite overrides this binding via `jest.spyOn` to assert the shim actually\n * reaches `createModelFactory` without stubbing `@open-mercato/ai-assistant`.\n */\nexport const __inboxOpsLlmProviderInternal = {\n createModelFactory,\n createContainer,\n}\n\nfunction tryFactoryResolution(input: {\n modelOverride?: string | null\n}): { modelId: string; providerId: OpenCodeProviderId; model: AiModel } | null {\n let factory: AiModelFactory\n try {\n const container = __inboxOpsLlmProviderInternal.createContainer()\n factory = __inboxOpsLlmProviderInternal.createModelFactory(container as AwilixContainer)\n } catch {\n return null\n }\n try {\n const resolution = factory.resolveModel({\n moduleId: 'inbox_ops',\n callerOverride: input.modelOverride ?? undefined,\n })\n const providerId = resolveOpenCodeProviderId(resolution.providerId)\n return {\n modelId: resolution.modelId,\n providerId,\n model: asAiModel(resolution.model),\n }\n } catch (err) {\n if (err instanceof AiModelFactoryError) {\n // Fall back to the legacy path so the shim keeps throwing the original\n // OPENCODE_*-era error messages existing tests/consumers rely on.\n return null\n }\n throw err\n }\n}\n\nexport async function runExtractionWithConfiguredProvider(input: {\n systemPrompt: string\n userPrompt: string\n modelOverride?: string | null\n timeoutMs: number\n}): Promise<{\n object: ReturnType<typeof extractionOutputSchema.parse>\n totalTokens: number\n modelWithProvider: string\n}> {\n const factoryResolution = tryFactoryResolution({ modelOverride: input.modelOverride })\n\n let model: AiModel\n let modelWithProvider: string\n if (factoryResolution) {\n model = factoryResolution.model\n modelWithProvider = `${factoryResolution.providerId}/${factoryResolution.modelId}`\n } else {\n const providerId = resolveExtractionProviderId()\n const apiKey = requireOpenCodeProviderApiKey(providerId)\n const modelConfig = resolveOpenCodeModel(providerId, {\n overrideModel: input.modelOverride,\n })\n model = await createStructuredModel(providerId, apiKey, modelConfig.modelId)\n modelWithProvider = modelConfig.modelWithProvider\n }\n\n const result = await withTimeout(\n generateObject({\n model,\n schema: extractionOutputSchema,\n system: input.systemPrompt,\n prompt: input.userPrompt,\n temperature: 0,\n }),\n input.timeoutMs,\n `LLM extraction timed out after ${input.timeoutMs}ms`,\n )\n\n return {\n object: result.object,\n totalTokens: Number(result.usage?.totalTokens ?? 0) || 0,\n modelWithProvider,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.6.1-develop.
|
|
3
|
+
"version": "0.6.1-develop.3198.1.aa979623f0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -237,12 +237,12 @@
|
|
|
237
237
|
"ts-pattern": "^5.0.0"
|
|
238
238
|
},
|
|
239
239
|
"peerDependencies": {
|
|
240
|
-
"@open-mercato/ai-assistant": "0.6.1-develop.
|
|
241
|
-
"@open-mercato/shared": "0.6.1-develop.
|
|
240
|
+
"@open-mercato/ai-assistant": "0.6.1-develop.3198.1.aa979623f0",
|
|
241
|
+
"@open-mercato/shared": "0.6.1-develop.3198.1.aa979623f0"
|
|
242
242
|
},
|
|
243
243
|
"devDependencies": {
|
|
244
|
-
"@open-mercato/ai-assistant": "0.6.1-develop.
|
|
245
|
-
"@open-mercato/shared": "0.6.1-develop.
|
|
244
|
+
"@open-mercato/ai-assistant": "0.6.1-develop.3198.1.aa979623f0",
|
|
245
|
+
"@open-mercato/shared": "0.6.1-develop.3198.1.aa979623f0",
|
|
246
246
|
"@testing-library/dom": "^10.4.1",
|
|
247
247
|
"@testing-library/jest-dom": "^6.9.1",
|
|
248
248
|
"@testing-library/react": "^16.3.1",
|
|
@@ -2,6 +2,7 @@ import { generateObject } from 'ai'
|
|
|
2
2
|
import type { AwilixContainer } from 'awilix'
|
|
3
3
|
import { createContainer } from 'awilix'
|
|
4
4
|
import {
|
|
5
|
+
resolveAiProviderIdFromEnv,
|
|
5
6
|
resolveFirstConfiguredOpenCodeProvider,
|
|
6
7
|
resolveOpenCodeModel,
|
|
7
8
|
requireOpenCodeProviderApiKey,
|
|
@@ -36,15 +37,19 @@ function asAiModel(model: unknown): AiModel {
|
|
|
36
37
|
* `OPENCODE_MODEL` / `OPENCODE_PROVIDER` envs remain honored via
|
|
37
38
|
* {@link resolveExtractionProviderId} and {@link resolveOpenCodeModel} so
|
|
38
39
|
* inbox_ops deployments do not see a behavior change — the factory is
|
|
39
|
-
* consulted first (honoring `INBOX_OPS_AI_MODEL` + `input.modelOverride`),
|
|
40
|
+
* consulted first (honoring `OM_AI_INBOX_OPS_MODEL` — legacy `INBOX_OPS_AI_MODEL` — + `input.modelOverride`),
|
|
40
41
|
* with the legacy path as the fallback when no registry provider is
|
|
41
42
|
* configured (preserving the historical error messages).
|
|
42
43
|
*/
|
|
43
44
|
|
|
44
45
|
export function resolveExtractionProviderId(): OpenCodeProviderId {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
// Honors OM_AI_PROVIDER first, then the legacy OPENCODE_PROVIDER, then the
|
|
47
|
+
// first configured provider from `OPEN_CODE_PROVIDER_IDS`, then the unified
|
|
48
|
+
// default (currently `openai`). Mirrors the precedence applied by the
|
|
49
|
+
// shared model factory so the BC fallback path stays consistent.
|
|
50
|
+
const explicit = (process.env.OM_AI_PROVIDER ?? process.env.OPENCODE_PROVIDER ?? '').trim()
|
|
51
|
+
if (explicit.length > 0) {
|
|
52
|
+
return resolveAiProviderIdFromEnv(process.env)
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
const firstConfiguredProvider = resolveFirstConfiguredOpenCodeProvider()
|