@fgv/ts-extras 5.1.0-55 → 5.1.0-57
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/CAPABILITIES.md +96 -0
- package/dist/packlets/ai-assist/cacheRequest.js +118 -0
- package/dist/packlets/ai-assist/cacheRequest.js.map +1 -0
- package/dist/packlets/ai-assist/chatRequestBuilders.js +72 -7
- package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
- package/dist/packlets/ai-assist/completionClient.js +195 -58
- package/dist/packlets/ai-assist/completionClient.js.map +1 -1
- package/dist/packlets/ai-assist/converters.js +54 -0
- package/dist/packlets/ai-assist/converters.js.map +1 -1
- package/dist/packlets/ai-assist/embeddingClient.js +16 -1
- package/dist/packlets/ai-assist/embeddingClient.js.map +1 -1
- package/dist/packlets/ai-assist/imageGenerationClient.js +17 -2
- package/dist/packlets/ai-assist/imageGenerationClient.js.map +1 -1
- package/dist/packlets/ai-assist/index.js +3 -1
- package/dist/packlets/ai-assist/index.js.map +1 -1
- package/dist/packlets/ai-assist/listModelsClient.js +19 -1
- package/dist/packlets/ai-assist/listModelsClient.js.map +1 -1
- package/dist/packlets/ai-assist/model.js.map +1 -1
- package/dist/packlets/ai-assist/promptCacheAnthropicBreakpointHarness.js +200 -0
- package/dist/packlets/ai-assist/promptCacheAnthropicBreakpointHarness.js.map +1 -0
- package/dist/packlets/ai-assist/promptCacheObservabilityHarness.js +137 -0
- package/dist/packlets/ai-assist/promptCacheObservabilityHarness.js.map +1 -0
- package/dist/packlets/ai-assist/promptCacheRoutingAbHarness.js +156 -0
- package/dist/packlets/ai-assist/promptCacheRoutingAbHarness.js.map +1 -0
- package/dist/packlets/ai-assist/promptCacheUsageMath.js +124 -0
- package/dist/packlets/ai-assist/promptCacheUsageMath.js.map +1 -0
- package/dist/packlets/ai-assist/registry.js +9 -11
- package/dist/packlets/ai-assist/registry.js.map +1 -1
- package/dist/packlets/ai-assist/streamUsageCapability.js +134 -0
- package/dist/packlets/ai-assist/streamUsageCapability.js.map +1 -0
- package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +32 -9
- package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -1
- package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +81 -35
- package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
- package/dist/packlets/ai-assist/streamingAdapters/common.js +25 -1
- package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
- package/dist/packlets/ai-assist/streamingAdapters/gemini.js +12 -5
- package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -1
- package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +45 -11
- package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -1
- package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +33 -22
- package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -1
- package/dist/packlets/ai-assist/streamingAdapters/proxy.js +62 -4
- package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
- package/dist/packlets/ai-assist/streamingClient.js +20 -5
- package/dist/packlets/ai-assist/streamingClient.js.map +1 -1
- package/dist/packlets/ai-assist/thinkingOptionsResolver.js +23 -5
- package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -1
- package/dist/packlets/ai-assist/toolFormats.js +80 -0
- package/dist/packlets/ai-assist/toolFormats.js.map +1 -1
- package/dist/packlets/ai-assist/toolTypes.js +21 -0
- package/dist/packlets/ai-assist/toolTypes.js.map +1 -0
- package/dist/packlets/ai-assist/usageNormalization.js +178 -0
- package/dist/packlets/ai-assist/usageNormalization.js.map +1 -0
- package/dist/packlets/ai-assist/usageTypes.js +21 -0
- package/dist/packlets/ai-assist/usageTypes.js.map +1 -0
- package/dist/packlets/mustache/index.js.map +1 -1
- package/dist/packlets/mustache/interfaces.js.map +1 -1
- package/dist/packlets/mustache/mustacheTemplate.js +91 -0
- package/dist/packlets/mustache/mustacheTemplate.js.map +1 -1
- package/dist/ts-extras.d.ts +764 -48
- package/lib/packlets/ai-assist/cacheRequest.d.ts +100 -0
- package/lib/packlets/ai-assist/cacheRequest.d.ts.map +1 -0
- package/lib/packlets/ai-assist/cacheRequest.js +123 -0
- package/lib/packlets/ai-assist/cacheRequest.js.map +1 -0
- package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +36 -6
- package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -1
- package/lib/packlets/ai-assist/chatRequestBuilders.js +75 -7
- package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -1
- package/lib/packlets/ai-assist/completionClient.d.ts +19 -0
- package/lib/packlets/ai-assist/completionClient.d.ts.map +1 -1
- package/lib/packlets/ai-assist/completionClient.js +194 -57
- package/lib/packlets/ai-assist/completionClient.js.map +1 -1
- package/lib/packlets/ai-assist/converters.d.ts +46 -0
- package/lib/packlets/ai-assist/converters.d.ts.map +1 -1
- package/lib/packlets/ai-assist/converters.js +55 -1
- package/lib/packlets/ai-assist/converters.js.map +1 -1
- package/lib/packlets/ai-assist/embeddingClient.d.ts +9 -0
- package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -1
- package/lib/packlets/ai-assist/embeddingClient.js +16 -1
- package/lib/packlets/ai-assist/embeddingClient.js.map +1 -1
- package/lib/packlets/ai-assist/imageGenerationClient.d.ts +9 -0
- package/lib/packlets/ai-assist/imageGenerationClient.d.ts.map +1 -1
- package/lib/packlets/ai-assist/imageGenerationClient.js +17 -2
- package/lib/packlets/ai-assist/imageGenerationClient.js.map +1 -1
- package/lib/packlets/ai-assist/index.d.ts +7 -2
- package/lib/packlets/ai-assist/index.d.ts.map +1 -1
- package/lib/packlets/ai-assist/index.js +11 -1
- package/lib/packlets/ai-assist/index.js.map +1 -1
- package/lib/packlets/ai-assist/listModelsClient.d.ts +12 -0
- package/lib/packlets/ai-assist/listModelsClient.d.ts.map +1 -1
- package/lib/packlets/ai-assist/listModelsClient.js +19 -1
- package/lib/packlets/ai-assist/listModelsClient.js.map +1 -1
- package/lib/packlets/ai-assist/model.d.ts +81 -295
- 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/promptCacheAnthropicBreakpointHarness.d.ts +124 -0
- package/lib/packlets/ai-assist/promptCacheAnthropicBreakpointHarness.d.ts.map +1 -0
- package/lib/packlets/ai-assist/promptCacheAnthropicBreakpointHarness.js +208 -0
- package/lib/packlets/ai-assist/promptCacheAnthropicBreakpointHarness.js.map +1 -0
- package/lib/packlets/ai-assist/promptCacheObservabilityHarness.d.ts +77 -0
- package/lib/packlets/ai-assist/promptCacheObservabilityHarness.d.ts.map +1 -0
- package/lib/packlets/ai-assist/promptCacheObservabilityHarness.js +143 -0
- package/lib/packlets/ai-assist/promptCacheObservabilityHarness.js.map +1 -0
- package/lib/packlets/ai-assist/promptCacheRoutingAbHarness.d.ts +84 -0
- package/lib/packlets/ai-assist/promptCacheRoutingAbHarness.d.ts.map +1 -0
- package/lib/packlets/ai-assist/promptCacheRoutingAbHarness.js +163 -0
- package/lib/packlets/ai-assist/promptCacheRoutingAbHarness.js.map +1 -0
- package/lib/packlets/ai-assist/promptCacheUsageMath.d.ts +105 -0
- package/lib/packlets/ai-assist/promptCacheUsageMath.d.ts.map +1 -0
- package/lib/packlets/ai-assist/promptCacheUsageMath.js +130 -0
- package/lib/packlets/ai-assist/promptCacheUsageMath.js.map +1 -0
- package/lib/packlets/ai-assist/registry.d.ts.map +1 -1
- package/lib/packlets/ai-assist/registry.js +9 -11
- package/lib/packlets/ai-assist/registry.js.map +1 -1
- package/lib/packlets/ai-assist/streamUsageCapability.d.ts +129 -0
- package/lib/packlets/ai-assist/streamUsageCapability.d.ts.map +1 -0
- package/lib/packlets/ai-assist/streamUsageCapability.js +140 -0
- package/lib/packlets/ai-assist/streamUsageCapability.js.map +1 -0
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +2 -1
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +29 -6
- package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +58 -14
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +81 -36
- package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +38 -3
- package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/common.js +25 -1
- package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/gemini.js +12 -5
- package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +2 -1
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +42 -8
- package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +2 -1
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +30 -19
- package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +22 -0
- package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingAdapters/proxy.js +62 -4
- package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
- package/lib/packlets/ai-assist/streamingClient.d.ts +5 -0
- package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -1
- package/lib/packlets/ai-assist/streamingClient.js +20 -5
- package/lib/packlets/ai-assist/streamingClient.js.map +1 -1
- package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +11 -3
- package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -1
- package/lib/packlets/ai-assist/thinkingOptionsResolver.js +23 -5
- package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -1
- package/lib/packlets/ai-assist/toolFormats.d.ts +55 -1
- package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -1
- package/lib/packlets/ai-assist/toolFormats.js +82 -0
- package/lib/packlets/ai-assist/toolFormats.js.map +1 -1
- package/lib/packlets/ai-assist/toolTypes.d.ts +386 -0
- package/lib/packlets/ai-assist/toolTypes.d.ts.map +1 -0
- package/lib/packlets/ai-assist/toolTypes.js +22 -0
- package/lib/packlets/ai-assist/toolTypes.js.map +1 -0
- package/lib/packlets/ai-assist/usageNormalization.d.ts +58 -0
- package/lib/packlets/ai-assist/usageNormalization.d.ts.map +1 -0
- package/lib/packlets/ai-assist/usageNormalization.js +184 -0
- package/lib/packlets/ai-assist/usageNormalization.js.map +1 -0
- package/lib/packlets/ai-assist/usageTypes.d.ts +84 -0
- package/lib/packlets/ai-assist/usageTypes.d.ts.map +1 -0
- package/lib/packlets/ai-assist/usageTypes.js +22 -0
- package/lib/packlets/ai-assist/usageTypes.js.map +1 -0
- package/lib/packlets/mustache/index.d.ts +1 -1
- package/lib/packlets/mustache/index.d.ts.map +1 -1
- package/lib/packlets/mustache/index.js.map +1 -1
- package/lib/packlets/mustache/interfaces.d.ts +30 -0
- package/lib/packlets/mustache/interfaces.d.ts.map +1 -1
- package/lib/packlets/mustache/interfaces.js.map +1 -1
- package/lib/packlets/mustache/mustacheTemplate.d.ts +56 -1
- package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -1
- package/lib/packlets/mustache/mustacheTemplate.js +91 -0
- package/lib/packlets/mustache/mustacheTemplate.js.map +1 -1
- package/package.json +16 -16
- package/perf/promptCacheAnthropicBreakpoint.js +135 -0
- package/perf/promptCacheObservability.js +107 -0
- package/perf/promptCacheRoutingAb.js +105 -0
|
@@ -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 {\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"]}
|
|
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 { isJsonObject, 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 { type IAiCacheRequest } from './cacheRequest';\nimport { aiCompletionUsage } from './converters';\nimport type { IAiCompletionUsage } from './usageTypes';\nimport {\n anthropicEffortToBudgetTokens,\n checkTemperatureConflict,\n mergeThinkingConfig,\n providerDiscriminatorForId,\n type IResolvedThinkingConfig\n} from './thinkingOptionsResolver';\nimport {\n buildAnthropicMessages,\n buildAnthropicSystem,\n buildGeminiContents,\n buildMessages,\n buildOpenAiChatSystemContent,\n buildOpenAiChatUserContent,\n buildOpenAiResponsesSystemContent,\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 {\n supportsCacheUsageReporting,\n supportsPromptCacheBreakpoints,\n supportsPromptCacheRouting\n} from './streamUsageCapability';\nimport type { StructuredOutputRequest } from './structuredOutputTypes';\nimport {\n normalizeAnthropicUsage,\n normalizeGeminiUsage,\n normalizeOpenAiChatUsage,\n normalizeOpenAiResponsesUsage\n} from './usageNormalization';\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 * Prompt-caching plan for this request. Omitted, nothing cache-related is sent — the request\n * body is byte-identical to a build predating this feature. See {@link AiAssist.IAiCacheRequest}.\n */\n readonly cache?: IAiCacheRequest;\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 // Optional: a part is not always a text part. Reasoning parts carry `thought`, and tool parts\n // carry `functionCall`; both arrive with no `text` at all.\n text?: string;\n}\n/** @internal */\ninterface IGeminiContent {\n parts?: IGeminiPart[];\n}\n/** @internal */\ninterface IGeminiCandidate {\n // Every field here is optional because a candidate that produced nothing still comes back —\n // as `content: {}`, or with no `content` key. Requiring them turned \"the model declined, and\n // here is why\" into an opaque validation error naming a field of an empty object.\n content?: IGeminiContent;\n finishReason?: string;\n finishMessage?: string;\n}\n/** @internal */\ninterface IGeminiResponse {\n candidates: IGeminiCandidate[];\n}\n\nconst geminiPart: Validator<IGeminiPart> = Validators.object<IGeminiPart>({\n text: Validators.string.optional()\n});\nconst geminiContent: Validator<IGeminiContent> = Validators.object<IGeminiContent>({\n // No non-empty constraint: `parts: []` is a shape Gemini actually returns, and rejecting it\n // here reports a schema violation for what is really \"the model produced no output\".\n parts: Validators.arrayOf(geminiPart).optional()\n});\nconst geminiCandidate: Validator<IGeminiCandidate> = Validators.object<IGeminiCandidate>({\n content: geminiContent.optional(),\n finishReason: Validators.string.optional(),\n finishMessage: Validators.string.optional()\n});\n\n// Terminal reasons that mean \"the model finished normally\", as distinct from a refusal. Kept in\n// step with the identical set in `imageGenerationClient.ts`; both exist so an empty response can\n// be reported as the decline it is rather than as an empty string or a parse error.\nconst benignGeminiFinishReasons: ReadonlySet<string> = new Set(['STOP', 'MAX_TOKENS']);\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 reportsUsage: boolean = false,\n cache?: IAiCacheRequest,\n cacheKeyHeader?: string\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/chat/completions`;\n const systemContentResult = buildOpenAiChatSystemContent(prompt.system, cache);\n if (systemContentResult.isFailure()) {\n return fail(systemContentResult.message);\n }\n const messages = buildMessages(systemContentResult.value, 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 // Pure additive routing plumbing (research.md §1.3) — no vocabulary, no cap. `cacheKey` is\n // gated at the dispatch site to descriptors with a confirmed routing transport (see\n // supportsPromptCacheRouting), and carried here as a body field only for providers that take\n // it that way. xAI takes it as the `cacheKeyHeader` below instead, so sending it in the body\n // as well would be an unrecognized field on a server whose tolerance is unconfirmed.\n ...(cache?.cacheKey !== undefined && cacheKeyHeader === undefined\n ? // eslint-disable-next-line @typescript-eslint/naming-convention -- wire field name\n { prompt_cache_key: cache.cacheKey }\n : {})\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 // Sticky-routing key, when the provider carries it as a header rather than a body field.\n // xAI's prompt cache is per-server, so an identical prefix can still miss if the request is\n // routed to a different box; `x-grok-conv-id` pins it.\n if (cache?.cacheKey !== undefined && cacheKeyHeader !== undefined) {\n headers[cacheKeyHeader] = cache.cacheKey;\n }\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 // Only descriptors with confirmed cache-relevant usage reporting are normalized — the\n // adapter is shared by Groq/Mistral/Ollama/openai-compat too, and an ordinary usage block\n // from one of those carries no cache information. See supportsCacheUsageReporting.\n const rawUsage = jsonResult.value.usage;\n const usage = reportsUsage\n ? normalizeOpenAiChatUsage(isJsonObject(rawUsage) ? rawUsage : undefined)\n : undefined;\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 ...(usage !== undefined ? { usage } : {})\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 reportsUsage: boolean = false,\n cache?: IAiCacheRequest\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/responses`;\n const systemContentResult = buildOpenAiResponsesSystemContent(prompt.system, cache);\n if (systemContentResult.isFailure()) {\n return fail(systemContentResult.message);\n }\n const input = buildMessages(systemContentResult.value, 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 // See the identical field and gating on callOpenAiCompletion's body — same routing plumbing,\n // confirmed on both Chat Completions and the Responses API (research.md §1.3).\n ...(cache?.cacheKey !== undefined\n ? // eslint-disable-next-line @typescript-eslint/naming-convention -- wire field name\n { prompt_cache_key: cache.cacheKey }\n : {})\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 // See the identical gate in callOpenAiCompletion above — this route is shared the same way.\n const rawResponsesUsage = jsonResult.value.usage;\n const responsesUsage = reportsUsage\n ? normalizeOpenAiResponsesUsage(isJsonObject(rawResponsesUsage) ? rawResponsesUsage : undefined)\n : undefined;\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 ...(responsesUsage !== undefined ? { usage: responsesUsage } : {})\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 cache?: IAiCacheRequest\n): Promise<Result<IAiCompletionResponse>> {\n const url = `${config.baseUrl}/messages`;\n const messages = buildAnthropicMessages(prompt, { head });\n const systemResult = buildAnthropicSystem(prompt.system, cache);\n if (systemResult.isFailure()) {\n return fail(systemResult.message);\n }\n const body: Record<string, unknown> = {\n model: config.model,\n system: systemResult.value,\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 const rawAnthropicUsage = jsonResult.value.usage;\n const anthropicUsage = normalizeAnthropicUsage(\n isJsonObject(rawAnthropicUsage) ? rawAnthropicUsage : undefined\n );\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 ...(anthropicUsage !== undefined ? { usage: anthropicUsage } : {})\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 const rawGeminiUsage = jsonResult.value.usageMetadata;\n const geminiUsage = normalizeGeminiUsage(isJsonObject(rawGeminiUsage) ? rawGeminiUsage : undefined);\n return geminiResponse\n .validate(jsonResult.value)\n .withErrorFormat((msg) => `Gemini API response: ${msg}`)\n .onSuccess((response) => {\n const candidate = response.candidates[0];\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 //\n // `part.text ?? ''` rather than `part.text`: a reasoning or tool part contributes no text,\n // and joining `undefined` would put the literal string \"undefined\" into the reply.\n const content = candidate.content?.parts?.map((part) => part.text ?? '').join('') ?? '';\n if (content.length === 0) {\n // Nothing came back. If the candidate says why, say so — an empty string handed to a\n // caller is indistinguishable from a model that legitimately replied with nothing, and\n // sends them looking in the wrong place.\n const reason = candidate.finishReason;\n if (reason !== undefined && !benignGeminiFinishReasons.has(reason)) {\n const suffix = candidate.finishMessage ? ` — ${candidate.finishMessage}` : '';\n return fail(`Gemini completion declined: ${reason}${suffix}`);\n }\n }\n return succeed({\n content,\n truncated: candidate.finishReason === 'MAX_TOKENS',\n structuredOutput: structured.enforcement,\n ...(geminiUsage !== undefined ? { usage: geminiUsage } : {})\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 cache\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 // `cache` carries two independently-supported things, and they are gated separately.\n // `systemBreakpoints` restructures `content` and needs the server to tolerate an\n // unrecognized field inside it (OpenAI only). `cacheKey` is an opaque routing string that\n // makes repeated requests with a shared prefix land on the same cache-holding server —\n // which xAI needs precisely because it does per-server byte-for-byte prefix matching.\n // Gating them together withheld the routing key from the provider that depends on it most.\n // Every descriptor supporting neither (Groq, Mistral, Ollama, openai-compat) still gets the\n // exact request body it would have gotten had the caller passed no `cache` at all.\n const routing = supportsPromptCacheRouting(descriptor);\n const breakpoints = supportsPromptCacheBreakpoints(descriptor) ? cache?.systemBreakpoints : undefined;\n const routedKey = routing !== undefined ? cache?.cacheKey : undefined;\n const gatedCache: IAiCacheRequest | undefined =\n breakpoints !== undefined || routedKey !== undefined\n ? { systemBreakpoints: breakpoints, cacheKey: routedKey }\n : undefined;\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 supportsCacheUsageReporting(descriptor),\n gatedCache\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 supportsCacheUsageReporting(descriptor),\n gatedCache,\n routing?.chatCompletionsHeader\n );\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 cache\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 *\n * @remarks\n * Two parameters are handled before the body is composed, rather than forwarded.\n * `tier` is resolved here and sent as a concrete `modelOverride`, because both\n * halves of the resolution live on the descriptor the caller already holds — so a\n * proxy needs no `tier` vocabulary, where a `tier` body field it did not understand\n * would be ignored and silently serve a frontier request from the base model.\n * `endpoint` is **refused**: it names where the prompt must go, the proxy is what\n * makes that call, and the field has never been sent to one — so honoring it is\n * unverifiable and ignoring it would reach the provider's default upstream instead\n * of the host the caller pinned. Use `callProviderCompletion`, or point the\n * proxy itself at the intended upstream.\n *\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 cache,\n tier,\n endpoint\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 // `endpoint` names the upstream the request must reach. Unlike `tier` it cannot be\n // resolved on this side, because the proxy is the one making that call — it would\n // have to be forwarded and honored. No proxy honors it: the field has never been\n // sent, so every deployed proxy would ignore it and fall back to the provider's\n // public API.\n //\n // Silently is the problem. A caller names an endpoint to pin *where the prompt\n // goes* — a self-hosted model, a LAN deployment, a residency boundary — so the\n // failure is not a degraded answer, it is the content going somewhere they\n // explicitly said it must not, discoverable only by watching the proxy's traffic.\n // That is the same shape as the structured-output silent-drop this function\n // already refuses to allow, with a worse consequence.\n //\n // So refuse rather than pretend. Honoring `endpoint` over a proxy needs a wire\n // field AND a report-back the caller can verify, the way `structuredOutput` is\n // acknowledged below; until that protocol exists, the direct path is where this\n // parameter works.\n if (endpoint !== undefined) {\n return fail(\n `callProxiedCompletion: endpoint is not supported on the proxied path — a proxy ` +\n `cannot confirm it honored it, and silently reaching the provider's default ` +\n `upstream would send the request somewhere the caller excluded. Use ` +\n `callProviderCompletion, or route the proxy itself at the intended upstream.`\n );\n }\n\n // The quality tier is resolved HERE rather than forwarded, because it can be:\n // the tier walk and the alias map both live on the descriptor, which is\n // client-side, so this side already holds everything the resolution needs.\n // Sending the concrete model through the existing `modelOverride` field means a\n // proxy needs no new vocabulary and an already-deployed one honors the tier\n // without being updated — where a `tier` body field it did not understand would\n // be ignored, silently serving a frontier request from the base model.\n //\n // Only when a tier was actually asked for. With no tier, `modelOverride` passes\n // through exactly as before, including absent — which is what lets a proxy apply\n // its own default.\n let effectiveModelOverride: ModelSpec | undefined = modelOverride;\n if (tier !== undefined) {\n const tierResult = resolveProviderModel(descriptor, modelOverride, tier);\n if (tierResult.isFailure()) {\n return fail(tierResult.message);\n }\n effectiveModelOverride = tierResult.value;\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 (effectiveModelOverride !== undefined) {\n body.modelOverride = effectiveModelOverride;\n }\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 // Part of the request, not a local-only concern: the hoist is applied\n // where the wire schema is built, which on this path is the proxy. Drop\n // it and an opted-in caller's schema gets refused or degraded instead of\n // hoisted, and `onUnsupported` reports a constraint loss the caller had\n // already opted out of.\n ...(structuredOutput.adaptOptionalToNullable !== undefined\n ? { adaptOptionalToNullable: structuredOutput.adaptOptionalToNullable }\n : {})\n }\n : {\n mode: 'json-object',\n ...(structuredOutput.onUnsupported !== undefined\n ? { onUnsupported: structuredOutput.onUnsupported }\n : {})\n };\n }\n // `IAiCacheRequest` is plain numbers and a string — JSON-serializable as-is, unlike\n // `structuredOutput`'s schema above, so it needs no wire projection before forwarding.\n if (cache !== undefined) {\n body.cache = cache;\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 // A proxy relaying `callProviderCompletion`'s result carries an already-normalized\n // IAiCompletionUsage, not a provider wire shape — so this validates that shape\n // rather than reaching for the per-provider normalizers. A proxy that reports\n // nothing, or reports something malformed, yields `undefined`: the documented\n // \"no normalized usage exposed\", never a partially-trusted object and never a\n // fabricated zero.\n const usage: IAiCompletionUsage | undefined = aiCompletionUsage.convert(response.usage).orDefault();\n\n // Built once: the two returns differ only in the enforcement they report, and\n // duplicating the shape is how a field added to one and not the other drifts.\n const base = {\n content: response.content,\n truncated: response.truncated === true,\n ...(usage !== undefined ? { usage } : {})\n };\n\n if (structuredOutput === undefined) {\n return succeed({ ...base, structuredOutput: 'none' });\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({ ...base, structuredOutput: response.structuredOutput });\n}\n"]}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @packageDocumentation
|
|
4
4
|
*/
|
|
5
5
|
import { type Converter } from '@fgv/ts-utils';
|
|
6
|
+
import type { AiCacheReportingLevel, IAiCompletionUsage } from './usageTypes';
|
|
6
7
|
import { type AiProviderId, type AiServerToolConfig, type AiServerToolType, type IAiAssistProviderConfig, type IAiAssistSettings, type IAiClientToolConfig, type IAiToolAnnotations, type IAiToolEnablement, type IAiWebSearchToolConfig, type ModelSpec, type ModelSpecKey } from './model';
|
|
7
8
|
/**
|
|
8
9
|
* Converter for {@link AiProviderId}.
|
|
@@ -66,4 +67,49 @@ export declare const aiAssistProviderConfig: Converter<IAiAssistProviderConfig>;
|
|
|
66
67
|
* @public
|
|
67
68
|
*/
|
|
68
69
|
export declare const aiAssistSettings: Converter<IAiAssistSettings>;
|
|
70
|
+
/**
|
|
71
|
+
* Converter for {@link AiAssist.AiCacheReportingLevel}.
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* Internal because it is not exported from the packlet barrel, so nothing
|
|
75
|
+
* outside this package can reach it — a `@public` tag would have claimed a
|
|
76
|
+
* reachability that does not exist. Its only consumer is
|
|
77
|
+
* {@link aiCompletionUsage} below. Promoting it later is additive and free;
|
|
78
|
+
* exporting it now to match the tag would add surface nobody has asked for,
|
|
79
|
+
* and un-exporting is the one direction that breaks callers.
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
export declare const aiCacheReportingLevel: Converter<AiCacheReportingLevel>;
|
|
83
|
+
/**
|
|
84
|
+
* Converter for {@link AiAssist.IAiCompletionUsage}.
|
|
85
|
+
*
|
|
86
|
+
* @remarks
|
|
87
|
+
* For the **proxy** path, where the usage block arrives already normalized rather
|
|
88
|
+
* than in a provider wire shape — the proxy ran `callProviderCompletion` and is
|
|
89
|
+
* relaying its `IAiCompletionUsage`. The per-provider helpers in
|
|
90
|
+
* `usageNormalization` translate wire shapes and are the wrong tool here; this
|
|
91
|
+
* validates the normalized shape itself.
|
|
92
|
+
*
|
|
93
|
+
* `reports` is required, matching the interface: a usage block that cannot say
|
|
94
|
+
* which of reads/writes it is able to report is not a usage block this package
|
|
95
|
+
* will hand on. A proxy relaying a malformed one gets the whole field dropped
|
|
96
|
+
* rather than a partially-trusted object.
|
|
97
|
+
*
|
|
98
|
+
* **Not `strictObject`, deliberately.** This validates a payload from a network
|
|
99
|
+
* peer that may be running a *newer* build of this library. Under strict rules one
|
|
100
|
+
* unrecognized field — a future token count, an echoed setting — would fail the
|
|
101
|
+
* conversion and drop the entire usage block, and `.orDefault()` would render that
|
|
102
|
+
* indistinguishable from "the provider reported nothing". Tolerating unknown fields
|
|
103
|
+
* is the same forward-compatibility posture the rest of the proxy path takes toward
|
|
104
|
+
* a peer of a different version. Required fields stay required; only openness to
|
|
105
|
+
* extra ones changes.
|
|
106
|
+
*
|
|
107
|
+
* Internal for the same reason as {@link aiCacheReportingLevel}: it is not in
|
|
108
|
+
* the packlet barrel, and its only consumer is `callProxiedCompletion`'s
|
|
109
|
+
* read-back. A proxy implementor validating the usage block they relay is the
|
|
110
|
+
* plausible external consumer, and exporting it for them is additive whenever
|
|
111
|
+
* one actually turns up.
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
114
|
+
export declare const aiCompletionUsage: Converter<IAiCompletionUsage>;
|
|
69
115
|
//# sourceMappingURL=converters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/converters.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AAEH,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,eAAe,CAAC;AAGvF,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,SAAS,EACd,KAAK,YAAY,EAElB,MAAM,SAAS,CAAC;AAOjB;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,YAAY,CAA4D,CAAC;AAY9G;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,CACS,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,CAAC,sBAAsB,CAOhE,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,kBAAkB,CAGzD,CAAC;AAyBL;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,kBAAkB,CAM1D,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,mBAAmB,CAQ5D,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,iBAAiB,CAIxD,CAAC;AAMH;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,YAAY,CACW,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,CAW1C,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,CAAC,uBAAuB,CAOlE,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,iBAAiB,CAKxD,CAAC"}
|
|
1
|
+
{"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/converters.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AAEH,OAAO,EAAE,KAAK,SAAS,EAA0C,MAAM,eAAe,CAAC;AAGvF,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE9E,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,SAAS,EACd,KAAK,YAAY,EAElB,MAAM,SAAS,CAAC;AAOjB;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,YAAY,CAA4D,CAAC;AAY9G;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,CACS,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,CAAC,sBAAsB,CAOhE,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,kBAAkB,CAGzD,CAAC;AAyBL;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,kBAAkB,CAM1D,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,mBAAmB,CAQ5D,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,iBAAiB,CAIxD,CAAC;AAMH;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,SAAS,CAAC,YAAY,CACW,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,CAW1C,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,CAAC,uBAAuB,CAOlE,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,iBAAiB,CAKxD,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,CAAC,qBAAqB,CACe,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,kBAAkB,CAQ1D,CAAC"}
|
|
@@ -19,12 +19,13 @@
|
|
|
19
19
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
// SOFTWARE.
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.aiAssistSettings = exports.aiAssistProviderConfig = exports.modelSpec = exports.modelSpecKey = exports.aiToolEnablement = exports.aiClientToolConfig = exports.aiToolAnnotations = exports.aiServerToolConfig = exports.aiWebSearchToolConfig = exports.aiServerToolType = exports.aiProviderId = void 0;
|
|
22
|
+
exports.aiCompletionUsage = exports.aiCacheReportingLevel = exports.aiAssistSettings = exports.aiAssistProviderConfig = exports.modelSpec = exports.modelSpecKey = exports.aiToolEnablement = exports.aiClientToolConfig = exports.aiToolAnnotations = exports.aiServerToolConfig = exports.aiWebSearchToolConfig = exports.aiServerToolType = exports.aiProviderId = void 0;
|
|
23
23
|
/**
|
|
24
24
|
* Converters for AI assist settings types.
|
|
25
25
|
* @packageDocumentation
|
|
26
26
|
*/
|
|
27
27
|
const ts_utils_1 = require("@fgv/ts-utils");
|
|
28
|
+
const ts_json_base_1 = require("@fgv/ts-json-base");
|
|
28
29
|
const model_1 = require("./model");
|
|
29
30
|
const registry_1 = require("./registry");
|
|
30
31
|
// ============================================================================
|
|
@@ -165,4 +166,57 @@ exports.aiAssistSettings = ts_utils_1.Converters.strictObject({
|
|
|
165
166
|
proxyUrl: ts_utils_1.Converters.string.optional(),
|
|
166
167
|
proxyAllProviders: ts_utils_1.Converters.boolean.optional()
|
|
167
168
|
});
|
|
169
|
+
/**
|
|
170
|
+
* Converter for {@link AiAssist.AiCacheReportingLevel}.
|
|
171
|
+
*
|
|
172
|
+
* @remarks
|
|
173
|
+
* Internal because it is not exported from the packlet barrel, so nothing
|
|
174
|
+
* outside this package can reach it — a `@public` tag would have claimed a
|
|
175
|
+
* reachability that does not exist. Its only consumer is
|
|
176
|
+
* {@link aiCompletionUsage} below. Promoting it later is additive and free;
|
|
177
|
+
* exporting it now to match the tag would add surface nobody has asked for,
|
|
178
|
+
* and un-exporting is the one direction that breaks callers.
|
|
179
|
+
* @internal
|
|
180
|
+
*/
|
|
181
|
+
exports.aiCacheReportingLevel = ts_utils_1.Converters.enumeratedValue(['reads', 'reads-and-writes']);
|
|
182
|
+
/**
|
|
183
|
+
* Converter for {@link AiAssist.IAiCompletionUsage}.
|
|
184
|
+
*
|
|
185
|
+
* @remarks
|
|
186
|
+
* For the **proxy** path, where the usage block arrives already normalized rather
|
|
187
|
+
* than in a provider wire shape — the proxy ran `callProviderCompletion` and is
|
|
188
|
+
* relaying its `IAiCompletionUsage`. The per-provider helpers in
|
|
189
|
+
* `usageNormalization` translate wire shapes and are the wrong tool here; this
|
|
190
|
+
* validates the normalized shape itself.
|
|
191
|
+
*
|
|
192
|
+
* `reports` is required, matching the interface: a usage block that cannot say
|
|
193
|
+
* which of reads/writes it is able to report is not a usage block this package
|
|
194
|
+
* will hand on. A proxy relaying a malformed one gets the whole field dropped
|
|
195
|
+
* rather than a partially-trusted object.
|
|
196
|
+
*
|
|
197
|
+
* **Not `strictObject`, deliberately.** This validates a payload from a network
|
|
198
|
+
* peer that may be running a *newer* build of this library. Under strict rules one
|
|
199
|
+
* unrecognized field — a future token count, an echoed setting — would fail the
|
|
200
|
+
* conversion and drop the entire usage block, and `.orDefault()` would render that
|
|
201
|
+
* indistinguishable from "the provider reported nothing". Tolerating unknown fields
|
|
202
|
+
* is the same forward-compatibility posture the rest of the proxy path takes toward
|
|
203
|
+
* a peer of a different version. Required fields stay required; only openness to
|
|
204
|
+
* extra ones changes.
|
|
205
|
+
*
|
|
206
|
+
* Internal for the same reason as {@link aiCacheReportingLevel}: it is not in
|
|
207
|
+
* the packlet barrel, and its only consumer is `callProxiedCompletion`'s
|
|
208
|
+
* read-back. A proxy implementor validating the usage block they relay is the
|
|
209
|
+
* plausible external consumer, and exporting it for them is additive whenever
|
|
210
|
+
* one actually turns up.
|
|
211
|
+
* @internal
|
|
212
|
+
*/
|
|
213
|
+
exports.aiCompletionUsage = ts_utils_1.Converters.object({
|
|
214
|
+
reports: exports.aiCacheReportingLevel,
|
|
215
|
+
uncachedInputTokens: ts_utils_1.Converters.number.optional(),
|
|
216
|
+
cachedInputTokens: ts_utils_1.Converters.number.optional(),
|
|
217
|
+
cacheWriteTokens: ts_utils_1.Converters.number.optional(),
|
|
218
|
+
outputTokens: ts_utils_1.Converters.number.optional(),
|
|
219
|
+
totalInputTokens: ts_utils_1.Converters.number.optional(),
|
|
220
|
+
raw: ts_json_base_1.Converters.jsonObject.optional()
|
|
221
|
+
});
|
|
168
222
|
//# sourceMappingURL=converters.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converters.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/converters.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 * Converters for AI assist settings types.\n * @packageDocumentation\n */\n\nimport { type Converter, Converters, type Validator, Validators } from '@fgv/ts-utils';\nimport { type JsonSchema } from '@fgv/ts-json-base';\n\nimport {\n type AiProviderId,\n type AiServerToolConfig,\n type AiServerToolType,\n type IAiAssistProviderConfig,\n type IAiAssistSettings,\n type IAiClientToolConfig,\n type IAiToolAnnotations,\n type IAiToolEnablement,\n type IAiWebSearchToolConfig,\n type ModelSpec,\n type ModelSpecKey,\n allModelSpecKeys\n} from './model';\nimport { allProviderIds } from './registry';\n\n// ============================================================================\n// Provider ID\n// ============================================================================\n\n/**\n * Converter for {@link AiProviderId}.\n * @public\n */\nexport const aiProviderId: Converter<AiProviderId> = Converters.enumeratedValue<AiProviderId>(allProviderIds);\n\n// ============================================================================\n// Server-Side Tool Converters\n// ============================================================================\n\n/**\n * All known server-side tool type values.\n * @internal\n */\nconst allServerToolTypes: ReadonlyArray<AiServerToolType> = ['web_search'];\n\n/**\n * Converter for {@link AiServerToolType}.\n * @public\n */\nexport const aiServerToolType: Converter<AiServerToolType> =\n Converters.enumeratedValue<AiServerToolType>(allServerToolTypes);\n\n/**\n * Converter for {@link IAiWebSearchToolConfig}.\n * @public\n */\nexport const aiWebSearchToolConfig: Converter<IAiWebSearchToolConfig> =\n Converters.strictObject<IAiWebSearchToolConfig>({\n type: Converters.enumeratedValue<'web_search'>(['web_search']),\n allowedDomains: Converters.arrayOf(Converters.string).optional(),\n blockedDomains: Converters.arrayOf(Converters.string).optional(),\n maxUses: Converters.number.optional(),\n enableImageUnderstanding: Converters.boolean.optional()\n });\n\n/**\n * Converter for {@link AiServerToolConfig} (discriminated union on `type`).\n * @public\n */\nexport const aiServerToolConfig: Converter<AiServerToolConfig> =\n Converters.discriminatedObject<AiServerToolConfig>('type', {\n web_search: aiWebSearchToolConfig\n });\n\n// ============================================================================\n// Client-Defined Tool Converters\n// ============================================================================\n\n/**\n * Validator for the `parametersSchema` field of a client tool config.\n * Checks that the value is a non-null object exposing both `validate` and `toJson`\n * as callable functions — the runtime presence check for {@link JsonSchema.ISchemaValidator}.\n * Does not inspect the inner JSON Schema structure.\n * @internal\n */\nconst parametersSchemaValidator: Validator<JsonSchema.ISchemaValidator<unknown>> = Validators.isA<\n JsonSchema.ISchemaValidator<unknown>\n>(\n 'ISchemaValidator (must expose .validate() and .toJson())',\n (v): v is JsonSchema.ISchemaValidator<unknown> =>\n v !== null &&\n v !== undefined &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>).validate === 'function' &&\n typeof (v as Record<string, unknown>).toJson === 'function'\n);\n\n/**\n * Converter for {@link AiAssist.IAiToolAnnotations} — the five optional host-advisory hints.\n * @public\n */\nexport const aiToolAnnotations: Converter<IAiToolAnnotations> = Converters.strictObject<IAiToolAnnotations>({\n title: Converters.string.optional(),\n readOnlyHint: Converters.boolean.optional(),\n destructiveHint: Converters.boolean.optional(),\n idempotentHint: Converters.boolean.optional(),\n openWorldHint: Converters.boolean.optional()\n});\n\n/**\n * Converter for {@link AiAssist.IAiClientToolConfig}. Validates the wrapper shape: `type`,\n * `name`, `description`, the presence of a usable `parametersSchema`, and optional\n * host-advisory `annotations`.\n * Does not inspect the inner JSON Schema structure — `JsonSchema.object(...)` already\n * guarantees the schema is valid.\n * @public\n */\nexport const aiClientToolConfig: Converter<IAiClientToolConfig> = Converters.object<IAiClientToolConfig>({\n type: Converters.enumeratedValue<'client_tool'>(['client_tool']),\n name: Converters.string.withConstraint((s) => s.length > 0, {\n description: 'name must be a non-empty string'\n }),\n description: Converters.string,\n parametersSchema: parametersSchemaValidator,\n annotations: aiToolAnnotations.optional()\n});\n\n/**\n * Converter for {@link IAiToolEnablement}.\n * @public\n */\nexport const aiToolEnablement: Converter<IAiToolEnablement> = Converters.strictObject<IAiToolEnablement>({\n type: aiServerToolType,\n enabled: Converters.boolean,\n config: aiServerToolConfig.optional()\n});\n\n// ============================================================================\n// Model Specification\n// ============================================================================\n\n/**\n * Converter for {@link ModelSpecKey}.\n * @public\n */\nexport const modelSpecKey: Converter<ModelSpecKey> =\n Converters.enumeratedValue<ModelSpecKey>(allModelSpecKeys);\n\n/**\n * Recursive converter for {@link ModelSpec}.\n * Accepts a string or an object whose values are themselves ModelSpec values,\n * with keys constrained to known {@link ModelSpecKey} values.\n * Uses the `self` parameter from `Converters.generic` for recursion.\n * @public\n */\nexport const modelSpec: Converter<ModelSpec> = Converters.generic<ModelSpec>(\n (from: unknown, self: Converter<ModelSpec>) => {\n return Converters.oneOf<ModelSpec>([\n Converters.string,\n Converters.recordOf(self, { keyConverter: modelSpecKey })\n ])\n .withFormattedError(\n () => 'expected model spec (string or object with keys: base, advanced, frontier, image, embedding)'\n )\n .convert(from);\n }\n);\n\n// ============================================================================\n// Provider Config & Settings\n// ============================================================================\n\n/**\n * Converter for {@link IAiAssistProviderConfig}.\n * @public\n */\nexport const aiAssistProviderConfig: Converter<IAiAssistProviderConfig> =\n Converters.strictObject<IAiAssistProviderConfig>({\n provider: aiProviderId,\n secretName: Converters.string.optional(),\n model: modelSpec.optional(),\n tools: Converters.arrayOf(aiToolEnablement).optional(),\n endpoint: Converters.string.optional()\n });\n\n/**\n * Converter for {@link IAiAssistSettings}.\n * @public\n */\nexport const aiAssistSettings: Converter<IAiAssistSettings> = Converters.strictObject<IAiAssistSettings>({\n providers: Converters.arrayOf(aiAssistProviderConfig),\n defaultProvider: aiProviderId.optional(),\n proxyUrl: Converters.string.optional(),\n proxyAllProviders: Converters.boolean.optional()\n});\n"]}
|
|
1
|
+
{"version":3,"file":"converters.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/converters.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 * Converters for AI assist settings types.\n * @packageDocumentation\n */\n\nimport { type Converter, Converters, type Validator, Validators } from '@fgv/ts-utils';\nimport { type JsonSchema, Converters as JsonConverters } from '@fgv/ts-json-base';\n\nimport type { AiCacheReportingLevel, IAiCompletionUsage } from './usageTypes';\n\nimport {\n type AiProviderId,\n type AiServerToolConfig,\n type AiServerToolType,\n type IAiAssistProviderConfig,\n type IAiAssistSettings,\n type IAiClientToolConfig,\n type IAiToolAnnotations,\n type IAiToolEnablement,\n type IAiWebSearchToolConfig,\n type ModelSpec,\n type ModelSpecKey,\n allModelSpecKeys\n} from './model';\nimport { allProviderIds } from './registry';\n\n// ============================================================================\n// Provider ID\n// ============================================================================\n\n/**\n * Converter for {@link AiProviderId}.\n * @public\n */\nexport const aiProviderId: Converter<AiProviderId> = Converters.enumeratedValue<AiProviderId>(allProviderIds);\n\n// ============================================================================\n// Server-Side Tool Converters\n// ============================================================================\n\n/**\n * All known server-side tool type values.\n * @internal\n */\nconst allServerToolTypes: ReadonlyArray<AiServerToolType> = ['web_search'];\n\n/**\n * Converter for {@link AiServerToolType}.\n * @public\n */\nexport const aiServerToolType: Converter<AiServerToolType> =\n Converters.enumeratedValue<AiServerToolType>(allServerToolTypes);\n\n/**\n * Converter for {@link IAiWebSearchToolConfig}.\n * @public\n */\nexport const aiWebSearchToolConfig: Converter<IAiWebSearchToolConfig> =\n Converters.strictObject<IAiWebSearchToolConfig>({\n type: Converters.enumeratedValue<'web_search'>(['web_search']),\n allowedDomains: Converters.arrayOf(Converters.string).optional(),\n blockedDomains: Converters.arrayOf(Converters.string).optional(),\n maxUses: Converters.number.optional(),\n enableImageUnderstanding: Converters.boolean.optional()\n });\n\n/**\n * Converter for {@link AiServerToolConfig} (discriminated union on `type`).\n * @public\n */\nexport const aiServerToolConfig: Converter<AiServerToolConfig> =\n Converters.discriminatedObject<AiServerToolConfig>('type', {\n web_search: aiWebSearchToolConfig\n });\n\n// ============================================================================\n// Client-Defined Tool Converters\n// ============================================================================\n\n/**\n * Validator for the `parametersSchema` field of a client tool config.\n * Checks that the value is a non-null object exposing both `validate` and `toJson`\n * as callable functions — the runtime presence check for {@link JsonSchema.ISchemaValidator}.\n * Does not inspect the inner JSON Schema structure.\n * @internal\n */\nconst parametersSchemaValidator: Validator<JsonSchema.ISchemaValidator<unknown>> = Validators.isA<\n JsonSchema.ISchemaValidator<unknown>\n>(\n 'ISchemaValidator (must expose .validate() and .toJson())',\n (v): v is JsonSchema.ISchemaValidator<unknown> =>\n v !== null &&\n v !== undefined &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>).validate === 'function' &&\n typeof (v as Record<string, unknown>).toJson === 'function'\n);\n\n/**\n * Converter for {@link AiAssist.IAiToolAnnotations} — the five optional host-advisory hints.\n * @public\n */\nexport const aiToolAnnotations: Converter<IAiToolAnnotations> = Converters.strictObject<IAiToolAnnotations>({\n title: Converters.string.optional(),\n readOnlyHint: Converters.boolean.optional(),\n destructiveHint: Converters.boolean.optional(),\n idempotentHint: Converters.boolean.optional(),\n openWorldHint: Converters.boolean.optional()\n});\n\n/**\n * Converter for {@link AiAssist.IAiClientToolConfig}. Validates the wrapper shape: `type`,\n * `name`, `description`, the presence of a usable `parametersSchema`, and optional\n * host-advisory `annotations`.\n * Does not inspect the inner JSON Schema structure — `JsonSchema.object(...)` already\n * guarantees the schema is valid.\n * @public\n */\nexport const aiClientToolConfig: Converter<IAiClientToolConfig> = Converters.object<IAiClientToolConfig>({\n type: Converters.enumeratedValue<'client_tool'>(['client_tool']),\n name: Converters.string.withConstraint((s) => s.length > 0, {\n description: 'name must be a non-empty string'\n }),\n description: Converters.string,\n parametersSchema: parametersSchemaValidator,\n annotations: aiToolAnnotations.optional()\n});\n\n/**\n * Converter for {@link IAiToolEnablement}.\n * @public\n */\nexport const aiToolEnablement: Converter<IAiToolEnablement> = Converters.strictObject<IAiToolEnablement>({\n type: aiServerToolType,\n enabled: Converters.boolean,\n config: aiServerToolConfig.optional()\n});\n\n// ============================================================================\n// Model Specification\n// ============================================================================\n\n/**\n * Converter for {@link ModelSpecKey}.\n * @public\n */\nexport const modelSpecKey: Converter<ModelSpecKey> =\n Converters.enumeratedValue<ModelSpecKey>(allModelSpecKeys);\n\n/**\n * Recursive converter for {@link ModelSpec}.\n * Accepts a string or an object whose values are themselves ModelSpec values,\n * with keys constrained to known {@link ModelSpecKey} values.\n * Uses the `self` parameter from `Converters.generic` for recursion.\n * @public\n */\nexport const modelSpec: Converter<ModelSpec> = Converters.generic<ModelSpec>(\n (from: unknown, self: Converter<ModelSpec>) => {\n return Converters.oneOf<ModelSpec>([\n Converters.string,\n Converters.recordOf(self, { keyConverter: modelSpecKey })\n ])\n .withFormattedError(\n () => 'expected model spec (string or object with keys: base, advanced, frontier, image, embedding)'\n )\n .convert(from);\n }\n);\n\n// ============================================================================\n// Provider Config & Settings\n// ============================================================================\n\n/**\n * Converter for {@link IAiAssistProviderConfig}.\n * @public\n */\nexport const aiAssistProviderConfig: Converter<IAiAssistProviderConfig> =\n Converters.strictObject<IAiAssistProviderConfig>({\n provider: aiProviderId,\n secretName: Converters.string.optional(),\n model: modelSpec.optional(),\n tools: Converters.arrayOf(aiToolEnablement).optional(),\n endpoint: Converters.string.optional()\n });\n\n/**\n * Converter for {@link IAiAssistSettings}.\n * @public\n */\nexport const aiAssistSettings: Converter<IAiAssistSettings> = Converters.strictObject<IAiAssistSettings>({\n providers: Converters.arrayOf(aiAssistProviderConfig),\n defaultProvider: aiProviderId.optional(),\n proxyUrl: Converters.string.optional(),\n proxyAllProviders: Converters.boolean.optional()\n});\n\n/**\n * Converter for {@link AiAssist.AiCacheReportingLevel}.\n *\n * @remarks\n * Internal because it is not exported from the packlet barrel, so nothing\n * outside this package can reach it — a `@public` tag would have claimed a\n * reachability that does not exist. Its only consumer is\n * {@link aiCompletionUsage} below. Promoting it later is additive and free;\n * exporting it now to match the tag would add surface nobody has asked for,\n * and un-exporting is the one direction that breaks callers.\n * @internal\n */\nexport const aiCacheReportingLevel: Converter<AiCacheReportingLevel> =\n Converters.enumeratedValue<AiCacheReportingLevel>(['reads', 'reads-and-writes']);\n\n/**\n * Converter for {@link AiAssist.IAiCompletionUsage}.\n *\n * @remarks\n * For the **proxy** path, where the usage block arrives already normalized rather\n * than in a provider wire shape — the proxy ran `callProviderCompletion` and is\n * relaying its `IAiCompletionUsage`. The per-provider helpers in\n * `usageNormalization` translate wire shapes and are the wrong tool here; this\n * validates the normalized shape itself.\n *\n * `reports` is required, matching the interface: a usage block that cannot say\n * which of reads/writes it is able to report is not a usage block this package\n * will hand on. A proxy relaying a malformed one gets the whole field dropped\n * rather than a partially-trusted object.\n *\n * **Not `strictObject`, deliberately.** This validates a payload from a network\n * peer that may be running a *newer* build of this library. Under strict rules one\n * unrecognized field — a future token count, an echoed setting — would fail the\n * conversion and drop the entire usage block, and `.orDefault()` would render that\n * indistinguishable from \"the provider reported nothing\". Tolerating unknown fields\n * is the same forward-compatibility posture the rest of the proxy path takes toward\n * a peer of a different version. Required fields stay required; only openness to\n * extra ones changes.\n *\n * Internal for the same reason as {@link aiCacheReportingLevel}: it is not in\n * the packlet barrel, and its only consumer is `callProxiedCompletion`'s\n * read-back. A proxy implementor validating the usage block they relay is the\n * plausible external consumer, and exporting it for them is additive whenever\n * one actually turns up.\n * @internal\n */\nexport const aiCompletionUsage: Converter<IAiCompletionUsage> = Converters.object<IAiCompletionUsage>({\n reports: aiCacheReportingLevel,\n uncachedInputTokens: Converters.number.optional(),\n cachedInputTokens: Converters.number.optional(),\n cacheWriteTokens: Converters.number.optional(),\n outputTokens: Converters.number.optional(),\n totalInputTokens: Converters.number.optional(),\n raw: JsonConverters.jsonObject.optional()\n});\n"]}
|
|
@@ -60,6 +60,15 @@ export declare function callProviderEmbedding(params: IProviderEmbeddingParams):
|
|
|
60
60
|
* handles descriptor lookup, model/capability resolution, and provider dispatch.
|
|
61
61
|
* Error body `{ error: string }` is surfaced as `proxy: ${error}`.
|
|
62
62
|
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* `endpoint` is **refused** on this path rather than forwarded or dropped, on the
|
|
65
|
+
* same terms as `callProxiedCompletion`. It matters more here than
|
|
66
|
+
* anywhere else: pointing `endpoint` at `http://localhost:11434/v1` is the
|
|
67
|
+
* documented way to reach a local Ollama, so dropping it does not degrade the
|
|
68
|
+
* answer — it sends the text to OpenAI's public API instead of the machine the
|
|
69
|
+
* caller named. Use `callProviderEmbedding`, or point the proxy
|
|
70
|
+
* itself at the intended upstream.
|
|
71
|
+
*
|
|
63
72
|
* @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`).
|
|
64
73
|
* @param params - Same parameters as {@link AiAssist.callProviderEmbedding}.
|
|
65
74
|
* @returns The embedding result, or a failure.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddingClient.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/embeddingClient.ts"],"names":[],"mappings":"AAoBA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,EAAuC,MAAM,eAAe,CAAC;AAEhG,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAEvB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EAEf,MAAM,SAAS,CAAC;AASjB;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAoSD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAwCrC;AA2CD
|
|
1
|
+
{"version":3,"file":"embeddingClient.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/embeddingClient.ts"],"names":[],"mappings":"AAoBA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,EAAuC,MAAM,eAAe,CAAC;AAEhG,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAEvB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EAEf,MAAM,SAAS,CAAC;AASjB;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAoSD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAwCrC;AA2CD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAsCrC"}
|
|
@@ -316,13 +316,28 @@ const proxiedEmbeddingResponse = ts_utils_1.Validators.object({
|
|
|
316
316
|
* handles descriptor lookup, model/capability resolution, and provider dispatch.
|
|
317
317
|
* Error body `{ error: string }` is surfaced as `proxy: ${error}`.
|
|
318
318
|
*
|
|
319
|
+
* @remarks
|
|
320
|
+
* `endpoint` is **refused** on this path rather than forwarded or dropped, on the
|
|
321
|
+
* same terms as `callProxiedCompletion`. It matters more here than
|
|
322
|
+
* anywhere else: pointing `endpoint` at `http://localhost:11434/v1` is the
|
|
323
|
+
* documented way to reach a local Ollama, so dropping it does not degrade the
|
|
324
|
+
* answer — it sends the text to OpenAI's public API instead of the machine the
|
|
325
|
+
* caller named. Use `callProviderEmbedding`, or point the proxy
|
|
326
|
+
* itself at the intended upstream.
|
|
327
|
+
*
|
|
319
328
|
* @param proxyUrl - Base URL of the proxy server (e.g. `http://localhost:3001`).
|
|
320
329
|
* @param params - Same parameters as {@link AiAssist.callProviderEmbedding}.
|
|
321
330
|
* @returns The embedding result, or a failure.
|
|
322
331
|
* @public
|
|
323
332
|
*/
|
|
324
333
|
async function callProxiedEmbedding(proxyUrl, params) {
|
|
325
|
-
const { descriptor, apiKey, params: request, modelOverride, logger, signal } = params;
|
|
334
|
+
const { descriptor, apiKey, params: request, modelOverride, logger, signal, endpoint } = params;
|
|
335
|
+
if (endpoint !== undefined) {
|
|
336
|
+
return (0, ts_utils_1.fail)(`callProxiedEmbedding: endpoint is not supported on the proxied path — a proxy ` +
|
|
337
|
+
`cannot confirm it honored it, and silently reaching the provider's default ` +
|
|
338
|
+
`upstream would send the request somewhere the caller excluded. Use ` +
|
|
339
|
+
`callProviderEmbedding, or route the proxy itself at the intended upstream.`);
|
|
340
|
+
}
|
|
326
341
|
const body = {
|
|
327
342
|
providerId: descriptor.id,
|
|
328
343
|
apiKey,
|