@workglow/openai 0.3.37 → 0.3.39
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/dist/ai/OpenAiProvider.d.ts +2 -64
- package/dist/ai/OpenAiProvider.d.ts.map +1 -1
- package/dist/ai/OpenAiQueuedProvider.d.ts +2 -64
- package/dist/ai/OpenAiQueuedProvider.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_CacheCheckpoint.d.ts +48 -0
- package/dist/ai/common/OpenAI_CacheCheckpoint.d.ts.map +1 -0
- package/dist/ai/common/OpenAI_Capabilities.d.ts +1 -1
- package/dist/ai/common/OpenAI_Capabilities.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_CapabilitySets.d.ts +2 -1
- package/dist/ai/common/OpenAI_CapabilitySets.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_Client.d.ts +34 -8
- package/dist/ai/common/OpenAI_Client.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_JobRunFns.browser.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_JobRunFns.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_ModelInfo.d.ts +4 -3
- package/dist/ai/common/OpenAI_ModelInfo.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_ModelSchema.d.ts +70 -3
- package/dist/ai/common/OpenAI_ModelSchema.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_StructuredGeneration.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_TextEmbedding.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_TextGeneration.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_TextRewriter.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_TextSummary.d.ts.map +1 -1
- package/dist/ai/common/OpenAI_ToolCalling.d.ts +3 -2
- package/dist/ai/common/OpenAI_ToolCalling.d.ts.map +1 -1
- package/dist/ai/index.d.ts +5 -24
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/runtime.browser.d.ts +1 -0
- package/dist/ai/runtime.browser.d.ts.map +1 -1
- package/dist/ai/runtime.d.ts +1 -0
- package/dist/ai/runtime.d.ts.map +1 -1
- package/dist/ai-runtime.browser.js +238 -74
- package/dist/ai-runtime.browser.js.map +16 -15
- package/dist/ai-runtime.js +235 -69
- package/dist/ai-runtime.js.map +15 -14
- package/dist/ai.browser.js +31 -5
- package/dist/ai.browser.js.map +6 -6
- package/dist/ai.js +235 -72
- package/dist/ai.js.map +17 -16
- package/package.json +13 -12
package/dist/ai.browser.js.map
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/ai/common/OpenAI_Client.ts", "../src/ai/common/OpenAI_Constants.ts", "../src/ai/common/OpenAI_ModelSchema.ts", "../src/ai/registerOpenAi.ts", "../src/ai/OpenAiQueuedProvider.ts", "../src/ai/common/OpenAI_CapabilitySets.ts", "../src/ai/common/OpenAI_Capabilities.ts", "../src/ai/common/OpenAI_ImageValidation.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { isBrowserLike, resolveApiKey, validateProviderBaseUrl } from \"@workglow/ai/provider-utils\";\nimport type { OpenAiModelConfig } from \"./OpenAI_ModelSchema\";\n\n/**\n * Hostnames (or hostname suffixes) accepted for OpenAI `base_url` without\n * the explicit `trustedBaseUrl` opt-out. Includes Azure OpenAI tenants.\n */\nexport const OPENAI_ALLOWED_HOSTS: readonly string[] = [\"api.openai.com\", \".openai.azure.com\"];\n\ntype OpenAIClientClass = new (config: any) => any;\n\nlet _loadPromise: Promise<OpenAIClientClass> | undefined;\n\n// NOTE: we do not want to de-dup this in the provider-utils, vite wants direct import with string literals.\nexport async function loadOpenAISDK(): Promise<OpenAIClientClass> {\n _loadPromise ??= import(/* @vite-ignore */ \"openai\")\n\n .then((mod) => mod.default as OpenAIClientClass)\n .catch(() => {\n _loadPromise = undefined;\n throw new Error(\"openai is required for OpenAI tasks. Install it with: bun add openai\");\n });\n return _loadPromise;\n}\n\ninterface ResolvedProviderConfig {\n readonly credential_key?: string;\n readonly api_key?: string;\n readonly model_name?: string;\n readonly base_url?: string;\n readonly organization?: string;\n readonly prompt_cache_key?: string;\n readonly reasoning?: { readonly effort?: string; readonly mode?: string };\n /**\n * When `true`, accept the `base_url` even if its hostname is not in\n * {@link OPENAI_ALLOWED_HOSTS}. Use only for known-good custom enterprise\n * gateways. The URL still has to parse and use a safe scheme.\n */\n readonly trustedBaseUrl?: boolean;\n}\n\nexport async function getClient(model: OpenAiModelConfig | undefined) {\n const OpenAI = await loadOpenAISDK();\n const config = model?.provider_config as ResolvedProviderConfig | undefined;\n const apiKey = resolveApiKey({\n config,\n envVar: \"OPENAI_API_KEY\",\n providerLabel: \"OpenAI\",\n });\n // Throw before SDK construction on a rejected base_url so the API key is\n // never sent to an unvalidated host.\n const baseURL = validateProviderBaseUrl(config?.base_url, {\n vendor: \"openai\",\n allowHosts: OPENAI_ALLOWED_HOSTS,\n trustedBaseUrl: config?.trustedBaseUrl,\n providerLabel: \"OpenAI\",\n });\n try {\n return new OpenAI({\n apiKey,\n baseURL,\n organization: config?.organization || undefined,\n dangerouslyAllowBrowser: isBrowserLike(),\n });\n } catch (err) {\n throw new Error(\n `Failed to create OpenAI client: ${err instanceof Error ? err.message : \"unknown error\"}`\n );\n }\n}\n\nexport function getModelName(model: OpenAiModelConfig | undefined): string {\n const name = model?.provider_config?.model_name;\n if (!name) {\n throw new Error(\"Missing model name in provider_config.model_name.\");\n }\n return name;\n}\n\n/**\n * Resolves the
|
|
5
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { isModelEffort, type ModelEffort } from \"@workglow/ai\";\nimport { isBrowserLike, resolveApiKey, validateProviderBaseUrl } from \"@workglow/ai/provider-utils\";\nimport type { OpenAiModelConfig } from \"./OpenAI_ModelSchema\";\n\n/** Maps coarse {@link ModelEffort} to OpenAI Responses `reasoning.effort`. */\nconst EFFORT_TO_OPENAI: Record<ModelEffort, string> = {\n none: \"none\",\n low: \"low\",\n medium: \"medium\",\n high: \"high\",\n extra: \"xhigh\",\n ultra: \"max\",\n};\n\n/**\n * Hostnames (or hostname suffixes) accepted for OpenAI `base_url` without\n * the explicit `trustedBaseUrl` opt-out. Includes Azure OpenAI tenants.\n */\nexport const OPENAI_ALLOWED_HOSTS: readonly string[] = [\"api.openai.com\", \".openai.azure.com\"];\n\ntype OpenAIClientClass = new (config: any) => any;\n\nlet _loadPromise: Promise<OpenAIClientClass> | undefined;\n\n// NOTE: we do not want to de-dup this in the provider-utils, vite wants direct import with string literals.\nexport async function loadOpenAISDK(): Promise<OpenAIClientClass> {\n _loadPromise ??= import(/* @vite-ignore */ \"openai\")\n\n .then((mod) => mod.default as OpenAIClientClass)\n .catch(() => {\n _loadPromise = undefined;\n throw new Error(\"openai is required for OpenAI tasks. Install it with: bun add openai\");\n });\n return _loadPromise;\n}\n\ninterface ResolvedProviderConfig {\n readonly credential_key?: string;\n readonly api_key?: string;\n readonly model_name?: string;\n readonly base_url?: string;\n readonly organization?: string;\n readonly prompt_cache_key?: string;\n readonly reasoning?: { readonly effort?: string; readonly mode?: string };\n /**\n * When `true`, accept the `base_url` even if its hostname is not in\n * {@link OPENAI_ALLOWED_HOSTS}. Use only for known-good custom enterprise\n * gateways. The URL still has to parse and use a safe scheme.\n */\n readonly trustedBaseUrl?: boolean;\n}\n\nlet _testClient: unknown;\n\n/**\n * Override the client returned by {@link getClient} so runtime tests can\n * capture the requests the OpenAI run-fns build without a live SDK, API key,\n * or network call. Pass `undefined` to restore normal SDK-backed creation.\n * This lives in the runtime module (not a `vi.mock` of `openai`) so it works\n * identically whether the provider resolves to `src` or the bundled `dist`,\n * and is immune to duplicate SDK copies across the workspace defeating\n * module-level mocks.\n */\nfunction setOpenAIClientForTests(client: unknown): void {\n _testClient = client;\n}\n\n/**\n * @internal Symbols exported only for use by `@workglow/test`. Not part of the\n * stable public API. Surfaced on the `ai-runtime` barrel (via `export *`) and\n * merged into the `/ai` barrel's `_testOnly`.\n */\nexport const _testOnly = {\n setOpenAIClientForTests,\n} as const;\n\nexport async function getClient(model: OpenAiModelConfig | undefined) {\n if (_testClient) return _testClient as InstanceType<OpenAIClientClass>;\n const OpenAI = await loadOpenAISDK();\n const config = model?.provider_config as ResolvedProviderConfig | undefined;\n const apiKey = resolveApiKey({\n config,\n envVar: \"OPENAI_API_KEY\",\n providerLabel: \"OpenAI\",\n });\n // Throw before SDK construction on a rejected base_url so the API key is\n // never sent to an unvalidated host.\n const baseURL = validateProviderBaseUrl(config?.base_url, {\n vendor: \"openai\",\n allowHosts: OPENAI_ALLOWED_HOSTS,\n trustedBaseUrl: config?.trustedBaseUrl,\n providerLabel: \"OpenAI\",\n });\n try {\n return new OpenAI({\n apiKey,\n baseURL,\n organization: config?.organization || undefined,\n dangerouslyAllowBrowser: isBrowserLike(),\n });\n } catch (err) {\n throw new Error(\n `Failed to create OpenAI client: ${err instanceof Error ? err.message : \"unknown error\"}`\n );\n }\n}\n\nexport function getModelName(model: OpenAiModelConfig | undefined): string {\n const name = model?.provider_config?.model_name;\n if (!name) {\n throw new Error(\"Missing model name in provider_config.model_name.\");\n }\n return name;\n}\n\n/**\n * Resolves the `reasoning` object for reasoning-capable models (GPT-5.6\n * sol/terra/luna and the o-series). Native `provider_config.reasoning` wins;\n * otherwise map `model.effort`. Returns `undefined` when neither is set.\n */\nexport function getReasoningConfig(\n model: OpenAiModelConfig | undefined\n): { effort?: string; mode?: string } | undefined {\n const reasoning = (model?.provider_config as ResolvedProviderConfig | undefined)?.reasoning;\n if (reasoning && (reasoning.effort !== undefined || reasoning.mode !== undefined)) {\n return reasoning;\n }\n if (isModelEffort(model?.effort)) {\n return { effort: EFFORT_TO_OPENAI[model.effort] };\n }\n return undefined;\n}\n\n/** Deterministic 32-bit FNV-1a hash → 8-char hex. Worker-safe (no crypto import). */\nfunction fnv1aHex(input: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Resolves the Responses `prompt_cache_key`. Uses an explicit\n * `provider_config.prompt_cache_key` override when set, otherwise derives a\n * stable key from the request's cache-relevant prefix (model + system\n * instructions + tools) so requests sharing that prefix converge on one key and\n * hit the cache. GPT-5.6 bills cache writes, so a stable key (not a random one)\n * is the cost-correct default.\n */\nexport function resolvePromptCacheKey(\n model: OpenAiModelConfig | undefined,\n params: { model?: unknown; instructions?: unknown; tools?: unknown }\n): string {\n const override = (model?.provider_config as ResolvedProviderConfig | undefined)?.prompt_cache_key;\n if (override) return override;\n const material = JSON.stringify([\n params.model ?? \"\",\n params.instructions ?? \"\",\n params.tools ?? null,\n ]);\n return `wg-${fnv1aHex(material)}`;\n}\n\n/**\n * Applies the per-request Responses fields common to every OpenAI text run-fn:\n * the model's `reasoning` config and a stable `prompt_cache_key`. Mutates and\n * returns `params` so callers can inline it into the create call. Call this\n * last, after model/instructions/tools/temperature are populated, so the cache\n * key sees the full prefix and the reasoning default can see the temperature.\n *\n * When the caller pinned a `temperature` but expressed no reasoning preference,\n * reasoning is forced off. The two are not independently selectable on the\n * reasoning families: `gpt-5.6-luna` answers `temperature` alone with\n * `400 Unsupported parameter: 'temperature' is not supported with this model`,\n * yet accepts `{reasoning: {effort: \"none\"}, temperature: 0}`. A caller asking\n * for a specific temperature is asking for controlled sampling, so honouring\n * that request — rather than failing it — is the useful reading. An explicit\n * `reasoning` in the model config always wins.\n */\nexport function finalizeResponsesRequest(\n model: OpenAiModelConfig | undefined,\n params: Record<string, unknown>\n): Record<string, unknown> {\n const reasoning = getReasoningConfig(model);\n if (reasoning !== undefined) params.reasoning = reasoning;\n else if (params.temperature !== undefined) params.reasoning = { effort: \"none\" };\n params.prompt_cache_key = resolvePromptCacheKey(model, params);\n return params;\n}\n",
|
|
6
6
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport const OPENAI = \"OPENAI\";\n",
|
|
7
|
-
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ModelConfigSchema, ModelRecordSchema } from \"@workglow/ai/worker\";\nimport { DataPortSchemaObject, FromSchema } from \"@workglow/util/worker\";\nimport { OPENAI } from \"./OpenAI_Constants\";\n\nexport const OpenAiModelSchema = {\n type: \"object\",\n properties: {\n provider: {\n const: OPENAI,\n description: \"Discriminator: OpenAI cloud provider.\",\n },\n provider_config: {\n type: \"object\",\n description: \"OpenAI-specific configuration.\",\n properties: {\n model_name: {\n type: \"string\",\n description: \"The OpenAI model identifier (e.g., 'gpt-4o', 'text-embedding-3-small').\",\n },\n credential_key: {\n type: \"string\",\n format: \"credential\",\n description: \"Key to look up in the credential store for the API key.\",\n \"x-ui-hidden\": true,\n },\n base_url: {\n type: \"string\",\n description: \"Base URL for the OpenAI API. Useful for Azure OpenAI or proxy servers.\",\n default: \"https://api.openai.com/v1\",\n },\n trustedBaseUrl: {\n type: \"boolean\",\n description:\n \"When true, accept a base_url whose hostname is not in the built-in allow-list. Use only for known-good custom enterprise gateways — otherwise an attacker can exfiltrate the API key by pointing base_url at their own server.\",\n default: false,\n \"x-ui-hidden\": true,\n },\n organization: {\n type: \"string\",\n description: \"OpenAI organization ID (optional).\",\n },\n prompt_cache_key: {\n type: \"string\",\n description:\n \"Overrides the auto-derived Responses prompt_cache_key. Requests sharing a key share a cached prefix; leave unset to derive a stable key from the model + system instructions + tools.\",\n \"x-ui-hidden\": true,\n },\n reasoning: {\n type: \"object\",\n description:\n \"Reasoning controls for reasoning-capable models (e.g. the GPT-5.6 sol/terra/luna family), sent on the Responses API.\",\n properties: {\n effort: {\n type: \"string\",\n enum: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"],\n description: \"Reasoning effort. Higher effort trades latency and cost for quality.\",\n },\n mode: {\n type: \"string\",\n enum: [\"pro\"],\n description:\n \"Set to 'pro' for the quality-first pro configuration on supported models.\",\n },\n },\n additionalProperties: false,\n },\n },\n required: [\"model_name\"],\n additionalProperties: false,\n },\n },\n required: [\"provider\", \"provider_config\"],\n additionalProperties: true,\n} as const satisfies DataPortSchemaObject;\n\nexport const OpenAiModelRecordSchema = {\n type: \"object\",\n properties: {\n ...ModelRecordSchema.properties,\n ...OpenAiModelSchema.properties,\n },\n required: [...ModelRecordSchema.required, ...OpenAiModelSchema.required],\n additionalProperties: false,\n} as const satisfies DataPortSchemaObject;\n\nexport type OpenAiModelRecord = FromSchema<typeof OpenAiModelRecordSchema
|
|
7
|
+
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { WithModelPricing } from \"@workglow/ai/worker\";\nimport { ModelConfigSchema, ModelRecordSchema } from \"@workglow/ai/worker\";\nimport type { DataPortSchemaObject, FromSchema } from \"@workglow/util/worker\";\nimport { OPENAI } from \"./OpenAI_Constants\";\n\nexport const OpenAiModelSchema = {\n type: \"object\",\n properties: {\n provider: {\n const: OPENAI,\n description: \"Discriminator: OpenAI cloud provider.\",\n },\n provider_config: {\n type: \"object\",\n description: \"OpenAI-specific configuration.\",\n properties: {\n model_name: {\n type: \"string\",\n description: \"The OpenAI model identifier (e.g., 'gpt-4o', 'text-embedding-3-small').\",\n },\n credential_key: {\n type: \"string\",\n format: \"credential\",\n description: \"Key to look up in the credential store for the API key.\",\n \"x-ui-hidden\": true,\n },\n base_url: {\n type: \"string\",\n description: \"Base URL for the OpenAI API. Useful for Azure OpenAI or proxy servers.\",\n default: \"https://api.openai.com/v1\",\n },\n trustedBaseUrl: {\n type: \"boolean\",\n description:\n \"When true, accept a base_url whose hostname is not in the built-in allow-list. Use only for known-good custom enterprise gateways — otherwise an attacker can exfiltrate the API key by pointing base_url at their own server.\",\n default: false,\n \"x-ui-hidden\": true,\n },\n organization: {\n type: \"string\",\n description: \"OpenAI organization ID (optional).\",\n },\n prompt_cache_key: {\n type: \"string\",\n description:\n \"Overrides the auto-derived Responses prompt_cache_key. Requests sharing a key share a cached prefix; leave unset to derive a stable key from the model + system instructions + tools.\",\n \"x-ui-hidden\": true,\n },\n reasoning: {\n type: \"object\",\n description:\n \"Reasoning controls for reasoning-capable models (e.g. the GPT-5.6 sol/terra/luna family), sent on the Responses API.\",\n properties: {\n effort: {\n type: \"string\",\n enum: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"],\n description: \"Reasoning effort. Higher effort trades latency and cost for quality.\",\n },\n mode: {\n type: \"string\",\n enum: [\"pro\"],\n description:\n \"Set to 'pro' for the quality-first pro configuration on supported models.\",\n },\n },\n additionalProperties: false,\n },\n },\n required: [\"model_name\"],\n additionalProperties: false,\n },\n },\n required: [\"provider\", \"provider_config\"],\n additionalProperties: true,\n} as const satisfies DataPortSchemaObject;\n\nexport const OpenAiModelRecordSchema = {\n type: \"object\",\n properties: {\n ...ModelRecordSchema.properties,\n ...OpenAiModelSchema.properties,\n },\n required: [...ModelRecordSchema.required, ...OpenAiModelSchema.required],\n additionalProperties: false,\n} as const satisfies DataPortSchemaObject;\n\nexport type OpenAiModelRecord = WithModelPricing<FromSchema<typeof OpenAiModelRecordSchema>>;\n\nexport const OpenAiModelConfigSchema = {\n type: \"object\",\n properties: {\n ...ModelConfigSchema.properties,\n ...OpenAiModelSchema.properties,\n },\n required: [...ModelConfigSchema.required, ...OpenAiModelSchema.required],\n additionalProperties: false,\n} as const satisfies DataPortSchemaObject;\n\nexport type OpenAiModelConfig = WithModelPricing<FromSchema<typeof OpenAiModelConfigSchema>>;\n",
|
|
8
8
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { AiProviderRegisterOptions } from \"@workglow/ai\";\nimport { registerProviderWithWorker } from \"@workglow/ai/provider-utils\";\nimport { OpenAiQueuedProvider } from \"./OpenAiQueuedProvider\";\nimport { registerOpenAiImageValidator } from \"./common/OpenAI_ImageValidation\";\n\nexport async function registerOpenAi(\n options: AiProviderRegisterOptions & {\n worker: Worker | (() => Worker);\n }\n): Promise<void> {\n registerOpenAiImageValidator();\n await registerProviderWithWorker(new OpenAiQueuedProvider(), \"OpenAI\", options);\n}\n",
|
|
9
9
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability, ModelRecord } from \"@workglow/ai\";\nimport { AiProvider } from \"@workglow/ai\";\nimport { createCloudProviderClass } from \"@workglow/ai/provider-utils\";\nimport { inferOpenAiCapabilities, openAiWorkerRunFnSpecs } from \"./common/OpenAI_Capabilities\";\nimport { OPENAI } from \"./common/OpenAI_Constants\";\nimport type { OpenAiModelConfig } from \"./common/OpenAI_ModelSchema\";\n\n/**\n * Main-thread registration shell for OpenAI. Used both for inline mode\n * (constructed with the run-fn registrations array) and worker-backed mode\n * (constructed empty so the base class registers worker proxies). No queue\n * is created — OpenAI uses {@link DirectExecutionStrategy}.\n */\nexport class OpenAiQueuedProvider extends createCloudProviderClass<OpenAiModelConfig>(AiProvider, {\n name: OPENAI,\n displayName: \"OpenAI\",\n}) {\n override inferCapabilities(model: ModelRecord): readonly Capability[] {\n return inferOpenAiCapabilities(model);\n }\n\n protected override workerRunFnSpecs(): readonly { serves: readonly Capability[] }[] {\n return openAiWorkerRunFnSpecs();\n }\n}\n",
|
|
10
|
-
"/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai/worker\";\n\n/**\n * Single source of truth for OpenAI's capability sets.\n *\n * Both `OPENAI_RUN_FNS` (the worker-side registration list) and\n * `workerRunFnSpecs()` (the main-thread proxy declaration) derive their\n * `serves` arrays from these named exports. SDK-free so the main thread\n * can import without paying the OpenAI client cost.\n *\n * To add a new capability set: declare a new `as const` constant here,\n * then reference it from both `OPENAI_RUN_FNS` and `OPENAI_RUN_FN_SPECS`.\n */\nexport const OPENAI_TEXT_GENERATION = [\"text.generation\"] as const satisfies Capability[];\nexport const OPENAI_TOOL_USE = [\"text.generation\", \"tool-use\"] as const satisfies Capability[];\nexport const OPENAI_JSON_MODE = [\"text.generation\", \"json-mode\"] as const satisfies Capability[];\nexport const OPENAI_TEXT_REWRITER = [\"text.rewriter\"] as const satisfies Capability[];\nexport const OPENAI_TEXT_SUMMARY = [\"text.summary\"] as const satisfies Capability[];\nexport const OPENAI_TEXT_EMBEDDING = [\"text.embedding\"] as const satisfies Capability[];\nexport const OPENAI_IMAGE_GENERATION = [\"image.generation\"] as const satisfies Capability[];\nexport const OPENAI_IMAGE_EDITING = [\"image.editing\"] as const satisfies Capability[];\nexport const OPENAI_COUNT_TOKENS = [\"model.count-tokens\"] as const satisfies Capability[];\nexport const OPENAI_MODEL_SEARCH = [\"model.search\"] as const satisfies Capability[];\nexport const OPENAI_MODEL_INFO = [\"model.info\"] as const satisfies Capability[];\n\n/** Aggregated list — for `workerRunFnSpecs()` derivation. Order MUST match `OPENAI_RUN_FNS`. */\nexport const OPENAI_CAPABILITY_SETS = [\n OPENAI_TEXT_GENERATION,\n OPENAI_TOOL_USE,\n OPENAI_JSON_MODE,\n OPENAI_TEXT_REWRITER,\n OPENAI_TEXT_SUMMARY,\n OPENAI_TEXT_EMBEDDING,\n OPENAI_IMAGE_GENERATION,\n OPENAI_IMAGE_EDITING,\n OPENAI_COUNT_TOKENS,\n OPENAI_MODEL_SEARCH,\n OPENAI_MODEL_INFO,\n] as const;\n",
|
|
11
|
-
"/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability, ModelRecord } from \"@workglow/ai/worker\";\nimport { OPENAI_CAPABILITY_SETS } from \"./OpenAI_CapabilitySets\";\n\n/**\n * Closed list of capability-set specs the OpenAI provider serves. Derived\n * from {@link OPENAI_CAPABILITY_SETS}. Used by the main-thread provider\n * shells when registering worker-mode proxies so the dispatcher can route\n * requests to the worker proxy.\n */\nexport const OPENAI_RUN_FN_SPECS = OPENAI_CAPABILITY_SETS.map((serves) => ({ serves }));\n\nexport function openAiWorkerRunFnSpecs(): readonly { readonly serves: readonly Capability[] }[] {\n return OPENAI_RUN_FN_SPECS;\n}\n\n/**\n * Shape used by the model-name regexes — `model_id` is required, the rest\n * is loosely-typed metadata only used to opportunistically widen the\n * inferred capability set.\n */\ntype CapabilityHints = Pick<ModelRecord, \"model_id\" | \"provider_config\" | \"capabilities\">;\n\n/**\n * Heuristic capability inference for an OpenAI {@link ModelRecord}. Pattern-\n * matches the canonical OpenAI model id strings (and the `provider_config.\n * model_name` if present) to a closed set of {@link Capability}s. Falls back\n * to the model's stored `capabilities` array (or a baseline of search +\n * info) when no pattern matches.\n *\n * Main-thread method only — workers do not run capability inference.\n */\nexport function inferOpenAiCapabilities(model: CapabilityHints): readonly Capability[] {\n const id = String(\n model.model_id ??\n (model.provider_config as { model_name?: string } | undefined)?.model_name ??\n \"\"\n );\n\n // Embedding models — text-embedding-3-{small,large}, text-embedding-ada-002.\n if (/^text-embedding/i.test(id)) {\n return [\"text.embedding\", \"model.count-tokens\", \"model.info\", \"model.search\"];\n }\n\n // Image models — DALL-E and gpt-image families.\n if (/^dall-e/i.test(id)) {\n // DALL-E 2/3 do NOT support edit consistently — gpt-image-* does. Cover\n // generation only here; the gpt-image branch below adds editing.\n return [\"image.generation\", \"model.info\", \"model.search\"];\n }\n if (/^gpt-image/i.test(id)) {\n return [\"image.generation\", \"image.editing\", \"model.info\", \"model.search\"];\n }\n\n // Chat / reasoning models — gpt-3.5/4/4o/5/...; o-series reasoning models (o1, o3, o4, future).\n // GPT-4o, gpt-4-vision-*, gpt-4-turbo, and all o-series additionally accept image inputs.\n if (/^gpt-/i.test(id) || /^o\\d/i.test(id)) {\n const caps: Capability[] = [\n \"text.generation\",\n \"text.rewriter\",\n \"text.summary\",\n \"tool-use\",\n \"json-mode\",\n \"model.count-tokens\",\n \"model.info\",\n \"model.search\",\n ];\n const supportsVision =\n /gpt-4o|gpt-4\\.1|gpt-5|gpt-4-vision|gpt-4-turbo/i.test(id) || /^o\\d/i.test(id);\n if (supportsVision) {\n caps.push(\"vision-input\");\n }\n return caps;\n }\n\n // Unknown model — fall back to whatever the record declared, or just\n // expose the meta-ops so the model can still be searched / inspected.\n const declared = (model.capabilities as readonly Capability[] | undefined) ?? [];\n if (declared.length > 0) return declared;\n return [\"model.search\", \"model.info\"];\n}\n",
|
|
10
|
+
"/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai/worker\";\n\n/**\n * Single source of truth for OpenAI's capability sets.\n *\n * Both `OPENAI_RUN_FNS` (the worker-side registration list) and\n * `workerRunFnSpecs()` (the main-thread proxy declaration) derive their\n * `serves` arrays from these named exports. SDK-free so the main thread\n * can import without paying the OpenAI client cost.\n *\n * To add a new capability set: declare a new `as const` constant here,\n * then reference it from both `OPENAI_RUN_FNS` and `OPENAI_RUN_FN_SPECS`.\n */\nexport const OPENAI_TEXT_GENERATION = [\"text.generation\"] as const satisfies Capability[];\nexport const OPENAI_TOOL_USE = [\"text.generation\", \"tool-use\"] as const satisfies Capability[];\nexport const OPENAI_JSON_MODE = [\"text.generation\", \"json-mode\"] as const satisfies Capability[];\nexport const OPENAI_TEXT_REWRITER = [\"text.rewriter\"] as const satisfies Capability[];\nexport const OPENAI_TEXT_SUMMARY = [\"text.summary\"] as const satisfies Capability[];\nexport const OPENAI_TEXT_EMBEDDING = [\"text.embedding\"] as const satisfies Capability[];\nexport const OPENAI_IMAGE_GENERATION = [\"image.generation\"] as const satisfies Capability[];\nexport const OPENAI_IMAGE_EDITING = [\"image.editing\"] as const satisfies Capability[];\nexport const OPENAI_COUNT_TOKENS = [\"model.count-tokens\"] as const satisfies Capability[];\nexport const OPENAI_MODEL_SEARCH = [\"model.search\"] as const satisfies Capability[];\nexport const OPENAI_MODEL_INFO = [\"model.info\"] as const satisfies Capability[];\nexport const OPENAI_CACHE_CHECKPOINT = [\"cache.checkpoint\"] as const satisfies Capability[];\n\n/** Aggregated list — for `workerRunFnSpecs()` derivation. Order MUST match `OPENAI_RUN_FNS`. */\nexport const OPENAI_CAPABILITY_SETS = [\n OPENAI_TEXT_GENERATION,\n OPENAI_TOOL_USE,\n OPENAI_JSON_MODE,\n OPENAI_TEXT_REWRITER,\n OPENAI_TEXT_SUMMARY,\n OPENAI_TEXT_EMBEDDING,\n OPENAI_IMAGE_GENERATION,\n OPENAI_IMAGE_EDITING,\n OPENAI_COUNT_TOKENS,\n OPENAI_MODEL_SEARCH,\n OPENAI_MODEL_INFO,\n OPENAI_CACHE_CHECKPOINT,\n] as const;\n",
|
|
11
|
+
"/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability, ModelRecord } from \"@workglow/ai/worker\";\nimport { OPENAI_CAPABILITY_SETS } from \"./OpenAI_CapabilitySets\";\n\n/**\n * Closed list of capability-set specs the OpenAI provider serves. Derived\n * from {@link OPENAI_CAPABILITY_SETS}. Used by the main-thread provider\n * shells when registering worker-mode proxies so the dispatcher can route\n * requests to the worker proxy.\n */\nexport const OPENAI_RUN_FN_SPECS = OPENAI_CAPABILITY_SETS.map((serves) => ({ serves }));\n\nexport function openAiWorkerRunFnSpecs(): readonly { readonly serves: readonly Capability[] }[] {\n return OPENAI_RUN_FN_SPECS;\n}\n\n/**\n * Shape used by the model-name regexes — `model_id` is required, the rest\n * is loosely-typed metadata only used to opportunistically widen the\n * inferred capability set.\n */\ntype CapabilityHints = Pick<ModelRecord, \"model_id\" | \"provider_config\" | \"capabilities\">;\n\n/**\n * Heuristic capability inference for an OpenAI {@link ModelRecord}. Pattern-\n * matches the canonical OpenAI model id strings (and the `provider_config.\n * model_name` if present) to a closed set of {@link Capability}s. Falls back\n * to the model's stored `capabilities` array (or a baseline of search +\n * info) when no pattern matches.\n *\n * Main-thread method only — workers do not run capability inference.\n */\nexport function inferOpenAiCapabilities(model: CapabilityHints): readonly Capability[] {\n const id = String(\n model.model_id ??\n (model.provider_config as { model_name?: string } | undefined)?.model_name ??\n \"\"\n );\n\n // Embedding models — text-embedding-3-{small,large}, text-embedding-ada-002.\n if (/^text-embedding/i.test(id)) {\n return [\"text.embedding\", \"model.count-tokens\", \"model.info\", \"model.search\"];\n }\n\n // Image models — DALL-E and gpt-image families.\n if (/^dall-e/i.test(id)) {\n // DALL-E 2/3 do NOT support edit consistently — gpt-image-* does. Cover\n // generation only here; the gpt-image branch below adds editing.\n return [\"image.generation\", \"model.info\", \"model.search\"];\n }\n if (/^gpt-image/i.test(id)) {\n return [\"image.generation\", \"image.editing\", \"model.info\", \"model.search\"];\n }\n\n // Chat / reasoning models — gpt-3.5/4/4o/5/...; o-series reasoning models (o1, o3, o4, future).\n // GPT-4o, gpt-4-vision-*, gpt-4-turbo, and all o-series additionally accept image inputs.\n if (/^gpt-/i.test(id) || /^o\\d/i.test(id)) {\n const caps: Capability[] = [\n \"text.generation\",\n \"text.rewriter\",\n \"text.summary\",\n \"tool-use\",\n \"json-mode\",\n \"cache.checkpoint\",\n \"model.count-tokens\",\n \"model.info\",\n \"model.search\",\n ];\n const supportsVision =\n /gpt-4o|gpt-4\\.1|gpt-5|gpt-4-vision|gpt-4-turbo/i.test(id) || /^o\\d/i.test(id);\n if (supportsVision) {\n caps.push(\"vision-input\");\n }\n return caps;\n }\n\n // Unknown model — fall back to whatever the record declared, or just\n // expose the meta-ops so the model can still be searched / inspected.\n const declared = (model.capabilities as readonly Capability[] | undefined) ?? [];\n if (declared.length > 0) return declared;\n return [\"model.search\", \"model.info\"];\n}\n",
|
|
12
12
|
"/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { ModelConfig } from \"@workglow/ai\";\nimport { AiImageOutputTask, ProviderUnsupportedFeatureError } from \"@workglow/ai\";\n\nimport { OPENAI } from \"./OpenAI_Constants\";\n\n/**\n * Registers the OpenAI per-provider image validator. Called at provider registration time\n * (both inline and worker-backed paths) so it runs on the main thread before any dispatch.\n *\n * Currently validates:\n * - DALL-E 2 + non-empty `additionalImages` → throws (single-image edit only).\n * DALL-E 3 + ImageEditTask is rejected upstream by the model registry task-array check.\n */\nexport function registerOpenAiImageValidator(): void {\n AiImageOutputTask.registerProviderImageValidator(\n OPENAI,\n (taskType, input, model: ModelConfig) => {\n if (taskType !== \"ImageEditTask\") return;\n const modelName =\n (model.provider_config as { model_name?: string } | undefined)?.model_name ?? \"\";\n const additional = input[\"additionalImages\"] as unknown[] | undefined;\n if (modelName.startsWith(\"dall-e-2\") && Array.isArray(additional) && additional.length > 0) {\n throw new ProviderUnsupportedFeatureError(\n \"additionalImages\",\n model.model_id ?? modelName,\n \"DALL-E 2 only supports single-image edits\"\n );\n }\n }\n );\n}\n"
|
|
13
13
|
],
|
|
14
|
-
"mappings": ";;;;;;;;;AAMA;
|
|
15
|
-
"debugId": "
|
|
14
|
+
"mappings": "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",
|
|
15
|
+
"debugId": "63C2F7EB0BD183BC64756E2164756E21",
|
|
16
16
|
"names": []
|
|
17
17
|
}
|
package/dist/ai.js
CHANGED
|
@@ -7,7 +7,16 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/ai/common/OpenAI_Client.ts
|
|
10
|
+
import { isModelEffort } from "@workglow/ai";
|
|
10
11
|
import { isBrowserLike, resolveApiKey, validateProviderBaseUrl } from "@workglow/ai/provider-utils";
|
|
12
|
+
var EFFORT_TO_OPENAI = {
|
|
13
|
+
none: "none",
|
|
14
|
+
low: "low",
|
|
15
|
+
medium: "medium",
|
|
16
|
+
high: "high",
|
|
17
|
+
extra: "xhigh",
|
|
18
|
+
ultra: "max"
|
|
19
|
+
};
|
|
11
20
|
var OPENAI_ALLOWED_HOSTS = ["api.openai.com", ".openai.azure.com"];
|
|
12
21
|
var _loadPromise;
|
|
13
22
|
async function loadOpenAISDK() {
|
|
@@ -17,7 +26,16 @@ async function loadOpenAISDK() {
|
|
|
17
26
|
});
|
|
18
27
|
return _loadPromise;
|
|
19
28
|
}
|
|
29
|
+
var _testClient;
|
|
30
|
+
function setOpenAIClientForTests(client) {
|
|
31
|
+
_testClient = client;
|
|
32
|
+
}
|
|
33
|
+
var _testOnly = {
|
|
34
|
+
setOpenAIClientForTests
|
|
35
|
+
};
|
|
20
36
|
async function getClient(model) {
|
|
37
|
+
if (_testClient)
|
|
38
|
+
return _testClient;
|
|
21
39
|
const OpenAI = await loadOpenAISDK();
|
|
22
40
|
const config = model?.provider_config;
|
|
23
41
|
const apiKey = resolveApiKey({
|
|
@@ -51,10 +69,13 @@ function getModelName(model) {
|
|
|
51
69
|
}
|
|
52
70
|
function getReasoningConfig(model) {
|
|
53
71
|
const reasoning = model?.provider_config?.reasoning;
|
|
54
|
-
if (
|
|
55
|
-
return;
|
|
72
|
+
if (reasoning && (reasoning.effort !== undefined || reasoning.mode !== undefined)) {
|
|
73
|
+
return reasoning;
|
|
56
74
|
}
|
|
57
|
-
|
|
75
|
+
if (isModelEffort(model?.effort)) {
|
|
76
|
+
return { effort: EFFORT_TO_OPENAI[model.effort] };
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
58
79
|
}
|
|
59
80
|
function fnv1aHex(input) {
|
|
60
81
|
let hash = 2166136261;
|
|
@@ -79,6 +100,8 @@ function finalizeResponsesRequest(model, params) {
|
|
|
79
100
|
const reasoning = getReasoningConfig(model);
|
|
80
101
|
if (reasoning !== undefined)
|
|
81
102
|
params.reasoning = reasoning;
|
|
103
|
+
else if (params.temperature !== undefined)
|
|
104
|
+
params.reasoning = { effort: "none" };
|
|
82
105
|
params.prompt_cache_key = resolvePromptCacheKey(model, params);
|
|
83
106
|
return params;
|
|
84
107
|
}
|
|
@@ -275,6 +298,7 @@ var OPENAI_IMAGE_EDITING = ["image.editing"];
|
|
|
275
298
|
var OPENAI_COUNT_TOKENS = ["model.count-tokens"];
|
|
276
299
|
var OPENAI_MODEL_SEARCH = ["model.search"];
|
|
277
300
|
var OPENAI_MODEL_INFO = ["model.info"];
|
|
301
|
+
var OPENAI_CACHE_CHECKPOINT = ["cache.checkpoint"];
|
|
278
302
|
var OPENAI_CAPABILITY_SETS = [
|
|
279
303
|
OPENAI_TEXT_GENERATION,
|
|
280
304
|
OPENAI_TOOL_USE,
|
|
@@ -286,7 +310,8 @@ var OPENAI_CAPABILITY_SETS = [
|
|
|
286
310
|
OPENAI_IMAGE_EDITING,
|
|
287
311
|
OPENAI_COUNT_TOKENS,
|
|
288
312
|
OPENAI_MODEL_SEARCH,
|
|
289
|
-
OPENAI_MODEL_INFO
|
|
313
|
+
OPENAI_MODEL_INFO,
|
|
314
|
+
OPENAI_CACHE_CHECKPOINT
|
|
290
315
|
];
|
|
291
316
|
|
|
292
317
|
// src/ai/common/OpenAI_Capabilities.ts
|
|
@@ -312,6 +337,7 @@ function inferOpenAiCapabilities(model) {
|
|
|
312
337
|
"text.summary",
|
|
313
338
|
"tool-use",
|
|
314
339
|
"json-mode",
|
|
340
|
+
"cache.checkpoint",
|
|
315
341
|
"model.count-tokens",
|
|
316
342
|
"model.info",
|
|
317
343
|
"model.search"
|
|
@@ -346,6 +372,54 @@ async function registerOpenAi(options) {
|
|
|
346
372
|
registerOpenAiImageValidator();
|
|
347
373
|
await registerProviderWithWorker(new OpenAiQueuedProvider, "OpenAI", options);
|
|
348
374
|
}
|
|
375
|
+
// src/ai/common/OpenAI_CacheCheckpoint.ts
|
|
376
|
+
import {
|
|
377
|
+
buildResponsesInput,
|
|
378
|
+
buildResponsesTools,
|
|
379
|
+
mapOpenAIResponsesUsage
|
|
380
|
+
} from "@workglow/ai/provider-utils";
|
|
381
|
+
import { promptToTailMessages, toOpenAIMessages } from "@workglow/ai/worker";
|
|
382
|
+
function mergeOpenAICheckpointPrefix(session, input) {
|
|
383
|
+
const prefix = session?.prefix;
|
|
384
|
+
if (!prefix)
|
|
385
|
+
return;
|
|
386
|
+
const tail = Array.isArray(input.messages) && input.messages.length > 0 ? input.messages : promptToTailMessages(input.prompt);
|
|
387
|
+
return {
|
|
388
|
+
messages: [...prefix.messages ?? [], ...tail],
|
|
389
|
+
systemPrompt: input.systemPrompt || prefix.systemPrompt,
|
|
390
|
+
tools: input.tools && input.tools.length > 0 ? input.tools : prefix.tools
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
var OpenAI_CacheCheckpoint_Stream = async (_input, model, signal, emit, _outputSchema, session) => {
|
|
394
|
+
const prefix = session?.prefix ?? {};
|
|
395
|
+
const client = await getClient(model);
|
|
396
|
+
const messages = toOpenAIMessages({
|
|
397
|
+
messages: prefix.messages ?? [],
|
|
398
|
+
systemPrompt: prefix.systemPrompt,
|
|
399
|
+
prompt: ".",
|
|
400
|
+
tools: []
|
|
401
|
+
});
|
|
402
|
+
const { input: responsesInput, instructions } = buildResponsesInput({ messages });
|
|
403
|
+
const params = {
|
|
404
|
+
model: getModelName(model),
|
|
405
|
+
input: responsesInput,
|
|
406
|
+
max_output_tokens: 16
|
|
407
|
+
};
|
|
408
|
+
if (instructions !== undefined)
|
|
409
|
+
params.instructions = instructions;
|
|
410
|
+
if (prefix.tools && prefix.tools.length > 0) {
|
|
411
|
+
params.tools = buildResponsesTools(prefix.tools);
|
|
412
|
+
}
|
|
413
|
+
finalizeResponsesRequest(model, params);
|
|
414
|
+
const response = await client.responses.create(params, { signal });
|
|
415
|
+
const usage = mapOpenAIResponsesUsage(response?.usage);
|
|
416
|
+
emit({
|
|
417
|
+
type: "finish",
|
|
418
|
+
data: { checkpoint: session?.sessionId ?? "" },
|
|
419
|
+
...usage ? { usage } : {}
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
|
|
349
423
|
// src/ai/common/OpenAI_CountTokens.ts
|
|
350
424
|
var _tiktoken;
|
|
351
425
|
async function loadTiktoken() {
|
|
@@ -563,13 +637,54 @@ var OPENAI_EMBEDDING_DIMENSIONS = {
|
|
|
563
637
|
"text-embedding-3-large": { native_dimensions: 3072, mrl: true },
|
|
564
638
|
"text-embedding-ada-002": { native_dimensions: 1536, mrl: false }
|
|
565
639
|
};
|
|
566
|
-
|
|
640
|
+
function modelNameOf(model) {
|
|
641
|
+
const name = model?.provider_config?.model_name;
|
|
642
|
+
if (!name) {
|
|
643
|
+
throw new Error("Missing model name in provider_config.model_name.");
|
|
644
|
+
}
|
|
645
|
+
return name;
|
|
646
|
+
}
|
|
647
|
+
function isNotFoundError(err) {
|
|
648
|
+
if (!err || typeof err !== "object")
|
|
649
|
+
return false;
|
|
650
|
+
const status = err.status;
|
|
651
|
+
const code = err.code;
|
|
652
|
+
const statusCode = err.statusCode;
|
|
653
|
+
return status === 404 || statusCode === 404 || code === "model_not_found";
|
|
654
|
+
}
|
|
655
|
+
async function assertOpenAiModelExists(model, signal) {
|
|
656
|
+
const modelName = modelNameOf(model);
|
|
657
|
+
const client = await getClient(model);
|
|
658
|
+
try {
|
|
659
|
+
await client.models.retrieve(modelName, signal ? { signal } : undefined);
|
|
660
|
+
} catch (err) {
|
|
661
|
+
if (isNotFoundError(err)) {
|
|
662
|
+
throw new Error(`${OPENAI} model "${modelName}" was not found (provider API returned not found)`);
|
|
663
|
+
}
|
|
664
|
+
throw err;
|
|
665
|
+
}
|
|
666
|
+
return modelName;
|
|
667
|
+
}
|
|
668
|
+
function remoteInfoBase(input) {
|
|
669
|
+
return {
|
|
670
|
+
model: input.model,
|
|
671
|
+
is_local: false,
|
|
672
|
+
is_remote: true,
|
|
673
|
+
supports_browser: true,
|
|
674
|
+
supports_node: true,
|
|
675
|
+
is_cached: false,
|
|
676
|
+
is_loaded: false,
|
|
677
|
+
file_sizes: null
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
var OpenAI_ModelInfo_Stream = async (input, model, signal, emit) => {
|
|
681
|
+
const modelName = await assertOpenAiModelExists(model, signal);
|
|
682
|
+
const base = remoteInfoBase(input);
|
|
567
683
|
if (input.detail === "dimensions") {
|
|
568
684
|
const pc = model?.provider_config;
|
|
569
685
|
let native_dimensions = typeof pc?.native_dimensions === "number" ? pc.native_dimensions : undefined;
|
|
570
686
|
let mrl = typeof pc?.mrl === "boolean" ? pc.mrl : undefined;
|
|
571
687
|
if (native_dimensions === undefined) {
|
|
572
|
-
const modelName = pc?.model_name ?? "";
|
|
573
688
|
const known = OPENAI_EMBEDDING_DIMENSIONS[modelName];
|
|
574
689
|
if (known) {
|
|
575
690
|
native_dimensions = known.native_dimensions;
|
|
@@ -579,38 +694,24 @@ var OpenAI_ModelInfo_Stream = async (input, model, _signal, emit) => {
|
|
|
579
694
|
emit({
|
|
580
695
|
type: "finish",
|
|
581
696
|
data: {
|
|
582
|
-
|
|
583
|
-
is_local: false,
|
|
584
|
-
is_remote: true,
|
|
585
|
-
supports_browser: true,
|
|
586
|
-
supports_node: true,
|
|
587
|
-
is_cached: false,
|
|
588
|
-
is_loaded: false,
|
|
589
|
-
file_sizes: null,
|
|
697
|
+
...base,
|
|
590
698
|
...native_dimensions !== undefined ? { native_dimensions } : {},
|
|
591
699
|
...mrl !== undefined ? { mrl } : {}
|
|
592
700
|
}
|
|
593
701
|
});
|
|
594
702
|
return;
|
|
595
703
|
}
|
|
596
|
-
emit({
|
|
597
|
-
type: "finish",
|
|
598
|
-
data: {
|
|
599
|
-
model: input.model,
|
|
600
|
-
is_local: false,
|
|
601
|
-
is_remote: true,
|
|
602
|
-
supports_browser: true,
|
|
603
|
-
supports_node: true,
|
|
604
|
-
is_cached: false,
|
|
605
|
-
is_loaded: false,
|
|
606
|
-
file_sizes: null
|
|
607
|
-
}
|
|
608
|
-
});
|
|
704
|
+
emit({ type: "finish", data: base });
|
|
609
705
|
};
|
|
610
706
|
|
|
611
707
|
// src/ai/common/OpenAI_StructuredGeneration.ts
|
|
612
|
-
import {
|
|
613
|
-
|
|
708
|
+
import {
|
|
709
|
+
createEstimatedOutputUsageReporter,
|
|
710
|
+
firstNonStrictReason,
|
|
711
|
+
isStrictCompatibleSchema,
|
|
712
|
+
mapOpenAIResponsesUsage as mapOpenAIResponsesUsage2
|
|
713
|
+
} from "@workglow/ai/provider-utils";
|
|
714
|
+
import { createPartialJsonStream } from "@workglow/util/worker";
|
|
614
715
|
|
|
615
716
|
// src/ai/common/OpenAI_ResponsesWarnings.ts
|
|
616
717
|
import { getLogger } from "@workglow/util/worker";
|
|
@@ -661,15 +762,20 @@ var OpenAI_StructuredGeneration_Stream = async (input, model, signal, emit, outp
|
|
|
661
762
|
if (input.temperature !== undefined)
|
|
662
763
|
params.temperature = input.temperature;
|
|
663
764
|
finalizeResponsesRequest(model, params);
|
|
765
|
+
const provisionalUsage = createEstimatedOutputUsageReporter(emit);
|
|
766
|
+
provisionalUsage.onPrompt(typeof input.prompt === "string" ? input.prompt : "");
|
|
664
767
|
const stream = await client.responses.create({ ...params, stream: true }, { signal });
|
|
665
|
-
|
|
768
|
+
const json = createPartialJsonStream();
|
|
666
769
|
let refusal = "";
|
|
770
|
+
let usage;
|
|
667
771
|
for await (const event of stream) {
|
|
668
|
-
if (event.type === "response.
|
|
772
|
+
if (event.type === "response.completed" || event.type === "response.incomplete" || event.type === "response.failed") {
|
|
773
|
+
usage = mapOpenAIResponsesUsage2(event.response?.usage) ?? usage;
|
|
774
|
+
} else if (event.type === "response.output_text.delta") {
|
|
669
775
|
const delta = event.delta ?? "";
|
|
670
776
|
if (delta) {
|
|
671
|
-
|
|
672
|
-
const partial =
|
|
777
|
+
provisionalUsage.onText(delta);
|
|
778
|
+
const partial = json.push(delta);
|
|
673
779
|
if (partial !== undefined) {
|
|
674
780
|
emit({ type: "object-delta", port: "object", objectDelta: partial });
|
|
675
781
|
}
|
|
@@ -678,19 +784,19 @@ var OpenAI_StructuredGeneration_Stream = async (input, model, signal, emit, outp
|
|
|
678
784
|
refusal += event.delta ?? "";
|
|
679
785
|
}
|
|
680
786
|
}
|
|
787
|
+
provisionalUsage.flush();
|
|
681
788
|
if (refusal) {
|
|
682
789
|
emit({ type: "refusal", refusal });
|
|
683
790
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
}
|
|
690
|
-
emit({ type: "finish", data: { object: finalObject } });
|
|
791
|
+
emit({
|
|
792
|
+
type: "finish",
|
|
793
|
+
data: { object: json.finishObject() },
|
|
794
|
+
usage
|
|
795
|
+
});
|
|
691
796
|
};
|
|
692
797
|
|
|
693
798
|
// src/ai/common/OpenAI_TextEmbedding.ts
|
|
799
|
+
import { toUsageCount, usageOrUndefined } from "@workglow/ai/provider-utils";
|
|
694
800
|
import { getLogger as getLogger2 } from "@workglow/util/worker";
|
|
695
801
|
var OpenAI_TextEmbedding_Stream = async (input, model, signal, emit) => {
|
|
696
802
|
const logger = getLogger2();
|
|
@@ -706,25 +812,41 @@ var OpenAI_TextEmbedding_Stream = async (input, model, signal, emit) => {
|
|
|
706
812
|
const result = Array.isArray(input.text) ? {
|
|
707
813
|
vector: response.data.map((item) => new Float32Array(item.embedding))
|
|
708
814
|
} : { vector: new Float32Array(response.data[0].embedding) };
|
|
709
|
-
|
|
815
|
+
const rawUsage = response.usage;
|
|
816
|
+
const usage = usageOrUndefined({
|
|
817
|
+
input: toUsageCount(rawUsage?.prompt_tokens),
|
|
818
|
+
output: undefined,
|
|
819
|
+
cached: undefined,
|
|
820
|
+
cacheWrite: undefined,
|
|
821
|
+
reasoning: undefined,
|
|
822
|
+
total: toUsageCount(rawUsage?.total_tokens),
|
|
823
|
+
extra: undefined
|
|
824
|
+
});
|
|
825
|
+
emit({ type: "finish", data: result, usage });
|
|
710
826
|
} finally {
|
|
711
827
|
logger.timeEnd(timerLabel, { model: getModelName(model) });
|
|
712
828
|
}
|
|
713
829
|
};
|
|
714
830
|
|
|
715
831
|
// src/ai/common/OpenAI_TextGeneration.ts
|
|
716
|
-
import {
|
|
717
|
-
|
|
832
|
+
import {
|
|
833
|
+
accumulateOpenAIResponsesStream,
|
|
834
|
+
buildResponsesInput as buildResponsesInput2,
|
|
835
|
+
buildResponsesTools as buildResponsesTools2,
|
|
836
|
+
createEstimatedOutputUsageReporter as createEstimatedOutputUsageReporter2,
|
|
837
|
+
promptTextForResponsesUsageEstimate
|
|
838
|
+
} from "@workglow/ai/provider-utils";
|
|
839
|
+
import { toOpenAIMessages as toOpenAIMessages2 } from "@workglow/ai/worker";
|
|
718
840
|
import { getLogger as getLogger3 } from "@workglow/util/worker";
|
|
719
841
|
function buildResponsesParams(input, model) {
|
|
720
842
|
const hasMessages = Array.isArray(input.messages) && input.messages.length > 0;
|
|
721
|
-
const messages = hasMessages ?
|
|
843
|
+
const messages = hasMessages ? toOpenAIMessages2({
|
|
722
844
|
messages: input.messages,
|
|
723
845
|
systemPrompt: input.systemPrompt,
|
|
724
846
|
prompt: "",
|
|
725
847
|
tools: []
|
|
726
848
|
}) : undefined;
|
|
727
|
-
const { input: responsesInput, instructions } =
|
|
849
|
+
const { input: responsesInput, instructions } = buildResponsesInput2({
|
|
728
850
|
messages,
|
|
729
851
|
prompt: hasMessages ? undefined : input.prompt,
|
|
730
852
|
systemPrompt: hasMessages ? undefined : input.systemPrompt
|
|
@@ -750,23 +872,38 @@ function buildResponsesParams(input, model) {
|
|
|
750
872
|
}
|
|
751
873
|
return params;
|
|
752
874
|
}
|
|
753
|
-
var OpenAI_TextGeneration_Stream = async (input, model, signal, emit) => {
|
|
875
|
+
var OpenAI_TextGeneration_Stream = async (input, model, signal, emit, _outputSchema, sessionContext) => {
|
|
754
876
|
const logger = getLogger3();
|
|
755
877
|
const timerLabel = `openai:TextGeneration:${getModelName(model)}`;
|
|
756
878
|
logger.time(timerLabel, { model: getModelName(model) });
|
|
757
879
|
try {
|
|
758
880
|
const client = await getClient(model);
|
|
759
|
-
const
|
|
881
|
+
const unified = input;
|
|
882
|
+
const merged = mergeOpenAICheckpointPrefix(sessionContext, unified);
|
|
883
|
+
const effective = merged ? { ...unified, messages: merged.messages, systemPrompt: merged.systemPrompt, prompt: "" } : unified;
|
|
884
|
+
const params = buildResponsesParams(effective, model);
|
|
885
|
+
if (merged?.tools && merged.tools.length > 0) {
|
|
886
|
+
params.tools = buildResponsesTools2(merged.tools);
|
|
887
|
+
}
|
|
888
|
+
finalizeResponsesRequest(model, params);
|
|
889
|
+
const promptText = promptTextForResponsesUsageEstimate(params);
|
|
890
|
+
createEstimatedOutputUsageReporter2(emit).onPrompt(promptText);
|
|
760
891
|
const stream = await client.responses.create({ ...params, stream: true }, { signal });
|
|
761
|
-
await accumulateOpenAIResponsesStream(stream, emit
|
|
762
|
-
|
|
892
|
+
const usage = await accumulateOpenAIResponsesStream(stream, emit, {
|
|
893
|
+
promptText
|
|
894
|
+
});
|
|
895
|
+
emit({ type: "finish", data: {}, usage });
|
|
763
896
|
} finally {
|
|
764
897
|
logger.timeEnd(timerLabel, { model: getModelName(model) });
|
|
765
898
|
}
|
|
766
899
|
};
|
|
767
900
|
|
|
768
901
|
// src/ai/common/OpenAI_TextRewriter.ts
|
|
769
|
-
import {
|
|
902
|
+
import {
|
|
903
|
+
accumulateOpenAIResponsesStream as accumulateOpenAIResponsesStream2,
|
|
904
|
+
createEstimatedOutputUsageReporter as createEstimatedOutputUsageReporter3,
|
|
905
|
+
promptTextForResponsesUsageEstimate as promptTextForResponsesUsageEstimate2
|
|
906
|
+
} from "@workglow/ai/provider-utils";
|
|
770
907
|
var OpenAI_TextRewriter_Stream = async (input, model, signal, emit) => {
|
|
771
908
|
const client = await getClient(model);
|
|
772
909
|
const params = {
|
|
@@ -775,13 +912,21 @@ var OpenAI_TextRewriter_Stream = async (input, model, signal, emit) => {
|
|
|
775
912
|
input: input.text
|
|
776
913
|
};
|
|
777
914
|
finalizeResponsesRequest(model, params);
|
|
915
|
+
const promptText = promptTextForResponsesUsageEstimate2(params);
|
|
916
|
+
createEstimatedOutputUsageReporter3(emit).onPrompt(promptText);
|
|
778
917
|
const stream = await client.responses.create({ ...params, stream: true }, { signal });
|
|
779
|
-
await accumulateOpenAIResponsesStream2(stream, emit
|
|
780
|
-
|
|
918
|
+
const usage = await accumulateOpenAIResponsesStream2(stream, emit, {
|
|
919
|
+
promptText
|
|
920
|
+
});
|
|
921
|
+
emit({ type: "finish", data: {}, usage });
|
|
781
922
|
};
|
|
782
923
|
|
|
783
924
|
// src/ai/common/OpenAI_TextSummary.ts
|
|
784
|
-
import {
|
|
925
|
+
import {
|
|
926
|
+
accumulateOpenAIResponsesStream as accumulateOpenAIResponsesStream3,
|
|
927
|
+
createEstimatedOutputUsageReporter as createEstimatedOutputUsageReporter4,
|
|
928
|
+
promptTextForResponsesUsageEstimate as promptTextForResponsesUsageEstimate3
|
|
929
|
+
} from "@workglow/ai/provider-utils";
|
|
785
930
|
var OpenAI_TextSummary_Stream = async (input, model, signal, emit) => {
|
|
786
931
|
const client = await getClient(model);
|
|
787
932
|
const params = {
|
|
@@ -790,25 +935,38 @@ var OpenAI_TextSummary_Stream = async (input, model, signal, emit) => {
|
|
|
790
935
|
input: input.text
|
|
791
936
|
};
|
|
792
937
|
finalizeResponsesRequest(model, params);
|
|
938
|
+
const promptText = promptTextForResponsesUsageEstimate3(params);
|
|
939
|
+
createEstimatedOutputUsageReporter4(emit).onPrompt(promptText);
|
|
793
940
|
const stream = await client.responses.create({ ...params, stream: true }, { signal });
|
|
794
|
-
await accumulateOpenAIResponsesStream3(stream, emit
|
|
795
|
-
|
|
941
|
+
const usage = await accumulateOpenAIResponsesStream3(stream, emit, {
|
|
942
|
+
promptText
|
|
943
|
+
});
|
|
944
|
+
emit({ type: "finish", data: {}, usage });
|
|
796
945
|
};
|
|
797
946
|
|
|
798
947
|
// src/ai/common/OpenAI_ToolCalling.ts
|
|
799
948
|
import {
|
|
800
949
|
accumulateOpenAIResponsesStream as accumulateOpenAIResponsesStream4,
|
|
801
|
-
buildResponsesInput as
|
|
802
|
-
buildResponsesTools,
|
|
803
|
-
|
|
950
|
+
buildResponsesInput as buildResponsesInput3,
|
|
951
|
+
buildResponsesTools as buildResponsesTools3,
|
|
952
|
+
createEstimatedOutputUsageReporter as createEstimatedOutputUsageReporter5,
|
|
953
|
+
mapResponsesToolChoice,
|
|
954
|
+
promptTextForResponsesUsageEstimate as promptTextForResponsesUsageEstimate4
|
|
804
955
|
} from "@workglow/ai/provider-utils";
|
|
805
|
-
import { filterValidToolCalls, toOpenAIMessages as
|
|
806
|
-
var OpenAI_ToolCalling_Stream = async (input, model, signal, emit) => {
|
|
956
|
+
import { filterValidToolCalls, toOpenAIMessages as toOpenAIMessages3 } from "@workglow/ai/worker";
|
|
957
|
+
var OpenAI_ToolCalling_Stream = async (input, model, signal, emit, _outputSchema, sessionContext) => {
|
|
807
958
|
const client = await getClient(model);
|
|
808
959
|
const modelName = getModelName(model);
|
|
809
|
-
const
|
|
810
|
-
const
|
|
811
|
-
|
|
960
|
+
const merged = mergeOpenAICheckpointPrefix(sessionContext, input);
|
|
961
|
+
const toolDefinitions = merged?.tools ?? input.tools;
|
|
962
|
+
const tools = buildResponsesTools3(toolDefinitions);
|
|
963
|
+
const { input: responsesInput, instructions } = buildResponsesInput3({
|
|
964
|
+
messages: toOpenAIMessages3(merged ? {
|
|
965
|
+
...input,
|
|
966
|
+
messages: merged.messages,
|
|
967
|
+
systemPrompt: merged.systemPrompt,
|
|
968
|
+
prompt: ""
|
|
969
|
+
} : input)
|
|
812
970
|
});
|
|
813
971
|
const toolChoice = mapResponsesToolChoice(input.toolChoice);
|
|
814
972
|
const params = {
|
|
@@ -824,18 +982,20 @@ var OpenAI_ToolCalling_Stream = async (input, model, signal, emit) => {
|
|
|
824
982
|
if (input.temperature !== undefined)
|
|
825
983
|
params.temperature = input.temperature;
|
|
826
984
|
finalizeResponsesRequest(model, params);
|
|
985
|
+
const promptText = promptTextForResponsesUsageEstimate4(params);
|
|
986
|
+
createEstimatedOutputUsageReporter5(emit).onPrompt(promptText);
|
|
827
987
|
const stream = await client.responses.create({ ...params, stream: true }, { signal });
|
|
828
|
-
await accumulateOpenAIResponsesStream4(stream, (event) => {
|
|
988
|
+
const usage = await accumulateOpenAIResponsesStream4(stream, (event) => {
|
|
829
989
|
if (event.type === "object-delta" && event.port === "toolCalls") {
|
|
830
|
-
const validated = filterValidToolCalls(event.objectDelta,
|
|
990
|
+
const validated = filterValidToolCalls(event.objectDelta, toolDefinitions);
|
|
831
991
|
if (validated.length > 0) {
|
|
832
992
|
emit({ type: "object-delta", port: "toolCalls", objectDelta: validated });
|
|
833
993
|
}
|
|
834
994
|
return;
|
|
835
995
|
}
|
|
836
996
|
emit(event);
|
|
837
|
-
});
|
|
838
|
-
emit({ type: "finish", data: { text: "", toolCalls: [] } });
|
|
997
|
+
}, { promptText });
|
|
998
|
+
emit({ type: "finish", data: { text: "", toolCalls: [] }, usage });
|
|
839
999
|
};
|
|
840
1000
|
|
|
841
1001
|
// src/ai/common/OpenAI_JobRunFns.ts
|
|
@@ -850,28 +1010,31 @@ var OPENAI_RUN_FNS = [
|
|
|
850
1010
|
{ serves: OPENAI_IMAGE_EDITING, runFn: OpenAI_ImageEdit_Stream },
|
|
851
1011
|
{ serves: OPENAI_COUNT_TOKENS, runFn: OpenAI_CountTokens_Stream },
|
|
852
1012
|
{ serves: OPENAI_MODEL_SEARCH, runFn: OpenAI_ModelSearch_Stream },
|
|
853
|
-
{ serves: OPENAI_MODEL_INFO, runFn: OpenAI_ModelInfo_Stream }
|
|
1013
|
+
{ serves: OPENAI_MODEL_INFO, runFn: OpenAI_ModelInfo_Stream },
|
|
1014
|
+
{ serves: OPENAI_CACHE_CHECKPOINT, runFn: OpenAI_CacheCheckpoint_Stream }
|
|
854
1015
|
];
|
|
855
1016
|
var OPENAI_PREVIEW_TASKS = {
|
|
856
1017
|
CountTokensTask: OpenAI_CountTokens_Preview
|
|
857
1018
|
};
|
|
858
1019
|
|
|
859
1020
|
// src/ai/index.ts
|
|
860
|
-
var
|
|
1021
|
+
var _testOnly2 = {
|
|
861
1022
|
OpenAiQueuedProvider,
|
|
862
1023
|
OPENAI_RUN_FN_SPECS,
|
|
863
1024
|
OPENAI_RUN_FNS,
|
|
1025
|
+
finalizeResponsesRequest,
|
|
864
1026
|
getReasoningConfig,
|
|
865
1027
|
resolvePromptCacheKey,
|
|
866
1028
|
isStrictCompatibleSchema,
|
|
867
1029
|
warnPenaltyDroppedOnce,
|
|
868
1030
|
warnStrictDowngradedOnce,
|
|
869
|
-
_resetOpenAIResponsesWarnings
|
|
1031
|
+
_resetOpenAIResponsesWarnings,
|
|
1032
|
+
setOpenAIClientForTests: _testOnly.setOpenAIClientForTests
|
|
870
1033
|
};
|
|
871
1034
|
export {
|
|
872
1035
|
registerOpenAiImageValidator,
|
|
873
1036
|
registerOpenAi,
|
|
874
|
-
_testOnly,
|
|
1037
|
+
_testOnly2 as _testOnly,
|
|
875
1038
|
OpenAiModelSchema,
|
|
876
1039
|
OpenAiModelRecordSchema,
|
|
877
1040
|
OpenAiModelConfigSchema,
|
|
@@ -880,4 +1043,4 @@ export {
|
|
|
880
1043
|
OPENAI
|
|
881
1044
|
};
|
|
882
1045
|
|
|
883
|
-
//# debugId=
|
|
1046
|
+
//# debugId=9552B65D8C18B6CE64756E2164756E21
|