veryfront 0.1.263 → 0.1.265
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/esm/deno.js +1 -1
- package/esm/src/agent/hosted-child-mirror.d.ts +91 -0
- package/esm/src/agent/hosted-child-mirror.d.ts.map +1 -0
- package/esm/src/agent/hosted-child-mirror.js +118 -0
- package/esm/src/agent/index.d.ts +2 -0
- package/esm/src/agent/index.d.ts.map +1 -1
- package/esm/src/agent/index.js +2 -0
- package/esm/src/chat/hosted-ui-chunk-mapping.d.ts +111 -0
- package/esm/src/chat/hosted-ui-chunk-mapping.d.ts.map +1 -0
- package/esm/src/chat/hosted-ui-chunk-mapping.js +123 -0
- package/esm/src/chat/index.d.ts +1 -0
- package/esm/src/chat/index.d.ts.map +1 -1
- package/esm/src/chat/index.js +1 -0
- package/esm/src/provider/runtime-loader/provider-embedding-responses.d.ts +5 -0
- package/esm/src/provider/runtime-loader/provider-embedding-responses.d.ts.map +1 -0
- package/esm/src/provider/runtime-loader/provider-embedding-responses.js +50 -0
- package/esm/src/provider/runtime-loader/provider-finish-reasons.d.ts +9 -0
- package/esm/src/provider/runtime-loader/provider-finish-reasons.d.ts.map +1 -0
- package/esm/src/provider/runtime-loader/provider-finish-reasons.js +60 -0
- package/esm/src/provider/runtime-loader/provider-sse.d.ts +5 -0
- package/esm/src/provider/runtime-loader/provider-sse.d.ts.map +1 -0
- package/esm/src/provider/runtime-loader/provider-sse.js +23 -0
- package/esm/src/provider/runtime-loader/provider-usage.d.ts +19 -0
- package/esm/src/provider/runtime-loader/provider-usage.d.ts.map +1 -0
- package/esm/src/provider/runtime-loader/provider-usage.js +109 -0
- package/esm/src/provider/runtime-loader.d.ts.map +1 -1
- package/esm/src/provider/runtime-loader.js +4 -240
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/agent/hosted-child-mirror.ts +208 -0
- package/src/src/agent/index.ts +15 -0
- package/src/src/chat/hosted-ui-chunk-mapping.ts +303 -0
- package/src/src/chat/index.ts +5 -0
- package/src/src/provider/runtime-loader/provider-embedding-responses.ts +61 -0
- package/src/src/provider/runtime-loader/provider-finish-reasons.ts +69 -0
- package/src/src/provider/runtime-loader/provider-sse.ts +29 -0
- package/src/src/provider/runtime-loader/provider-usage.ts +135 -0
- package/src/src/provider/runtime-loader.ts +21 -300
- package/src/src/utils/version-constant.ts +1 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { readRecord } from "./provider-records.js";
|
|
2
|
+
|
|
3
|
+
export type RuntimeUsage = {
|
|
4
|
+
inputTokens?: number;
|
|
5
|
+
outputTokens?: number;
|
|
6
|
+
totalTokens?: number;
|
|
7
|
+
cacheCreationInputTokens?: number;
|
|
8
|
+
cacheReadInputTokens?: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function extractAnthropicUsage(payload: unknown): RuntimeUsage | undefined {
|
|
12
|
+
const record = readRecord(payload);
|
|
13
|
+
const usage = readRecord(record?.usage);
|
|
14
|
+
if (!usage) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const inputTokens = usage.input_tokens;
|
|
19
|
+
const outputTokens = usage.output_tokens;
|
|
20
|
+
const cacheCreationInputTokens = usage.cache_creation_input_tokens;
|
|
21
|
+
const cacheReadInputTokens = usage.cache_read_input_tokens;
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
|
|
25
|
+
outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
|
|
26
|
+
totalTokens: typeof inputTokens === "number" || typeof outputTokens === "number"
|
|
27
|
+
? (typeof inputTokens === "number" ? inputTokens : 0) +
|
|
28
|
+
(typeof outputTokens === "number" ? outputTokens : 0)
|
|
29
|
+
: undefined,
|
|
30
|
+
...(typeof cacheCreationInputTokens === "number" ? { cacheCreationInputTokens } : {}),
|
|
31
|
+
...(typeof cacheReadInputTokens === "number" ? { cacheReadInputTokens } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function extractGoogleUsage(payload: unknown): RuntimeUsage | undefined {
|
|
36
|
+
const record = readRecord(payload);
|
|
37
|
+
const usage = readRecord(record?.usageMetadata);
|
|
38
|
+
if (!usage) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const inputTokens = usage.promptTokenCount;
|
|
43
|
+
const outputTokens = usage.candidatesTokenCount;
|
|
44
|
+
const totalTokens = usage.totalTokenCount;
|
|
45
|
+
const cachedContentTokenCount = usage.cachedContentTokenCount;
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
|
|
49
|
+
outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
|
|
50
|
+
totalTokens: typeof totalTokens === "number" ? totalTokens : undefined,
|
|
51
|
+
...(typeof cachedContentTokenCount === "number"
|
|
52
|
+
? { cacheReadInputTokens: cachedContentTokenCount }
|
|
53
|
+
: {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function extractOpenAIUsage(payload: unknown): RuntimeUsage | undefined {
|
|
58
|
+
const record = readRecord(payload);
|
|
59
|
+
const usage = readRecord(record?.usage);
|
|
60
|
+
if (!usage) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const inputTokens = usage.prompt_tokens;
|
|
65
|
+
const outputTokens = usage.completion_tokens;
|
|
66
|
+
const totalTokens = usage.total_tokens;
|
|
67
|
+
const promptTokensDetails = readRecord(usage.prompt_tokens_details);
|
|
68
|
+
const cachedTokens = promptTokensDetails?.cached_tokens;
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
|
|
72
|
+
outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
|
|
73
|
+
totalTokens: typeof totalTokens === "number" ? totalTokens : undefined,
|
|
74
|
+
...(typeof cachedTokens === "number" ? { cacheReadInputTokens: cachedTokens } : {}),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The Responses API uses `input_tokens` / `output_tokens` field names
|
|
80
|
+
* instead of Chat Completions' `prompt_tokens` / `completion_tokens`.
|
|
81
|
+
* It also nests cached input tokens under `input_tokens_details` and
|
|
82
|
+
* exposes reasoning tokens via `output_tokens_details.reasoning_tokens`.
|
|
83
|
+
*/
|
|
84
|
+
export function extractOpenAIResponsesUsage(payload: unknown): RuntimeUsage | undefined {
|
|
85
|
+
const record = readRecord(payload);
|
|
86
|
+
// Streaming usage lives on response.completed inside `response.usage`;
|
|
87
|
+
// non-streaming has it at the top level.
|
|
88
|
+
const responseRecord = readRecord(record?.response);
|
|
89
|
+
const usage = readRecord(responseRecord?.usage) ?? readRecord(record?.usage);
|
|
90
|
+
if (!usage) return undefined;
|
|
91
|
+
|
|
92
|
+
const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : undefined;
|
|
93
|
+
const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : undefined;
|
|
94
|
+
const totalTokens = typeof usage.total_tokens === "number"
|
|
95
|
+
? usage.total_tokens
|
|
96
|
+
: (inputTokens !== undefined || outputTokens !== undefined
|
|
97
|
+
? (inputTokens ?? 0) + (outputTokens ?? 0)
|
|
98
|
+
: undefined);
|
|
99
|
+
const inputDetails = readRecord(usage.input_tokens_details);
|
|
100
|
+
const cachedTokens = inputDetails?.cached_tokens;
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
inputTokens,
|
|
104
|
+
outputTokens,
|
|
105
|
+
totalTokens,
|
|
106
|
+
...(typeof cachedTokens === "number" ? { cacheReadInputTokens: cachedTokens } : {}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function mergeUsage(
|
|
111
|
+
current: RuntimeUsage | undefined,
|
|
112
|
+
next: RuntimeUsage | undefined,
|
|
113
|
+
): RuntimeUsage | undefined {
|
|
114
|
+
if (!current) {
|
|
115
|
+
return next;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!next) {
|
|
119
|
+
return current;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const inputTokens = next.inputTokens ?? current.inputTokens;
|
|
123
|
+
const outputTokens = next.outputTokens ?? current.outputTokens;
|
|
124
|
+
const cacheCreationInputTokens = next.cacheCreationInputTokens ??
|
|
125
|
+
current.cacheCreationInputTokens;
|
|
126
|
+
const cacheReadInputTokens = next.cacheReadInputTokens ?? current.cacheReadInputTokens;
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
inputTokens,
|
|
130
|
+
outputTokens,
|
|
131
|
+
totalTokens: (inputTokens ?? 0) + (outputTokens ?? 0),
|
|
132
|
+
...(cacheCreationInputTokens !== undefined ? { cacheCreationInputTokens } : {}),
|
|
133
|
+
...(cacheReadInputTokens !== undefined ? { cacheReadInputTokens } : {}),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -8,11 +8,32 @@ import {
|
|
|
8
8
|
getOpenAIEmbeddingUrl,
|
|
9
9
|
getOpenAIResponsesUrl,
|
|
10
10
|
} from "./runtime-loader/provider-endpoints.js";
|
|
11
|
+
import {
|
|
12
|
+
extractGoogleEmbedding,
|
|
13
|
+
extractGoogleUsageTokens,
|
|
14
|
+
extractOpenAIEmbeddings,
|
|
15
|
+
extractOpenAIUsageTokens,
|
|
16
|
+
} from "./runtime-loader/provider-embedding-responses.js";
|
|
17
|
+
import {
|
|
18
|
+
normalizeAnthropicFinishReason,
|
|
19
|
+
normalizeGoogleFinishReason,
|
|
20
|
+
normalizeOpenAIFinishReason,
|
|
21
|
+
normalizeOpenAIResponsesFinishReason,
|
|
22
|
+
} from "./runtime-loader/provider-finish-reasons.js";
|
|
11
23
|
import {
|
|
12
24
|
createAnthropicRequestInit,
|
|
13
25
|
createGoogleRequestInit,
|
|
14
26
|
createOpenAIRequestInit,
|
|
15
27
|
} from "./runtime-loader/provider-request-init.js";
|
|
28
|
+
import { parseSseChunk } from "./runtime-loader/provider-sse.js";
|
|
29
|
+
import {
|
|
30
|
+
extractAnthropicUsage,
|
|
31
|
+
extractGoogleUsage,
|
|
32
|
+
extractOpenAIResponsesUsage,
|
|
33
|
+
extractOpenAIUsage,
|
|
34
|
+
mergeUsage,
|
|
35
|
+
type RuntimeUsage,
|
|
36
|
+
} from "./runtime-loader/provider-usage.js";
|
|
16
37
|
import type { ProviderKind } from "./runtime-loader/provider-http.js";
|
|
17
38
|
import { requestJson, requestStream } from "./runtime-loader/provider-http.js";
|
|
18
39
|
import { readRecord } from "./runtime-loader/provider-records.js";
|
|
@@ -407,66 +428,6 @@ type GoogleCompatibleRequest = {
|
|
|
407
428
|
[key: string]: unknown;
|
|
408
429
|
};
|
|
409
430
|
|
|
410
|
-
function isNumberArray(value: unknown): value is number[] {
|
|
411
|
-
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
function extractOpenAIEmbeddings(payload: unknown): number[][] {
|
|
415
|
-
const record = readRecord(payload);
|
|
416
|
-
const data = record?.data;
|
|
417
|
-
if (!Array.isArray(data)) {
|
|
418
|
-
throw new Error("Invalid OpenAI embedding response: data array missing");
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
const embeddings: number[][] = [];
|
|
422
|
-
|
|
423
|
-
for (const item of data) {
|
|
424
|
-
const itemRecord = readRecord(item);
|
|
425
|
-
const embedding = itemRecord?.embedding;
|
|
426
|
-
if (!isNumberArray(embedding)) {
|
|
427
|
-
throw new Error("Invalid OpenAI embedding response: embedding vector missing");
|
|
428
|
-
}
|
|
429
|
-
embeddings.push(embedding);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
return embeddings;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
function extractOpenAIUsageTokens(payload: unknown): number | undefined {
|
|
436
|
-
const record = readRecord(payload);
|
|
437
|
-
const usage = readRecord(record?.usage);
|
|
438
|
-
const totalTokens = usage?.total_tokens;
|
|
439
|
-
return typeof totalTokens === "number" ? totalTokens : undefined;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
function extractGoogleEmbedding(payload: unknown): number[] {
|
|
443
|
-
const record = readRecord(payload);
|
|
444
|
-
const embeddings = record?.embeddings;
|
|
445
|
-
|
|
446
|
-
if (Array.isArray(embeddings) && embeddings.length > 0) {
|
|
447
|
-
const firstEmbedding = readRecord(embeddings[0]);
|
|
448
|
-
const values = firstEmbedding?.values;
|
|
449
|
-
if (isNumberArray(values)) {
|
|
450
|
-
return values;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
const embedding = readRecord(record?.embedding);
|
|
455
|
-
const values = embedding?.values;
|
|
456
|
-
if (isNumberArray(values)) {
|
|
457
|
-
return values;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
throw new Error("Invalid Google embedding response: embedding vector missing");
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
function extractGoogleUsageTokens(payload: unknown): number | undefined {
|
|
464
|
-
const record = readRecord(payload);
|
|
465
|
-
const usageMetadata = readRecord(record?.usageMetadata);
|
|
466
|
-
const promptTokenCount = usageMetadata?.promptTokenCount;
|
|
467
|
-
return typeof promptTokenCount === "number" ? promptTokenCount : undefined;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
431
|
/**
|
|
471
432
|
* Structured warning emitted when a provider runtime drops or rewrites a
|
|
472
433
|
* caller-provided option. Mirrors the AI ecosystem convention (Vercel AI
|
|
@@ -624,85 +585,6 @@ function readProviderOptions(
|
|
|
624
585
|
return merged;
|
|
625
586
|
}
|
|
626
587
|
|
|
627
|
-
function normalizeAnthropicFinishReason(
|
|
628
|
-
raw: unknown,
|
|
629
|
-
): string | { unified: string; raw: string } | null {
|
|
630
|
-
if (typeof raw !== "string") {
|
|
631
|
-
return null;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
switch (raw) {
|
|
635
|
-
case "tool_use":
|
|
636
|
-
return { unified: "tool-calls", raw };
|
|
637
|
-
case "end_turn":
|
|
638
|
-
case "stop_sequence":
|
|
639
|
-
return { unified: "stop", raw };
|
|
640
|
-
case "max_tokens":
|
|
641
|
-
return { unified: "length", raw };
|
|
642
|
-
default:
|
|
643
|
-
return raw;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
type RuntimeUsage = {
|
|
648
|
-
inputTokens?: number;
|
|
649
|
-
outputTokens?: number;
|
|
650
|
-
totalTokens?: number;
|
|
651
|
-
cacheCreationInputTokens?: number;
|
|
652
|
-
cacheReadInputTokens?: number;
|
|
653
|
-
};
|
|
654
|
-
|
|
655
|
-
function extractAnthropicUsage(payload: unknown): RuntimeUsage | undefined {
|
|
656
|
-
const record = readRecord(payload);
|
|
657
|
-
const usage = readRecord(record?.usage);
|
|
658
|
-
if (!usage) {
|
|
659
|
-
return undefined;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
const inputTokens = usage.input_tokens;
|
|
663
|
-
const outputTokens = usage.output_tokens;
|
|
664
|
-
const cacheCreationInputTokens = usage.cache_creation_input_tokens;
|
|
665
|
-
const cacheReadInputTokens = usage.cache_read_input_tokens;
|
|
666
|
-
|
|
667
|
-
return {
|
|
668
|
-
inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
|
|
669
|
-
outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
|
|
670
|
-
totalTokens: typeof inputTokens === "number" || typeof outputTokens === "number"
|
|
671
|
-
? (typeof inputTokens === "number" ? inputTokens : 0) +
|
|
672
|
-
(typeof outputTokens === "number" ? outputTokens : 0)
|
|
673
|
-
: undefined,
|
|
674
|
-
...(typeof cacheCreationInputTokens === "number" ? { cacheCreationInputTokens } : {}),
|
|
675
|
-
...(typeof cacheReadInputTokens === "number" ? { cacheReadInputTokens } : {}),
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
function mergeUsage(
|
|
680
|
-
current: RuntimeUsage | undefined,
|
|
681
|
-
next: RuntimeUsage | undefined,
|
|
682
|
-
): RuntimeUsage | undefined {
|
|
683
|
-
if (!current) {
|
|
684
|
-
return next;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
if (!next) {
|
|
688
|
-
return current;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
const inputTokens = next.inputTokens ?? current.inputTokens;
|
|
692
|
-
const outputTokens = next.outputTokens ?? current.outputTokens;
|
|
693
|
-
const cacheCreationInputTokens = next.cacheCreationInputTokens ??
|
|
694
|
-
current.cacheCreationInputTokens;
|
|
695
|
-
const cacheReadInputTokens = next.cacheReadInputTokens ?? current.cacheReadInputTokens;
|
|
696
|
-
|
|
697
|
-
return {
|
|
698
|
-
inputTokens,
|
|
699
|
-
outputTokens,
|
|
700
|
-
totalTokens: (inputTokens ?? 0) + (outputTokens ?? 0),
|
|
701
|
-
...(cacheCreationInputTokens !== undefined ? { cacheCreationInputTokens } : {}),
|
|
702
|
-
...(cacheReadInputTokens !== undefined ? { cacheReadInputTokens } : {}),
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
|
|
706
588
|
function normalizeAnthropicToolChoice(toolChoice: unknown): unknown {
|
|
707
589
|
if (typeof toolChoice === "string") {
|
|
708
590
|
return { type: toolChoice };
|
|
@@ -1342,36 +1224,6 @@ function buildAnthropicGenerateResult(payload: unknown): {
|
|
|
1342
1224
|
};
|
|
1343
1225
|
}
|
|
1344
1226
|
|
|
1345
|
-
function parseSseChunk(chunk: string): {
|
|
1346
|
-
events: Array<unknown | "[DONE]">;
|
|
1347
|
-
remainder: string;
|
|
1348
|
-
} {
|
|
1349
|
-
const blocks = chunk.split(/\r?\n\r?\n/);
|
|
1350
|
-
const remainder = blocks.pop() ?? "";
|
|
1351
|
-
const events = blocks.flatMap((block) => {
|
|
1352
|
-
const dataLines = block.split(/\r?\n/)
|
|
1353
|
-
.filter((line) => line.startsWith("data:"))
|
|
1354
|
-
.map((line) => line.slice(5).trimStart());
|
|
1355
|
-
|
|
1356
|
-
if (!dataLines.length) {
|
|
1357
|
-
return [];
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
const payload = dataLines.join("\n").trim();
|
|
1361
|
-
if (payload === "[DONE]") {
|
|
1362
|
-
return ["[DONE]" as const];
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
|
-
try {
|
|
1366
|
-
return [JSON.parse(payload) as unknown];
|
|
1367
|
-
} catch {
|
|
1368
|
-
return [];
|
|
1369
|
-
}
|
|
1370
|
-
});
|
|
1371
|
-
|
|
1372
|
-
return { events, remainder };
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
1227
|
async function* streamAnthropicCompatibleParts(
|
|
1376
1228
|
stream: ReadableStream<Uint8Array>,
|
|
1377
1229
|
): AsyncIterable<unknown> {
|
|
@@ -1613,45 +1465,6 @@ async function* streamAnthropicCompatibleParts(
|
|
|
1613
1465
|
};
|
|
1614
1466
|
}
|
|
1615
1467
|
|
|
1616
|
-
function normalizeOpenAIFinishReason(
|
|
1617
|
-
raw: unknown,
|
|
1618
|
-
): string | { unified: string; raw: string } | null {
|
|
1619
|
-
if (typeof raw !== "string") {
|
|
1620
|
-
return null;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
if (raw === "tool_calls") {
|
|
1624
|
-
return { unified: "tool-calls", raw };
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
|
-
if (raw === "content_filter") {
|
|
1628
|
-
return { unified: "content-filter", raw };
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
return raw;
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
function extractOpenAIUsage(payload: unknown): RuntimeUsage | undefined {
|
|
1635
|
-
const record = readRecord(payload);
|
|
1636
|
-
const usage = readRecord(record?.usage);
|
|
1637
|
-
if (!usage) {
|
|
1638
|
-
return undefined;
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
const inputTokens = usage.prompt_tokens;
|
|
1642
|
-
const outputTokens = usage.completion_tokens;
|
|
1643
|
-
const totalTokens = usage.total_tokens;
|
|
1644
|
-
const promptTokensDetails = readRecord(usage.prompt_tokens_details);
|
|
1645
|
-
const cachedTokens = promptTokensDetails?.cached_tokens;
|
|
1646
|
-
|
|
1647
|
-
return {
|
|
1648
|
-
inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
|
|
1649
|
-
outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
|
|
1650
|
-
totalTokens: typeof totalTokens === "number" ? totalTokens : undefined,
|
|
1651
|
-
...(typeof cachedTokens === "number" ? { cacheReadInputTokens: cachedTokens } : {}),
|
|
1652
|
-
};
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
1468
|
function extractOpenAIContentText(content: unknown): string {
|
|
1656
1469
|
if (typeof content === "string") {
|
|
1657
1470
|
return content;
|
|
@@ -1874,48 +1687,6 @@ function buildOpenAIChatRequest(
|
|
|
1874
1687
|
return body;
|
|
1875
1688
|
}
|
|
1876
1689
|
|
|
1877
|
-
function normalizeGoogleFinishReason(
|
|
1878
|
-
raw: unknown,
|
|
1879
|
-
): string | { unified: string; raw: string } | null {
|
|
1880
|
-
if (typeof raw !== "string") {
|
|
1881
|
-
return null;
|
|
1882
|
-
}
|
|
1883
|
-
|
|
1884
|
-
switch (raw) {
|
|
1885
|
-
case "STOP":
|
|
1886
|
-
return { unified: "stop", raw };
|
|
1887
|
-
case "MAX_TOKENS":
|
|
1888
|
-
return { unified: "length", raw };
|
|
1889
|
-
case "SAFETY":
|
|
1890
|
-
case "RECITATION":
|
|
1891
|
-
return { unified: "content-filter", raw };
|
|
1892
|
-
default:
|
|
1893
|
-
return raw.toLowerCase();
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
function extractGoogleUsage(payload: unknown): RuntimeUsage | undefined {
|
|
1898
|
-
const record = readRecord(payload);
|
|
1899
|
-
const usage = readRecord(record?.usageMetadata);
|
|
1900
|
-
if (!usage) {
|
|
1901
|
-
return undefined;
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
const inputTokens = usage.promptTokenCount;
|
|
1905
|
-
const outputTokens = usage.candidatesTokenCount;
|
|
1906
|
-
const totalTokens = usage.totalTokenCount;
|
|
1907
|
-
const cachedContentTokenCount = usage.cachedContentTokenCount;
|
|
1908
|
-
|
|
1909
|
-
return {
|
|
1910
|
-
inputTokens: typeof inputTokens === "number" ? inputTokens : undefined,
|
|
1911
|
-
outputTokens: typeof outputTokens === "number" ? outputTokens : undefined,
|
|
1912
|
-
totalTokens: typeof totalTokens === "number" ? totalTokens : undefined,
|
|
1913
|
-
...(typeof cachedContentTokenCount === "number"
|
|
1914
|
-
? { cacheReadInputTokens: cachedContentTokenCount }
|
|
1915
|
-
: {}),
|
|
1916
|
-
};
|
|
1917
|
-
}
|
|
1918
|
-
|
|
1919
1690
|
function toGoogleContents(
|
|
1920
1691
|
prompt: RuntimePromptMessage[],
|
|
1921
1692
|
): {
|
|
@@ -2941,56 +2712,6 @@ function buildOpenAIResponsesRequest(
|
|
|
2941
2712
|
return body;
|
|
2942
2713
|
}
|
|
2943
2714
|
|
|
2944
|
-
/**
|
|
2945
|
-
* The Responses API uses `input_tokens` / `output_tokens` field names
|
|
2946
|
-
* instead of Chat Completions' `prompt_tokens` / `completion_tokens`.
|
|
2947
|
-
* It also nests cached input tokens under `input_tokens_details` and
|
|
2948
|
-
* exposes reasoning tokens via `output_tokens_details.reasoning_tokens`.
|
|
2949
|
-
*/
|
|
2950
|
-
function extractOpenAIResponsesUsage(payload: unknown): RuntimeUsage | undefined {
|
|
2951
|
-
const record = readRecord(payload);
|
|
2952
|
-
// Streaming usage lives on response.completed inside `response.usage`;
|
|
2953
|
-
// non-streaming has it at the top level.
|
|
2954
|
-
const responseRecord = readRecord(record?.response);
|
|
2955
|
-
const usage = readRecord(responseRecord?.usage) ?? readRecord(record?.usage);
|
|
2956
|
-
if (!usage) return undefined;
|
|
2957
|
-
|
|
2958
|
-
const inputTokens = typeof usage.input_tokens === "number" ? usage.input_tokens : undefined;
|
|
2959
|
-
const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : undefined;
|
|
2960
|
-
const totalTokens = typeof usage.total_tokens === "number"
|
|
2961
|
-
? usage.total_tokens
|
|
2962
|
-
: (inputTokens !== undefined || outputTokens !== undefined
|
|
2963
|
-
? (inputTokens ?? 0) + (outputTokens ?? 0)
|
|
2964
|
-
: undefined);
|
|
2965
|
-
const inputDetails = readRecord(usage.input_tokens_details);
|
|
2966
|
-
const cachedTokens = inputDetails?.cached_tokens;
|
|
2967
|
-
|
|
2968
|
-
return {
|
|
2969
|
-
inputTokens,
|
|
2970
|
-
outputTokens,
|
|
2971
|
-
totalTokens,
|
|
2972
|
-
...(typeof cachedTokens === "number" ? { cacheReadInputTokens: cachedTokens } : {}),
|
|
2973
|
-
};
|
|
2974
|
-
}
|
|
2975
|
-
|
|
2976
|
-
function normalizeOpenAIResponsesFinishReason(
|
|
2977
|
-
raw: unknown,
|
|
2978
|
-
): string | { unified: string; raw: string } | null {
|
|
2979
|
-
if (typeof raw !== "string") return null;
|
|
2980
|
-
switch (raw) {
|
|
2981
|
-
case "completed":
|
|
2982
|
-
return { unified: "stop", raw };
|
|
2983
|
-
case "incomplete":
|
|
2984
|
-
return { unified: "length", raw };
|
|
2985
|
-
case "failed":
|
|
2986
|
-
return { unified: "error", raw };
|
|
2987
|
-
case "in_progress":
|
|
2988
|
-
return null;
|
|
2989
|
-
default:
|
|
2990
|
-
return raw;
|
|
2991
|
-
}
|
|
2992
|
-
}
|
|
2993
|
-
|
|
2994
2715
|
type OpenAIResponsesContentPart =
|
|
2995
2716
|
| { type: "text"; text: string }
|
|
2996
2717
|
| {
|