@fgv/ts-extras 5.1.0-52 → 5.1.0-53
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/packlets/ai-assist/completionClient.js +147 -19
- package/dist/packlets/ai-assist/completionClient.js.map +1 -1
- package/dist/packlets/ai-assist/index.js +2 -1
- package/dist/packlets/ai-assist/index.js.map +1 -1
- package/dist/packlets/ai-assist/jsonCompletion.js +20 -2
- package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -1
- package/dist/packlets/ai-assist/model.js.map +1 -1
- package/dist/packlets/ai-assist/registry.js +39 -1
- package/dist/packlets/ai-assist/registry.js.map +1 -1
- package/dist/packlets/ai-assist/structuredOutput.js +315 -0
- package/dist/packlets/ai-assist/structuredOutput.js.map +1 -0
- package/dist/packlets/ai-assist/structuredOutputTypes.js +21 -0
- package/dist/packlets/ai-assist/structuredOutputTypes.js.map +1 -0
- package/dist/ts-extras.d.ts +229 -2
- package/lib/packlets/ai-assist/completionClient.d.ts +13 -0
- package/lib/packlets/ai-assist/completionClient.d.ts.map +1 -1
- package/lib/packlets/ai-assist/completionClient.js +146 -18
- package/lib/packlets/ai-assist/completionClient.js.map +1 -1
- package/lib/packlets/ai-assist/index.d.ts +3 -1
- package/lib/packlets/ai-assist/index.d.ts.map +1 -1
- package/lib/packlets/ai-assist/index.js +6 -2
- package/lib/packlets/ai-assist/index.js.map +1 -1
- package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -1
- package/lib/packlets/ai-assist/jsonCompletion.js +20 -2
- package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -1
- package/lib/packlets/ai-assist/model.d.ts +38 -2
- package/lib/packlets/ai-assist/model.d.ts.map +1 -1
- package/lib/packlets/ai-assist/model.js.map +1 -1
- package/lib/packlets/ai-assist/registry.d.ts +20 -0
- package/lib/packlets/ai-assist/registry.d.ts.map +1 -1
- package/lib/packlets/ai-assist/registry.js +41 -1
- package/lib/packlets/ai-assist/registry.js.map +1 -1
- package/lib/packlets/ai-assist/structuredOutput.d.ts +88 -0
- package/lib/packlets/ai-assist/structuredOutput.d.ts.map +1 -0
- package/lib/packlets/ai-assist/structuredOutput.js +321 -0
- package/lib/packlets/ai-assist/structuredOutput.js.map +1 -0
- package/lib/packlets/ai-assist/structuredOutputTypes.d.ts +142 -0
- package/lib/packlets/ai-assist/structuredOutputTypes.d.ts.map +1 -0
- package/lib/packlets/ai-assist/structuredOutputTypes.js +22 -0
- package/lib/packlets/ai-assist/structuredOutputTypes.js.map +1 -0
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completionClient.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/completionClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Chat completion clients for AI assist. One provider dispatcher over\n * `IAiProviderDescriptor.apiFormat`, the four adapters it routes to (OpenAI Chat\n * Completions, OpenAI/xAI Responses, Anthropic, Google Gemini), the response\n * validators those adapters use, and the proxied variant of the same modality.\n *\n * @packageDocumentation\n */\n\nimport { type JsonObject } from '@fgv/ts-json-base';\nimport { fail, type Logging, Result, succeed, type Validator, Validators } from '@fgv/ts-utils';\n\nimport {\n AiPrompt,\n type AiServerToolConfig,\n DEFAULT_ANTHROPIC_MAX_TOKENS,\n type IAiCompletionResponse,\n type IAiProviderDescriptor,\n type IChatMessage,\n type IChatRequest,\n type IThinkingConfig,\n type ModelSpec,\n type ModelSpecKey,\n isAdaptiveThinkingModel,\n isResponsesOnlyModel,\n resolveProviderModel,\n usesMaxCompletionTokensField\n} from './model';\nimport {\n anthropicEffortToBudgetTokens,\n checkTemperatureConflict,\n mergeThinkingConfig,\n providerDiscriminatorForId,\n type IResolvedThinkingConfig\n} from './thinkingOptionsResolver';\nimport {\n buildAnthropicMessages,\n buildGeminiContents,\n buildMessages,\n buildOpenAiChatUserContent,\n buildOpenAiResponsesUserContent,\n normalizeOutboundMessages,\n splitChatRequest\n} from './chatRequestBuilders';\nimport {\n anthropicAuthHeaders,\n bearerAuthHeader,\n geminiAuthHeader,\n resolveEffectiveBaseUrl\n} from './endpoint';\nimport { type IAiApiConfig, fetchJson } from './http';\nimport { toAnthropicTools, toGeminiTools, toResponsesApiTools } from './toolFormats';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Parameters for a provider completion request. Carries the unified\n * {@link AiAssist.IChatRequest} shape (`system?` + ordered `messages`, last =\n * current user turn); history is linearized before the current turn.\n * @public\n */\nexport interface IProviderCompletionParams extends IChatRequest {\n /** The provider descriptor */\n readonly descriptor: IAiProviderDescriptor;\n /** API key for authentication */\n readonly apiKey: string;\n /**\n * Sampling temperature. Sent to the provider only when explicitly provided; omitted otherwise\n * so the provider's own default applies (current-gen models reject a caller-supplied default).\n */\n readonly temperature?: number;\n /** Optional model override — string or context-aware map (uses descriptor.defaultModel otherwise) */\n readonly modelOverride?: ModelSpec;\n /**\n * Optional quality tier selecting which completion model to use. `undefined`\n * selects the `base` tier; `'frontier'` cascades to `advanced` then `base`\n * when a tier is unset for a provider. Orthogonal to `thinking` and `tools`,\n * which never select a model.\n */\n readonly tier?: 'advanced' | 'frontier';\n /** Optional logger for request/response observability. */\n readonly logger?: Logging.ILogger;\n /** Server-side tools to include in the request. Overrides settings-level tool config when provided. */\n readonly tools?: ReadonlyArray<AiServerToolConfig>;\n /** Optional abort signal for cancelling the in-flight request. */\n readonly signal?: AbortSignal;\n /**\n * Optional override of the descriptor's default base URL (scheme + host +\n * optional port + path prefix). The per-route suffix (e.g. `/chat/completions`)\n * is appended unchanged. Must be a well-formed `http`/`https` URL. Auth shape\n * is unchanged: `needsSecret` providers still require an API key.\n */\n readonly endpoint?: string;\n /**\n * Optional thinking/reasoning config. Anthropic, OpenAI, and xAI reject `temperature` when\n * the effective merged effort is non-`'none'`; Gemini always accepts both.\n */\n readonly thinking?: IThinkingConfig;\n /**\n * Optional cap on generated output tokens, mapped to each provider's native field:\n * Anthropic `max_tokens`, OpenAI Chat Completions `max_completion_tokens`, OpenAI/xAI\n * Responses `max_output_tokens`, Gemini `generationConfig.maxOutputTokens`, and the\n * xAI/Groq/Mistral/Ollama/`openai-compat` chat-completions path `max_tokens`. When unset,\n * every provider except Anthropic omits the field and applies its own default; Anthropic's\n * Messages API requires the field, so it falls back to `DEFAULT_ANTHROPIC_MAX_TOKENS`.\n */\n readonly maxTokens?: number;\n}\n\n// ============================================================================\n// Response validators (non-strict — extra API fields preserved for debugging)\n// ============================================================================\n\n// ---- OpenAI Chat Completions format ----\n\n/** @internal */\ninterface IOpenAiMessage {\n content: string;\n}\n/** @internal */\ninterface IOpenAiChoice {\n message: IOpenAiMessage;\n finish_reason: string;\n}\n/** @internal */\ninterface IOpenAiResponse {\n choices: IOpenAiChoice[];\n}\n\nconst openAiMessage: Validator<IOpenAiMessage> = Validators.object<IOpenAiMessage>({\n content: Validators.string\n});\nconst openAiChoice: Validator<IOpenAiChoice> = Validators.object<IOpenAiChoice>({\n message: openAiMessage,\n finish_reason: Validators.string\n});\nconst openAiResponse: Validator<IOpenAiResponse> = Validators.object<IOpenAiResponse>({\n choices: Validators.arrayOf(openAiChoice).withConstraint((arr) => arr.length > 0)\n});\n\n// ---- OpenAI/xAI Responses API format ----\n\n/** @internal */\ninterface IResponsesApiOutputText {\n type: 'output_text';\n text: string;\n}\n/** @internal */\ninterface IResponsesApiMessage {\n type: 'message';\n role: string;\n content: IResponsesApiOutputText[];\n}\n/** @internal */\ninterface IResponsesApiResponse {\n output: Array<Record<string, unknown>>;\n status: string;\n}\n\nconst responsesApiOutputText: Validator<IResponsesApiOutputText> = Validators.object<IResponsesApiOutputText>(\n {\n type: Validators.literal('output_text'),\n text: Validators.string\n }\n);\nconst responsesApiMessage: Validator<IResponsesApiMessage> = Validators.object<IResponsesApiMessage>({\n type: Validators.literal('message'),\n role: Validators.string,\n content: Validators.arrayOf(responsesApiOutputText).withConstraint((arr) => arr.length > 0)\n});\nconst responsesApiOutputItem: Validator<Record<string, unknown>> = Validators.isA(\n 'object',\n (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null\n);\nconst responsesApiResponse: Validator<IResponsesApiResponse> = Validators.object<IResponsesApiResponse>({\n output: Validators.arrayOf(responsesApiOutputItem).withConstraint((arr) => arr.length > 0),\n status: Validators.string\n});\n\n// ---- Gemini format ----\n\n/** @internal */\ninterface IGeminiPart {\n text: string;\n}\n/** @internal */\ninterface IGeminiContent {\n parts: IGeminiPart[];\n}\n/** @internal */\ninterface IGeminiCandidate {\n content: IGeminiContent;\n finishReason: string;\n}\n/** @internal */\ninterface IGeminiResponse {\n candidates: IGeminiCandidate[];\n}\n\nconst geminiPart: Validator<IGeminiPart> = Validators.object<IGeminiPart>({\n text: Validators.string\n});\nconst geminiContent: Validator<IGeminiContent> = Validators.object<IGeminiContent>({\n parts: Validators.arrayOf(geminiPart).withConstraint((arr) => arr.length > 0)\n});\nconst geminiCandidate: Validator<IGeminiCandidate> = Validators.object<IGeminiCandidate>({\n content: geminiContent,\n finishReason: Validators.string\n});\nconst geminiResponse: Validator<IGeminiResponse> = Validators.object<IGeminiResponse>({\n candidates: Validators.arrayOf(geminiCandidate).withConstraint((arr) => arr.length > 0)\n});\n\n// ============================================================================\n// OpenAI-compatible client (Chat Completions — no tools)\n// ============================================================================\n\n/**\n * Calls an OpenAI-compatible chat completion endpoint.\n * Works for xAI Grok, OpenAI, Groq, and Mistral.\n * @internal\n */\nasync function callOpenAiCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number,\n useMaxCompletionTokensField: boolean = false\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/chat/completions`;\n const messages = buildMessages(prompt.system, buildOpenAiChatUserContent(prompt), {\n head\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const maxTokensField = useMaxCompletionTokensField ? 'max_completion_tokens' : 'max_tokens';\n const body: Record<string, unknown> = {\n model: config.model,\n messages,\n // Temperature is sent only when the caller explicitly provided one — omitting it lets each\n // provider apply its own default (current-gen models reject a non-default temperature). The\n // completion path already rejects temperature + non-'none' thinking upstream\n // (checkTemperatureConflict), so no effort gate is needed here.\n ...(temperature !== undefined ? { temperature } : {}),\n ...(effort !== undefined && config.model !== 'grok-4' ? { reasoning_effort: effort } : {}),\n // Omitted when the caller doesn't set maxTokens — every non-Anthropic provider applies its\n // own default. See AiAssist.usesMaxCompletionTokensField for the field-name split.\n ...(maxTokens !== undefined ? { [maxTokensField]: maxTokens } : {})\n };\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`OpenAI completion: model=${config.model}`);\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return openAiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `OpenAI API response: ${msg}`)\n .onSuccess((response) => {\n const choice = response.choices[0];\n return succeed({\n content: choice.message.content,\n truncated: choice.finish_reason === 'length'\n });\n });\n}\n\n// ============================================================================\n// OpenAI/xAI Responses API (with tools)\n// ============================================================================\n\n/**\n * Extracts text content from a Responses API output array.\n * Finds the first message-type output item and concatenates its text content blocks.\n * @internal\n */\nfunction extractResponsesApiText(output: Array<Record<string, unknown>>): Result<string> {\n for (const item of output) {\n if (item.type === 'message') {\n const messageResult = responsesApiMessage.validate(item as JsonObject);\n if (messageResult.isSuccess()) {\n return succeed(messageResult.value.content.map((c) => c.text).join(''));\n }\n }\n }\n return fail('Responses API output contained no message with text content');\n}\n\n/**\n * Calls the xAI/OpenAI Responses API with server-side tools.\n * Used when tools are configured for an openai-format provider.\n * @internal\n */\nasync function callOpenAiResponsesCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n tools: ReadonlyArray<AiServerToolConfig> = [],\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/responses`;\n const input = buildMessages(prompt.system, buildOpenAiResponsesUserContent(prompt), {\n head\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const body: Record<string, unknown> = {\n model: config.model,\n input,\n // `tools` is omitted entirely when none are requested — a Responses-only model routed\n // here for tier/model reasons (not tools) must not send an empty tools array.\n ...(tools.length > 0 ? { tools: toResponsesApiTools(tools) } : {}),\n // Temperature is sent only when the caller explicitly provided one (see callOpenAiCompletion).\n ...(temperature !== undefined ? { temperature } : {}),\n ...(effort !== undefined && config.model !== 'grok-4' ? { reasoning: { effort } } : {})\n };\n // Shared by OpenAI and xAI — both route through the Responses API with the same field name.\n if (maxTokens !== undefined) {\n body.max_output_tokens = maxTokens;\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`OpenAI Responses API: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return responsesApiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Responses API response: ${msg}`)\n .onSuccess((response) => {\n return extractResponsesApiText(response.output).onSuccess((text) =>\n succeed({\n content: text,\n truncated: response.status === 'incomplete'\n })\n );\n });\n}\n\n// ============================================================================\n// Anthropic adapter\n// ============================================================================\n\n/**\n * Extracts text content from Anthropic response content blocks.\n * When tools are used, the content array contains mixed block types\n * (text, server_tool_use, web_search_tool_result). We extract and\n * concatenate only the text blocks.\n * @internal\n */\nfunction extractAnthropicText(content: unknown[]): Result<string> {\n const textParts: string[] = [];\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block) {\n const typed = block as Record<string, unknown>;\n if (typed.type === 'text' && typeof typed.text === 'string') {\n textParts.push(typed.text);\n }\n }\n }\n if (textParts.length === 0) {\n return fail('Anthropic response contained no text content blocks');\n }\n return succeed(textParts.join(''));\n}\n\n/** Calls the Anthropic Messages API with optional tool support. @internal */\nasync function callAnthropicCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n tools?: ReadonlyArray<AiServerToolConfig>,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n useAdaptiveThinking: boolean = false,\n maxTokens?: number\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/messages`;\n const messages = buildAnthropicMessages(prompt, { head });\n const body: Record<string, unknown> = {\n model: config.model,\n system: prompt.system,\n messages,\n // Anthropic's Messages API requires max_tokens on every request — see\n // AiAssist.DEFAULT_ANTHROPIC_MAX_TOKENS for why only this provider defaults it.\n max_tokens: maxTokens ?? DEFAULT_ANTHROPIC_MAX_TOKENS,\n // Temperature is sent only when explicitly provided (Claude-5 rejects any temperature). The\n // completion path rejects temperature + thinking upstream (checkTemperatureConflict), so no\n // effort gate is needed here.\n ...(temperature !== undefined ? { temperature } : {})\n };\n\n const effort = resolvedThinking?.anthropicEffort;\n if (effort !== undefined) {\n if (useAdaptiveThinking) {\n // Claude 5 family: adaptive thinking — no budget_tokens; effort moves to the\n // top-level output_config block. See AiAssist.isAdaptiveThinkingModel.\n body.thinking = { type: 'adaptive' };\n body.output_config = { effort };\n } else {\n body.thinking = { type: 'enabled', budget_tokens: anthropicEffortToBudgetTokens(effort) };\n }\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n\n if (tools && tools.length > 0) {\n body.tools = toAnthropicTools(tools);\n /* c8 ignore next 3 - optional logger diagnostic output */\n logger?.info(`Anthropic completion: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n } else {\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Anthropic completion: model=${config.model}`);\n }\n\n const headers: Record<string, string> = anthropicAuthHeaders(config.apiKey);\n\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n\n const rawContent = (jsonResult.value as Record<string, unknown>).content;\n const stopReason = (jsonResult.value as Record<string, unknown>).stop_reason;\n if (!Array.isArray(rawContent)) {\n return fail('Anthropic API response: content is not an array');\n }\n if (typeof stopReason !== 'string') {\n return fail('Anthropic API response: stop_reason is missing or not a string');\n }\n return extractAnthropicText(rawContent).onSuccess((text) =>\n succeed({\n content: text,\n truncated: stopReason === 'max_tokens'\n })\n );\n}\n\n// ============================================================================\n// Google Gemini adapter\n// ============================================================================\n\n/**\n * Calls the Google Gemini generateContent API.\n * When tools are configured, includes Google Search grounding.\n * @internal\n */\nasync function callGeminiCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n tools?: ReadonlyArray<AiServerToolConfig>,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/models/${config.model}:generateContent`;\n const contents = buildGeminiContents(prompt, { head });\n\n // Temperature is sent only when explicitly provided; otherwise Gemini's default applies.\n const generationConfig: Record<string, unknown> = {};\n if (temperature !== undefined) {\n generationConfig.temperature = temperature;\n }\n if (maxTokens !== undefined) {\n generationConfig.maxOutputTokens = maxTokens;\n }\n if (resolvedThinking?.geminiThinkingBudget !== undefined) {\n generationConfig.thinkingConfig = { thinkingBudget: resolvedThinking.geminiThinkingBudget };\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(generationConfig, resolvedThinking.otherParams);\n }\n const body: Record<string, unknown> = {\n systemInstruction: { parts: [{ text: prompt.system }] },\n contents,\n generationConfig\n };\n\n if (tools && tools.length > 0) {\n body.tools = toGeminiTools(tools);\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Gemini completion: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n } else {\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Gemini completion: model=${config.model}`);\n }\n\n const headers: Record<string, string> = geminiAuthHeader(config.apiKey);\n\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return geminiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Gemini API response: ${msg}`)\n .onSuccess((response) => {\n const candidate = response.candidates[0];\n return succeed({\n content: candidate.content.parts[0].text,\n truncated: candidate.finishReason === 'MAX_TOKENS'\n });\n });\n}\n\n// ============================================================================\n// Provider dispatcher\n// ============================================================================\n\n/**\n * Calls the appropriate chat completion API for a given provider. Routes by\n * `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API\n * when tools are set), `'anthropic'`, or `'gemini'`.\n * @public\n */\nexport async function callProviderCompletion(\n params: IProviderCompletionParams\n): Promise<Result<IAiCompletionResponse>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n tier,\n logger,\n tools,\n signal,\n endpoint,\n thinking,\n maxTokens\n } = params;\n\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n const { prompt, head } = splitResult.value;\n\n const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);\n if (baseUrlResult.isFailure()) {\n return fail(baseUrlResult.message);\n }\n if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const hasTools = tools !== undefined && tools.length > 0;\n const discriminator = providerDiscriminatorForId(descriptor.id);\n // The quality tier is the only completion-model selector; thinking and tools\n // are orthogonal request params/capabilities and never pick a model.\n const modelContext: ModelSpecKey | undefined = tier;\n\n const modelResult = resolveProviderModel(descriptor, modelOverride, modelContext);\n if (modelResult.isFailure()) {\n return fail(modelResult.message);\n }\n const model = modelResult.value;\n\n let resolvedThinking: IResolvedThinkingConfig | undefined;\n if (thinking !== undefined) {\n if (discriminator !== undefined) {\n const mergeResult = mergeThinkingConfig(thinking, model, discriminator);\n /* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */\n if (mergeResult.isFailure()) {\n return fail(mergeResult.message);\n }\n resolvedThinking = mergeResult.value;\n const conflictResult = checkTemperatureConflict(resolvedThinking, discriminator, temperature);\n if (conflictResult.isFailure()) {\n return fail(conflictResult.message);\n }\n }\n }\n\n const config: IAiApiConfig = {\n baseUrl: baseUrlResult.value,\n apiKey,\n model\n };\n /* c8 ignore next 8 - optional logger diagnostic output */\n if (logger) {\n const toolTypes = hasTools ? tools.map((t) => t.type).join(',') : 'none';\n const supported = descriptor.supportedTools.length > 0 ? descriptor.supportedTools.join(',') : 'none';\n logger.info(\n `AI completion: provider=${descriptor.id}, format=${descriptor.apiFormat}, model=${config.model}, ` +\n `tools=${toolTypes}, supported=${supported}`\n );\n }\n\n switch (descriptor.apiFormat) {\n case 'openai':\n // Responses-API-only models (e.g. gpt-5.5-pro) 400 on /chat/completions, so they route\n // to the Responses path even with no tools requested — same path the tools case uses.\n if (hasTools || isResponsesOnlyModel(descriptor, config.model)) {\n return callOpenAiResponsesCompletion(\n config,\n prompt,\n tools,\n head,\n temperature,\n logger,\n signal,\n resolvedThinking,\n maxTokens\n );\n }\n return callOpenAiCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n signal,\n resolvedThinking,\n maxTokens,\n usesMaxCompletionTokensField(descriptor)\n );\n case 'anthropic':\n return callAnthropicCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n tools,\n signal,\n resolvedThinking,\n isAdaptiveThinkingModel(descriptor, config.model),\n maxTokens\n );\n case 'gemini':\n return callGeminiCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n tools,\n signal,\n resolvedThinking,\n maxTokens\n );\n /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = descriptor.apiFormat;\n return fail(`unsupported API format: ${String(_exhaustive)}`);\n }\n }\n}\n\n// ============================================================================\n// Proxied completion (routes through a backend server)\n// ============================================================================\n\n/**\n * Calls the AI completion endpoint on a proxy server instead of calling the\n * provider API directly from the browser. The proxy handles provider dispatch,\n * CORS, and API key forwarding. The request body serializes the unified\n * {@link AiAssist.IChatRequest} shape (`system?` + `messages`). Enforces the same\n * non-empty / trailing-user-turn and image-input invariants as the direct path.\n * @param proxyUrl - Base URL of the proxy server\n * @param params - Same parameters as {@link callProviderCompletion}\n * @public\n */\nexport async function callProxiedCompletion(\n proxyUrl: string,\n params: IProviderCompletionParams\n): Promise<Result<IAiCompletionResponse>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n logger,\n tools,\n signal,\n thinking,\n maxTokens\n } = params;\n\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n if (splitResult.value.prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const body: Record<string, unknown> = {\n providerId: descriptor.id,\n apiKey,\n messages: normalizeOutboundMessages(splitResult.value)\n };\n // Temperature is forwarded only when explicitly provided, matching the direct path — the proxy\n // omits it from the upstream request so the provider default applies.\n if (temperature !== undefined) {\n body.temperature = temperature;\n }\n if (system !== undefined) {\n body.system = system;\n }\n if (modelOverride !== undefined) {\n body.modelOverride = modelOverride;\n }\n if (tools && tools.length > 0) {\n body.tools = tools;\n }\n if (thinking !== undefined) {\n body.thinking = thinking;\n }\n // Forwarded only when explicitly provided; the proxy is responsible for mapping it to the\n // correct upstream provider field (see AiAssist.usesMaxCompletionTokensField).\n if (maxTokens !== undefined) {\n body.maxTokens = maxTokens;\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);\n const url = `${proxyUrl}/api/ai/completion`;\n const jsonResult = await fetchJson(url, {}, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n\n const response = jsonResult.value as Record<string, unknown>;\n if (typeof response.error === 'string') {\n return fail(`proxy: ${response.error}`);\n }\n\n if (typeof response.content !== 'string') {\n return fail('proxy returned invalid response: missing content');\n }\n\n return succeed({\n content: response.content,\n truncated: response.truncated === true\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"completionClient.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/completionClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * Chat completion clients for AI assist. One provider dispatcher over\n * `IAiProviderDescriptor.apiFormat`, the four adapters it routes to (OpenAI Chat\n * Completions, OpenAI/xAI Responses, Anthropic, Google Gemini), the response\n * validators those adapters use, and the proxied variant of the same modality.\n *\n * @packageDocumentation\n */\n\nimport { type JsonObject } from '@fgv/ts-json-base';\nimport {\n captureResult,\n fail,\n type Logging,\n Result,\n succeed,\n type Validator,\n Validators\n} from '@fgv/ts-utils';\n\nimport {\n AiPrompt,\n type AiServerToolConfig,\n DEFAULT_ANTHROPIC_MAX_TOKENS,\n type IAiCompletionResponse,\n type IAiProviderDescriptor,\n type IChatMessage,\n type IChatRequest,\n type IThinkingConfig,\n type ModelSpec,\n type ModelSpecKey,\n isAdaptiveThinkingModel,\n isResponsesOnlyModel,\n resolveProviderModel,\n usesMaxCompletionTokensField\n} from './model';\nimport {\n anthropicEffortToBudgetTokens,\n checkTemperatureConflict,\n mergeThinkingConfig,\n providerDiscriminatorForId,\n type IResolvedThinkingConfig\n} from './thinkingOptionsResolver';\nimport {\n buildAnthropicMessages,\n buildGeminiContents,\n buildMessages,\n buildOpenAiChatUserContent,\n buildOpenAiResponsesUserContent,\n normalizeOutboundMessages,\n splitChatRequest\n} from './chatRequestBuilders';\nimport {\n anthropicAuthHeaders,\n bearerAuthHeader,\n geminiAuthHeader,\n resolveEffectiveBaseUrl\n} from './endpoint';\nimport { type IAiApiConfig, fetchJson } from './http';\nimport { toAnthropicTools, toGeminiTools, toResponsesApiTools } from './toolFormats';\nimport {\n ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME,\n type IResolvedStructuredOutput,\n NO_STRUCTURED_OUTPUT,\n isStructuredOutputEnforcement,\n resolveStructuredOutput\n} from './structuredOutput';\nimport { resolveStructuredOutputCapability } from './registry';\nimport type { StructuredOutputRequest } from './structuredOutputTypes';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Parameters for a provider completion request. Carries the unified\n * {@link AiAssist.IChatRequest} shape (`system?` + ordered `messages`, last =\n * current user turn); history is linearized before the current turn.\n * @public\n */\nexport interface IProviderCompletionParams extends IChatRequest {\n /** The provider descriptor */\n readonly descriptor: IAiProviderDescriptor;\n /** API key for authentication */\n readonly apiKey: string;\n /**\n * Sampling temperature. Sent to the provider only when explicitly provided; omitted otherwise\n * so the provider's own default applies (current-gen models reject a caller-supplied default).\n */\n readonly temperature?: number;\n /** Optional model override — string or context-aware map (uses descriptor.defaultModel otherwise) */\n readonly modelOverride?: ModelSpec;\n /**\n * Optional quality tier selecting which completion model to use. `undefined`\n * selects the `base` tier; `'frontier'` cascades to `advanced` then `base`\n * when a tier is unset for a provider. Orthogonal to `thinking` and `tools`,\n * which never select a model.\n */\n readonly tier?: 'advanced' | 'frontier';\n /** Optional logger for request/response observability. */\n readonly logger?: Logging.ILogger;\n /** Server-side tools to include in the request. Overrides settings-level tool config when provided. */\n readonly tools?: ReadonlyArray<AiServerToolConfig>;\n /** Optional abort signal for cancelling the in-flight request. */\n readonly signal?: AbortSignal;\n /**\n * Optional override of the descriptor's default base URL (scheme + host +\n * optional port + path prefix). The per-route suffix (e.g. `/chat/completions`)\n * is appended unchanged. Must be a well-formed `http`/`https` URL. Auth shape\n * is unchanged: `needsSecret` providers still require an API key.\n */\n readonly endpoint?: string;\n /**\n * Optional thinking/reasoning config. Anthropic, OpenAI, and xAI reject `temperature` when\n * the effective merged effort is non-`'none'`; Gemini always accepts both.\n */\n readonly thinking?: IThinkingConfig;\n /**\n * Optional cap on generated output tokens, mapped to each provider's native field:\n * Anthropic `max_tokens`, OpenAI Chat Completions `max_completion_tokens`, OpenAI/xAI\n * Responses `max_output_tokens`, Gemini `generationConfig.maxOutputTokens`, and the\n * xAI/Groq/Mistral/Ollama/`openai-compat` chat-completions path `max_tokens`. When unset,\n * every provider except Anthropic omits the field and applies its own default; Anthropic's\n * Messages API requires the field, so it falls back to `DEFAULT_ANTHROPIC_MAX_TOKENS`.\n */\n readonly maxTokens?: number;\n /**\n * Ask the provider to constrain its output — to a schema, or to syntactically\n * valid JSON of arbitrary shape.\n *\n * @remarks\n * **The caller supplies intent; the response reports outcome.** A caller cannot\n * know up front which concrete model will serve the request (a `tier` request\n * cascades, and aliases resolve at call time), so it never has to: whatever was\n * actually enforced comes back on\n * `IAiCompletionResponse.structuredOutput`.\n */\n readonly structuredOutput?: StructuredOutputRequest;\n}\n\n// ============================================================================\n// Response validators (non-strict — extra API fields preserved for debugging)\n// ============================================================================\n\n// ---- OpenAI Chat Completions format ----\n\n/** @internal */\ninterface IOpenAiMessage {\n content: string;\n}\n/** @internal */\ninterface IOpenAiChoice {\n message: IOpenAiMessage;\n finish_reason: string;\n}\n/** @internal */\ninterface IOpenAiResponse {\n choices: IOpenAiChoice[];\n}\n\nconst openAiMessage: Validator<IOpenAiMessage> = Validators.object<IOpenAiMessage>({\n content: Validators.string\n});\nconst openAiChoice: Validator<IOpenAiChoice> = Validators.object<IOpenAiChoice>({\n message: openAiMessage,\n finish_reason: Validators.string\n});\nconst openAiResponse: Validator<IOpenAiResponse> = Validators.object<IOpenAiResponse>({\n choices: Validators.arrayOf(openAiChoice).withConstraint((arr) => arr.length > 0)\n});\n\n// ---- OpenAI/xAI Responses API format ----\n\n/** @internal */\ninterface IResponsesApiOutputText {\n type: 'output_text';\n text: string;\n}\n/** @internal */\ninterface IResponsesApiMessage {\n type: 'message';\n role: string;\n content: IResponsesApiOutputText[];\n}\n/** @internal */\ninterface IResponsesApiResponse {\n output: Array<Record<string, unknown>>;\n status: string;\n}\n\nconst responsesApiOutputText: Validator<IResponsesApiOutputText> = Validators.object<IResponsesApiOutputText>(\n {\n type: Validators.literal('output_text'),\n text: Validators.string\n }\n);\nconst responsesApiMessage: Validator<IResponsesApiMessage> = Validators.object<IResponsesApiMessage>({\n type: Validators.literal('message'),\n role: Validators.string,\n content: Validators.arrayOf(responsesApiOutputText).withConstraint((arr) => arr.length > 0)\n});\nconst responsesApiOutputItem: Validator<Record<string, unknown>> = Validators.isA(\n 'object',\n (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null\n);\nconst responsesApiResponse: Validator<IResponsesApiResponse> = Validators.object<IResponsesApiResponse>({\n output: Validators.arrayOf(responsesApiOutputItem).withConstraint((arr) => arr.length > 0),\n status: Validators.string\n});\n\n// ---- Gemini format ----\n\n/** @internal */\ninterface IGeminiPart {\n text: string;\n}\n/** @internal */\ninterface IGeminiContent {\n parts: IGeminiPart[];\n}\n/** @internal */\ninterface IGeminiCandidate {\n content: IGeminiContent;\n finishReason: string;\n}\n/** @internal */\ninterface IGeminiResponse {\n candidates: IGeminiCandidate[];\n}\n\nconst geminiPart: Validator<IGeminiPart> = Validators.object<IGeminiPart>({\n text: Validators.string\n});\nconst geminiContent: Validator<IGeminiContent> = Validators.object<IGeminiContent>({\n parts: Validators.arrayOf(geminiPart).withConstraint((arr) => arr.length > 0)\n});\nconst geminiCandidate: Validator<IGeminiCandidate> = Validators.object<IGeminiCandidate>({\n content: geminiContent,\n finishReason: Validators.string\n});\nconst geminiResponse: Validator<IGeminiResponse> = Validators.object<IGeminiResponse>({\n candidates: Validators.arrayOf(geminiCandidate).withConstraint((arr) => arr.length > 0)\n});\n\n// ============================================================================\n// OpenAI-compatible client (Chat Completions — no tools)\n// ============================================================================\n\n/**\n * Calls an OpenAI-compatible chat completion endpoint.\n * Works for xAI Grok, OpenAI, Groq, and Mistral.\n * @internal\n */\nasync function callOpenAiCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number,\n useMaxCompletionTokensField: boolean = false,\n structured: IResolvedStructuredOutput = NO_STRUCTURED_OUTPUT\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/chat/completions`;\n const messages = buildMessages(prompt.system, buildOpenAiChatUserContent(prompt), {\n head\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const maxTokensField = useMaxCompletionTokensField ? 'max_completion_tokens' : 'max_tokens';\n const body: Record<string, unknown> = {\n model: config.model,\n messages,\n // Temperature is sent only when the caller explicitly provided one — omitting it lets each\n // provider apply its own default (current-gen models reject a non-default temperature). The\n // completion path already rejects temperature + non-'none' thinking upstream\n // (checkTemperatureConflict), so no effort gate is needed here.\n ...(temperature !== undefined ? { temperature } : {}),\n ...(effort !== undefined && config.model !== 'grok-4' ? { reasoning_effort: effort } : {}),\n // Omitted when the caller doesn't set maxTokens — every non-Anthropic provider applies its\n // own default. See AiAssist.usesMaxCompletionTokensField for the field-name split.\n ...(maxTokens !== undefined ? { [maxTokensField]: maxTokens } : {})\n };\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n Object.assign(body, structured.wire);\n\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`OpenAI completion: model=${config.model}`);\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return openAiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `OpenAI API response: ${msg}`)\n .onSuccess((response) => {\n const choice = response.choices[0];\n return succeed({\n content: choice.message.content,\n truncated: choice.finish_reason === 'length',\n structuredOutput: structured.enforcement\n });\n });\n}\n\n// ============================================================================\n// OpenAI/xAI Responses API (with tools)\n// ============================================================================\n\n/**\n * Extracts text content from a Responses API output array.\n * Finds the first message-type output item and concatenates its text content blocks.\n * @internal\n */\nfunction extractResponsesApiText(output: Array<Record<string, unknown>>): Result<string> {\n for (const item of output) {\n if (item.type === 'message') {\n const messageResult = responsesApiMessage.validate(item as JsonObject);\n if (messageResult.isSuccess()) {\n return succeed(messageResult.value.content.map((c) => c.text).join(''));\n }\n }\n }\n return fail('Responses API output contained no message with text content');\n}\n\n/**\n * Calls the xAI/OpenAI Responses API with server-side tools.\n * Used when tools are configured for an openai-format provider.\n * @internal\n */\nasync function callOpenAiResponsesCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n tools: ReadonlyArray<AiServerToolConfig> = [],\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number,\n structured: IResolvedStructuredOutput = NO_STRUCTURED_OUTPUT\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/responses`;\n const input = buildMessages(prompt.system, buildOpenAiResponsesUserContent(prompt), {\n head\n });\n const effort = resolvedThinking?.openAiEffort ?? resolvedThinking?.xaiEffort;\n const body: Record<string, unknown> = {\n model: config.model,\n input,\n // `tools` is omitted entirely when none are requested — a Responses-only model routed\n // here for tier/model reasons (not tools) must not send an empty tools array.\n ...(tools.length > 0 ? { tools: toResponsesApiTools(tools) } : {}),\n // Temperature is sent only when the caller explicitly provided one (see callOpenAiCompletion).\n ...(temperature !== undefined ? { temperature } : {}),\n ...(effort !== undefined && config.model !== 'grok-4' ? { reasoning: { effort } } : {})\n };\n // Shared by OpenAI and xAI — both route through the Responses API with the same field name.\n if (maxTokens !== undefined) {\n body.max_output_tokens = maxTokens;\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n Object.assign(body, structured.wire);\n\n const headers: Record<string, string> = bearerAuthHeader(config.apiKey);\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`OpenAI Responses API: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return responsesApiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Responses API response: ${msg}`)\n .onSuccess((response) => {\n return extractResponsesApiText(response.output).onSuccess((text) =>\n succeed({\n content: text,\n truncated: response.status === 'incomplete',\n structuredOutput: structured.enforcement\n })\n );\n });\n}\n\n// ============================================================================\n// Anthropic adapter\n// ============================================================================\n\n/**\n * Extracts text content from Anthropic response content blocks.\n * When tools are used, the content array contains mixed block types\n * (text, server_tool_use, web_search_tool_result). We extract and\n * concatenate only the text blocks.\n * @internal\n */\nfunction extractAnthropicText(content: unknown[]): Result<string> {\n const textParts: string[] = [];\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block) {\n const typed = block as Record<string, unknown>;\n if (typed.type === 'text' && typeof typed.text === 'string') {\n textParts.push(typed.text);\n }\n }\n }\n if (textParts.length === 0) {\n return fail('Anthropic response contained no text content blocks');\n }\n return succeed(textParts.join(''));\n}\n\n/**\n * Extracts the forced structured-output tool's input from Anthropic response\n * content blocks and re-serializes it.\n *\n * @remarks\n * Under `'tool-forced'` enforcement the model's answer arrives as a `tool_use`\n * block's `input` — a parsed object — rather than as text. Re-serializing it here\n * keeps `IAiCompletionResponse.content` a JSON **string** on every provider, so a\n * caller's converter is written once and does not branch on which enforcement it\n * got. A useful side effect: the string is produced by `JSON.stringify` rather\n * than by the model, so under this enforcement it is syntactically valid by\n * construction.\n * @internal\n */\nfunction extractAnthropicStructuredOutput(content: unknown[]): Result<string> {\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block) {\n const typed = block as Record<string, unknown>;\n if (typed.type === 'tool_use' && typed.name === ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME) {\n // `JSON.stringify` returns `undefined` — not a string, and not a throw —\n // for `undefined` and for a function or symbol. `captureResult` would wrap\n // that as a Success, putting `undefined` behind a `content: string`\n // contract with nothing to catch it downstream. A `tool_use` block with no\n // `input` is exactly that case.\n return captureResult(() => JSON.stringify(typed.input))\n .withErrorFormat(\n (msg) => `Anthropic API response: structured output could not be serialized: ${msg}`\n )\n .onSuccess((json) =>\n typeof json === 'string'\n ? succeed(json)\n : fail(\n `Anthropic API response: forced tool '${ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME}' returned no serializable input`\n )\n );\n }\n }\n }\n // Loud rather than a silent fall back to text: we forced the tool, so its\n // absence means the request did not do what the response is about to claim it\n // did — and `structuredOutput: 'tool-forced'` would then be a lie.\n return fail(\n `Anthropic API response: structured output was forced but no '${ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME}' tool_use block was returned`\n );\n}\n\n/** Calls the Anthropic Messages API with optional tool support. @internal */\nasync function callAnthropicCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n tools?: ReadonlyArray<AiServerToolConfig>,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n useAdaptiveThinking: boolean = false,\n maxTokens?: number,\n structured: IResolvedStructuredOutput = NO_STRUCTURED_OUTPUT\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/messages`;\n const messages = buildAnthropicMessages(prompt, { head });\n const body: Record<string, unknown> = {\n model: config.model,\n system: prompt.system,\n messages,\n // Anthropic's Messages API requires max_tokens on every request — see\n // AiAssist.DEFAULT_ANTHROPIC_MAX_TOKENS for why only this provider defaults it.\n max_tokens: maxTokens ?? DEFAULT_ANTHROPIC_MAX_TOKENS,\n // Temperature is sent only when explicitly provided (Claude-5 rejects any temperature). The\n // completion path rejects temperature + thinking upstream (checkTemperatureConflict), so no\n // effort gate is needed here.\n ...(temperature !== undefined ? { temperature } : {})\n };\n\n const effort = resolvedThinking?.anthropicEffort;\n if (effort !== undefined) {\n if (useAdaptiveThinking) {\n // Claude 5 family: adaptive thinking — no budget_tokens; effort moves to the\n // top-level output_config block. See AiAssist.isAdaptiveThinkingModel.\n body.thinking = { type: 'adaptive' };\n body.output_config = { effort };\n } else {\n body.thinking = { type: 'enabled', budget_tokens: anthropicEffortToBudgetTokens(effort) };\n }\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(body, resolvedThinking.otherParams);\n }\n\n // The structured-output wire carries `tools` + `tool_choice` of its own, so the\n // server-tool assignment below would clobber it. `resolveStructuredOutput`\n // refuses that combination up front, which is what makes the two mutually\n // exclusive — but that is an invariant held in a DIFFERENT FILE, and a future\n // second Anthropic capability entry (or a relaxed conflict guard) would\n // reintroduce silent clobbering with nothing failing at this line. So assert it\n // here rather than trusting a comment across a file boundary.\n // Unreachable through the public API — resolveStructuredOutput refuses this\n // combination before dispatch — and unreachable BY DESIGN: it cannot be\n // exercised without first breaking the very thing it guards against.\n /* c8 ignore next 6 - defensive: internal consistency check, see above */\n if (structured.enforcement === 'tool-forced' && tools !== undefined && tools.length > 0) {\n return fail(\n `Anthropic completion: structured output and server-side tools both claim the tools channel; ` +\n `this combination must be refused before reaching the adapter`\n );\n }\n Object.assign(body, structured.wire);\n\n if (tools && tools.length > 0) {\n body.tools = toAnthropicTools(tools);\n /* c8 ignore next 3 - optional logger diagnostic output */\n logger?.info(`Anthropic completion: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n } else {\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Anthropic completion: model=${config.model}`);\n }\n\n const headers: Record<string, string> = anthropicAuthHeaders(config.apiKey);\n\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n\n const rawContent = (jsonResult.value as Record<string, unknown>).content;\n const stopReason = (jsonResult.value as Record<string, unknown>).stop_reason;\n if (!Array.isArray(rawContent)) {\n return fail('Anthropic API response: content is not an array');\n }\n if (typeof stopReason !== 'string') {\n return fail('Anthropic API response: stop_reason is missing or not a string');\n }\n const extracted =\n structured.enforcement === 'tool-forced'\n ? extractAnthropicStructuredOutput(rawContent)\n : extractAnthropicText(rawContent);\n return extracted.onSuccess((text) =>\n succeed({\n content: text,\n truncated: stopReason === 'max_tokens',\n structuredOutput: structured.enforcement\n })\n );\n}\n\n// ============================================================================\n// Google Gemini adapter\n// ============================================================================\n\n/**\n * Calls the Google Gemini generateContent API.\n * When tools are configured, includes Google Search grounding.\n * @internal\n */\nasync function callGeminiCompletion(\n config: IAiApiConfig,\n prompt: AiPrompt,\n head?: ReadonlyArray<IChatMessage>,\n temperature?: number,\n logger?: Logging.ILogger,\n tools?: ReadonlyArray<AiServerToolConfig>,\n signal?: AbortSignal,\n resolvedThinking?: IResolvedThinkingConfig,\n maxTokens?: number,\n structured: IResolvedStructuredOutput = NO_STRUCTURED_OUTPUT\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/models/${config.model}:generateContent`;\n const contents = buildGeminiContents(prompt, { head });\n\n // Temperature is sent only when explicitly provided; otherwise Gemini's default applies.\n const generationConfig: Record<string, unknown> = {};\n if (temperature !== undefined) {\n generationConfig.temperature = temperature;\n }\n if (maxTokens !== undefined) {\n generationConfig.maxOutputTokens = maxTokens;\n }\n if (resolvedThinking?.geminiThinkingBudget !== undefined) {\n generationConfig.thinkingConfig = { thinkingBudget: resolvedThinking.geminiThinkingBudget };\n }\n if (resolvedThinking?.otherParams !== undefined) {\n Object.assign(generationConfig, resolvedThinking.otherParams);\n }\n // Gemini nests the constraint INSIDE generationConfig, not on the body.\n Object.assign(generationConfig, structured.wire);\n const body: Record<string, unknown> = {\n systemInstruction: { parts: [{ text: prompt.system }] },\n contents,\n generationConfig\n };\n\n if (tools && tools.length > 0) {\n body.tools = toGeminiTools(tools);\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Gemini completion: model=${config.model}, tools=${tools.map((t) => t.type).join(',')}`);\n } else {\n /* c8 ignore next 1 - optional logger */\n logger?.info(`Gemini completion: model=${config.model}`);\n }\n\n const headers: Record<string, string> = geminiAuthHeader(config.apiKey);\n\n const jsonResult = await fetchJson(url, headers, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n return geminiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Gemini API response: ${msg}`)\n .onSuccess((response) => {\n const candidate = response.candidates[0];\n return succeed({\n // ALL parts, not `parts[0]`. Gemini may split one reply across several\n // text parts, and reading only the first silently discards the rest —\n // yielding a truncated document that often still parses, which is the\n // worst way to be wrong. The streaming adapter has always concatenated\n // (`fullText += part.text`); this path did not, so the same response gave\n // different text depending on which one you called.\n content: candidate.content.parts.map((part) => part.text).join(''),\n truncated: candidate.finishReason === 'MAX_TOKENS',\n structuredOutput: structured.enforcement\n });\n });\n}\n\n// ============================================================================\n// Provider dispatcher\n// ============================================================================\n\n/**\n * Calls the appropriate chat completion API for a given provider. Routes by\n * `apiFormat`: `'openai'` (xAI/OpenAI/Groq/Mistral — switches to Responses API\n * when tools are set), `'anthropic'`, or `'gemini'`.\n * @public\n */\nexport async function callProviderCompletion(\n params: IProviderCompletionParams\n): Promise<Result<IAiCompletionResponse>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n tier,\n logger,\n tools,\n signal,\n endpoint,\n thinking,\n maxTokens,\n structuredOutput\n } = params;\n\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n const { prompt, head } = splitResult.value;\n\n const baseUrlResult = resolveEffectiveBaseUrl(descriptor, endpoint);\n if (baseUrlResult.isFailure()) {\n return fail(baseUrlResult.message);\n }\n if (prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const hasTools = tools !== undefined && tools.length > 0;\n const discriminator = providerDiscriminatorForId(descriptor.id);\n // The quality tier is the only completion-model selector; thinking and tools\n // are orthogonal request params/capabilities and never pick a model.\n const modelContext: ModelSpecKey | undefined = tier;\n\n const modelResult = resolveProviderModel(descriptor, modelOverride, modelContext);\n if (modelResult.isFailure()) {\n return fail(modelResult.message);\n }\n const model = modelResult.value;\n\n let resolvedThinking: IResolvedThinkingConfig | undefined;\n if (thinking !== undefined) {\n if (discriminator !== undefined) {\n const mergeResult = mergeThinkingConfig(thinking, model, discriminator);\n /* c8 ignore next 3 - mergeThinkingConfig always succeeds; defensive guard */\n if (mergeResult.isFailure()) {\n return fail(mergeResult.message);\n }\n resolvedThinking = mergeResult.value;\n const conflictResult = checkTemperatureConflict(resolvedThinking, discriminator, temperature);\n if (conflictResult.isFailure()) {\n return fail(conflictResult.message);\n }\n }\n }\n\n // Resolved against the CONCRETE model, after resolveProviderModel — passing an\n // alias here is the defect resolveImageCapability once had.\n // The OpenAI route depends on tools AND the model, so it is computed here (once,\n // beside the switch that uses it) and handed to the resolver — a capability keyed\n // on the model alone cannot know which of the two OpenAI wire shapes applies.\n const usesResponsesApi: boolean =\n descriptor.apiFormat === 'openai' && (hasTools || isResponsesOnlyModel(descriptor, model));\n const structuredResult = resolveStructuredOutput(\n descriptor,\n model,\n structuredOutput,\n tools,\n usesResponsesApi,\n resolveStructuredOutputCapability\n );\n if (structuredResult.isFailure()) {\n return fail(structuredResult.message);\n }\n const resolvedStructured = structuredResult.value;\n\n // OpenAI rejects `response_format: { type: 'json_object' }` with a 400 unless the\n // conversation mentions JSON somewhere — a documented API rule, and one a caller\n // has no way to discover from a schema-mode request that worked. Pre-empted with a\n // named failure before the wire call, the same treatment the Gemini\n // grounding-plus-function-calling conflict already gets. `generateJsonCompletion`\n // satisfies it for free via its prompt hint; a direct caller may not.\n if (resolvedStructured.enforcement === 'json-mode' && descriptor.apiFormat === 'openai') {\n const mentionsJson: boolean =\n (system ?? '').toLowerCase().includes('json') ||\n messages.some((m) => m.content.toLowerCase().includes('json'));\n if (!mentionsJson) {\n return fail(\n `provider '${descriptor.id}': json-object structured output requires the word 'json' to ` +\n `appear in the system prompt or a message — OpenAI rejects the request otherwise. Mention ` +\n `it, or use structuredOutput: { mode: 'schema', schema } which carries no such rule`\n );\n }\n }\n\n const config: IAiApiConfig = {\n baseUrl: baseUrlResult.value,\n apiKey,\n model\n };\n /* c8 ignore next 8 - optional logger diagnostic output */\n if (logger) {\n const toolTypes = hasTools ? tools.map((t) => t.type).join(',') : 'none';\n const supported = descriptor.supportedTools.length > 0 ? descriptor.supportedTools.join(',') : 'none';\n logger.info(\n `AI completion: provider=${descriptor.id}, format=${descriptor.apiFormat}, model=${config.model}, ` +\n `tools=${toolTypes}, supported=${supported}`\n );\n }\n\n switch (descriptor.apiFormat) {\n case 'openai':\n // Responses-API-only models (e.g. gpt-5.5-pro) 400 on /chat/completions, so they route\n // to the Responses path even with no tools requested — same path the tools case uses.\n if (usesResponsesApi) {\n return callOpenAiResponsesCompletion(\n config,\n prompt,\n tools,\n head,\n temperature,\n logger,\n signal,\n resolvedThinking,\n maxTokens,\n resolvedStructured\n );\n }\n return callOpenAiCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n signal,\n resolvedThinking,\n maxTokens,\n usesMaxCompletionTokensField(descriptor),\n resolvedStructured\n );\n case 'anthropic':\n return callAnthropicCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n tools,\n signal,\n resolvedThinking,\n isAdaptiveThinkingModel(descriptor, config.model),\n maxTokens,\n resolvedStructured\n );\n case 'gemini':\n return callGeminiCompletion(\n config,\n prompt,\n head,\n temperature,\n logger,\n tools,\n signal,\n resolvedThinking,\n maxTokens,\n resolvedStructured\n );\n /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */\n default: {\n const _exhaustive: never = descriptor.apiFormat;\n return fail(`unsupported API format: ${String(_exhaustive)}`);\n }\n }\n}\n\n// ============================================================================\n// Proxied completion (routes through a backend server)\n// ============================================================================\n\n/**\n * Calls the AI completion endpoint on a proxy server instead of calling the\n * provider API directly from the browser. The proxy handles provider dispatch,\n * CORS, and API key forwarding. The request body serializes the unified\n * {@link AiAssist.IChatRequest} shape (`system?` + `messages`). Enforces the same\n * non-empty / trailing-user-turn and image-input invariants as the direct path.\n * @param proxyUrl - Base URL of the proxy server\n * @param params - Same parameters as {@link callProviderCompletion}\n * @public\n */\nexport async function callProxiedCompletion(\n proxyUrl: string,\n params: IProviderCompletionParams\n): Promise<Result<IAiCompletionResponse>> {\n const {\n descriptor,\n apiKey,\n system,\n messages,\n temperature,\n modelOverride,\n logger,\n tools,\n signal,\n thinking,\n maxTokens,\n structuredOutput\n } = params;\n\n const splitResult = splitChatRequest(system, messages);\n if (splitResult.isFailure()) {\n return fail(splitResult.message);\n }\n if (splitResult.value.prompt.attachments.length > 0 && !descriptor.acceptsImageInput) {\n return fail(`provider \"${descriptor.id}\" does not accept image input`);\n }\n\n const body: Record<string, unknown> = {\n providerId: descriptor.id,\n apiKey,\n messages: normalizeOutboundMessages(splitResult.value)\n };\n // Temperature is forwarded only when explicitly provided, matching the direct path — the proxy\n // omits it from the upstream request so the provider default applies.\n if (temperature !== undefined) {\n body.temperature = temperature;\n }\n if (system !== undefined) {\n body.system = system;\n }\n if (modelOverride !== undefined) {\n body.modelOverride = modelOverride;\n }\n if (tools && tools.length > 0) {\n body.tools = tools;\n }\n if (thinking !== undefined) {\n body.thinking = thinking;\n }\n // Forwarded only when explicitly provided; the proxy is responsible for mapping it to the\n // correct upstream provider field (see AiAssist.usesMaxCompletionTokensField).\n if (maxTokens !== undefined) {\n body.maxTokens = maxTokens;\n }\n if (structuredOutput !== undefined) {\n // The schema travels as its draft-07 wire form, not as the validator object —\n // an `ISchemaValidator` is not JSON-serializable. A proxy reconstitutes it with\n // `JsonSchema.fromJson(raw)` before calling `callProviderCompletion`.\n body.structuredOutput =\n structuredOutput.mode === 'schema'\n ? {\n mode: 'schema',\n schema: structuredOutput.schema.toJson(),\n ...(structuredOutput.onUnsupported !== undefined\n ? { onUnsupported: structuredOutput.onUnsupported }\n : {})\n }\n : {\n mode: 'json-object',\n ...(structuredOutput.onUnsupported !== undefined\n ? { onUnsupported: structuredOutput.onUnsupported }\n : {})\n };\n }\n\n /* c8 ignore next 1 - optional logger */\n logger?.info(`AI proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);\n const url = `${proxyUrl}/api/ai/completion`;\n const jsonResult = await fetchJson(url, {}, body, logger, signal);\n if (jsonResult.isFailure()) {\n return fail(jsonResult.message);\n }\n\n const response = jsonResult.value as Record<string, unknown>;\n if (typeof response.error === 'string') {\n return fail(`proxy: ${response.error}`);\n }\n\n if (typeof response.content !== 'string') {\n return fail('proxy returned invalid response: missing content');\n }\n\n // A caller who asked for nothing gets `'none'` without the proxy having to say\n // so. A caller who DID ask gets a loud failure when the proxy cannot report,\n // rather than a response claiming an enforcement nobody verified — a proxy\n // predating this feature drops the constraint silently, which is the exact\n // failure this surface exists to remove.\n if (structuredOutput === undefined) {\n return succeed({\n content: response.content,\n truncated: response.truncated === true,\n structuredOutput: 'none'\n });\n }\n if (!isStructuredOutputEnforcement(response.structuredOutput)) {\n return fail(\n `proxy did not report which structured-output constraint it applied ` +\n `(got ${JSON.stringify(response.structuredOutput)}); it may predate the feature and have ` +\n `dropped the request silently`\n );\n }\n return succeed({\n content: response.content,\n truncated: response.truncated === true,\n structuredOutput: response.structuredOutput\n });\n}\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { AiPrompt, type AiModelCapability, allModelCapabilities, type AiProviderId, type AiServerToolType, type AiServerToolConfig, type AiToolConfig, type IAiWebSearchToolConfig, type IAiClientToolConfig, type IAiToolAnnotations, type IAiClientTool, type IAiClientToolCallSummary, type IAiClientToolContinuation, type IAiClientToolTurnResult, type IAiToolEnablement, type IAiCompletionResponse, DEFAULT_ANTHROPIC_MAX_TOKENS, type IChatMessage, type IChatRequest, type AiApiFormat, type AiImageApiFormat, type AiEmbeddingApiFormat, type AiEmbeddingTaskType, type IAiEmbeddingModelCapability, type IAiEmbeddingParams, type IAiEmbeddingUsage, type IAiEmbeddingResult, type IAiImageModelCapability, type IAiProviderDescriptor, type IAiAssistProviderConfig, type IAiAssistSettings, DEFAULT_AI_ASSIST, type IAiAssistKeyStore, providerApiKeySecretName, type IAiImageAttachment, type IAiImageData, type AiImageSize, type AiImageQuality, type GptImageSize, type GptImageQuality, type GptImageModelNames, type GrokImagineModelNames, type GeminiFlashImageModelNames, type IGptImageGenerationConfig, type IGrokImagineImageGenerationConfig, type IGeminiFlashImageGenerationConfig, type IGptImageModelOptions, type IGrokImagineModelOptions, type IGeminiFlashImageModelOptions, type IOtherModelOptions, type IModelFamilyConfig, type IAiImageGenerationOptions, type IAiImageGenerationParams, type IAiGeneratedImage, type IAiImageGenerationResponse, type IAiModelCapabilityRule, type IAiModelCapabilityConfig, type IAiModelInfo, type IAiStreamEvent, type IAiStreamTextDelta, type IAiStreamToolEvent, type IAiStreamToolUseStart, type IAiStreamToolUseDelta, type IAiStreamToolUseComplete, type IAiStreamDone, type IAiStreamError, type ModelSpec, type ModelSpecKey, type IModelSpecMap, allModelSpecKeys, MODEL_SPEC_BASE_KEY, resolveModel, type IModelAliasMap, MODEL_ALIAS_SIGIL, resolveModelAlias, resolveProviderModel, isResponsesOnlyModel, isAdaptiveThinkingModel, usesMaxCompletionTokensField, toDataUrl, type AiThinkingMode, type IThinkingConfig, type IThinkingProviderConfig, type IAnthropicThinkingOptions, type IOpenAiThinkingOptions, type IGeminiThinkingOptions, type IXAiThinkingOptions, type IOtherThinkingOptions, type IAnthropicThinkingConfig, type IOpenAiThinkingConfig, type IGeminiThinkingConfig, type IXAiThinkingConfig, type AnthropicThinkingModelNames, type OpenAiThinkingModelNames, type GeminiThinkingModelNames, type XAiThinkingModelNames } from './model';
|
|
6
6
|
export { type IResolvedImageOptions, resolveImageOptions, validateResolvedOptions } from './imageOptionsResolver';
|
|
7
|
-
export { allProviderIds, getProviderDescriptors, getProviderDescriptor, resolveImageCapability, supportsImageGeneration, resolveEmbeddingCapability, supportsEmbedding, DEFAULT_MODEL_CAPABILITY_CONFIG } from './registry';
|
|
7
|
+
export { allProviderIds, getProviderDescriptors, getProviderDescriptor, resolveImageCapability, supportsImageGeneration, resolveEmbeddingCapability, supportsEmbedding, resolveStructuredOutputCapability, supportsStructuredOutput, DEFAULT_MODEL_CAPABILITY_CONFIG } from './registry';
|
|
8
8
|
export { callProviderCompletion, callProxiedCompletion, type IProviderCompletionParams } from './completionClient';
|
|
9
9
|
export { callProviderImageGeneration, callProxiedImageGeneration, type IProviderImageGenerationParams } from './imageGenerationClient';
|
|
10
10
|
export { callProviderListModels, callProxiedListModels, type IProviderListModelsParams } from './listModelsClient';
|
|
@@ -12,6 +12,8 @@ export { callProviderEmbedding, callProxiedEmbedding, type IProviderEmbeddingPar
|
|
|
12
12
|
export { callProviderCompletionStream, callProxiedCompletionStream, type IProviderCompletionStreamParams, executeClientToolTurn, type IExecuteClientToolTurnParams, type IExecuteClientToolTurnResult, type IToolExecutionDecision } from './streamingClient';
|
|
13
13
|
export { aiProviderId, aiServerToolType, aiWebSearchToolConfig, aiServerToolConfig, aiToolAnnotations, aiClientToolConfig, aiToolEnablement, aiAssistProviderConfig, aiAssistSettings, modelSpecKey, modelSpec } from './converters';
|
|
14
14
|
export { resolveEffectiveTools } from './toolFormats';
|
|
15
|
+
export { ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME } from './structuredOutput';
|
|
16
|
+
export type { AiStructuredOutputFormat, IAiStructuredOutputCapability, IJsonObjectStructuredOutputRequest, ISchemaStructuredOutputRequest, StructuredOutputEnforcement, StructuredOutputFallback, StructuredOutputRequest } from './structuredOutputTypes';
|
|
15
17
|
export { classifyJsonParseFailure, extractJsonText, fencedStringifiedJson, type IFencedStringifiedJsonExtractorOptions, type IFencedStringifiedJsonOptions, type JsonParseFailureReason, type JsonTextExtractor } from './jsonResponse';
|
|
16
18
|
export { generateJsonCompletion, SMART_JSON_PROMPT_HINT, type IGenerateJsonCompletionParams, type IGenerateJsonCompletionResult, type JsonPromptHint } from './jsonCompletion';
|
|
17
19
|
export { anthropicEffortToBudgetTokens, type IResolvedThinkingConfig } from './thinkingOptionsResolver';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
8
|
-
exports.anthropicEffortToBudgetTokens = exports.SMART_JSON_PROMPT_HINT = exports.generateJsonCompletion = exports.fencedStringifiedJson = void 0;
|
|
7
|
+
exports.resolveEffectiveTools = exports.modelSpec = exports.modelSpecKey = exports.aiAssistSettings = exports.aiAssistProviderConfig = exports.aiToolEnablement = exports.aiClientToolConfig = exports.aiToolAnnotations = exports.aiServerToolConfig = exports.aiWebSearchToolConfig = exports.aiServerToolType = exports.aiProviderId = exports.executeClientToolTurn = exports.callProxiedCompletionStream = exports.callProviderCompletionStream = exports.callProxiedEmbedding = exports.callProviderEmbedding = exports.callProxiedListModels = exports.callProviderListModels = exports.callProxiedImageGeneration = exports.callProviderImageGeneration = exports.callProxiedCompletion = exports.callProviderCompletion = exports.DEFAULT_MODEL_CAPABILITY_CONFIG = exports.supportsStructuredOutput = exports.resolveStructuredOutputCapability = exports.supportsEmbedding = exports.resolveEmbeddingCapability = exports.supportsImageGeneration = exports.resolveImageCapability = exports.getProviderDescriptor = exports.getProviderDescriptors = exports.allProviderIds = exports.validateResolvedOptions = exports.resolveImageOptions = exports.toDataUrl = exports.usesMaxCompletionTokensField = exports.isAdaptiveThinkingModel = exports.isResponsesOnlyModel = exports.resolveProviderModel = exports.resolveModelAlias = exports.MODEL_ALIAS_SIGIL = exports.resolveModel = exports.MODEL_SPEC_BASE_KEY = exports.allModelSpecKeys = exports.providerApiKeySecretName = exports.DEFAULT_AI_ASSIST = exports.DEFAULT_ANTHROPIC_MAX_TOKENS = exports.allModelCapabilities = exports.AiPrompt = void 0;
|
|
8
|
+
exports.anthropicEffortToBudgetTokens = exports.SMART_JSON_PROMPT_HINT = exports.generateJsonCompletion = exports.fencedStringifiedJson = exports.extractJsonText = exports.classifyJsonParseFailure = exports.ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME = void 0;
|
|
9
9
|
var model_1 = require("./model");
|
|
10
10
|
Object.defineProperty(exports, "AiPrompt", { enumerable: true, get: function () { return model_1.AiPrompt; } });
|
|
11
11
|
Object.defineProperty(exports, "allModelCapabilities", { enumerable: true, get: function () { return model_1.allModelCapabilities; } });
|
|
@@ -33,6 +33,8 @@ Object.defineProperty(exports, "resolveImageCapability", { enumerable: true, get
|
|
|
33
33
|
Object.defineProperty(exports, "supportsImageGeneration", { enumerable: true, get: function () { return registry_1.supportsImageGeneration; } });
|
|
34
34
|
Object.defineProperty(exports, "resolveEmbeddingCapability", { enumerable: true, get: function () { return registry_1.resolveEmbeddingCapability; } });
|
|
35
35
|
Object.defineProperty(exports, "supportsEmbedding", { enumerable: true, get: function () { return registry_1.supportsEmbedding; } });
|
|
36
|
+
Object.defineProperty(exports, "resolveStructuredOutputCapability", { enumerable: true, get: function () { return registry_1.resolveStructuredOutputCapability; } });
|
|
37
|
+
Object.defineProperty(exports, "supportsStructuredOutput", { enumerable: true, get: function () { return registry_1.supportsStructuredOutput; } });
|
|
36
38
|
Object.defineProperty(exports, "DEFAULT_MODEL_CAPABILITY_CONFIG", { enumerable: true, get: function () { return registry_1.DEFAULT_MODEL_CAPABILITY_CONFIG; } });
|
|
37
39
|
var completionClient_1 = require("./completionClient");
|
|
38
40
|
Object.defineProperty(exports, "callProviderCompletion", { enumerable: true, get: function () { return completionClient_1.callProviderCompletion; } });
|
|
@@ -64,6 +66,8 @@ Object.defineProperty(exports, "modelSpecKey", { enumerable: true, get: function
|
|
|
64
66
|
Object.defineProperty(exports, "modelSpec", { enumerable: true, get: function () { return converters_1.modelSpec; } });
|
|
65
67
|
var toolFormats_1 = require("./toolFormats");
|
|
66
68
|
Object.defineProperty(exports, "resolveEffectiveTools", { enumerable: true, get: function () { return toolFormats_1.resolveEffectiveTools; } });
|
|
69
|
+
var structuredOutput_1 = require("./structuredOutput");
|
|
70
|
+
Object.defineProperty(exports, "ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME", { enumerable: true, get: function () { return structuredOutput_1.ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME; } });
|
|
67
71
|
var jsonResponse_1 = require("./jsonResponse");
|
|
68
72
|
Object.defineProperty(exports, "classifyJsonParseFailure", { enumerable: true, get: function () { return jsonResponse_1.classifyJsonParseFailure; } });
|
|
69
73
|
Object.defineProperty(exports, "extractJsonText", { enumerable: true, get: function () { return jsonResponse_1.extractJsonText; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;AAEH,iCAiGiB;AAhGf,iGAAA,QAAQ,OAAA;AAER,6GAAA,oBAAoB,OAAA;AAcpB,qHAAA,4BAA4B,OAAA;AAe5B,0GAAA,iBAAiB,OAAA;AAEjB,iHAAA,wBAAwB,OAAA;AAoCxB,yGAAA,gBAAgB,OAAA;AAChB,4GAAA,mBAAmB,OAAA;AACnB,qGAAA,YAAY,OAAA;AAEZ,0GAAA,iBAAiB,OAAA;AACjB,0GAAA,iBAAiB,OAAA;AACjB,6GAAA,oBAAoB,OAAA;AACpB,6GAAA,oBAAoB,OAAA;AACpB,gHAAA,uBAAuB,OAAA;AACvB,qHAAA,4BAA4B,OAAA;AAC5B,kGAAA,SAAS,OAAA;AAmBX,+DAIgC;AAF9B,2HAAA,mBAAmB,OAAA;AACnB,+HAAA,uBAAuB,OAAA;AAGzB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;AAEH,iCAiGiB;AAhGf,iGAAA,QAAQ,OAAA;AAER,6GAAA,oBAAoB,OAAA;AAcpB,qHAAA,4BAA4B,OAAA;AAe5B,0GAAA,iBAAiB,OAAA;AAEjB,iHAAA,wBAAwB,OAAA;AAoCxB,yGAAA,gBAAgB,OAAA;AAChB,4GAAA,mBAAmB,OAAA;AACnB,qGAAA,YAAY,OAAA;AAEZ,0GAAA,iBAAiB,OAAA;AACjB,0GAAA,iBAAiB,OAAA;AACjB,6GAAA,oBAAoB,OAAA;AACpB,6GAAA,oBAAoB,OAAA;AACpB,gHAAA,uBAAuB,OAAA;AACvB,qHAAA,4BAA4B,OAAA;AAC5B,kGAAA,SAAS,OAAA;AAmBX,+DAIgC;AAF9B,2HAAA,mBAAmB,OAAA;AACnB,+HAAA,uBAAuB,OAAA;AAGzB,uCAWoB;AAVlB,0GAAA,cAAc,OAAA;AACd,kHAAA,sBAAsB,OAAA;AACtB,iHAAA,qBAAqB,OAAA;AACrB,kHAAA,sBAAsB,OAAA;AACtB,mHAAA,uBAAuB,OAAA;AACvB,sHAAA,0BAA0B,OAAA;AAC1B,6GAAA,iBAAiB,OAAA;AACjB,6HAAA,iCAAiC,OAAA;AACjC,oHAAA,wBAAwB,OAAA;AACxB,2HAAA,+BAA+B,OAAA;AAGjC,uDAI4B;AAH1B,0HAAA,sBAAsB,OAAA;AACtB,yHAAA,qBAAqB,OAAA;AAIvB,iEAIiC;AAH/B,oIAAA,2BAA2B,OAAA;AAC3B,mIAAA,0BAA0B,OAAA;AAI5B,uDAI4B;AAH1B,0HAAA,sBAAsB,OAAA;AACtB,yHAAA,qBAAqB,OAAA;AAIvB,qDAI2B;AAHzB,wHAAA,qBAAqB,OAAA;AACrB,uHAAA,oBAAoB,OAAA;AAItB,qDAQ2B;AAPzB,+HAAA,4BAA4B,OAAA;AAC5B,8HAAA,2BAA2B,OAAA;AAE3B,wHAAA,qBAAqB,OAAA;AAMvB,2CAYsB;AAXpB,0GAAA,YAAY,OAAA;AACZ,8GAAA,gBAAgB,OAAA;AAChB,mHAAA,qBAAqB,OAAA;AACrB,gHAAA,kBAAkB,OAAA;AAClB,+GAAA,iBAAiB,OAAA;AACjB,gHAAA,kBAAkB,OAAA;AAClB,8GAAA,gBAAgB,OAAA;AAChB,oHAAA,sBAAsB,OAAA;AACtB,8GAAA,gBAAgB,OAAA;AAChB,0GAAA,YAAY,OAAA;AACZ,uGAAA,SAAS,OAAA;AAGX,6CAAsD;AAA7C,oHAAA,qBAAqB,OAAA;AAE9B,uDAA2E;AAAlE,yIAAA,qCAAqC,OAAA;AAY9C,+CAQwB;AAPtB,wHAAA,wBAAwB,OAAA;AACxB,+GAAA,eAAe,OAAA;AACf,qHAAA,qBAAqB,OAAA;AAOvB,mDAM0B;AALxB,wHAAA,sBAAsB,OAAA;AACtB,wHAAA,sBAAsB,OAAA;AAMxB,qEAAwG;AAA/F,wIAAA,6BAA6B,OAAA","sourcesContent":["/**\n * AI assist packlet - provider registry, prompt class, settings, and API client.\n * @packageDocumentation\n */\n\nexport {\n AiPrompt,\n type AiModelCapability,\n allModelCapabilities,\n type AiProviderId,\n type AiServerToolType,\n type AiServerToolConfig,\n type AiToolConfig,\n type IAiWebSearchToolConfig,\n type IAiClientToolConfig,\n type IAiToolAnnotations,\n type IAiClientTool,\n type IAiClientToolCallSummary,\n type IAiClientToolContinuation,\n type IAiClientToolTurnResult,\n type IAiToolEnablement,\n type IAiCompletionResponse,\n DEFAULT_ANTHROPIC_MAX_TOKENS,\n type IChatMessage,\n type IChatRequest,\n type AiApiFormat,\n type AiImageApiFormat,\n type AiEmbeddingApiFormat,\n type AiEmbeddingTaskType,\n type IAiEmbeddingModelCapability,\n type IAiEmbeddingParams,\n type IAiEmbeddingUsage,\n type IAiEmbeddingResult,\n type IAiImageModelCapability,\n type IAiProviderDescriptor,\n type IAiAssistProviderConfig,\n type IAiAssistSettings,\n DEFAULT_AI_ASSIST,\n type IAiAssistKeyStore,\n providerApiKeySecretName,\n type IAiImageAttachment,\n type IAiImageData,\n type AiImageSize,\n type AiImageQuality,\n type GptImageSize,\n type GptImageQuality,\n type GptImageModelNames,\n type GrokImagineModelNames,\n type GeminiFlashImageModelNames,\n type IGptImageGenerationConfig,\n type IGrokImagineImageGenerationConfig,\n type IGeminiFlashImageGenerationConfig,\n type IGptImageModelOptions,\n type IGrokImagineModelOptions,\n type IGeminiFlashImageModelOptions,\n type IOtherModelOptions,\n type IModelFamilyConfig,\n type IAiImageGenerationOptions,\n type IAiImageGenerationParams,\n type IAiGeneratedImage,\n type IAiImageGenerationResponse,\n type IAiModelCapabilityRule,\n type IAiModelCapabilityConfig,\n type IAiModelInfo,\n type IAiStreamEvent,\n type IAiStreamTextDelta,\n type IAiStreamToolEvent,\n type IAiStreamToolUseStart,\n type IAiStreamToolUseDelta,\n type IAiStreamToolUseComplete,\n type IAiStreamDone,\n type IAiStreamError,\n type ModelSpec,\n type ModelSpecKey,\n type IModelSpecMap,\n allModelSpecKeys,\n MODEL_SPEC_BASE_KEY,\n resolveModel,\n type IModelAliasMap,\n MODEL_ALIAS_SIGIL,\n resolveModelAlias,\n resolveProviderModel,\n isResponsesOnlyModel,\n isAdaptiveThinkingModel,\n usesMaxCompletionTokensField,\n toDataUrl,\n type AiThinkingMode,\n type IThinkingConfig,\n type IThinkingProviderConfig,\n type IAnthropicThinkingOptions,\n type IOpenAiThinkingOptions,\n type IGeminiThinkingOptions,\n type IXAiThinkingOptions,\n type IOtherThinkingOptions,\n type IAnthropicThinkingConfig,\n type IOpenAiThinkingConfig,\n type IGeminiThinkingConfig,\n type IXAiThinkingConfig,\n type AnthropicThinkingModelNames,\n type OpenAiThinkingModelNames,\n type GeminiThinkingModelNames,\n type XAiThinkingModelNames\n} from './model';\n\nexport {\n type IResolvedImageOptions,\n resolveImageOptions,\n validateResolvedOptions\n} from './imageOptionsResolver';\n\nexport {\n allProviderIds,\n getProviderDescriptors,\n getProviderDescriptor,\n resolveImageCapability,\n supportsImageGeneration,\n resolveEmbeddingCapability,\n supportsEmbedding,\n resolveStructuredOutputCapability,\n supportsStructuredOutput,\n DEFAULT_MODEL_CAPABILITY_CONFIG\n} from './registry';\n\nexport {\n callProviderCompletion,\n callProxiedCompletion,\n type IProviderCompletionParams\n} from './completionClient';\n\nexport {\n callProviderImageGeneration,\n callProxiedImageGeneration,\n type IProviderImageGenerationParams\n} from './imageGenerationClient';\n\nexport {\n callProviderListModels,\n callProxiedListModels,\n type IProviderListModelsParams\n} from './listModelsClient';\n\nexport {\n callProviderEmbedding,\n callProxiedEmbedding,\n type IProviderEmbeddingParams\n} from './embeddingClient';\n\nexport {\n callProviderCompletionStream,\n callProxiedCompletionStream,\n type IProviderCompletionStreamParams,\n executeClientToolTurn,\n type IExecuteClientToolTurnParams,\n type IExecuteClientToolTurnResult,\n type IToolExecutionDecision\n} from './streamingClient';\n\nexport {\n aiProviderId,\n aiServerToolType,\n aiWebSearchToolConfig,\n aiServerToolConfig,\n aiToolAnnotations,\n aiClientToolConfig,\n aiToolEnablement,\n aiAssistProviderConfig,\n aiAssistSettings,\n modelSpecKey,\n modelSpec\n} from './converters';\n\nexport { resolveEffectiveTools } from './toolFormats';\n\nexport { ANTHROPIC_STRUCTURED_OUTPUT_TOOL_NAME } from './structuredOutput';\n\nexport type {\n AiStructuredOutputFormat,\n IAiStructuredOutputCapability,\n IJsonObjectStructuredOutputRequest,\n ISchemaStructuredOutputRequest,\n StructuredOutputEnforcement,\n StructuredOutputFallback,\n StructuredOutputRequest\n} from './structuredOutputTypes';\n\nexport {\n classifyJsonParseFailure,\n extractJsonText,\n fencedStringifiedJson,\n type IFencedStringifiedJsonExtractorOptions,\n type IFencedStringifiedJsonOptions,\n type JsonParseFailureReason,\n type JsonTextExtractor\n} from './jsonResponse';\n\nexport {\n generateJsonCompletion,\n SMART_JSON_PROMPT_HINT,\n type IGenerateJsonCompletionParams,\n type IGenerateJsonCompletionResult,\n type JsonPromptHint\n} from './jsonCompletion';\n\nexport { anthropicEffortToBudgetTokens, type IResolvedThinkingConfig } from './thinkingOptionsResolver';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonCompletion.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/jsonCompletion.ts"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAQ,MAAM,EAAW,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"jsonCompletion.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/jsonCompletion.ts"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAQ,MAAM,EAAW,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAGtF,OAAO,EAA0B,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE5F,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAGrD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAE2C,CAAC;AAEjF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,6BAA6B,CAAC,CAAC,CAAE,SAAQ,yBAAyB;IACjF;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAEjD;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAEtC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,6BAA6B,CAAC,CAAC;IAC9C,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,sDAAsD;IACtD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;CAC1C;AAUD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,MAAM,EAAE,6BAA6B,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC,CAAC,CAAC,CA4CnD"}
|
|
@@ -41,6 +41,7 @@ exports.generateJsonCompletion = generateJsonCompletion;
|
|
|
41
41
|
* @packageDocumentation
|
|
42
42
|
*/
|
|
43
43
|
const ts_utils_1 = require("@fgv/ts-utils");
|
|
44
|
+
const ts_json_base_1 = require("@fgv/ts-json-base");
|
|
44
45
|
const completionClient_1 = require("./completionClient");
|
|
45
46
|
const jsonResponse_1 = require("./jsonResponse");
|
|
46
47
|
/**
|
|
@@ -78,13 +79,30 @@ function applyPromptHint(system, hint) {
|
|
|
78
79
|
* @public
|
|
79
80
|
*/
|
|
80
81
|
async function generateJsonCompletion(params) {
|
|
81
|
-
const { converter, jsonConverter, promptHint = 'smart', system } = params, rest = __rest(params, ["converter", "jsonConverter", "promptHint", "system"]);
|
|
82
|
+
const { converter, jsonConverter, promptHint = 'smart', system, structuredOutput } = params, rest = __rest(params, ["converter", "jsonConverter", "promptHint", "system", "structuredOutput"]);
|
|
82
83
|
if (jsonConverter === undefined && converter === undefined) {
|
|
83
84
|
return (0, ts_utils_1.fail)('generateJsonCompletion: either converter or jsonConverter must be provided.');
|
|
84
85
|
}
|
|
85
86
|
const pipeline = jsonConverter !== null && jsonConverter !== void 0 ? jsonConverter : (0, jsonResponse_1.fencedStringifiedJson)({ inner: converter });
|
|
86
87
|
const augmentedSystem = applyPromptHint(system, promptHint);
|
|
87
|
-
|
|
88
|
+
// If the caller authored `converter` with `JsonSchema.object({...})`, the same
|
|
89
|
+
// object is already both the wire schema and the reply validator — so send it,
|
|
90
|
+
// and there is no second declaration to drift from. A plain Converter carries no
|
|
91
|
+
// schema, so nothing is sent and the report reads 'none': existing callers are
|
|
92
|
+
// byte-for-byte unaffected. Deliberately NOT a new parameter, which would
|
|
93
|
+
// reintroduce exactly the converter/schema drift `JsonSchema` exists to remove.
|
|
94
|
+
//
|
|
95
|
+
// The inference is gated on `jsonConverter === undefined` for that same reason.
|
|
96
|
+
// `pipeline` above prefers `jsonConverter` and ignores `converter` entirely when
|
|
97
|
+
// both are supplied, so inferring from `converter` regardless would constrain the
|
|
98
|
+
// REQUEST to a schema that has nothing to do with what validates the REPLY —
|
|
99
|
+
// reintroducing the exact drift this design exists to remove, in the one place
|
|
100
|
+
// two validation paths coexist. A caller who wants a constraint alongside a
|
|
101
|
+
// `jsonConverter` states it explicitly via `structuredOutput`.
|
|
102
|
+
const inferred = structuredOutput !== null && structuredOutput !== void 0 ? structuredOutput : (jsonConverter === undefined && ts_json_base_1.JsonSchema.isSchemaValidator(converter)
|
|
103
|
+
? { mode: 'schema', schema: converter }
|
|
104
|
+
: undefined);
|
|
105
|
+
const response = await (0, completionClient_1.callProviderCompletion)(Object.assign(Object.assign(Object.assign({}, rest), { system: augmentedSystem }), (inferred !== undefined ? { structuredOutput: inferred } : {})));
|
|
88
106
|
if (response.isFailure()) {
|
|
89
107
|
return (0, ts_utils_1.fail)(response.message);
|
|
90
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonCompletion.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/jsonCompletion.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;;;;;;;;;;;;;AAiHZ,wDAsBC;AArID;;;;;;;GAOG;AAEH,4CAAsF;AAEtF,yDAA4F;AAC5F,iDAAuD;AAGvD;;;;;GAKG;AACU,QAAA,sBAAsB,GACjC,8EAA8E;IAC9E,8EAA8E,CAAC;AA6DjF,SAAS,eAAe,CAAC,MAA0B,EAAE,IAAoB;IACvE,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,8BAAsB,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AACvF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACI,KAAK,UAAU,sBAAsB,CAC1C,MAAwC;IAExC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,GAAG,OAAO,EAAE,MAAM,KAAc,MAAM,EAAf,IAAI,UAAK,MAAM,EAA5E,sDAAmE,CAAS,CAAC;IAEnF,IAAI,aAAa,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,IAAA,eAAI,EAAC,6EAA6E,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,QAAQ,GAAiB,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,IAAA,oCAAqB,EAAI,EAAE,KAAK,EAAE,SAAU,EAAE,CAAC,CAAC;IAChG,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,MAAM,IAAA,yCAAsB,kCAAM,IAAI,KAAE,MAAM,EAAE,eAAe,IAAG,CAAC;IACpF,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;QACzB,OAAO,IAAA,eAAI,EAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC;IAElC,OAAO,QAAQ;SACZ,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;SAC3B,eAAe,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,2BAA2B,GAAG,EAAE,CAAC;SAC1D,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,kBAAO,EAAC,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * `generateJsonCompletion<T>` — request a JSON-shaped completion from any\n * provider supported by AiAssist and validate it against a caller-supplied\n * `Converter<T>` or `Validator<T>`. Wraps fence/preamble tolerance + parsing +\n * validation into a single call so consumers don't reinvent the pipeline.\n *\n * @packageDocumentation\n */\n\nimport { type Converter, fail, Result, succeed, type Validator } from '@fgv/ts-utils';\n\nimport { callProviderCompletion, type IProviderCompletionParams } from './completionClient';\nimport { fencedStringifiedJson } from './jsonResponse';\nimport { type IAiCompletionResponse } from './model';\n\n/**\n * Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}\n * is `'smart'` (the default). Designed to discourage code fences and prose in\n * the model's response while still tolerating them via the read-side extractor.\n * @public\n */\nexport const SMART_JSON_PROMPT_HINT: string =\n 'Respond with raw JSON only — no Markdown code fences, no explanatory prose, ' +\n 'no preamble or trailing commentary. The response must parse with JSON.parse.';\n\n/**\n * Controls the optional system-prompt augmentation applied by\n * {@link AiAssist.generateJsonCompletion}.\n *\n * - `'smart'` (default): append {@link AiAssist.SMART_JSON_PROMPT_HINT}.\n * - `'none'`: do not modify the prompt.\n * - A string: append the supplied text verbatim.\n *\n * @remarks\n * The `string & {}` branch is the standard TypeScript trick that prevents\n * the literal members from being widened away — callers still get\n * autocomplete for `'smart'` and `'none'` while accepting any string.\n *\n * @public\n */\nexport type JsonPromptHint = 'smart' | 'none' | (string & {});\n\n/**\n * Parameters for {@link AiAssist.generateJsonCompletion}. Extends\n * {@link AiAssist.IProviderCompletionParams} with JSON-validation knobs.\n * @public\n */\nexport interface IGenerateJsonCompletionParams<T> extends IProviderCompletionParams {\n /**\n * Caller-supplied `Converter<T>` or `Validator<T>` applied to the parsed\n * JSON value. Wrapped internally in {@link AiAssist.fencedStringifiedJson}\n * unless {@link AiAssist.IGenerateJsonCompletionParams.jsonConverter} is\n * provided.\n */\n readonly converter?: Converter<T> | Validator<T>;\n\n /**\n * Full string-to-`T` pipeline override. When supplied, takes precedence over\n * {@link AiAssist.IGenerateJsonCompletionParams.converter} and lets the\n * caller plug in a custom extractor or skip the default fence tolerance\n * entirely.\n */\n readonly jsonConverter?: Converter<T>;\n\n /**\n * Controls the optional system-prompt augmentation. Defaults to `'smart'`.\n * Pass `'none'` to disable, or a string to append custom guidance.\n */\n readonly promptHint?: JsonPromptHint;\n}\n\n/**\n * Successful result of {@link AiAssist.generateJsonCompletion}.\n * @public\n */\nexport interface IGenerateJsonCompletionResult<T> {\n /** The validated JSON value. */\n readonly value: T;\n /** The raw response text returned by the provider. */\n readonly raw: string;\n /** The full underlying completion response. */\n readonly response: IAiCompletionResponse;\n}\n\nfunction applyPromptHint(system: string | undefined, hint: JsonPromptHint): string | undefined {\n if (hint === 'none') {\n return system;\n }\n const suffix = hint === 'smart' ? SMART_JSON_PROMPT_HINT : hint;\n return system !== undefined && system.length > 0 ? `${system}\\n\\n${suffix}` : suffix;\n}\n\n/**\n * Calls {@link AiAssist.callProviderCompletion}, then runs the response text\n * through a tolerant JSON converter (default:\n * {@link AiAssist.fencedStringifiedJson}) and the caller's\n * `converter`/`validator`. Returns the validated value plus the raw text and\n * underlying completion response for diagnostics.\n *\n * @remarks\n * The default smart prompt hint asks the model to emit raw JSON. The read-side\n * extractor still tolerates fences and prose, so models that ignore the hint\n * are still handled.\n *\n * Either `converter` or `jsonConverter` must be provided; passing both lets\n * `jsonConverter` win.\n *\n * @param params - Provider parameters plus JSON validation options.\n * @returns The validated value, the raw text, and the underlying response.\n * @public\n */\nexport async function generateJsonCompletion<T>(\n params: IGenerateJsonCompletionParams<T>\n): Promise<Result<IGenerateJsonCompletionResult<T>>> {\n const { converter, jsonConverter, promptHint = 'smart', system, ...rest } = params;\n\n if (jsonConverter === undefined && converter === undefined) {\n return fail('generateJsonCompletion: either converter or jsonConverter must be provided.');\n }\n\n const pipeline: Converter<T> = jsonConverter ?? fencedStringifiedJson<T>({ inner: converter! });\n const augmentedSystem = applyPromptHint(system, promptHint);\n\n const response = await callProviderCompletion({ ...rest, system: augmentedSystem });\n if (response.isFailure()) {\n return fail(response.message);\n }\n const completion = response.value;\n\n return pipeline\n .convert(completion.content)\n .withErrorFormat((msg) => `generateJsonCompletion: ${msg}`)\n .onSuccess((value) => succeed({ value, raw: completion.content, response: completion }));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"jsonCompletion.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/jsonCompletion.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * `generateJsonCompletion<T>` — request a JSON-shaped completion from any\n * provider supported by AiAssist and validate it against a caller-supplied\n * `Converter<T>` or `Validator<T>`. Wraps fence/preamble tolerance + parsing +\n * validation into a single call so consumers don't reinvent the pipeline.\n *\n * @packageDocumentation\n */\n\nimport { type Converter, fail, Result, succeed, type Validator } from '@fgv/ts-utils';\nimport { JsonSchema } from '@fgv/ts-json-base';\n\nimport { callProviderCompletion, type IProviderCompletionParams } from './completionClient';\nimport { fencedStringifiedJson } from './jsonResponse';\nimport { type IAiCompletionResponse } from './model';\nimport { type StructuredOutputRequest } from './structuredOutputTypes';\n\n/**\n * Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}\n * is `'smart'` (the default). Designed to discourage code fences and prose in\n * the model's response while still tolerating them via the read-side extractor.\n * @public\n */\nexport const SMART_JSON_PROMPT_HINT: string =\n 'Respond with raw JSON only — no Markdown code fences, no explanatory prose, ' +\n 'no preamble or trailing commentary. The response must parse with JSON.parse.';\n\n/**\n * Controls the optional system-prompt augmentation applied by\n * {@link AiAssist.generateJsonCompletion}.\n *\n * - `'smart'` (default): append {@link AiAssist.SMART_JSON_PROMPT_HINT}.\n * - `'none'`: do not modify the prompt.\n * - A string: append the supplied text verbatim.\n *\n * @remarks\n * The `string & {}` branch is the standard TypeScript trick that prevents\n * the literal members from being widened away — callers still get\n * autocomplete for `'smart'` and `'none'` while accepting any string.\n *\n * @public\n */\nexport type JsonPromptHint = 'smart' | 'none' | (string & {});\n\n/**\n * Parameters for {@link AiAssist.generateJsonCompletion}. Extends\n * {@link AiAssist.IProviderCompletionParams} with JSON-validation knobs.\n * @public\n */\nexport interface IGenerateJsonCompletionParams<T> extends IProviderCompletionParams {\n /**\n * Caller-supplied `Converter<T>` or `Validator<T>` applied to the parsed\n * JSON value. Wrapped internally in {@link AiAssist.fencedStringifiedJson}\n * unless {@link AiAssist.IGenerateJsonCompletionParams.jsonConverter} is\n * provided.\n */\n readonly converter?: Converter<T> | Validator<T>;\n\n /**\n * Full string-to-`T` pipeline override. When supplied, takes precedence over\n * {@link AiAssist.IGenerateJsonCompletionParams.converter} and lets the\n * caller plug in a custom extractor or skip the default fence tolerance\n * entirely.\n */\n readonly jsonConverter?: Converter<T>;\n\n /**\n * Controls the optional system-prompt augmentation. Defaults to `'smart'`.\n * Pass `'none'` to disable, or a string to append custom guidance.\n */\n readonly promptHint?: JsonPromptHint;\n}\n\n/**\n * Successful result of {@link AiAssist.generateJsonCompletion}.\n * @public\n */\nexport interface IGenerateJsonCompletionResult<T> {\n /** The validated JSON value. */\n readonly value: T;\n /** The raw response text returned by the provider. */\n readonly raw: string;\n /** The full underlying completion response. */\n readonly response: IAiCompletionResponse;\n}\n\nfunction applyPromptHint(system: string | undefined, hint: JsonPromptHint): string | undefined {\n if (hint === 'none') {\n return system;\n }\n const suffix = hint === 'smart' ? SMART_JSON_PROMPT_HINT : hint;\n return system !== undefined && system.length > 0 ? `${system}\\n\\n${suffix}` : suffix;\n}\n\n/**\n * Calls {@link AiAssist.callProviderCompletion}, then runs the response text\n * through a tolerant JSON converter (default:\n * {@link AiAssist.fencedStringifiedJson}) and the caller's\n * `converter`/`validator`. Returns the validated value plus the raw text and\n * underlying completion response for diagnostics.\n *\n * @remarks\n * The default smart prompt hint asks the model to emit raw JSON. The read-side\n * extractor still tolerates fences and prose, so models that ignore the hint\n * are still handled.\n *\n * Either `converter` or `jsonConverter` must be provided; passing both lets\n * `jsonConverter` win.\n *\n * @param params - Provider parameters plus JSON validation options.\n * @returns The validated value, the raw text, and the underlying response.\n * @public\n */\nexport async function generateJsonCompletion<T>(\n params: IGenerateJsonCompletionParams<T>\n): Promise<Result<IGenerateJsonCompletionResult<T>>> {\n const { converter, jsonConverter, promptHint = 'smart', system, structuredOutput, ...rest } = params;\n\n if (jsonConverter === undefined && converter === undefined) {\n return fail('generateJsonCompletion: either converter or jsonConverter must be provided.');\n }\n\n const pipeline: Converter<T> = jsonConverter ?? fencedStringifiedJson<T>({ inner: converter! });\n const augmentedSystem = applyPromptHint(system, promptHint);\n\n // If the caller authored `converter` with `JsonSchema.object({...})`, the same\n // object is already both the wire schema and the reply validator — so send it,\n // and there is no second declaration to drift from. A plain Converter carries no\n // schema, so nothing is sent and the report reads 'none': existing callers are\n // byte-for-byte unaffected. Deliberately NOT a new parameter, which would\n // reintroduce exactly the converter/schema drift `JsonSchema` exists to remove.\n //\n // The inference is gated on `jsonConverter === undefined` for that same reason.\n // `pipeline` above prefers `jsonConverter` and ignores `converter` entirely when\n // both are supplied, so inferring from `converter` regardless would constrain the\n // REQUEST to a schema that has nothing to do with what validates the REPLY —\n // reintroducing the exact drift this design exists to remove, in the one place\n // two validation paths coexist. A caller who wants a constraint alongside a\n // `jsonConverter` states it explicitly via `structuredOutput`.\n const inferred: StructuredOutputRequest | undefined =\n structuredOutput ??\n (jsonConverter === undefined && JsonSchema.isSchemaValidator(converter)\n ? { mode: 'schema', schema: converter }\n : undefined);\n\n const response = await callProviderCompletion({\n ...rest,\n system: augmentedSystem,\n ...(inferred !== undefined ? { structuredOutput: inferred } : {})\n });\n if (response.isFailure()) {\n return fail(response.message);\n }\n const completion = response.value;\n\n return pipeline\n .convert(completion.content)\n .withErrorFormat((msg) => `generateJsonCompletion: ${msg}`)\n .onSuccess((value) => succeed({ value, raw: completion.content, response: completion }));\n}\n"]}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { type Result } from '@fgv/ts-utils';
|
|
6
6
|
import { type JsonObject, type JsonSchema } from '@fgv/ts-json-base';
|
|
7
|
+
import type { IAiStructuredOutputCapability, StructuredOutputEnforcement } from './structuredOutputTypes';
|
|
7
8
|
/**
|
|
8
9
|
* Universal image representation used for both image input (vision prompts)
|
|
9
10
|
* and image output (generation responses).
|
|
@@ -675,6 +676,24 @@ export interface IAiCompletionResponse {
|
|
|
675
676
|
readonly content: string;
|
|
676
677
|
/** Whether the response was truncated due to token limits */
|
|
677
678
|
readonly truncated: boolean;
|
|
679
|
+
/**
|
|
680
|
+
* Which structured-output constraint the provider was **asked** to apply.
|
|
681
|
+
*
|
|
682
|
+
* @remarks
|
|
683
|
+
* **Required, not optional, and that is the point.** An optional field would
|
|
684
|
+
* make absence three-ways ambiguous — no capability / not requested / a build
|
|
685
|
+
* predating the feature — and disambiguating exactly that is what this field
|
|
686
|
+
* exists for. `'none'` already expresses *"no constraint sent"*, so
|
|
687
|
+
* always-present costs nothing and removes the ambiguity by construction. The
|
|
688
|
+
* same remedy as `MemoryEmbedOutcome` in `@fgv/ts-agent-memory`, applied to the
|
|
689
|
+
* same defect.
|
|
690
|
+
*
|
|
691
|
+
* It reports what was *sent*, never whether **this** response conforms — that
|
|
692
|
+
* is the caller's converter's answer and re-deriving it here would be a second
|
|
693
|
+
* source of truth. See `StructuredOutputEnforcement` for the three-question
|
|
694
|
+
* split.
|
|
695
|
+
*/
|
|
696
|
+
readonly structuredOutput: StructuredOutputEnforcement;
|
|
678
697
|
}
|
|
679
698
|
/**
|
|
680
699
|
* Default `max_tokens` sent to the Anthropic Messages API when the caller does
|
|
@@ -875,6 +894,23 @@ export interface IAiProviderDescriptor {
|
|
|
875
894
|
* caller supplies the embedding model via `modelOverride`.
|
|
876
895
|
*/
|
|
877
896
|
readonly embedding?: ReadonlyArray<IAiEmbeddingModelCapability>;
|
|
897
|
+
/**
|
|
898
|
+
* Per-model-family structured-output capability, longest-prefix matched against
|
|
899
|
+
* the **resolved** completion model id. Absent (or no matching entry) means the
|
|
900
|
+
* model can enforce nothing, and a request against it reports `'none'`.
|
|
901
|
+
*
|
|
902
|
+
* @remarks
|
|
903
|
+
* Same declaration idiom as `imageGeneration` and
|
|
904
|
+
* `embedding`, resolved through the same
|
|
905
|
+
* alias-first helper — a capability lookup on an unresolved alias is the defect
|
|
906
|
+
* `resolveImageCapability` once had, where a catch-all `modelPrefix: ''` turned
|
|
907
|
+
* an unknown alias into a confidently wrong answer.
|
|
908
|
+
*
|
|
909
|
+
* Note this declares which wire format a model *family* supports, not which
|
|
910
|
+
* OpenAI endpoint a given call will take — that also depends on whether the
|
|
911
|
+
* call carries server tools, so the dispatcher supplies it.
|
|
912
|
+
*/
|
|
913
|
+
readonly structuredOutput?: ReadonlyArray<IAiStructuredOutputCapability>;
|
|
878
914
|
/**
|
|
879
915
|
* Concrete model ids (prefix-matched) that must be invoked via the OpenAI
|
|
880
916
|
* Responses API rather than chat completions — e.g. `gpt-5.5-pro`. Non-OpenAI
|
|
@@ -915,7 +951,7 @@ export interface IAiProviderDescriptor {
|
|
|
915
951
|
}
|
|
916
952
|
/**
|
|
917
953
|
* Image-generation capability for a model family within a provider. Used as
|
|
918
|
-
* an entry in
|
|
954
|
+
* an entry in `imageGeneration`.
|
|
919
955
|
*
|
|
920
956
|
* @public
|
|
921
957
|
*/
|
|
@@ -955,7 +991,7 @@ export interface IAiImageModelCapability {
|
|
|
955
991
|
}
|
|
956
992
|
/**
|
|
957
993
|
* Embedding capability for a model family within a provider. Used as an entry
|
|
958
|
-
* in
|
|
994
|
+
* in `embedding`.
|
|
959
995
|
*
|
|
960
996
|
* @public
|
|
961
997
|
*/
|