@alvin0/ai-agent-sdk-provider-openai 0.1.1 → 0.1.3
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/README.md +9 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Runtime: **Universal** (Edge/Worker, browser, Deno, Bun, and Node).
|
|
4
4
|
|
|
5
|
+
Compatible gateways can configure `baseUrl`, `models`, `fetch`, and `headers`
|
|
6
|
+
(a string record or synchronous function returning one per operation).
|
|
7
|
+
Generation uses Responses; embedding uses the OpenAI embeddings protocol.
|
|
8
|
+
The embedding adapter/plugin also supports custom headers.
|
|
9
|
+
Header names are case-insensitive; collisions and reserved auth/transport headers
|
|
10
|
+
are rejected. Supply credentials with `apiKey`. Static records are copied;
|
|
11
|
+
prepared embedding calls keep the same header snapshot across all batches.
|
|
12
|
+
Trusted local HTTP gateways require `allowInsecureHttp: true`.
|
|
13
|
+
|
|
5
14
|
```sh
|
|
6
15
|
pnpm add @alvin0/ai-agent-sdk-core @alvin0/ai-agent-sdk-provider-openai
|
|
7
16
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ interface OpenAiAdapterOptions {
|
|
|
18
18
|
* Point this at a compatible gateway to reuse this provider wholesale.
|
|
19
19
|
*/
|
|
20
20
|
baseUrl?: string;
|
|
21
|
+
/** Extra endpoint headers, captured once per operation. Reserved names and collisions fail. */
|
|
22
|
+
headers?: Readonly<Record<string, string>> | (() => Readonly<Record<string, string>>);
|
|
23
|
+
/** Permit cleartext HTTP explicitly for trusted local gateways. */
|
|
24
|
+
allowInsecureHttp?: boolean;
|
|
21
25
|
/** Organization to bill, when the key belongs to several. */
|
|
22
26
|
organization?: string;
|
|
23
27
|
/** Project to attribute usage to. */
|
|
@@ -79,6 +83,8 @@ declare function openAiPlugin(options: OpenAiPluginOptions): ModelProviderPlugin
|
|
|
79
83
|
interface OpenAiEmbeddingProviderOptions {
|
|
80
84
|
/** Injected API key or credential source; universal packages never read the environment. */
|
|
81
85
|
readonly apiKey: CredentialInput;
|
|
86
|
+
/** Extra endpoint headers, captured once per logical call; reserved names fail. */
|
|
87
|
+
readonly headers?: Readonly<Record<string, string>> | (() => Readonly<Record<string, string>>);
|
|
82
88
|
/**
|
|
83
89
|
* Endpoint base; defaults to {@link OPENAI_BASE_URL}.
|
|
84
90
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/adapter.ts","../src/embedding.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/adapter.ts","../src/embedding.ts"],"mappings":";;;;;;;cAoCa;;KAGD,mBAAmB;;UAGd;;EAEf,QAAQ;;;;;;EAMR;;EAEA,UAAU,SAAS,iCAAiC,SAAS;;EAE7D;;EAEA;;EAEA;;;;;;;;EAQA,kBAAkB;;EAElB;;EAEA;;EAEA;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA,cAAc;;EAEd,gBAAgB;EAChB,eAAe,WAAW;;;;;;;iBAQZ,cAAc,SAAS,uBAAuB;UAkC7C,4BAA4B;;WAElC;;UAGM,8BAA8B,KAAK;WACzC,wBAAwB;WACxB,QAAQ;WACR;WACA;;;iBAIK,aACd,SAAS,wBACR;WAA2C;;iBAC9B,aAAa,SAAS,sBAAsB;;;;UC9B3C;;WAEN,QAAQ;;WAER,UAAU,SAAS,iCAAiC,SAAS;;;;;;;;WAQ7D;;WAEA;;WAEA;;WAEA;;WAEA;;;;;;;;;WASA,kBAAkB;;WAElB;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA,cAAc;WACd,eAAe,WAAW;;;;;;;iBAkcrB,uBACd,SAAS,iCACR;;;;;;;;;iBAYa,sBACd,SAAS,iCACR;WAA+C"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineEmbeddingProviderPlugin, defineModelProviderPlugin } from "@alvin0/ai-agent-sdk-core/provider";
|
|
2
|
-
import { captureTransportConnection, createHttpProvider, createModelContextPolicy, createRuntimeHttpProvider, embeddingCatalogModelInfo, resolvedEmbeddingCatalogModelInfo, transportJson } from "@alvin0/ai-agent-sdk-provider-http";
|
|
2
|
+
import { captureTransportConnection, createHttpProvider, createModelContextPolicy, createRuntimeHttpProvider, embeddingCatalogModelInfo, endpointHeaders, resolvedEmbeddingCatalogModelInfo, transportJson } from "@alvin0/ai-agent-sdk-provider-http";
|
|
3
3
|
import { openAiResponsesProtocol, openAiResponsesProtocol as openAiResponsesProtocol$1 } from "@alvin0/ai-agent-sdk-protocol-responses";
|
|
4
4
|
import { resolveRetryPolicy } from "@alvin0/ai-agent-sdk-core";
|
|
5
5
|
import { EMBEDDING_ERROR_CODES, EmbeddingAdapter, EmbeddingError, defaultEmbeddingProfile, deriveSpaceId, resolveBatchLimits, validateBatchResult } from "@alvin0/ai-agent-sdk-core/embedding";
|
|
@@ -40,10 +40,10 @@ function openAiAdapter(options) {
|
|
|
40
40
|
label: "the `apiKey` option"
|
|
41
41
|
},
|
|
42
42
|
dialect,
|
|
43
|
-
headers: {
|
|
43
|
+
headers: endpointHeaders(options.headers, {
|
|
44
44
|
...options.organization === void 0 ? {} : { "openai-organization": options.organization },
|
|
45
45
|
...options.project === void 0 ? {} : { "openai-project": options.project }
|
|
46
|
-
},
|
|
46
|
+
}),
|
|
47
47
|
...options.models === void 0 ? {} : { models: options.models },
|
|
48
48
|
defaultMaxTokens: options.defaultMaxTokens ?? 32e3,
|
|
49
49
|
defaultContextWindow: options.defaultContextWindow ?? 128e3,
|
|
@@ -95,10 +95,10 @@ function createRuntimeOpenAiAdapter(options) {
|
|
|
95
95
|
label: "the `apiKey` option"
|
|
96
96
|
},
|
|
97
97
|
dialect: options.store === void 0 ? {} : { store: options.store },
|
|
98
|
-
headers: {
|
|
98
|
+
headers: endpointHeaders(options.headers, {
|
|
99
99
|
...options.organization === void 0 ? {} : { "openai-organization": options.organization },
|
|
100
100
|
...options.project === void 0 ? {} : { "openai-project": options.project }
|
|
101
|
-
},
|
|
101
|
+
}),
|
|
102
102
|
...options.models === void 0 ? {} : { models: options.models },
|
|
103
103
|
defaultMaxTokens: options.defaultMaxTokens ?? 32e3,
|
|
104
104
|
defaultContextWindow: options.defaultContextWindow ?? 128e3,
|
|
@@ -124,6 +124,7 @@ function runtimeDefaultModel(value, routes) {
|
|
|
124
124
|
}
|
|
125
125
|
function transportLimits(options) {
|
|
126
126
|
return {
|
|
127
|
+
...options.allowInsecureHttp === void 0 ? {} : { allowInsecureHttp: options.allowInsecureHttp },
|
|
127
128
|
...options.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: options.requestTimeoutMs },
|
|
128
129
|
...options.maxRequestBytes === void 0 ? {} : { maxRequestBytes: options.maxRequestBytes },
|
|
129
130
|
...options.maxResponseBytes === void 0 ? {} : { maxResponseBytes: options.maxResponseBytes },
|
|
@@ -214,9 +215,14 @@ var OpenAiEmbeddingAdapter = class extends EmbeddingAdapter {
|
|
|
214
215
|
baseUrl;
|
|
215
216
|
models;
|
|
216
217
|
retry;
|
|
218
|
+
headers;
|
|
217
219
|
constructor(options) {
|
|
218
220
|
super();
|
|
219
221
|
this.options = options;
|
|
222
|
+
this.headers = endpointHeaders(options.headers, {
|
|
223
|
+
...options.organization === void 0 ? {} : { "openai-organization": options.organization },
|
|
224
|
+
...options.project === void 0 ? {} : { "openai-project": options.project }
|
|
225
|
+
});
|
|
220
226
|
this.baseUrl = (options.baseUrl ?? "https://api.openai.com/v1").replace(/\/+$/, "");
|
|
221
227
|
this.models = Object.freeze([...options.models ?? []]);
|
|
222
228
|
this.retry = resolveRetryPolicy(options.retryPolicy, "openAiEmbedding.retryPolicy");
|
|
@@ -292,9 +298,12 @@ var OpenAiEmbeddingAdapter = class extends EmbeddingAdapter {
|
|
|
292
298
|
}
|
|
293
299
|
/** Everything one embedding request needs, read together, once per operation. */
|
|
294
300
|
async connect(signal, context) {
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
301
|
+
const extraHeaders = this.headers();
|
|
302
|
+
const token = await resolveApiKey(this.options.apiKey, signal, context);
|
|
303
|
+
const headers = {
|
|
304
|
+
...extraHeaders,
|
|
305
|
+
authorization: `Bearer ${token}`
|
|
306
|
+
};
|
|
298
307
|
return Object.freeze({
|
|
299
308
|
baseUrl: this.baseUrl,
|
|
300
309
|
headers: Object.freeze(headers),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["openAiResponsesProtocol"],"sources":["../src/context-policy.ts","../src/adapter.ts","../src/embedding.ts"],"sourcesContent":["import { createModelContextPolicy } from '@alvin0/ai-agent-sdk-provider-http'\nimport type { ModelContextPolicyOptions } from '@alvin0/ai-agent-sdk-provider-http'\n\n// Verified 2026-09-13: https://developers.openai.com/api/docs/models/gpt-5.6-luna\n// https://developers.openai.com/api/docs/models/gpt-5.6-sol\n// https://developers.openai.com/api/docs/models/gpt-5.6-terra\nconst GPT_56 = { defaultContextWindow: 272_000, maxContextWindow: 1_050_000, standardPriceInputTokens: 272_000 }\nexport function openAiContextPolicy(options: ModelContextPolicyOptions) {\n return createModelContextPolicy(\n options.baseUrl === undefined || options.baseUrl.replace(/\\/$/, '') === 'https://api.openai.com/v1'\n ? { 'gpt-5.6-luna': GPT_56, 'gpt-5.6-sol': GPT_56, 'gpt-5.6-terra': GPT_56 }\n : {}, options.models, options.defaultContextWindow)\n}\n","/**\n * The OpenAI provider: the Responses API on `api.openai.com`.\n *\n * Note how little there is here. Every endpoint fact is configuration handed to\n * {@link createHttpProvider}; the protocol, the pipeline, and the error mapping are\n * all shared. That is the intended shape for any endpoint speaking a protocol this\n * package already implements — including your own gateway.\n *\n * @module ai-agent-sdk/providers/openai/adapter\n */\n\nimport type { ModelProviderPlugin, ModelProviderRegistrar, RetryPolicyConfig } from '@alvin0/ai-agent-sdk-core'\nimport {\n defineModelProviderPlugin,\n type ComposableModelProviderPlugin,\n type CredentialInput,\n type ModelTarget,\n} from '@alvin0/ai-agent-sdk-core/provider'\nimport type {\n HttpModelAdapter,\n ProviderCatalogModel,\n ProviderRequestLogger,\n} from '@alvin0/ai-agent-sdk-provider-http'\nimport {\n createHttpProvider,\n createRuntimeHttpProvider,\n type CredentialSource,\n} from '@alvin0/ai-agent-sdk-provider-http'\nimport {\n openAiResponsesProtocol,\n type ResponsesDialect,\n} from '@alvin0/ai-agent-sdk-protocol-responses'\nimport { openAiContextPolicy } from './context-policy.ts'\n\n/** The OpenAI API base. */\nexport const OPENAI_BASE_URL = 'https://api.openai.com/v1'\n\n/** How the API key is obtained. */\nexport type OpenAiCredential = CredentialSource\n\n/** Options for {@link openAiAdapter}. */\nexport interface OpenAiAdapterOptions {\n /** Injected API key or resolver. Universal packages never read environment variables. */\n apiKey: OpenAiCredential\n /**\n * Endpoint base; defaults to {@link OPENAI_BASE_URL}.\n *\n * Point this at a compatible gateway to reuse this provider wholesale.\n */\n baseUrl?: string\n /** Organization to bill, when the key belongs to several. */\n organization?: string\n /** Project to attribute usage to. */\n project?: string\n /**\n * Advisory model catalog.\n *\n * Empty by default: this package cannot know which model ids are current, and a\n * stale built-in list would name retired models. Supply entries to declare\n * capabilities the SDK cannot infer, such as image support.\n */\n models?: readonly ProviderCatalogModel[]\n /** Whether the provider may retain responses server-side. Defaults to false. */\n store?: boolean\n /** Output cap when neither caller nor catalog names one. */\n defaultMaxTokens?: number\n /** Context capacity assumed for an uncatalogued model. */\n defaultContextWindow?: number\n /** Idle bound while a stream read is outstanding. */\n streamIdleTimeoutMs?: number\n requestTimeoutMs?: number\n maxRequestBytes?: number\n maxResponseBytes?: number\n maxResponseChunks?: number\n maxSseEvents?: number\n maxSseEventChars?: number\n maxErrorBodyBytes?: number\n requestLoggerTimeoutMs?: number\n /** Retry policy this route owns. */\n retryPolicy?: RetryPolicyConfig\n /** Optional exact wire-request logger; credentials are redacted. */\n requestLogger?: ProviderRequestLogger\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Create an OpenAI adapter.\n * @param options - credential, endpoint, and catalog overrides.\n * @returns the adapter, ready to register.\n */\nexport function openAiAdapter(options: OpenAiAdapterOptions): HttpModelAdapter {\n const dialect: Partial<ResponsesDialect> = options.store === undefined\n ? {}\n : { store: options.store }\n\n return createHttpProvider({\n displayName: 'OpenAI',\n describeModel: openAiContextPolicy(options),\n protocol: openAiResponsesProtocol,\n baseUrl: options.baseUrl ?? OPENAI_BASE_URL,\n auth: {\n kind: 'bearer',\n token: options.apiKey,\n label: 'the `apiKey` option',\n },\n dialect,\n headers: {\n ...options.organization === undefined\n ? {}\n : { 'openai-organization': options.organization },\n ...options.project === undefined ? {} : { 'openai-project': options.project },\n },\n ...options.models === undefined ? {} : { models: options.models },\n defaultMaxTokens: options.defaultMaxTokens ?? 32_000,\n defaultContextWindow: options.defaultContextWindow ?? 128_000,\n ...options.streamIdleTimeoutMs === undefined\n ? {}\n : { streamIdleTimeoutMs: options.streamIdleTimeoutMs },\n ...transportLimits(options),\n ...options.retryPolicy === undefined ? {} : { retryPolicy: options.retryPolicy },\n ...options.requestLogger === undefined ? {} : { requestLogger: options.requestLogger },\n })\n}\n\nexport interface OpenAiPluginOptions extends OpenAiAdapterOptions {\n /** Registry routes installed by the plugin. Defaults to `['openai']`. */\n readonly routes?: readonly string[]\n}\n\nexport interface OpenAiProviderOptions extends Omit<OpenAiAdapterOptions, 'apiKey'> {\n readonly defaultModel?: string | ModelTarget\n readonly apiKey: CredentialInput\n readonly id?: string\n readonly routes?: readonly string[]\n}\n\n/** Preferred transactional plugin for installing the OpenAI provider. */\nexport function openAiPlugin(\n options: OpenAiProviderOptions,\n): ComposableModelProviderPlugin & { readonly family: 'openai' }\nexport function openAiPlugin(options: OpenAiPluginOptions): ModelProviderPlugin\nexport function openAiPlugin(\n options: OpenAiProviderOptions | OpenAiPluginOptions,\n): ModelProviderPlugin | (ComposableModelProviderPlugin & { readonly family: 'openai' }) {\n if (!usesRuntimeComposition(options)) return legacyOpenAiPlugin(options)\n const id = options.id ?? 'openai'\n const routes = Object.freeze([...(options.routes ?? [id])])\n return defineModelProviderPlugin({\n id,\n family: 'openai',\n displayName: 'OpenAI',\n routes,\n ...runtimeDefaultModel(options.defaultModel, routes),\n setup(registrar) {\n const adapter = createRuntimeOpenAiAdapter(options)\n const remove = registrar.registerAdapter(adapter)\n return () => { remove(); return undefined }\n },\n }) as ComposableModelProviderPlugin & { readonly family: 'openai' }\n}\n\nfunction legacyOpenAiPlugin(options: OpenAiPluginOptions): ModelProviderPlugin {\n const routes = Object.freeze([...(options.routes ?? ['openai'])])\n const adapter = openAiAdapter(options)\n return Object.freeze({\n id: 'openai',\n displayName: 'OpenAI',\n setup(registrar: ModelProviderRegistrar) {\n registrar.registerAdapter(routes, adapter)\n },\n })\n}\n\nfunction createRuntimeOpenAiAdapter(options: OpenAiProviderOptions): HttpModelAdapter {\n return createRuntimeHttpProvider({\n describeModel: openAiContextPolicy(options),\n displayName: 'OpenAI',\n protocol: openAiResponsesProtocol,\n baseUrl: options.baseUrl ?? OPENAI_BASE_URL,\n auth: { kind: 'bearer', token: options.apiKey, label: 'the `apiKey` option' },\n dialect: options.store === undefined ? {} : { store: options.store },\n headers: {\n ...(options.organization === undefined ? {} : { 'openai-organization': options.organization }),\n ...(options.project === undefined ? {} : { 'openai-project': options.project }),\n },\n ...(options.models === undefined ? {} : { models: options.models }),\n defaultMaxTokens: options.defaultMaxTokens ?? 32_000,\n defaultContextWindow: options.defaultContextWindow ?? 128_000,\n ...(options.streamIdleTimeoutMs === undefined ? {} : { streamIdleTimeoutMs: options.streamIdleTimeoutMs }),\n ...transportLimits(options),\n ...(options.retryPolicy === undefined ? {} : { retryPolicy: options.retryPolicy }),\n ...(options.requestLogger === undefined ? {} : { requestLogger: options.requestLogger }),\n })\n}\n\nfunction usesRuntimeComposition(\n options: OpenAiProviderOptions | OpenAiPluginOptions,\n): options is OpenAiProviderOptions {\n if ('id' in options || 'defaultModel' in options) return true\n if (typeof options.apiKey === 'object' && options.apiKey !== null) return true\n return typeof options.apiKey !== 'function'\n}\n\nfunction runtimeDefaultModel(\n value: string | ModelTarget | undefined,\n routes: readonly string[],\n): { readonly defaultModel?: ModelTarget } {\n if (value === undefined) return {}\n if (typeof value !== 'string') return { defaultModel: value }\n if (routes.length !== 1) {\n throw new TypeError('A string defaultModel requires exactly one OpenAI route')\n }\n return { defaultModel: Object.freeze({ provider: routes[0]!, id: value }) }\n}\n\nfunction transportLimits(options: OpenAiAdapterOptions | OpenAiProviderOptions) {\n return {\n ...options.requestTimeoutMs === undefined ? {} : { requestTimeoutMs: options.requestTimeoutMs },\n ...options.maxRequestBytes === undefined ? {} : { maxRequestBytes: options.maxRequestBytes },\n ...options.maxResponseBytes === undefined ? {} : { maxResponseBytes: options.maxResponseBytes },\n ...options.maxResponseChunks === undefined ? {} : { maxResponseChunks: options.maxResponseChunks },\n ...options.maxSseEvents === undefined ? {} : { maxSseEvents: options.maxSseEvents },\n ...options.maxSseEventChars === undefined ? {} : { maxSseEventChars: options.maxSseEventChars },\n ...options.maxErrorBodyBytes === undefined ? {} : { maxErrorBodyBytes: options.maxErrorBodyBytes },\n ...options.requestLoggerTimeoutMs === undefined ? {} : { requestLoggerTimeoutMs: options.requestLoggerTimeoutMs },\n ...options.fetch === undefined ? {} : { fetch: options.fetch },\n }\n}\n","/**\n * The OpenAI embeddings endpoint: `POST {baseUrl}/embeddings`.\n *\n * Deliberately a separate module from {@link ./adapter.ts}: it shares no protocol,\n * no dialect and no request vocabulary with `openAiResponsesProtocol`, and wiring\n * embedding through the generation pipeline would mean one of the two shapes\n * standing in for the other (Requirement 14.1). What the two DO share is the\n * transport — the fused signal, the redirect guard, the attempt ledger, the\n * attribution headers — because that chain is where a missing step is expensive.\n *\n * Three facts about this endpoint decide most of what is here, and each has a\n * plausible-looking wrong answer:\n *\n * - **There is no purpose parameter.** A route declares\n * `purposeHandling: 'unsupported'` and this adapter sends the caller's text\n * verbatim. Inventing a `\"query: \"` prefix would change every vector the caller\n * gets while looking like a helpful default (Requirement 7.5).\n * - **There is no truncation parameter.** `truncation: 'allow'` is therefore\n * refused with `EMBEDDING_TRUNCATION_UNSUPPORTED` rather than accepted and\n * quietly not honoured (Requirement 9.7).\n * - **`dimensions` is a model-line capability, not an endpoint one.** It goes on\n * the wire only when the route DECLARES the widths it supports; an `unknown`\n * catalog is not a licence to send a parameter an endpoint may reject\n * (Requirement 14.4).\n *\n * `baseUrl` is configurable because a self-hosted OpenAI-compatible endpoint is\n * the only mechanism this needs (Requirement 15.1). What it is NOT is an\n * inference: compatibility is a profile someone declared through\n * `EmbeddingCatalogModel`, never something read off the path, and a cleartext\n * `http://` base still requires `allowInsecureHttp` (Requirements 15.3, 15.5).\n *\n * @module ai-agent-sdk/providers/openai/embedding\n */\n\nimport { resolveRetryPolicy, type RetryPolicyConfig } from '@alvin0/ai-agent-sdk-core'\nimport {\n EMBEDDING_ERROR_CODES,\n EmbeddingAdapter,\n EmbeddingError,\n defaultEmbeddingProfile,\n deriveSpaceId,\n resolveBatchLimits,\n validateBatchResult,\n type EmbeddingBatchRequest,\n type EmbeddingBatchResult,\n type EmbeddingItem,\n type EmbeddingModelInfo,\n type EmbeddingProfile,\n type EmbeddingProfileInput,\n type EmbeddingVector,\n type PrepareEmbeddingOptions,\n type PreparedEmbeddingCall,\n type ResolvedEmbeddingModelInfo,\n} from '@alvin0/ai-agent-sdk-core/embedding'\nimport {\n defineEmbeddingProviderPlugin,\n type ComposableEmbeddingProviderPlugin,\n type CredentialInput,\n type ModelInvocationContext,\n type ProviderInfo,\n type ProviderRequestId,\n type ResolvedRetryPolicy,\n type SdkLogger,\n} from '@alvin0/ai-agent-sdk-core/provider'\nimport {\n captureTransportConnection,\n embeddingCatalogModelInfo,\n resolvedEmbeddingCatalogModelInfo,\n transportJson,\n type EmbeddingCatalogModel,\n type EmbeddingHttpConnection,\n} from '@alvin0/ai-agent-sdk-provider-http'\nimport { OPENAI_BASE_URL } from './adapter.ts'\n\n/** Display name used in every diagnostic this module raises. */\nconst DISPLAY_NAME = 'OpenAI'\n\n/** Path appended to the configured base. */\nconst EMBEDDINGS_PATH = '/embeddings'\n\n/** Media type this endpoint answers with, and the only one accepted back. */\nconst JSON_MEDIA_TYPE = 'application/json'\n\n/**\n * The one encoding this adapter asks for.\n *\n * Base64 would halve the bytes on the wire and cost a decode step that could\n * silently reorder or requantise values; float arrays are what the contract's\n * fidelity rule (Requirement 14.8) is cheapest to keep.\n */\nconst ENCODING_FORMAT = 'float'\n\n/**\n * Compatibility identity prefix for an OpenAI embedding model line.\n *\n * Route-independent on purpose: two routes pointing at the same model line — the\n * public API and a mirror of it — produce vectors in the SAME space, so keying\n * the identity on the route name would make them look incompatible.\n */\nconst IDENTITY_PREFIX = 'openai'\n\nconst NEVER_ABORTED_SIGNAL = new AbortController().signal\n\nconst NULL_LOGGER: SdkLogger = Object.freeze({\n child: () => NULL_LOGGER,\n trace: () => undefined,\n debug: () => undefined,\n info: () => undefined,\n warn: () => undefined,\n error: () => undefined,\n fatal: () => undefined,\n})\n\n/** Options for {@link openAiEmbeddingAdapter} and {@link openAiEmbeddingPlugin}. */\nexport interface OpenAiEmbeddingProviderOptions {\n /** Injected API key or credential source; universal packages never read the environment. */\n readonly apiKey: CredentialInput\n /**\n * Endpoint base; defaults to {@link OPENAI_BASE_URL}.\n *\n * Point this at a self-hosted OpenAI-compatible endpoint. Declare that\n * endpoint's models through {@link models}: the compatibility claim is the\n * configuration's, not this adapter's (Requirement 15.3).\n */\n readonly baseUrl?: string\n /** Organization to bill, when the key belongs to several. */\n readonly organization?: string\n /** Project to attribute usage to. */\n readonly project?: string\n /** Plugin id; also the default route. Defaults to `'openai'`. */\n readonly id?: string\n /** Registry routes the plugin claims. Defaults to `[id]`. */\n readonly routes?: readonly string[]\n /**\n * Advisory embedding catalog.\n *\n * Empty by default, for the same reason the generation adapter ships no model\n * list: a stale built-in catalog would name retired models. A declared entry is\n * what makes `dimensions` reachable on the wire and what states the embedding\n * space, so a route that cares about either declares its models.\n */\n readonly models?: readonly EmbeddingCatalogModel[]\n /** Permit cleartext HTTP explicitly, for trusted local endpoints only. */\n readonly allowInsecureHttp?: boolean\n readonly requestTimeoutMs?: number\n readonly maxRequestBytes?: number\n readonly maxResponseBytes?: number\n readonly maxResponseChunks?: number\n readonly maxErrorBodyBytes?: number\n readonly requestLoggerTimeoutMs?: number\n /** Retry policy this route owns. */\n readonly retryPolicy?: RetryPolicyConfig\n readonly fetch?: typeof globalThis.fetch\n}\n\n/**\n * `POST /embeddings` as an {@link EmbeddingAdapter}.\n *\n * Private: the exported surface is {@link openAiEmbeddingAdapter}, so this class\n * can change shape without a caller having come to depend on it.\n */\nclass OpenAiEmbeddingAdapter extends EmbeddingAdapter {\n private readonly baseUrl: string\n private readonly models: readonly EmbeddingCatalogModel[]\n private readonly retry: ResolvedRetryPolicy\n\n constructor(private readonly options: OpenAiEmbeddingProviderOptions) {\n super()\n this.baseUrl = (options.baseUrl ?? OPENAI_BASE_URL).replace(/\\/+$/, '')\n this.models = Object.freeze([...(options.models ?? [])])\n this.retry = resolveRetryPolicy(options.retryPolicy, 'openAiEmbedding.retryPolicy')\n }\n\n override providerInfo(provider: string): ProviderInfo {\n return { id: provider, name: DISPLAY_NAME }\n }\n\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return this.retry\n }\n\n override listEmbeddingModels(\n provider: string,\n signal?: AbortSignal,\n ): Promise<readonly EmbeddingModelInfo[]> {\n signal?.throwIfAborted()\n return Promise.resolve(Object.freeze(\n this.models.map(model => embeddingCatalogModelInfo(provider, model)),\n ))\n }\n\n override resolveEmbeddingModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<ResolvedEmbeddingModelInfo> {\n signal?.throwIfAborted()\n return Promise.resolve(resolvedEmbeddingCatalogModelInfo(provider, model, this.models))\n }\n\n /**\n * States what this model line declares about its embedding space.\n *\n * Overridden rather than inherited because the default answer is derived from\n * `${route}:${modelId}`, which makes one model line look like two spaces when\n * it is reachable through two routes. Two things differ here: the identity is\n * the model line's (see {@link IDENTITY_PREFIX}), and normalization is reported\n * only when the ROUTE declared it — never inferred from OpenAI's reputation for\n * returning unit vectors (Requirements 6.1, 6.3).\n */\n override embeddingProfile(\n model: ResolvedEmbeddingModelInfo,\n request: EmbeddingProfileInput,\n ): EmbeddingProfile {\n const base = defaultEmbeddingProfile(model, request)\n return Object.freeze({\n ...base,\n compatibilityIdentity: model.compatibilityIdentity.state === 'supported'\n ? model.compatibilityIdentity.value\n : `${IDENTITY_PREFIX}:${model.id}`,\n normalization: model.normalization.state === 'supported'\n ? model.normalization.value\n : base.normalization,\n })\n }\n\n /**\n * Captures endpoint, credential and bounds ONCE, then binds dispatch to that\n * capture.\n *\n * Overridden because this adapter's connection facts come from configuration\n * and a credential resolved per operation: reading them again inside\n * `embedBatch()` would let a rotating secret pair with another generation's URL,\n * and would let dimensions be validated against one catalog while the request\n * went out under another (Requirements 2.2, 2.3, 2.4).\n */\n override async prepareEmbeddingCall(\n provider: string,\n model: string,\n options: PrepareEmbeddingOptions,\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n ): Promise<PreparedEmbeddingCall> {\n const connection = await this.connect(signal, context)\n const resolved = resolvedEmbeddingCatalogModelInfo(provider, model, connection.models)\n const profile = this.embeddingProfile(resolved, options)\n return Object.freeze({\n model: resolved,\n profile,\n spaceId: deriveSpaceId(profile),\n limits: resolveBatchLimits(resolved, options.limits),\n embedBatch: (batch: EmbeddingBatchRequest, invocation = context) =>\n this.dispatch(connection, resolved, batch, invocation),\n })\n }\n\n /**\n * One `Physical_Batch`, one `Provider_Attempt`.\n *\n * Reachable directly for an adapter used without a prepared call; the shared\n * path is {@link dispatch}, so both routes send the same body under the same\n * guards.\n */\n override async embedBatch(\n batch: EmbeddingBatchRequest,\n context?: ModelInvocationContext,\n ): Promise<EmbeddingBatchResult> {\n const connection = await this.connect(batch.signal, context)\n const model = resolvedEmbeddingCatalogModelInfo(\n batch.provider,\n batch.model,\n connection.models,\n )\n return this.dispatch(connection, model, batch, context)\n }\n\n /** Everything one embedding request needs, read together, once per operation. */\n private async connect(\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n ): Promise<EmbeddingHttpConnection> {\n const token = await resolveApiKey(this.options.apiKey, signal, context)\n // The credential and the endpoint-scoped account headers travel together as\n // the auth layer; the transport merges its own layer and attribution on top,\n // which is what makes attribution unforgettable (Requirement 14.7).\n const headers: Record<string, string> = { authorization: `Bearer ${token}` }\n if (this.options.organization !== undefined) {\n headers['openai-organization'] = this.options.organization\n }\n if (this.options.project !== undefined) {\n headers['openai-project'] = this.options.project\n }\n return Object.freeze({\n baseUrl: this.baseUrl,\n headers: Object.freeze(headers),\n sensitiveHeaderNames: Object.freeze(Object.keys(headers)),\n models: this.models,\n retryPolicy: this.retry,\n ...(this.options.allowInsecureHttp === undefined\n ? {}\n : { allowInsecureHttp: this.options.allowInsecureHttp }),\n ...(this.options.requestTimeoutMs === undefined\n ? {}\n : { requestTimeoutMs: this.options.requestTimeoutMs }),\n ...(this.options.maxRequestBytes === undefined\n ? {}\n : { maxRequestBytes: this.options.maxRequestBytes }),\n ...(this.options.maxResponseBytes === undefined\n ? {}\n : { maxResponseBytes: this.options.maxResponseBytes }),\n ...(this.options.maxResponseChunks === undefined\n ? {}\n : { maxResponseChunks: this.options.maxResponseChunks }),\n ...(this.options.maxErrorBodyBytes === undefined\n ? {}\n : { maxErrorBodyBytes: this.options.maxErrorBodyBytes }),\n ...(this.options.requestLoggerTimeoutMs === undefined\n ? {}\n : { requestLoggerTimeoutMs: this.options.requestLoggerTimeoutMs }),\n ...(this.options.fetch === undefined ? {} : { fetch: this.options.fetch }),\n })\n }\n\n /** Serialize, send through the shared chain, and map the parsed body back. */\n private async dispatch(\n connection: EmbeddingHttpConnection,\n model: ResolvedEmbeddingModelInfo,\n batch: EmbeddingBatchRequest,\n context?: ModelInvocationContext,\n ): Promise<EmbeddingBatchResult> {\n if (batch.truncation === 'allow') {\n // Accepting this would promise a behaviour nothing on this wire can express.\n throw new EmbeddingError(\n `${DISPLAY_NAME} embeddings exposes no truncation parameter`,\n EMBEDDING_ERROR_CODES.TRUNCATION_UNSUPPORTED,\n { provider: batch.provider, model: batch.model },\n )\n }\n\n const body: Record<string, unknown> = {\n model: batch.model,\n // One element per item, in item order. The purpose does NOT appear here:\n // this endpoint has no parameter for it and no prefix is invented.\n input: batch.items.map(itemInput),\n encoding_format: ENCODING_FORMAT,\n }\n // Declared widths only. An `unknown` capability states nothing, and sending a\n // parameter on the strength of nothing is how a compatible endpoint 400s.\n if (batch.dimensions !== undefined && model.dimensions.state === 'supported') {\n body['dimensions'] = batch.dimensions\n }\n\n const encoded = JSON.stringify(body)\n // `decode` extracts the payload and NOTHING else. The shared chain normalizes\n // anything thrown inside `decode` through `normalizeHttpBoundaryError`, which\n // has no data twin to read off an `EmbeddingError` and would flatten every\n // stable embedding code into `ModelError{code:'UNKNOWN'}`. Validating after\n // `transportJson` returns is what lets `EMBEDDING_VECTOR_COUNT_MISMATCH` and\n // its siblings reach the caller as themselves (Requirement 9.3–9.5).\n const received = await transportJson({\n connection: captureTransportConnection(connection, {\n 'content-type': JSON_MEDIA_TYPE,\n accept: JSON_MEDIA_TYPE,\n }),\n displayName: DISPLAY_NAME,\n provider: batch.provider,\n model: batch.model,\n path: EMBEDDINGS_PATH,\n accept: JSON_MEDIA_TYPE,\n body: {\n value: body,\n encoded,\n bytes: new TextEncoder().encode(encoded).length,\n },\n ...(batch.signal === undefined ? {} : { signal: batch.signal }),\n ...(context === undefined ? {} : { context }),\n }, (session, payload) => Object.freeze({\n payload,\n ...(session.providerRequestId === undefined\n ? {}\n : { providerRequestId: session.providerRequestId }),\n }))\n return decodeEmbeddingResponse(batch, received)\n }\n}\n\n/** A response body that cleared every transport guard, plus its correlation id. */\ninterface ReceivedEmbeddingResponse {\n readonly payload: unknown\n readonly providerRequestId?: ProviderRequestId\n}\n\n/**\n * Concatenates one item's content parts into a single wire input.\n *\n * The rule is recorded as `documentRecipeRevision` on the profile, and revision\n * `'1'` is exactly this: the text of each part, in order, with no separator and no\n * added markup. It matches the effective text the contract's own length check and\n * cache key derive, so a batch split, a rejection and a wire body can never\n * disagree about what an item's text is. One item produces one element, so the\n * provider returns exactly one vector for it (Requirement 8.7).\n */\nfunction itemInput(item: EmbeddingItem): string {\n let text = ''\n for (const part of item.contentParts) {\n if (part.type === 'text') text += part.text\n }\n return text\n}\n\n/**\n * Maps one parsed response body onto the batch that produced it, in ONE fixed\n * order.\n *\n * The order is the contract, not an implementation detail — the same malformed\n * response has to produce the same code here as it does for every other provider,\n * which is what lets a single conformance suite judge all of them:\n *\n * 1. a shape this contract does not recognise ⇒ `RESPONSE_MALFORMED`\n * 2. `data.length !== items.length` ⇒ `VECTOR_COUNT_MISMATCH`\n * 3. `{ data[i].index }` is not a permutation of `0..N-1` ⇒ `VECTOR_INDEX_INVALID`\n * 4. a non-finite element ⇒ `VECTOR_VALUE_INVALID`\n * 5. a width other than the one requested ⇒ `VECTOR_DIMENSIONS_MISMATCH`\n *\n * Steps 4 and 5 are delegated to the shared {@link validateBatchResult}, which\n * already runs them in exactly this order; re-deriving them here would be a second\n * place for the ordering to drift.\n *\n * The count check comes FIRST on purpose. Reading the entries one at a time and\n * refusing the first bad index would report a mapping failure for a response whose\n * real fault is that it answered a different number of inputs — two different\n * repairs for a caller, told apart by which check ran first.\n *\n * Nothing here slices, pads, sorts or repairs a value. The `index` a vector carries\n * out is the item's index in the `Logical_Call`, taken from `items[data[i].index]`,\n * never its position in this batch (Requirement 8.4).\n */\nfunction decodeEmbeddingResponse(\n batch: EmbeddingBatchRequest,\n received: ReceivedEmbeddingResponse,\n): EmbeddingBatchResult {\n const entries = readEntries(batch, received.payload)\n checkEntryCount(batch, entries)\n const positions = readPositions(batch, entries)\n const vectors: EmbeddingVector[] = entries.map((entry, at) => Object.freeze({\n // The item's index in the `Logical_Call`, not its position in this batch.\n index: batch.items[positions[at]!]!.index,\n values: readValues(batch, entry),\n }))\n const usage = readUsage(received.payload)\n const result: EmbeddingBatchResult = Object.freeze({\n vectors: Object.freeze(vectors),\n ...(usage === undefined ? {} : { usage }),\n ...(received.providerRequestId === undefined\n ? {}\n : { providerRequestId: received.providerRequestId }),\n })\n // Steps 4 and 5, plus the count and logical-index invariants restated against\n // the `Logical_Call` indexes this result now carries.\n validateBatchResult(batch, result)\n return result\n}\n\n/** A `data` array of objects, or a structural refusal naming the batch it belongs to. */\nfunction readEntries(\n batch: EmbeddingBatchRequest,\n payload: unknown,\n): readonly Readonly<Record<string, unknown>>[] {\n const data = record(payload)?.['data']\n if (!Array.isArray(data)) throw malformed(batch, 'response carries no `data` array')\n return data.map(entry => {\n const source = record(entry)\n if (source === undefined) throw malformed(batch, 'response `data` entry is not an object')\n return source\n })\n}\n\n/** Step 2: one vector per input sent, counted before anything is interpreted. */\nfunction checkEntryCount(\n batch: EmbeddingBatchRequest,\n entries: readonly unknown[],\n): void {\n if (entries.length === batch.items.length) return\n throw new EmbeddingError(\n `${DISPLAY_NAME} returned ${entries.length} vectors for ${batch.items.length} inputs`,\n EMBEDDING_ERROR_CODES.VECTOR_COUNT_MISMATCH,\n { provider: batch.provider, model: batch.model },\n )\n}\n\n/**\n * Step 3: the reported positions, once they are known to be a permutation of\n * `0..N-1`.\n *\n * A duplicate, a gap, a non-integer and an out-of-range value all land in the same\n * refusal, because they all break the same thing: without a bijection between\n * response entries and batch items, restoring input order would be guesswork, and\n * a position to \"fall back on\" would silently attach one input's vector to another\n * (Requirement 8.2).\n */\nfunction readPositions(\n batch: EmbeddingBatchRequest,\n entries: readonly Readonly<Record<string, unknown>>[],\n): readonly number[] {\n const positions: number[] = []\n const seen = new Set<number>()\n for (const entry of entries) {\n const position = entry['index']\n if (typeof position !== 'number' || !Number.isInteger(position)\n || position < 0 || position >= batch.items.length || seen.has(position)) {\n throw new EmbeddingError(\n `${DISPLAY_NAME} returned a duplicate, missing or out-of-range vector index`,\n EMBEDDING_ERROR_CODES.VECTOR_INDEX_INVALID,\n { provider: batch.provider, model: batch.model },\n )\n }\n seen.add(position)\n positions.push(position)\n }\n return positions\n}\n\n/**\n * Reads one `embedding` array with every number exactly as it arrived.\n *\n * Only the SHAPE is judged here: a non-finite or non-numeric element is step 4's\n * business, so it travels through untouched and is refused by\n * {@link validateBatchResult} under `VECTOR_VALUE_INVALID` rather than being\n * repaired, dropped, or relabelled as a malformed shape.\n */\nfunction readValues(\n batch: EmbeddingBatchRequest,\n entry: Readonly<Record<string, unknown>>,\n): readonly number[] {\n const values = entry['embedding']\n if (!Array.isArray(values)) {\n throw malformed(batch, 'response vector is not an array')\n }\n return Object.freeze([...values as readonly number[]])\n}\n\n/**\n * Maps `prompt_tokens` and `total_tokens` onto the two embedding counters.\n *\n * There is no `outputTokens`, which is why embedding reports\n * `EmbeddingTokenUsage` rather than generation's `TokenUsage`. A counter that is\n * absent or unreadable stays ABSENT: a zero here would be indistinguishable from\n * a provider that reported no cost at all.\n */\nfunction readUsage(payload: unknown): { inputTokens?: number; totalTokens?: number } | undefined {\n const usage = record(record(payload)?.['usage'])\n if (usage === undefined) return undefined\n const inputTokens = usage['prompt_tokens']\n const totalTokens = usage['total_tokens']\n const counters = {\n ...(typeof inputTokens === 'number' ? { inputTokens } : {}),\n ...(typeof totalTokens === 'number' ? { totalTokens } : {}),\n }\n return Reflect.ownKeys(counters).length === 0 ? undefined : counters\n}\n\n/** A plain-record view of an unknown value, or `undefined`. */\nfunction record(value: unknown): Readonly<Record<string, unknown>> | undefined {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined\n return value as Readonly<Record<string, unknown>>\n}\n\n/** A structural refusal: the response is not a shape this contract recognises. */\nfunction malformed(batch: EmbeddingBatchRequest, detail: string): EmbeddingError {\n return new EmbeddingError(\n `${DISPLAY_NAME} embeddings ${detail}`,\n EMBEDDING_ERROR_CODES.RESPONSE_MALFORMED,\n { provider: batch.provider, model: batch.model },\n )\n}\n\n/** Resolves a literal key or a credential source, once per operation. */\nasync function resolveApiKey(\n apiKey: CredentialInput,\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n): Promise<string> {\n const value = typeof apiKey === 'string'\n ? apiKey\n : await apiKey.resolve({\n signal: signal ?? NEVER_ABORTED_SIGNAL,\n logger: context?.logger ?? NULL_LOGGER,\n })\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new EmbeddingError(\n `${DISPLAY_NAME} embeddings requires a non-empty \\`apiKey\\``,\n EMBEDDING_ERROR_CODES.CONFIGURATION_INVALID,\n )\n }\n return value\n}\n\n/**\n * Create an OpenAI embedding adapter.\n * @param options - credential, endpoint, catalog and transport bounds.\n * @returns the adapter, ready to register on an embedding route.\n */\nexport function openAiEmbeddingAdapter(\n options: OpenAiEmbeddingProviderOptions,\n): EmbeddingAdapter {\n return new OpenAiEmbeddingAdapter(options)\n}\n\n/**\n * Preferred transactional plugin for installing OpenAI embeddings.\n *\n * Its `kind` is `'embedding-provider-plugin'`, so it installs beside\n * {@link openAiPlugin} on the same route without either standing in for the other.\n * @param options - credential, endpoint, catalog and transport bounds.\n * @returns an inert plugin; the adapter is constructed during activation.\n */\nexport function openAiEmbeddingPlugin(\n options: OpenAiEmbeddingProviderOptions,\n): ComposableEmbeddingProviderPlugin & { readonly family: 'openai' } {\n const id = options.id ?? 'openai'\n const routes = Object.freeze([...(options.routes ?? [id])])\n return defineEmbeddingProviderPlugin({\n id,\n family: 'openai',\n displayName: DISPLAY_NAME,\n routes,\n setup(registrar) {\n const remove = registrar.registerEmbeddingAdapter(openAiEmbeddingAdapter(options))\n return () => {\n remove()\n return undefined\n }\n },\n }) as ComposableEmbeddingProviderPlugin & { readonly family: 'openai' }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["openAiResponsesProtocol"],"sources":["../src/context-policy.ts","../src/adapter.ts","../src/embedding.ts"],"sourcesContent":["import { createModelContextPolicy } from '@alvin0/ai-agent-sdk-provider-http'\nimport type { ModelContextPolicyOptions } from '@alvin0/ai-agent-sdk-provider-http'\n\n// Verified 2026-09-13: https://developers.openai.com/api/docs/models/gpt-5.6-luna\n// https://developers.openai.com/api/docs/models/gpt-5.6-sol\n// https://developers.openai.com/api/docs/models/gpt-5.6-terra\nconst GPT_56 = { defaultContextWindow: 272_000, maxContextWindow: 1_050_000, standardPriceInputTokens: 272_000 }\nexport function openAiContextPolicy(options: ModelContextPolicyOptions) {\n return createModelContextPolicy(\n options.baseUrl === undefined || options.baseUrl.replace(/\\/$/, '') === 'https://api.openai.com/v1'\n ? { 'gpt-5.6-luna': GPT_56, 'gpt-5.6-sol': GPT_56, 'gpt-5.6-terra': GPT_56 }\n : {}, options.models, options.defaultContextWindow)\n}\n","/**\n * The OpenAI provider: the Responses API on `api.openai.com`.\n *\n * Note how little there is here. Every endpoint fact is configuration handed to\n * {@link createHttpProvider}; the protocol, the pipeline, and the error mapping are\n * all shared. That is the intended shape for any endpoint speaking a protocol this\n * package already implements — including your own gateway.\n *\n * @module ai-agent-sdk/providers/openai/adapter\n */\n\nimport type { ModelProviderPlugin, ModelProviderRegistrar, RetryPolicyConfig } from '@alvin0/ai-agent-sdk-core'\nimport {\n defineModelProviderPlugin,\n type ComposableModelProviderPlugin,\n type CredentialInput,\n type ModelTarget,\n} from '@alvin0/ai-agent-sdk-core/provider'\nimport type {\n HttpModelAdapter,\n ProviderCatalogModel,\n ProviderRequestLogger,\n} from '@alvin0/ai-agent-sdk-provider-http'\nimport {\n createHttpProvider,\n endpointHeaders,\n createRuntimeHttpProvider,\n type CredentialSource,\n} from '@alvin0/ai-agent-sdk-provider-http'\nimport {\n openAiResponsesProtocol,\n type ResponsesDialect,\n} from '@alvin0/ai-agent-sdk-protocol-responses'\nimport { openAiContextPolicy } from './context-policy.ts'\n\n/** The OpenAI API base. */\nexport const OPENAI_BASE_URL = 'https://api.openai.com/v1'\n\n/** How the API key is obtained. */\nexport type OpenAiCredential = CredentialSource\n\n/** Options for {@link openAiAdapter}. */\nexport interface OpenAiAdapterOptions {\n /** Injected API key or resolver. Universal packages never read environment variables. */\n apiKey: OpenAiCredential\n /**\n * Endpoint base; defaults to {@link OPENAI_BASE_URL}.\n *\n * Point this at a compatible gateway to reuse this provider wholesale.\n */\n baseUrl?: string\n /** Extra endpoint headers, captured once per operation. Reserved names and collisions fail. */\n headers?: Readonly<Record<string, string>> | (() => Readonly<Record<string, string>>)\n /** Permit cleartext HTTP explicitly for trusted local gateways. */\n allowInsecureHttp?: boolean\n /** Organization to bill, when the key belongs to several. */\n organization?: string\n /** Project to attribute usage to. */\n project?: string\n /**\n * Advisory model catalog.\n *\n * Empty by default: this package cannot know which model ids are current, and a\n * stale built-in list would name retired models. Supply entries to declare\n * capabilities the SDK cannot infer, such as image support.\n */\n models?: readonly ProviderCatalogModel[]\n /** Whether the provider may retain responses server-side. Defaults to false. */\n store?: boolean\n /** Output cap when neither caller nor catalog names one. */\n defaultMaxTokens?: number\n /** Context capacity assumed for an uncatalogued model. */\n defaultContextWindow?: number\n /** Idle bound while a stream read is outstanding. */\n streamIdleTimeoutMs?: number\n requestTimeoutMs?: number\n maxRequestBytes?: number\n maxResponseBytes?: number\n maxResponseChunks?: number\n maxSseEvents?: number\n maxSseEventChars?: number\n maxErrorBodyBytes?: number\n requestLoggerTimeoutMs?: number\n /** Retry policy this route owns. */\n retryPolicy?: RetryPolicyConfig\n /** Optional exact wire-request logger; credentials are redacted. */\n requestLogger?: ProviderRequestLogger\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Create an OpenAI adapter.\n * @param options - credential, endpoint, and catalog overrides.\n * @returns the adapter, ready to register.\n */\nexport function openAiAdapter(options: OpenAiAdapterOptions): HttpModelAdapter {\n const dialect: Partial<ResponsesDialect> = options.store === undefined\n ? {}\n : { store: options.store }\n\n return createHttpProvider({\n displayName: 'OpenAI',\n describeModel: openAiContextPolicy(options),\n protocol: openAiResponsesProtocol,\n baseUrl: options.baseUrl ?? OPENAI_BASE_URL,\n auth: {\n kind: 'bearer',\n token: options.apiKey,\n label: 'the `apiKey` option',\n },\n dialect,\n headers: endpointHeaders(options.headers, {\n ...options.organization === undefined\n ? {}\n : { 'openai-organization': options.organization },\n ...options.project === undefined ? {} : { 'openai-project': options.project },\n }),\n ...options.models === undefined ? {} : { models: options.models },\n defaultMaxTokens: options.defaultMaxTokens ?? 32_000,\n defaultContextWindow: options.defaultContextWindow ?? 128_000,\n ...options.streamIdleTimeoutMs === undefined\n ? {}\n : { streamIdleTimeoutMs: options.streamIdleTimeoutMs },\n ...transportLimits(options),\n ...options.retryPolicy === undefined ? {} : { retryPolicy: options.retryPolicy },\n ...options.requestLogger === undefined ? {} : { requestLogger: options.requestLogger },\n })\n}\n\nexport interface OpenAiPluginOptions extends OpenAiAdapterOptions {\n /** Registry routes installed by the plugin. Defaults to `['openai']`. */\n readonly routes?: readonly string[]\n}\n\nexport interface OpenAiProviderOptions extends Omit<OpenAiAdapterOptions, 'apiKey'> {\n readonly defaultModel?: string | ModelTarget\n readonly apiKey: CredentialInput\n readonly id?: string\n readonly routes?: readonly string[]\n}\n\n/** Preferred transactional plugin for installing the OpenAI provider. */\nexport function openAiPlugin(\n options: OpenAiProviderOptions,\n): ComposableModelProviderPlugin & { readonly family: 'openai' }\nexport function openAiPlugin(options: OpenAiPluginOptions): ModelProviderPlugin\nexport function openAiPlugin(\n options: OpenAiProviderOptions | OpenAiPluginOptions,\n): ModelProviderPlugin | (ComposableModelProviderPlugin & { readonly family: 'openai' }) {\n if (!usesRuntimeComposition(options)) return legacyOpenAiPlugin(options)\n const id = options.id ?? 'openai'\n const routes = Object.freeze([...(options.routes ?? [id])])\n return defineModelProviderPlugin({\n id,\n family: 'openai',\n displayName: 'OpenAI',\n routes,\n ...runtimeDefaultModel(options.defaultModel, routes),\n setup(registrar) {\n const adapter = createRuntimeOpenAiAdapter(options)\n const remove = registrar.registerAdapter(adapter)\n return () => { remove(); return undefined }\n },\n }) as ComposableModelProviderPlugin & { readonly family: 'openai' }\n}\n\nfunction legacyOpenAiPlugin(options: OpenAiPluginOptions): ModelProviderPlugin {\n const routes = Object.freeze([...(options.routes ?? ['openai'])])\n const adapter = openAiAdapter(options)\n return Object.freeze({\n id: 'openai',\n displayName: 'OpenAI',\n setup(registrar: ModelProviderRegistrar) {\n registrar.registerAdapter(routes, adapter)\n },\n })\n}\n\nfunction createRuntimeOpenAiAdapter(options: OpenAiProviderOptions): HttpModelAdapter {\n return createRuntimeHttpProvider({\n describeModel: openAiContextPolicy(options),\n displayName: 'OpenAI',\n protocol: openAiResponsesProtocol,\n baseUrl: options.baseUrl ?? OPENAI_BASE_URL,\n auth: { kind: 'bearer', token: options.apiKey, label: 'the `apiKey` option' },\n dialect: options.store === undefined ? {} : { store: options.store },\n headers: endpointHeaders(options.headers, {\n ...(options.organization === undefined ? {} : { 'openai-organization': options.organization }),\n ...(options.project === undefined ? {} : { 'openai-project': options.project }),\n }),\n ...(options.models === undefined ? {} : { models: options.models }),\n defaultMaxTokens: options.defaultMaxTokens ?? 32_000,\n defaultContextWindow: options.defaultContextWindow ?? 128_000,\n ...(options.streamIdleTimeoutMs === undefined ? {} : { streamIdleTimeoutMs: options.streamIdleTimeoutMs }),\n ...transportLimits(options),\n ...(options.retryPolicy === undefined ? {} : { retryPolicy: options.retryPolicy }),\n ...(options.requestLogger === undefined ? {} : { requestLogger: options.requestLogger }),\n })\n}\n\nfunction usesRuntimeComposition(\n options: OpenAiProviderOptions | OpenAiPluginOptions,\n): options is OpenAiProviderOptions {\n if ('id' in options || 'defaultModel' in options) return true\n if (typeof options.apiKey === 'object' && options.apiKey !== null) return true\n return typeof options.apiKey !== 'function'\n}\n\nfunction runtimeDefaultModel(\n value: string | ModelTarget | undefined,\n routes: readonly string[],\n): { readonly defaultModel?: ModelTarget } {\n if (value === undefined) return {}\n if (typeof value !== 'string') return { defaultModel: value }\n if (routes.length !== 1) {\n throw new TypeError('A string defaultModel requires exactly one OpenAI route')\n }\n return { defaultModel: Object.freeze({ provider: routes[0]!, id: value }) }\n}\n\nfunction transportLimits(options: OpenAiAdapterOptions | OpenAiProviderOptions) {\n return {\n ...(options.allowInsecureHttp === undefined ? {} : { allowInsecureHttp: options.allowInsecureHttp }),\n ...options.requestTimeoutMs === undefined ? {} : { requestTimeoutMs: options.requestTimeoutMs },\n ...options.maxRequestBytes === undefined ? {} : { maxRequestBytes: options.maxRequestBytes },\n ...options.maxResponseBytes === undefined ? {} : { maxResponseBytes: options.maxResponseBytes },\n ...options.maxResponseChunks === undefined ? {} : { maxResponseChunks: options.maxResponseChunks },\n ...options.maxSseEvents === undefined ? {} : { maxSseEvents: options.maxSseEvents },\n ...options.maxSseEventChars === undefined ? {} : { maxSseEventChars: options.maxSseEventChars },\n ...options.maxErrorBodyBytes === undefined ? {} : { maxErrorBodyBytes: options.maxErrorBodyBytes },\n ...options.requestLoggerTimeoutMs === undefined ? {} : { requestLoggerTimeoutMs: options.requestLoggerTimeoutMs },\n ...options.fetch === undefined ? {} : { fetch: options.fetch },\n }\n}\n","/**\n * The OpenAI embeddings endpoint: `POST {baseUrl}/embeddings`.\n *\n * Deliberately a separate module from {@link ./adapter.ts}: it shares no protocol,\n * no dialect and no request vocabulary with `openAiResponsesProtocol`, and wiring\n * embedding through the generation pipeline would mean one of the two shapes\n * standing in for the other (Requirement 14.1). What the two DO share is the\n * transport — the fused signal, the redirect guard, the attempt ledger, the\n * attribution headers — because that chain is where a missing step is expensive.\n *\n * Three facts about this endpoint decide most of what is here, and each has a\n * plausible-looking wrong answer:\n *\n * - **There is no purpose parameter.** A route declares\n * `purposeHandling: 'unsupported'` and this adapter sends the caller's text\n * verbatim. Inventing a `\"query: \"` prefix would change every vector the caller\n * gets while looking like a helpful default (Requirement 7.5).\n * - **There is no truncation parameter.** `truncation: 'allow'` is therefore\n * refused with `EMBEDDING_TRUNCATION_UNSUPPORTED` rather than accepted and\n * quietly not honoured (Requirement 9.7).\n * - **`dimensions` is a model-line capability, not an endpoint one.** It goes on\n * the wire only when the route DECLARES the widths it supports; an `unknown`\n * catalog is not a licence to send a parameter an endpoint may reject\n * (Requirement 14.4).\n *\n * `baseUrl` is configurable because a self-hosted OpenAI-compatible endpoint is\n * the only mechanism this needs (Requirement 15.1). What it is NOT is an\n * inference: compatibility is a profile someone declared through\n * `EmbeddingCatalogModel`, never something read off the path, and a cleartext\n * `http://` base still requires `allowInsecureHttp` (Requirements 15.3, 15.5).\n *\n * @module ai-agent-sdk/providers/openai/embedding\n */\n\nimport { resolveRetryPolicy, type RetryPolicyConfig } from '@alvin0/ai-agent-sdk-core'\nimport {\n EMBEDDING_ERROR_CODES,\n EmbeddingAdapter,\n EmbeddingError,\n defaultEmbeddingProfile,\n deriveSpaceId,\n resolveBatchLimits,\n validateBatchResult,\n type EmbeddingBatchRequest,\n type EmbeddingBatchResult,\n type EmbeddingItem,\n type EmbeddingModelInfo,\n type EmbeddingProfile,\n type EmbeddingProfileInput,\n type EmbeddingVector,\n type PrepareEmbeddingOptions,\n type PreparedEmbeddingCall,\n type ResolvedEmbeddingModelInfo,\n} from '@alvin0/ai-agent-sdk-core/embedding'\nimport {\n defineEmbeddingProviderPlugin,\n type ComposableEmbeddingProviderPlugin,\n type CredentialInput,\n type ModelInvocationContext,\n type ProviderInfo,\n type ProviderRequestId,\n type ResolvedRetryPolicy,\n type SdkLogger,\n} from '@alvin0/ai-agent-sdk-core/provider'\nimport {\n captureTransportConnection,\n endpointHeaders,\n embeddingCatalogModelInfo,\n resolvedEmbeddingCatalogModelInfo,\n transportJson,\n type EmbeddingCatalogModel,\n type EmbeddingHttpConnection,\n} from '@alvin0/ai-agent-sdk-provider-http'\nimport { OPENAI_BASE_URL } from './adapter.ts'\n\n/** Display name used in every diagnostic this module raises. */\nconst DISPLAY_NAME = 'OpenAI'\n\n/** Path appended to the configured base. */\nconst EMBEDDINGS_PATH = '/embeddings'\n\n/** Media type this endpoint answers with, and the only one accepted back. */\nconst JSON_MEDIA_TYPE = 'application/json'\n\n/**\n * The one encoding this adapter asks for.\n *\n * Base64 would halve the bytes on the wire and cost a decode step that could\n * silently reorder or requantise values; float arrays are what the contract's\n * fidelity rule (Requirement 14.8) is cheapest to keep.\n */\nconst ENCODING_FORMAT = 'float'\n\n/**\n * Compatibility identity prefix for an OpenAI embedding model line.\n *\n * Route-independent on purpose: two routes pointing at the same model line — the\n * public API and a mirror of it — produce vectors in the SAME space, so keying\n * the identity on the route name would make them look incompatible.\n */\nconst IDENTITY_PREFIX = 'openai'\n\nconst NEVER_ABORTED_SIGNAL = new AbortController().signal\n\nconst NULL_LOGGER: SdkLogger = Object.freeze({\n child: () => NULL_LOGGER,\n trace: () => undefined,\n debug: () => undefined,\n info: () => undefined,\n warn: () => undefined,\n error: () => undefined,\n fatal: () => undefined,\n})\n\n/** Options for {@link openAiEmbeddingAdapter} and {@link openAiEmbeddingPlugin}. */\nexport interface OpenAiEmbeddingProviderOptions {\n /** Injected API key or credential source; universal packages never read the environment. */\n readonly apiKey: CredentialInput\n /** Extra endpoint headers, captured once per logical call; reserved names fail. */\n readonly headers?: Readonly<Record<string, string>> | (() => Readonly<Record<string, string>>)\n /**\n * Endpoint base; defaults to {@link OPENAI_BASE_URL}.\n *\n * Point this at a self-hosted OpenAI-compatible endpoint. Declare that\n * endpoint's models through {@link models}: the compatibility claim is the\n * configuration's, not this adapter's (Requirement 15.3).\n */\n readonly baseUrl?: string\n /** Organization to bill, when the key belongs to several. */\n readonly organization?: string\n /** Project to attribute usage to. */\n readonly project?: string\n /** Plugin id; also the default route. Defaults to `'openai'`. */\n readonly id?: string\n /** Registry routes the plugin claims. Defaults to `[id]`. */\n readonly routes?: readonly string[]\n /**\n * Advisory embedding catalog.\n *\n * Empty by default, for the same reason the generation adapter ships no model\n * list: a stale built-in catalog would name retired models. A declared entry is\n * what makes `dimensions` reachable on the wire and what states the embedding\n * space, so a route that cares about either declares its models.\n */\n readonly models?: readonly EmbeddingCatalogModel[]\n /** Permit cleartext HTTP explicitly, for trusted local endpoints only. */\n readonly allowInsecureHttp?: boolean\n readonly requestTimeoutMs?: number\n readonly maxRequestBytes?: number\n readonly maxResponseBytes?: number\n readonly maxResponseChunks?: number\n readonly maxErrorBodyBytes?: number\n readonly requestLoggerTimeoutMs?: number\n /** Retry policy this route owns. */\n readonly retryPolicy?: RetryPolicyConfig\n readonly fetch?: typeof globalThis.fetch\n}\n\n/**\n * `POST /embeddings` as an {@link EmbeddingAdapter}.\n *\n * Private: the exported surface is {@link openAiEmbeddingAdapter}, so this class\n * can change shape without a caller having come to depend on it.\n */\nclass OpenAiEmbeddingAdapter extends EmbeddingAdapter {\n private readonly baseUrl: string\n private readonly models: readonly EmbeddingCatalogModel[]\n private readonly retry: ResolvedRetryPolicy\n private readonly headers: () => Readonly<Record<string, string>>\n\n constructor(private readonly options: OpenAiEmbeddingProviderOptions) {\n super()\n this.headers = endpointHeaders(options.headers, {\n ...(options.organization === undefined ? {} : { 'openai-organization': options.organization }),\n ...(options.project === undefined ? {} : { 'openai-project': options.project }),\n })\n this.baseUrl = (options.baseUrl ?? OPENAI_BASE_URL).replace(/\\/+$/, '')\n this.models = Object.freeze([...(options.models ?? [])])\n this.retry = resolveRetryPolicy(options.retryPolicy, 'openAiEmbedding.retryPolicy')\n }\n\n override providerInfo(provider: string): ProviderInfo {\n return { id: provider, name: DISPLAY_NAME }\n }\n\n override providerRetryPolicy(_provider: string): ResolvedRetryPolicy {\n return this.retry\n }\n\n override listEmbeddingModels(\n provider: string,\n signal?: AbortSignal,\n ): Promise<readonly EmbeddingModelInfo[]> {\n signal?.throwIfAborted()\n return Promise.resolve(Object.freeze(\n this.models.map(model => embeddingCatalogModelInfo(provider, model)),\n ))\n }\n\n override resolveEmbeddingModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<ResolvedEmbeddingModelInfo> {\n signal?.throwIfAborted()\n return Promise.resolve(resolvedEmbeddingCatalogModelInfo(provider, model, this.models))\n }\n\n /**\n * States what this model line declares about its embedding space.\n *\n * Overridden rather than inherited because the default answer is derived from\n * `${route}:${modelId}`, which makes one model line look like two spaces when\n * it is reachable through two routes. Two things differ here: the identity is\n * the model line's (see {@link IDENTITY_PREFIX}), and normalization is reported\n * only when the ROUTE declared it — never inferred from OpenAI's reputation for\n * returning unit vectors (Requirements 6.1, 6.3).\n */\n override embeddingProfile(\n model: ResolvedEmbeddingModelInfo,\n request: EmbeddingProfileInput,\n ): EmbeddingProfile {\n const base = defaultEmbeddingProfile(model, request)\n return Object.freeze({\n ...base,\n compatibilityIdentity: model.compatibilityIdentity.state === 'supported'\n ? model.compatibilityIdentity.value\n : `${IDENTITY_PREFIX}:${model.id}`,\n normalization: model.normalization.state === 'supported'\n ? model.normalization.value\n : base.normalization,\n })\n }\n\n /**\n * Captures endpoint, credential and bounds ONCE, then binds dispatch to that\n * capture.\n *\n * Overridden because this adapter's connection facts come from configuration\n * and a credential resolved per operation: reading them again inside\n * `embedBatch()` would let a rotating secret pair with another generation's URL,\n * and would let dimensions be validated against one catalog while the request\n * went out under another (Requirements 2.2, 2.3, 2.4).\n */\n override async prepareEmbeddingCall(\n provider: string,\n model: string,\n options: PrepareEmbeddingOptions,\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n ): Promise<PreparedEmbeddingCall> {\n const connection = await this.connect(signal, context)\n const resolved = resolvedEmbeddingCatalogModelInfo(provider, model, connection.models)\n const profile = this.embeddingProfile(resolved, options)\n return Object.freeze({\n model: resolved,\n profile,\n spaceId: deriveSpaceId(profile),\n limits: resolveBatchLimits(resolved, options.limits),\n embedBatch: (batch: EmbeddingBatchRequest, invocation = context) =>\n this.dispatch(connection, resolved, batch, invocation),\n })\n }\n\n /**\n * One `Physical_Batch`, one `Provider_Attempt`.\n *\n * Reachable directly for an adapter used without a prepared call; the shared\n * path is {@link dispatch}, so both routes send the same body under the same\n * guards.\n */\n override async embedBatch(\n batch: EmbeddingBatchRequest,\n context?: ModelInvocationContext,\n ): Promise<EmbeddingBatchResult> {\n const connection = await this.connect(batch.signal, context)\n const model = resolvedEmbeddingCatalogModelInfo(\n batch.provider,\n batch.model,\n connection.models,\n )\n return this.dispatch(connection, model, batch, context)\n }\n\n /** Everything one embedding request needs, read together, once per operation. */\n private async connect(\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n ): Promise<EmbeddingHttpConnection> {\n const extraHeaders = this.headers()\n const token = await resolveApiKey(this.options.apiKey, signal, context)\n // The credential and the endpoint-scoped account headers travel together as\n // the auth layer; the transport merges its own layer and attribution on top,\n // which is what makes attribution unforgettable (Requirement 14.7).\n const headers: Record<string, string> = { ...extraHeaders, authorization: `Bearer ${token}` }\n return Object.freeze({\n baseUrl: this.baseUrl,\n headers: Object.freeze(headers),\n sensitiveHeaderNames: Object.freeze(Object.keys(headers)),\n models: this.models,\n retryPolicy: this.retry,\n ...(this.options.allowInsecureHttp === undefined\n ? {}\n : { allowInsecureHttp: this.options.allowInsecureHttp }),\n ...(this.options.requestTimeoutMs === undefined\n ? {}\n : { requestTimeoutMs: this.options.requestTimeoutMs }),\n ...(this.options.maxRequestBytes === undefined\n ? {}\n : { maxRequestBytes: this.options.maxRequestBytes }),\n ...(this.options.maxResponseBytes === undefined\n ? {}\n : { maxResponseBytes: this.options.maxResponseBytes }),\n ...(this.options.maxResponseChunks === undefined\n ? {}\n : { maxResponseChunks: this.options.maxResponseChunks }),\n ...(this.options.maxErrorBodyBytes === undefined\n ? {}\n : { maxErrorBodyBytes: this.options.maxErrorBodyBytes }),\n ...(this.options.requestLoggerTimeoutMs === undefined\n ? {}\n : { requestLoggerTimeoutMs: this.options.requestLoggerTimeoutMs }),\n ...(this.options.fetch === undefined ? {} : { fetch: this.options.fetch }),\n })\n }\n\n /** Serialize, send through the shared chain, and map the parsed body back. */\n private async dispatch(\n connection: EmbeddingHttpConnection,\n model: ResolvedEmbeddingModelInfo,\n batch: EmbeddingBatchRequest,\n context?: ModelInvocationContext,\n ): Promise<EmbeddingBatchResult> {\n if (batch.truncation === 'allow') {\n // Accepting this would promise a behaviour nothing on this wire can express.\n throw new EmbeddingError(\n `${DISPLAY_NAME} embeddings exposes no truncation parameter`,\n EMBEDDING_ERROR_CODES.TRUNCATION_UNSUPPORTED,\n { provider: batch.provider, model: batch.model },\n )\n }\n\n const body: Record<string, unknown> = {\n model: batch.model,\n // One element per item, in item order. The purpose does NOT appear here:\n // this endpoint has no parameter for it and no prefix is invented.\n input: batch.items.map(itemInput),\n encoding_format: ENCODING_FORMAT,\n }\n // Declared widths only. An `unknown` capability states nothing, and sending a\n // parameter on the strength of nothing is how a compatible endpoint 400s.\n if (batch.dimensions !== undefined && model.dimensions.state === 'supported') {\n body['dimensions'] = batch.dimensions\n }\n\n const encoded = JSON.stringify(body)\n // `decode` extracts the payload and NOTHING else. The shared chain normalizes\n // anything thrown inside `decode` through `normalizeHttpBoundaryError`, which\n // has no data twin to read off an `EmbeddingError` and would flatten every\n // stable embedding code into `ModelError{code:'UNKNOWN'}`. Validating after\n // `transportJson` returns is what lets `EMBEDDING_VECTOR_COUNT_MISMATCH` and\n // its siblings reach the caller as themselves (Requirement 9.3–9.5).\n const received = await transportJson({\n connection: captureTransportConnection(connection, {\n 'content-type': JSON_MEDIA_TYPE,\n accept: JSON_MEDIA_TYPE,\n }),\n displayName: DISPLAY_NAME,\n provider: batch.provider,\n model: batch.model,\n path: EMBEDDINGS_PATH,\n accept: JSON_MEDIA_TYPE,\n body: {\n value: body,\n encoded,\n bytes: new TextEncoder().encode(encoded).length,\n },\n ...(batch.signal === undefined ? {} : { signal: batch.signal }),\n ...(context === undefined ? {} : { context }),\n }, (session, payload) => Object.freeze({\n payload,\n ...(session.providerRequestId === undefined\n ? {}\n : { providerRequestId: session.providerRequestId }),\n }))\n return decodeEmbeddingResponse(batch, received)\n }\n}\n\n/** A response body that cleared every transport guard, plus its correlation id. */\ninterface ReceivedEmbeddingResponse {\n readonly payload: unknown\n readonly providerRequestId?: ProviderRequestId\n}\n\n/**\n * Concatenates one item's content parts into a single wire input.\n *\n * The rule is recorded as `documentRecipeRevision` on the profile, and revision\n * `'1'` is exactly this: the text of each part, in order, with no separator and no\n * added markup. It matches the effective text the contract's own length check and\n * cache key derive, so a batch split, a rejection and a wire body can never\n * disagree about what an item's text is. One item produces one element, so the\n * provider returns exactly one vector for it (Requirement 8.7).\n */\nfunction itemInput(item: EmbeddingItem): string {\n let text = ''\n for (const part of item.contentParts) {\n if (part.type === 'text') text += part.text\n }\n return text\n}\n\n/**\n * Maps one parsed response body onto the batch that produced it, in ONE fixed\n * order.\n *\n * The order is the contract, not an implementation detail — the same malformed\n * response has to produce the same code here as it does for every other provider,\n * which is what lets a single conformance suite judge all of them:\n *\n * 1. a shape this contract does not recognise ⇒ `RESPONSE_MALFORMED`\n * 2. `data.length !== items.length` ⇒ `VECTOR_COUNT_MISMATCH`\n * 3. `{ data[i].index }` is not a permutation of `0..N-1` ⇒ `VECTOR_INDEX_INVALID`\n * 4. a non-finite element ⇒ `VECTOR_VALUE_INVALID`\n * 5. a width other than the one requested ⇒ `VECTOR_DIMENSIONS_MISMATCH`\n *\n * Steps 4 and 5 are delegated to the shared {@link validateBatchResult}, which\n * already runs them in exactly this order; re-deriving them here would be a second\n * place for the ordering to drift.\n *\n * The count check comes FIRST on purpose. Reading the entries one at a time and\n * refusing the first bad index would report a mapping failure for a response whose\n * real fault is that it answered a different number of inputs — two different\n * repairs for a caller, told apart by which check ran first.\n *\n * Nothing here slices, pads, sorts or repairs a value. The `index` a vector carries\n * out is the item's index in the `Logical_Call`, taken from `items[data[i].index]`,\n * never its position in this batch (Requirement 8.4).\n */\nfunction decodeEmbeddingResponse(\n batch: EmbeddingBatchRequest,\n received: ReceivedEmbeddingResponse,\n): EmbeddingBatchResult {\n const entries = readEntries(batch, received.payload)\n checkEntryCount(batch, entries)\n const positions = readPositions(batch, entries)\n const vectors: EmbeddingVector[] = entries.map((entry, at) => Object.freeze({\n // The item's index in the `Logical_Call`, not its position in this batch.\n index: batch.items[positions[at]!]!.index,\n values: readValues(batch, entry),\n }))\n const usage = readUsage(received.payload)\n const result: EmbeddingBatchResult = Object.freeze({\n vectors: Object.freeze(vectors),\n ...(usage === undefined ? {} : { usage }),\n ...(received.providerRequestId === undefined\n ? {}\n : { providerRequestId: received.providerRequestId }),\n })\n // Steps 4 and 5, plus the count and logical-index invariants restated against\n // the `Logical_Call` indexes this result now carries.\n validateBatchResult(batch, result)\n return result\n}\n\n/** A `data` array of objects, or a structural refusal naming the batch it belongs to. */\nfunction readEntries(\n batch: EmbeddingBatchRequest,\n payload: unknown,\n): readonly Readonly<Record<string, unknown>>[] {\n const data = record(payload)?.['data']\n if (!Array.isArray(data)) throw malformed(batch, 'response carries no `data` array')\n return data.map(entry => {\n const source = record(entry)\n if (source === undefined) throw malformed(batch, 'response `data` entry is not an object')\n return source\n })\n}\n\n/** Step 2: one vector per input sent, counted before anything is interpreted. */\nfunction checkEntryCount(\n batch: EmbeddingBatchRequest,\n entries: readonly unknown[],\n): void {\n if (entries.length === batch.items.length) return\n throw new EmbeddingError(\n `${DISPLAY_NAME} returned ${entries.length} vectors for ${batch.items.length} inputs`,\n EMBEDDING_ERROR_CODES.VECTOR_COUNT_MISMATCH,\n { provider: batch.provider, model: batch.model },\n )\n}\n\n/**\n * Step 3: the reported positions, once they are known to be a permutation of\n * `0..N-1`.\n *\n * A duplicate, a gap, a non-integer and an out-of-range value all land in the same\n * refusal, because they all break the same thing: without a bijection between\n * response entries and batch items, restoring input order would be guesswork, and\n * a position to \"fall back on\" would silently attach one input's vector to another\n * (Requirement 8.2).\n */\nfunction readPositions(\n batch: EmbeddingBatchRequest,\n entries: readonly Readonly<Record<string, unknown>>[],\n): readonly number[] {\n const positions: number[] = []\n const seen = new Set<number>()\n for (const entry of entries) {\n const position = entry['index']\n if (typeof position !== 'number' || !Number.isInteger(position)\n || position < 0 || position >= batch.items.length || seen.has(position)) {\n throw new EmbeddingError(\n `${DISPLAY_NAME} returned a duplicate, missing or out-of-range vector index`,\n EMBEDDING_ERROR_CODES.VECTOR_INDEX_INVALID,\n { provider: batch.provider, model: batch.model },\n )\n }\n seen.add(position)\n positions.push(position)\n }\n return positions\n}\n\n/**\n * Reads one `embedding` array with every number exactly as it arrived.\n *\n * Only the SHAPE is judged here: a non-finite or non-numeric element is step 4's\n * business, so it travels through untouched and is refused by\n * {@link validateBatchResult} under `VECTOR_VALUE_INVALID` rather than being\n * repaired, dropped, or relabelled as a malformed shape.\n */\nfunction readValues(\n batch: EmbeddingBatchRequest,\n entry: Readonly<Record<string, unknown>>,\n): readonly number[] {\n const values = entry['embedding']\n if (!Array.isArray(values)) {\n throw malformed(batch, 'response vector is not an array')\n }\n return Object.freeze([...values as readonly number[]])\n}\n\n/**\n * Maps `prompt_tokens` and `total_tokens` onto the two embedding counters.\n *\n * There is no `outputTokens`, which is why embedding reports\n * `EmbeddingTokenUsage` rather than generation's `TokenUsage`. A counter that is\n * absent or unreadable stays ABSENT: a zero here would be indistinguishable from\n * a provider that reported no cost at all.\n */\nfunction readUsage(payload: unknown): { inputTokens?: number; totalTokens?: number } | undefined {\n const usage = record(record(payload)?.['usage'])\n if (usage === undefined) return undefined\n const inputTokens = usage['prompt_tokens']\n const totalTokens = usage['total_tokens']\n const counters = {\n ...(typeof inputTokens === 'number' ? { inputTokens } : {}),\n ...(typeof totalTokens === 'number' ? { totalTokens } : {}),\n }\n return Reflect.ownKeys(counters).length === 0 ? undefined : counters\n}\n\n/** A plain-record view of an unknown value, or `undefined`. */\nfunction record(value: unknown): Readonly<Record<string, unknown>> | undefined {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined\n return value as Readonly<Record<string, unknown>>\n}\n\n/** A structural refusal: the response is not a shape this contract recognises. */\nfunction malformed(batch: EmbeddingBatchRequest, detail: string): EmbeddingError {\n return new EmbeddingError(\n `${DISPLAY_NAME} embeddings ${detail}`,\n EMBEDDING_ERROR_CODES.RESPONSE_MALFORMED,\n { provider: batch.provider, model: batch.model },\n )\n}\n\n/** Resolves a literal key or a credential source, once per operation. */\nasync function resolveApiKey(\n apiKey: CredentialInput,\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n): Promise<string> {\n const value = typeof apiKey === 'string'\n ? apiKey\n : await apiKey.resolve({\n signal: signal ?? NEVER_ABORTED_SIGNAL,\n logger: context?.logger ?? NULL_LOGGER,\n })\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new EmbeddingError(\n `${DISPLAY_NAME} embeddings requires a non-empty \\`apiKey\\``,\n EMBEDDING_ERROR_CODES.CONFIGURATION_INVALID,\n )\n }\n return value\n}\n\n/**\n * Create an OpenAI embedding adapter.\n * @param options - credential, endpoint, catalog and transport bounds.\n * @returns the adapter, ready to register on an embedding route.\n */\nexport function openAiEmbeddingAdapter(\n options: OpenAiEmbeddingProviderOptions,\n): EmbeddingAdapter {\n return new OpenAiEmbeddingAdapter(options)\n}\n\n/**\n * Preferred transactional plugin for installing OpenAI embeddings.\n *\n * Its `kind` is `'embedding-provider-plugin'`, so it installs beside\n * {@link openAiPlugin} on the same route without either standing in for the other.\n * @param options - credential, endpoint, catalog and transport bounds.\n * @returns an inert plugin; the adapter is constructed during activation.\n */\nexport function openAiEmbeddingPlugin(\n options: OpenAiEmbeddingProviderOptions,\n): ComposableEmbeddingProviderPlugin & { readonly family: 'openai' } {\n const id = options.id ?? 'openai'\n const routes = Object.freeze([...(options.routes ?? [id])])\n return defineEmbeddingProviderPlugin({\n id,\n family: 'openai',\n displayName: DISPLAY_NAME,\n routes,\n setup(registrar) {\n const remove = registrar.registerEmbeddingAdapter(openAiEmbeddingAdapter(options))\n return () => {\n remove()\n return undefined\n }\n },\n }) as ComposableEmbeddingProviderPlugin & { readonly family: 'openai' }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"name": "alvin0 - chaulamdinhai",
|
|
5
5
|
"email": "chaulamdinhai@gmail.com"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.1.
|
|
7
|
+
"version": "0.1.3",
|
|
8
8
|
"description": "Universal OpenAI adapter and provider plugin for ai-agent-sdk",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
@@ -38,15 +38,15 @@
|
|
|
38
38
|
"provenance": true
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@alvin0/ai-agent-sdk-provider-http": "^0.1.
|
|
42
|
-
"@alvin0/ai-agent-sdk-protocol-responses": "^0.1.
|
|
41
|
+
"@alvin0/ai-agent-sdk-provider-http": "^0.1.3",
|
|
42
|
+
"@alvin0/ai-agent-sdk-protocol-responses": "^0.1.3"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@alvin0/ai-agent-sdk-core": "^0.1.
|
|
45
|
+
"@alvin0/ai-agent-sdk-core": "^0.1.3"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@alvin0/ai-agent-sdk-core": "^0.1.
|
|
49
|
-
"@alvin0/ai-agent-sdk-testkit": "^0.1.
|
|
48
|
+
"@alvin0/ai-agent-sdk-core": "^0.1.3",
|
|
49
|
+
"@alvin0/ai-agent-sdk-testkit": "^0.1.3",
|
|
50
50
|
"@arethetypeswrong/cli": "0.18.5",
|
|
51
51
|
"playwright": "1.62.1",
|
|
52
52
|
"publint": "0.3.24",
|