@kindgi/adapter-model-openai-compat 0.1.4-rc.4 → 0.1.4
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 +26 -6
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +36 -7
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +90 -27
- package/dist/provider.js.map +1 -1
- package/dist/responses.d.ts +43 -0
- package/dist/responses.d.ts.map +1 -0
- package/dist/responses.js +345 -0
- package/dist/responses.js.map +1 -0
- package/dist/wire.d.ts +73 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +71 -0
- package/dist/wire.js.map +1 -0
- package/package.json +3 -3
- package/src/index.ts +8 -1
- package/src/provider.ts +125 -39
- package/src/responses.ts +474 -0
- package/src/wire.ts +130 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
import { computeCost, decodeToolName, encodeToolName, parseArguments } from './wire.js';
|
|
4
|
+
/** Request fields the Responses path sets itself; `extraBody` can't override them. */
|
|
5
|
+
export const EXTRA_BODY_RESERVED_RESPONSES = [
|
|
6
|
+
'model',
|
|
7
|
+
'input',
|
|
8
|
+
'tools',
|
|
9
|
+
'text',
|
|
10
|
+
'temperature',
|
|
11
|
+
'max_output_tokens',
|
|
12
|
+
'stream',
|
|
13
|
+
'store',
|
|
14
|
+
];
|
|
15
|
+
export async function invokeResponses(call) {
|
|
16
|
+
const { input } = call;
|
|
17
|
+
const tools = input.tools?.map(toTool);
|
|
18
|
+
const counted = await call.attempts.count(() => call.client.responses.create({
|
|
19
|
+
...call.extraBody,
|
|
20
|
+
model: input.model,
|
|
21
|
+
input: toInput(input.messages, input.model),
|
|
22
|
+
...(tools !== undefined && tools.length > 0 && { tools }),
|
|
23
|
+
...(input.structuredOutput !== undefined && {
|
|
24
|
+
text: {
|
|
25
|
+
format: {
|
|
26
|
+
type: 'json_schema',
|
|
27
|
+
name: input.structuredOutput.name,
|
|
28
|
+
schema: input.structuredOutput.schema,
|
|
29
|
+
strict: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
...(call.temperature !== undefined && { temperature: call.temperature }),
|
|
34
|
+
...(call.reasoningEffort !== undefined && {
|
|
35
|
+
reasoning: {
|
|
36
|
+
...(isRecord(call.extraBody.reasoning) ? call.extraBody.reasoning : {}),
|
|
37
|
+
effort: call.reasoningEffort,
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
...(input.maxOutputTokens !== undefined && { max_output_tokens: input.maxOutputTokens }),
|
|
41
|
+
store: false,
|
|
42
|
+
stream: false,
|
|
43
|
+
}, input.abortSignal !== undefined ? { signal: input.abortSignal } : undefined));
|
|
44
|
+
const response = counted.value;
|
|
45
|
+
const durationMs = Date.now() - call.startedAt;
|
|
46
|
+
refuseUnfinished(response, call.providerId);
|
|
47
|
+
const output = readOutput(response.output, input.model);
|
|
48
|
+
const usage = toFrameworkUsage(response.usage);
|
|
49
|
+
const warnings = call.warnings ?? [];
|
|
50
|
+
return {
|
|
51
|
+
message: {
|
|
52
|
+
role: 'assistant',
|
|
53
|
+
content: output.content,
|
|
54
|
+
...(output.toolCalls.length > 0 && { toolCalls: output.toolCalls }),
|
|
55
|
+
},
|
|
56
|
+
finishReason: finishReasonOf(response, output.toolCalls.length > 0),
|
|
57
|
+
usage,
|
|
58
|
+
costUsd: computeCost(call.modelInfo, usage, { dataResidency: call.dataResidency }),
|
|
59
|
+
durationMs,
|
|
60
|
+
provider: { id: call.providerId, model: input.model },
|
|
61
|
+
...(typeof response.model === 'string' &&
|
|
62
|
+
response.model !== '' && { servedModel: response.model }),
|
|
63
|
+
...(typeof response._request_id === 'string' && {
|
|
64
|
+
providerRequestId: response._request_id,
|
|
65
|
+
}),
|
|
66
|
+
// An injected client sends with its own fetch: nothing was counted.
|
|
67
|
+
...(counted.attempts > 0 && { attempts: counted.attempts }),
|
|
68
|
+
...(response.usage !== undefined && { rawUsage: { ...response.usage } }),
|
|
69
|
+
...(warnings.length > 0 && { warnings: [...warnings] }),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Request
|
|
74
|
+
/** The conversation as Responses input items, in order. */
|
|
75
|
+
function toInput(messages, model) {
|
|
76
|
+
const items = [];
|
|
77
|
+
for (const m of messages) {
|
|
78
|
+
switch (m.role) {
|
|
79
|
+
case 'system':
|
|
80
|
+
// The role OpenAI's Responses guides give an app's instructions.
|
|
81
|
+
items.push({ role: 'developer', content: m.content });
|
|
82
|
+
break;
|
|
83
|
+
case 'user':
|
|
84
|
+
items.push({ role: 'user', content: m.content });
|
|
85
|
+
break;
|
|
86
|
+
case 'tool':
|
|
87
|
+
items.push({
|
|
88
|
+
type: 'function_call_output',
|
|
89
|
+
call_id: m.toolCallId ?? '',
|
|
90
|
+
output: m.content,
|
|
91
|
+
});
|
|
92
|
+
break;
|
|
93
|
+
case 'assistant':
|
|
94
|
+
items.push(...assistantItems(m, model));
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return items;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* An assistant turn. With tool calls this model made, and their carried
|
|
102
|
+
* output (`readCarried`), it goes back as the response gave it: reasoning,
|
|
103
|
+
* message and calls in their order, linked by their ids. Otherwise as its
|
|
104
|
+
* text and its calls, without ids: an item id names output the reasoning
|
|
105
|
+
* belongs with, so none is sent without it.
|
|
106
|
+
*/
|
|
107
|
+
function assistantItems(m, model) {
|
|
108
|
+
const calls = m.toolCalls ?? [];
|
|
109
|
+
const carried = readCarried(calls, model);
|
|
110
|
+
if (carried === undefined) {
|
|
111
|
+
return [
|
|
112
|
+
...(m.content !== '' ? [{ role: 'assistant', content: m.content }] : []),
|
|
113
|
+
...calls.map((c) => functionCall(c, undefined)),
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
// Item ids link reasoning to what follows it; without reasoning, none are sent.
|
|
117
|
+
const linked = carried.some((item) => item.type === 'reasoning');
|
|
118
|
+
const byId = new Map(calls.map((c) => [c.id, c]));
|
|
119
|
+
return carried.flatMap((item) => {
|
|
120
|
+
switch (item.type) {
|
|
121
|
+
case 'reasoning':
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
type: 'reasoning',
|
|
125
|
+
id: item.id,
|
|
126
|
+
summary: item.summary.map((s) => ({ type: 'summary_text', text: s.text })),
|
|
127
|
+
encrypted_content: item.encrypted_content,
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
case 'message':
|
|
131
|
+
return m.content === '' ? [] : [carriedMessage(item, m.content, linked)];
|
|
132
|
+
case 'function_call':
|
|
133
|
+
// readCarried checked the turn has this call.
|
|
134
|
+
return [
|
|
135
|
+
functionCall(byId.get(item.call_id), linked ? item.id : undefined),
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/** The turn's text, as the carried message it came in. */
|
|
141
|
+
function carriedMessage(item, text, linked) {
|
|
142
|
+
const phase = item.phase !== undefined ? { phase: item.phase } : {};
|
|
143
|
+
return linked
|
|
144
|
+
? {
|
|
145
|
+
type: 'message',
|
|
146
|
+
id: item.id,
|
|
147
|
+
role: 'assistant',
|
|
148
|
+
status: 'completed',
|
|
149
|
+
content: [{ type: 'output_text', text, annotations: [] }],
|
|
150
|
+
...phase,
|
|
151
|
+
}
|
|
152
|
+
: { role: 'assistant', content: text, ...phase };
|
|
153
|
+
}
|
|
154
|
+
function functionCall(call, id) {
|
|
155
|
+
return {
|
|
156
|
+
type: 'function_call',
|
|
157
|
+
call_id: call.id,
|
|
158
|
+
// Encode when replaying prior assistant turns — see `encodeToolName`.
|
|
159
|
+
name: encodeToolName(call.name),
|
|
160
|
+
arguments: JSON.stringify(call.arguments),
|
|
161
|
+
...(id !== undefined && { id }),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function toTool(tool) {
|
|
165
|
+
return {
|
|
166
|
+
type: 'function',
|
|
167
|
+
name: encodeToolName(tool.name),
|
|
168
|
+
description: tool.description,
|
|
169
|
+
parameters: tool.inputSchema,
|
|
170
|
+
// As on the Chat Completions path: tools' schemas needn't meet strict mode.
|
|
171
|
+
strict: false,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
// Response
|
|
176
|
+
/** A `failed` (or never finished) response throws, naming OpenAI's error. */
|
|
177
|
+
function refuseUnfinished(response, providerId) {
|
|
178
|
+
const status = response.status ?? 'completed';
|
|
179
|
+
if (status === 'completed' || status === 'incomplete')
|
|
180
|
+
return;
|
|
181
|
+
const error = response.error;
|
|
182
|
+
const why = error != null ? `${error.code}: ${error.message}` : `status "${status}"`;
|
|
183
|
+
throw new Error(`@kindgi/adapter-model-openai-compat: provider "${providerId}": the response ${status === 'failed' ? 'failed' : `ended "${status}"`} (${why}).`);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The answer's text (its refusal when it has no text) and tool calls.
|
|
187
|
+
* The first call carries what the next call needs back.
|
|
188
|
+
*/
|
|
189
|
+
function readOutput(output, model) {
|
|
190
|
+
const read = {
|
|
191
|
+
text: '',
|
|
192
|
+
refusal: '',
|
|
193
|
+
calls: [],
|
|
194
|
+
carried: [],
|
|
195
|
+
reasoning: 0,
|
|
196
|
+
messages: 0,
|
|
197
|
+
phased: false,
|
|
198
|
+
unlinkable: false,
|
|
199
|
+
};
|
|
200
|
+
for (const item of output) {
|
|
201
|
+
if (item.type === 'reasoning')
|
|
202
|
+
readReasoning(item, read);
|
|
203
|
+
else if (item.type === 'message')
|
|
204
|
+
readMessage(item, read);
|
|
205
|
+
else if (item.type === 'function_call')
|
|
206
|
+
readFunctionCall(item, read);
|
|
207
|
+
}
|
|
208
|
+
// Carried when there's something to send back (reasoning, or a phase)
|
|
209
|
+
// and the next call can send it as it came: every reasoning item with
|
|
210
|
+
// its encrypted content, every call with its id, and at most one
|
|
211
|
+
// message (the turn keeps one text, so two can't be told apart).
|
|
212
|
+
const carry = read.calls.length > 0 &&
|
|
213
|
+
(read.reasoning > 0 || read.phased) &&
|
|
214
|
+
!read.unlinkable &&
|
|
215
|
+
read.messages <= 1
|
|
216
|
+
? writeSignature({ model, items: read.carried })
|
|
217
|
+
: undefined;
|
|
218
|
+
return {
|
|
219
|
+
content: read.text !== '' ? read.text : read.refusal,
|
|
220
|
+
toolCalls: read.calls.map((c, i) => i === 0 && carry !== undefined ? { ...c, signature: carry } : c),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function readReasoning(item, read) {
|
|
224
|
+
read.reasoning += 1;
|
|
225
|
+
if (typeof item.encrypted_content !== 'string' || item.encrypted_content === '') {
|
|
226
|
+
read.unlinkable = true;
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
read.carried.push({
|
|
230
|
+
type: 'reasoning',
|
|
231
|
+
id: item.id,
|
|
232
|
+
summary: item.summary.map((s) => ({ text: s.text })),
|
|
233
|
+
encrypted_content: item.encrypted_content,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function readMessage(item, read) {
|
|
237
|
+
read.messages += 1;
|
|
238
|
+
for (const part of item.content) {
|
|
239
|
+
if (part.type === 'output_text')
|
|
240
|
+
read.text += part.text;
|
|
241
|
+
else if (part.type === 'refusal')
|
|
242
|
+
read.refusal += part.refusal;
|
|
243
|
+
}
|
|
244
|
+
const phase = item.phase ?? undefined;
|
|
245
|
+
if (phase !== undefined)
|
|
246
|
+
read.phased = true;
|
|
247
|
+
read.carried.push({ type: 'message', id: item.id, ...(phase !== undefined && { phase }) });
|
|
248
|
+
}
|
|
249
|
+
function readFunctionCall(item, read) {
|
|
250
|
+
// Decode: the wire returns the encoded name; the framework
|
|
251
|
+
// expects the canonical dotted form.
|
|
252
|
+
read.calls.push({
|
|
253
|
+
id: item.call_id,
|
|
254
|
+
name: decodeToolName(item.name),
|
|
255
|
+
arguments: parseArguments(item.arguments),
|
|
256
|
+
});
|
|
257
|
+
if (item.id === undefined)
|
|
258
|
+
read.unlinkable = true;
|
|
259
|
+
else
|
|
260
|
+
read.carried.push({ type: 'function_call', id: item.id, call_id: item.call_id });
|
|
261
|
+
}
|
|
262
|
+
function finishReasonOf(response, hasToolCalls) {
|
|
263
|
+
if (response.status === 'incomplete') {
|
|
264
|
+
switch (response.incomplete_details?.reason) {
|
|
265
|
+
case 'max_output_tokens':
|
|
266
|
+
return 'length';
|
|
267
|
+
case 'content_filter':
|
|
268
|
+
return 'content-filter';
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return hasToolCalls ? 'tool-use' : 'stop';
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* The response's usage as the framework's counters. `input_tokens`
|
|
275
|
+
* include the cached ones (`input_tokens_details`), and `output_tokens`
|
|
276
|
+
* the reasoning ones (`output_tokens_details.reasoning_tokens`): reported
|
|
277
|
+
* apart when the response gives them.
|
|
278
|
+
*/
|
|
279
|
+
function toFrameworkUsage(usage) {
|
|
280
|
+
const cacheRead = usage?.input_tokens_details?.cached_tokens;
|
|
281
|
+
const cacheWrite = usage?.input_tokens_details?.cache_write_tokens;
|
|
282
|
+
const reasoning = usage?.output_tokens_details?.reasoning_tokens;
|
|
283
|
+
return {
|
|
284
|
+
promptTokens: usage?.input_tokens ?? 0,
|
|
285
|
+
completionTokens: usage?.output_tokens ?? 0,
|
|
286
|
+
// A part the response reports is kept, 0 included.
|
|
287
|
+
...(typeof cacheRead === 'number' && { cacheReadTokens: cacheRead }),
|
|
288
|
+
...(typeof cacheWrite === 'number' && { cacheWriteTokens: cacheWrite }),
|
|
289
|
+
...(typeof reasoning === 'number' && { reasoningTokens: reasoning }),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/** Versioned, so a later shape can tell this one apart. */
|
|
293
|
+
const SIGNATURE_PREFIX = 'oair1.';
|
|
294
|
+
function writeSignature(carried) {
|
|
295
|
+
return SIGNATURE_PREFIX + Buffer.from(JSON.stringify(carried), 'utf8').toString('base64url');
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* The output carried on an assistant turn's first call, when it's this
|
|
299
|
+
* adapter's, for `model`, and names exactly the turn's calls in order.
|
|
300
|
+
* Anything else (another adapter's signature, another model's, one that
|
|
301
|
+
* doesn't parse) is ignored: the turn goes back without it.
|
|
302
|
+
*/
|
|
303
|
+
function readCarried(calls, model) {
|
|
304
|
+
const signature = calls[0]?.signature;
|
|
305
|
+
if (signature === undefined || !signature.startsWith(SIGNATURE_PREFIX))
|
|
306
|
+
return undefined;
|
|
307
|
+
let parsed;
|
|
308
|
+
try {
|
|
309
|
+
parsed = JSON.parse(Buffer.from(signature.slice(SIGNATURE_PREFIX.length), 'base64url').toString('utf8'));
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
if (!isRecord(parsed) || parsed.model !== model || !Array.isArray(parsed.items)) {
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
const items = parsed.items;
|
|
318
|
+
if (!items.every(isCarriedItem))
|
|
319
|
+
return undefined;
|
|
320
|
+
const callIds = items.flatMap((item) => (item.type === 'function_call' ? [item.call_id] : []));
|
|
321
|
+
if (callIds.length !== calls.length || callIds.some((id, i) => id !== calls[i]?.id)) {
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
return items;
|
|
325
|
+
}
|
|
326
|
+
function isCarriedItem(value) {
|
|
327
|
+
if (!isRecord(value) || typeof value.id !== 'string')
|
|
328
|
+
return false;
|
|
329
|
+
switch (value.type) {
|
|
330
|
+
case 'reasoning':
|
|
331
|
+
return (typeof value.encrypted_content === 'string' &&
|
|
332
|
+
Array.isArray(value.summary) &&
|
|
333
|
+
value.summary.every((s) => isRecord(s) && typeof s.text === 'string'));
|
|
334
|
+
case 'message':
|
|
335
|
+
return (value.phase === undefined || value.phase === 'commentary' || value.phase === 'final_answer');
|
|
336
|
+
case 'function_call':
|
|
337
|
+
return typeof value.call_id === 'string';
|
|
338
|
+
default:
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function isRecord(value) {
|
|
343
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.js","sourceRoot":"","sources":["../src/responses.ts"],"names":[],"mappings":"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"}
|
package/dist/wire.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What both of the adapter's OpenAI APIs (Chat Completions and
|
|
3
|
+
* Responses) share: tool names on the wire, tool-call arguments, cost.
|
|
4
|
+
*/
|
|
5
|
+
import type { ModelInfo, UsageCounters } from '@kindgi/capabilities';
|
|
6
|
+
/**
|
|
7
|
+
* OpenAI (and every downstream compat endpoint — Ollama, vLLM, Groq,
|
|
8
|
+
* OpenRouter, Together, Fireworks, LiteLLM, ...) constrains
|
|
9
|
+
* `function.name` to `^[a-zA-Z0-9_-]{1,128}$` — dots are rejected.
|
|
10
|
+
* The framework's tool id convention is `<pack>.<tool>`, so this
|
|
11
|
+
* adapter transparently encodes on send and decodes on receive.
|
|
12
|
+
*
|
|
13
|
+
* See the sibling comment in
|
|
14
|
+
* `packages/adapters/model-anthropic/src/translate.ts` — same
|
|
15
|
+
* substitution (`.` → `__`), same reversibility caveat (authors
|
|
16
|
+
* should not put literal `__` in tool ids).
|
|
17
|
+
*/
|
|
18
|
+
export declare function encodeToolName(name: string): string;
|
|
19
|
+
export declare function decodeToolName(name: string): string;
|
|
20
|
+
/** A tool call's JSON arguments as an object; `{}` when they don't parse. */
|
|
21
|
+
export declare function parseArguments(raw: string): Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* A model's rates, per 1K tokens, with the pricing extras an
|
|
24
|
+
* OpenAI-compatible endpoint may have. The names are the ones the Gemini
|
|
25
|
+
* and Anthropic adapters already price with.
|
|
26
|
+
*/
|
|
27
|
+
export interface OpenAICompatCostRates {
|
|
28
|
+
readonly promptUsdPer1kTokens: number;
|
|
29
|
+
readonly completionUsdPer1kTokens: number;
|
|
30
|
+
/**
|
|
31
|
+
* Cached prompt tokens' share of the prompt rate (OpenAI's GPT-6: 0.1;
|
|
32
|
+
* GPT-6.1 Sol: 0.05). Absent: they bill at the prompt rate.
|
|
33
|
+
*/
|
|
34
|
+
readonly cachedPromptMultiplier?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Prompt tokens written to the cache, as a multiple of the prompt rate
|
|
37
|
+
* (OpenAI's GPT-6: 1.25). Absent: they bill at the prompt rate.
|
|
38
|
+
*/
|
|
39
|
+
readonly promptCacheCreationMultiplier?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Long-context pricing: when a call's prompt (its cached and cache-write
|
|
42
|
+
* tokens included) exceeds `thresholdTokens`, the whole call bills at
|
|
43
|
+
* these rates, the cache multipliers applying to the long prompt rate
|
|
44
|
+
* (OpenAI's GPT-6: twice the prompt and 1.5 times the completion rate
|
|
45
|
+
* past 272,000 input tokens).
|
|
46
|
+
*/
|
|
47
|
+
readonly longContext?: {
|
|
48
|
+
readonly thresholdTokens: number;
|
|
49
|
+
readonly promptUsdPer1kTokens: number;
|
|
50
|
+
readonly completionUsdPer1kTokens: number;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The uplift on a whole call sent to a data-residency host
|
|
54
|
+
* (`eu.api.openai.com`: 1.1 for OpenAI models released on or after
|
|
55
|
+
* 2026-03-05). Applied only on such a host.
|
|
56
|
+
*/
|
|
57
|
+
readonly dataResidencyMultiplier?: number;
|
|
58
|
+
}
|
|
59
|
+
/** `ModelInfo` whose `cost` takes the rates in `OpenAICompatCostRates`. */
|
|
60
|
+
export interface OpenAICompatModelInfo extends ModelInfo {
|
|
61
|
+
readonly cost: ModelInfo['cost'] & Omit<OpenAICompatCostRates, keyof ModelInfo['cost']>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A call's cost from its usage and the model's rates: cached and
|
|
65
|
+
* cache-write prompt tokens at their multipliers, the whole call at the
|
|
66
|
+
* long-context rates past their threshold, and a data-residency host's
|
|
67
|
+
* uplift. A rate that isn't a finite, non-negative number is ignored (it
|
|
68
|
+
* came from a registration stored before rates were checked).
|
|
69
|
+
*/
|
|
70
|
+
export declare function computeCost(modelInfo: ModelInfo, usage: UsageCounters, options?: {
|
|
71
|
+
readonly dataResidency?: boolean;
|
|
72
|
+
}): number;
|
|
73
|
+
//# sourceMappingURL=wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../src/wire.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErE;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMnE;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C;;;OAGG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IAChD;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;QACjC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;QACtC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;KAC3C,CAAC;IACF;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED,2EAA2E;AAC3E,MAAM,WAAW,qBAAsB,SAAQ,SAAS;IACtD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,qBAAqB,EAAE,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;CACzF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACjD,MAAM,CAmBR"}
|
package/dist/wire.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
/**
|
|
4
|
+
* OpenAI (and every downstream compat endpoint — Ollama, vLLM, Groq,
|
|
5
|
+
* OpenRouter, Together, Fireworks, LiteLLM, ...) constrains
|
|
6
|
+
* `function.name` to `^[a-zA-Z0-9_-]{1,128}$` — dots are rejected.
|
|
7
|
+
* The framework's tool id convention is `<pack>.<tool>`, so this
|
|
8
|
+
* adapter transparently encodes on send and decodes on receive.
|
|
9
|
+
*
|
|
10
|
+
* See the sibling comment in
|
|
11
|
+
* `packages/adapters/model-anthropic/src/translate.ts` — same
|
|
12
|
+
* substitution (`.` → `__`), same reversibility caveat (authors
|
|
13
|
+
* should not put literal `__` in tool ids).
|
|
14
|
+
*/
|
|
15
|
+
export function encodeToolName(name) {
|
|
16
|
+
return name.replace(/\./g, '__');
|
|
17
|
+
}
|
|
18
|
+
export function decodeToolName(name) {
|
|
19
|
+
return name.replace(/__/g, '.');
|
|
20
|
+
}
|
|
21
|
+
/** A tool call's JSON arguments as an object; `{}` when they don't parse. */
|
|
22
|
+
export function parseArguments(raw) {
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(raw);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A call's cost from its usage and the model's rates: cached and
|
|
32
|
+
* cache-write prompt tokens at their multipliers, the whole call at the
|
|
33
|
+
* long-context rates past their threshold, and a data-residency host's
|
|
34
|
+
* uplift. A rate that isn't a finite, non-negative number is ignored (it
|
|
35
|
+
* came from a registration stored before rates were checked).
|
|
36
|
+
*/
|
|
37
|
+
export function computeCost(modelInfo, usage, options = {}) {
|
|
38
|
+
const cost = modelInfo.cost;
|
|
39
|
+
const longContext = longContextOf(cost.longContext);
|
|
40
|
+
const long = longContext !== undefined && usage.promptTokens > longContext.thresholdTokens
|
|
41
|
+
? longContext
|
|
42
|
+
: undefined;
|
|
43
|
+
const promptRate = long?.promptUsdPer1kTokens ?? modelInfo.cost.promptUsdPer1kTokens;
|
|
44
|
+
const completionRate = long?.completionUsdPer1kTokens ?? modelInfo.cost.completionUsdPer1kTokens;
|
|
45
|
+
const cached = usage.cacheReadTokens ?? 0;
|
|
46
|
+
const written = usage.cacheWriteTokens ?? 0;
|
|
47
|
+
const fresh = Math.max(0, usage.promptTokens - cached - written);
|
|
48
|
+
const promptUnits = fresh +
|
|
49
|
+
cached * (rateOf(cost.cachedPromptMultiplier) ?? 1) +
|
|
50
|
+
written * (rateOf(cost.promptCacheCreationMultiplier) ?? 1);
|
|
51
|
+
const total = (promptUnits * promptRate + usage.completionTokens * completionRate) / 1000;
|
|
52
|
+
const uplift = options.dataResidency === true ? rateOf(cost.dataResidencyMultiplier) : undefined;
|
|
53
|
+
return uplift !== undefined ? total * uplift : total;
|
|
54
|
+
}
|
|
55
|
+
function rateOf(value) {
|
|
56
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
57
|
+
}
|
|
58
|
+
function longContextOf(value) {
|
|
59
|
+
if (typeof value !== 'object' || value === null)
|
|
60
|
+
return undefined;
|
|
61
|
+
const tier = value;
|
|
62
|
+
const thresholdTokens = rateOf(tier.thresholdTokens);
|
|
63
|
+
const promptUsdPer1kTokens = rateOf(tier.promptUsdPer1kTokens);
|
|
64
|
+
const completionUsdPer1kTokens = rateOf(tier.completionUsdPer1kTokens);
|
|
65
|
+
return thresholdTokens !== undefined &&
|
|
66
|
+
promptUsdPer1kTokens !== undefined &&
|
|
67
|
+
completionUsdPer1kTokens !== undefined
|
|
68
|
+
? { thresholdTokens, promptUsdPer1kTokens, completionUsdPer1kTokens }
|
|
69
|
+
: undefined;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=wire.js.map
|
package/dist/wire.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.js","sourceRoot":"","sources":["../src/wire.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AASjC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AA6CD;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,SAAoB,EACpB,KAAoB,EACpB,UAAgD,EAAE;IAElD,MAAM,IAAI,GAAG,SAAS,CAAC,IAA6D,CAAC;IACrF,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,IAAI,GACR,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,YAAY,GAAG,WAAW,CAAC,eAAe;QAC3E,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,UAAU,GAAG,IAAI,EAAE,oBAAoB,IAAI,SAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC;IACrF,MAAM,cAAc,GAAG,IAAI,EAAE,wBAAwB,IAAI,SAAS,CAAC,IAAI,CAAC,wBAAwB,CAAC;IACjG,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,IAAI,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACjE,MAAM,WAAW,GACf,KAAK;QACL,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QACnD,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,CAAC,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC,gBAAgB,GAAG,cAAc,CAAC,GAAG,IAAI,CAAC;IAC1F,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjG,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACvD,CAAC;AAED,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/F,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,MAAM,IAAI,GAAG,KAAgC,CAAC;IAC9C,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACrD,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC/D,MAAM,wBAAwB,GAAG,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACvE,OAAO,eAAe,KAAK,SAAS;QAClC,oBAAoB,KAAK,SAAS;QAClC,wBAAwB,KAAK,SAAS;QACtC,CAAC,CAAC,EAAE,eAAe,EAAE,oBAAoB,EAAE,wBAAwB,EAAE;QACrE,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kindgi/adapter-model-openai-compat",
|
|
3
|
-
"version": "0.1.4
|
|
4
|
-
"description": "OpenAI-compatible ModelProvider for @kindgi/capabilities.
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "OpenAI-compatible ModelProvider for @kindgi/capabilities. Speaks OpenAI's Responses API to OpenAI itself, and the Chat Completions wire format to any compatible endpoint — Ollama (/v1), vLLM, llama-server, LM Studio, OpenRouter, Groq, Together, Fireworks, DeepInfra, LiteLLM proxy (base URLs exported as BASE_URLS), or any other compatible endpoint. One adapter, many backends. Cost per 1K tokens is supplied by the caller (from the provider's public pricing) since the API surface itself doesn't expose it.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"README.md"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@kindgi/capabilities": "0.1.4
|
|
31
|
+
"@kindgi/capabilities": "0.1.4",
|
|
32
32
|
"openai": "^7.17.0"
|
|
33
33
|
},
|
|
34
34
|
"engines": {
|
package/src/index.ts
CHANGED
|
@@ -6,10 +6,17 @@ export {
|
|
|
6
6
|
EXTRA_BODY_PREFIX,
|
|
7
7
|
EXTRA_BODY_RESERVED,
|
|
8
8
|
OPENAI_COMPAT_ADAPTER_ID,
|
|
9
|
+
OPENAI_COMPAT_APIS,
|
|
9
10
|
createOpenAICompatModelProvider,
|
|
11
|
+
defaultOpenAICompatApi,
|
|
12
|
+
isDataResidencyHost,
|
|
10
13
|
openAICompatAdapterFactory,
|
|
14
|
+
openAICompatApi,
|
|
11
15
|
openAICompatBaseUrl,
|
|
12
16
|
openAICompatExtraBody,
|
|
13
17
|
} from './provider.js';
|
|
14
|
-
export
|
|
18
|
+
export { EXTRA_BODY_RESERVED_RESPONSES } from './responses.js';
|
|
19
|
+
export { computeCost } from './wire.js';
|
|
20
|
+
export type { OpenAICompatCostRates, OpenAICompatModelInfo } from './wire.js';
|
|
21
|
+
export type { OpenAICompatApi, OpenAICompatProviderOptions } from './provider.js';
|
|
15
22
|
export type { ModelProvider } from '@kindgi/capabilities';
|