@codehz/ai 0.1.4 → 0.1.6
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 +2 -2
- package/dist/index.d.mts +62 -15
- package/dist/index.mjs +122 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/chat-completions.ts +10 -18
- package/src/adapters/messages.ts +18 -25
- package/src/adapters/ollama.ts +7 -17
- package/src/adapters/responses.ts +4 -11
- package/src/core/validation.ts +21 -3
- package/src/helpers/index.ts +6 -0
- package/src/helpers/mapping.ts +3 -2
- package/src/helpers/usage-mapping.ts +150 -0
- package/src/types/content.ts +5 -2
- package/src/types/index.ts +1 -1
- package/src/types/items.ts +1 -1
- package/src/types/request.ts +2 -2
- package/src/types/response.ts +7 -0
- package/bun.lock +0 -231
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ for await (const event of stream) {
|
|
|
39
39
|
|
|
40
40
|
```ts
|
|
41
41
|
type AIRequest = {
|
|
42
|
-
instructions?: string; //
|
|
42
|
+
instructions?: string | InstructionBlock[]; // 系统级指令
|
|
43
43
|
input: InputItem[]; // 输入 items
|
|
44
44
|
tools?: ToolDefinition[]; // 工具声明
|
|
45
45
|
toolChoice?: ToolChoice; // 工具选择策略
|
|
@@ -53,7 +53,7 @@ type AIRequest = {
|
|
|
53
53
|
|
|
54
54
|
| Item 类型 | 用途 |
|
|
55
55
|
| ------------- | ----------------------------------- |
|
|
56
|
-
| `message` | 用户 /
|
|
56
|
+
| `message` | 用户 / 助手消息 |
|
|
57
57
|
| `reasoning` | 思维链(输入侧 replay) |
|
|
58
58
|
| `tool_call` | 模型发起的工具调用(输入侧 replay) |
|
|
59
59
|
| `tool_result` | 工具执行结果 |
|
package/dist/index.d.mts
CHANGED
|
@@ -4,13 +4,16 @@
|
|
|
4
4
|
*
|
|
5
5
|
* 覆盖文本、JSON、图片、二进制引用和后端私有内容。
|
|
6
6
|
*/
|
|
7
|
-
type
|
|
7
|
+
type TextContentBlock = {
|
|
8
8
|
type: "text";
|
|
9
9
|
text: string;
|
|
10
|
-
}
|
|
10
|
+
};
|
|
11
|
+
type JsonContentBlock = {
|
|
11
12
|
type: "json";
|
|
12
13
|
json: unknown;
|
|
13
|
-
}
|
|
14
|
+
};
|
|
15
|
+
type InstructionBlock = TextContentBlock | JsonContentBlock;
|
|
16
|
+
type ContentBlock = InstructionBlock | {
|
|
14
17
|
type: "image";
|
|
15
18
|
imageUrl: string;
|
|
16
19
|
} | {
|
|
@@ -25,7 +28,7 @@ type ContentBlock = {
|
|
|
25
28
|
type MessageItem = {
|
|
26
29
|
type: "message";
|
|
27
30
|
id?: string;
|
|
28
|
-
role: "user" | "assistant"
|
|
31
|
+
role: "user" | "assistant";
|
|
29
32
|
content: ContentBlock[];
|
|
30
33
|
};
|
|
31
34
|
type ReasoningItem = {
|
|
@@ -78,7 +81,7 @@ type IncludeSettings = {
|
|
|
78
81
|
providerMetadata?: "off" | "best_effort";
|
|
79
82
|
};
|
|
80
83
|
type AIRequest = {
|
|
81
|
-
instructions?: string |
|
|
84
|
+
instructions?: string | InstructionBlock[];
|
|
82
85
|
input: InputItem[];
|
|
83
86
|
tools?: ToolDefinition[];
|
|
84
87
|
toolChoice?: ToolChoice;
|
|
@@ -91,13 +94,13 @@ type AIRequest = {
|
|
|
91
94
|
//#region src/types/response.d.ts
|
|
92
95
|
type StopReason = "end_turn" | "tool_call" | "max_output_tokens" | "content_filter" | "error" | "unknown";
|
|
93
96
|
type Usage = {
|
|
94
|
-
inputTokens?: number;
|
|
95
|
-
outputTokens?: number;
|
|
97
|
+
/** Provider prompt / input token count */inputTokens?: number; /** Provider completion / output token count */
|
|
98
|
+
outputTokens?: number; /** Reasoning tokens when provider exposes output breakdown (e.g. OpenAI Responses) */
|
|
96
99
|
reasoningTokens?: number;
|
|
97
|
-
totalTokens?: number;
|
|
98
|
-
cachedInputTokens?: number;
|
|
99
|
-
cacheWriteInputTokens?: number;
|
|
100
|
-
billableInputTokens?: number;
|
|
100
|
+
totalTokens?: number; /** Tokens read from prompt cache (OpenAI cached_tokens, Anthropic cache_read_input_tokens) */
|
|
101
|
+
cachedInputTokens?: number; /** Tokens written to prompt cache (Anthropic cache_creation_input_tokens) */
|
|
102
|
+
cacheWriteInputTokens?: number; /** Best-effort billable input (full-rate input; excludes discounted cache reads where known) */
|
|
103
|
+
billableInputTokens?: number; /** Best-effort billable output (non-reasoning slice when provider gives reasoning breakdown) */
|
|
101
104
|
billableOutputTokens?: number;
|
|
102
105
|
};
|
|
103
106
|
type BillingInfo = {
|
|
@@ -542,7 +545,7 @@ type ResponsesAPIRequest = {
|
|
|
542
545
|
};
|
|
543
546
|
type ResponsesInputItem = {
|
|
544
547
|
type: "message";
|
|
545
|
-
role: "user" | "assistant"
|
|
548
|
+
role: "user" | "assistant";
|
|
546
549
|
content: string;
|
|
547
550
|
} | {
|
|
548
551
|
type: "message";
|
|
@@ -959,9 +962,9 @@ declare function blockToText(b: ContentBlock): string;
|
|
|
959
962
|
*/
|
|
960
963
|
declare function contentBlocksToText(blocks: ContentBlock[]): string;
|
|
961
964
|
/**
|
|
962
|
-
* 将 instructions(string |
|
|
965
|
+
* 将 instructions(string | InstructionBlock[])归一化为纯文本。
|
|
963
966
|
*/
|
|
964
|
-
declare function instructionsToText(instructions: string |
|
|
967
|
+
declare function instructionsToText(instructions: string | InstructionBlock[]): string;
|
|
965
968
|
/**
|
|
966
969
|
* 从 OutputItem 数组中提取所有 message 类型 item 的文本内容。
|
|
967
970
|
*/
|
|
@@ -1043,5 +1046,49 @@ type SyntheticStreamOptions = {
|
|
|
1043
1046
|
*/
|
|
1044
1047
|
declare function syntheticStream(options: SyntheticStreamOptions): AsyncIterable<AIStreamEvent>;
|
|
1045
1048
|
//#endregion
|
|
1046
|
-
|
|
1049
|
+
//#region src/helpers/usage-mapping.d.ts
|
|
1050
|
+
/** OpenAI Chat Completions `usage` */
|
|
1051
|
+
declare function usageFromChatCompletions(raw: {
|
|
1052
|
+
prompt_tokens?: number;
|
|
1053
|
+
completion_tokens?: number;
|
|
1054
|
+
total_tokens?: number;
|
|
1055
|
+
prompt_tokens_details?: {
|
|
1056
|
+
cached_tokens?: number;
|
|
1057
|
+
[key: string]: unknown;
|
|
1058
|
+
};
|
|
1059
|
+
completion_tokens_details?: {
|
|
1060
|
+
reasoning_tokens?: number;
|
|
1061
|
+
[key: string]: unknown;
|
|
1062
|
+
};
|
|
1063
|
+
}): Partial<Usage>;
|
|
1064
|
+
/** OpenAI Responses API `usage` */
|
|
1065
|
+
declare function usageFromOpenAIResponses(raw: {
|
|
1066
|
+
input_tokens?: number;
|
|
1067
|
+
output_tokens?: number;
|
|
1068
|
+
total_tokens?: number;
|
|
1069
|
+
input_tokens_details?: {
|
|
1070
|
+
cached_tokens?: number;
|
|
1071
|
+
[key: string]: unknown;
|
|
1072
|
+
};
|
|
1073
|
+
output_tokens_details?: {
|
|
1074
|
+
reasoning_tokens?: number;
|
|
1075
|
+
[key: string]: unknown;
|
|
1076
|
+
};
|
|
1077
|
+
[key: string]: unknown;
|
|
1078
|
+
}): Partial<Usage>;
|
|
1079
|
+
/** Anthropic Messages `usage`(message_start / message_delta) */
|
|
1080
|
+
declare function usageFromAnthropicMessages(raw: {
|
|
1081
|
+
input_tokens?: number;
|
|
1082
|
+
output_tokens?: number;
|
|
1083
|
+
cache_creation_input_tokens?: number;
|
|
1084
|
+
cache_read_input_tokens?: number;
|
|
1085
|
+
[key: string]: unknown;
|
|
1086
|
+
}): Partial<Usage>;
|
|
1087
|
+
/** Ollama 流式 chunk(无 cache / reasoning 细分时仅填基础与 billable 镜像) */
|
|
1088
|
+
declare function usageFromOllama(raw: {
|
|
1089
|
+
prompt_eval_count?: number;
|
|
1090
|
+
eval_count?: number;
|
|
1091
|
+
}): Partial<Usage>;
|
|
1092
|
+
//#endregion
|
|
1093
|
+
export { type AIClient, AIError, AIMappingError, AIProviderError, type AIRequest, AIRequestError, type AIResponse, AIStreamError, type AIStreamEvent, AdapterAuxiliaryState, AdapterBase, AuxiliaryCollector, type AuxiliaryFinalizeOptions, type AuxiliaryFinalizeResult, type AuxiliaryInfo, type BackendAdapter, type BackendTrace, type BillingInfo, type BillingPostprocessHook, type BillingSource, ChatCompletionsAdapter, type ChatCompletionsAdapterOptions, type ContentBlock, type CreateAIClientOptions, type EventFactory, type EventFactoryBackend, type EventFactoryState, type FetchFn, type IncludeSettings, type InputItem, type InstructionBlock, type JsonContentBlock, type LookupResult, type MessageCompletedEvent, type MessageDeltaEvent, type MessageItem, type MessageStartedEvent, MessagesAdapter, type MessagesAdapterOptions, MockAdapter, type MockAdapterOptions, type MockAuxiliaryStep, type MockCompleteStep, type MockErrorStep, type MockHandler, type MockHandlerContext, type MockHistoryRecord, type MockInputExpectation, type MockInterruptStep, type MockMessageStep, type MockOutputStep, type MockReasoningStep, type MockRequestExpectation, type MockStaticHandler, type MockStep, type MockTextStreamOptions, type MockThrowStep, type MockToolCallStep, type MockWarningStep, type NormalizeOptions, type NormalizedRequest, OllamaAdapter, type OllamaAdapterOptions, type OpaqueItem, type OutputItem, type ReasoningCompletedEvent, type ReasoningDeltaEvent, type ReasoningItem, type ReasoningStartedEvent, type ReplayItem, type ResponseAuxiliaryEvent, type ResponseCompletedEvent, type ResponseStartedEvent, type ResponseWarningEvent, ResponsesAdapter, type ResponsesAdapterOptions, type SSEEvent, type StopReason, type StreamEventBase, type StreamResult, type SyntheticStreamOptions, type TextContentBlock, type ToolCallCompletedEvent, type ToolCallDeltaEvent, type ToolCallItem, type ToolCallStartedEvent, type ToolChoice, type ToolDefinition, type ToolResultItem, type Usage, type UsageSource, type ValidationIssue, WarningCode, aggregateEvents, assertMockRequest, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createEventFactory, emitMalformedStreamWarning, extractText, imageBlock, instructionsToText, jsonBlock, mapReasoningVisibility, mapStopReason, messageItem, metadataSourceList, normalizeRequest, opaqueBlock, opaqueItem, parseSSEEvents, reasoningItem, replayFromOutput, syntheticStream, textBlock, toolCallItem, toolResultItem, usageFromAnthropicMessages, usageFromChatCompletions, usageFromOllama, usageFromOpenAIResponses, validateRequest, withMockStreaming };
|
|
1047
1094
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -63,12 +63,7 @@ const WarningCode = {
|
|
|
63
63
|
};
|
|
64
64
|
//#endregion
|
|
65
65
|
//#region src/core/validation.ts
|
|
66
|
-
const MESSAGE_ROLES = /* @__PURE__ */ new Set([
|
|
67
|
-
"user",
|
|
68
|
-
"assistant",
|
|
69
|
-
"system",
|
|
70
|
-
"developer"
|
|
71
|
-
]);
|
|
66
|
+
const MESSAGE_ROLES = /* @__PURE__ */ new Set(["user", "assistant"]);
|
|
72
67
|
const REASONING_VISIBILITIES = /* @__PURE__ */ new Set([
|
|
73
68
|
"full",
|
|
74
69
|
"summary",
|
|
@@ -122,6 +117,19 @@ function validateContentArray(content, field, issues, code) {
|
|
|
122
117
|
}
|
|
123
118
|
for (let i = 0; i < content.length; i++) validateContentBlock(content[i], `${field}[${i}]`, issues);
|
|
124
119
|
}
|
|
120
|
+
function validateInstructionArray(content, field, issues) {
|
|
121
|
+
if (!Array.isArray(content)) {
|
|
122
|
+
pushIssue(issues, field, "INSTRUCTIONS_INVALID", `${field} must be an InstructionBlock[]`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
for (let i = 0; i < content.length; i++) {
|
|
126
|
+
const block = content[i];
|
|
127
|
+
const blockField = `${field}[${i}]`;
|
|
128
|
+
validateContentBlock(block, blockField, issues);
|
|
129
|
+
if (!isRecord(block) || typeof block.type !== "string") continue;
|
|
130
|
+
if (block.type !== "text" && block.type !== "json") pushIssue(issues, blockField, "INSTRUCTIONS_INVALID", `${blockField} only supports text/json blocks`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
125
133
|
function validateInputItem(item, field, issues) {
|
|
126
134
|
if (!isRecord(item)) {
|
|
127
135
|
pushIssue(issues, field, "INPUT_INVALID_ITEM", `${field} must be a valid InputItem`);
|
|
@@ -192,8 +200,8 @@ function validateToolChoice(toolChoice, issues) {
|
|
|
192
200
|
*/
|
|
193
201
|
function validateRequest(request) {
|
|
194
202
|
const issues = [];
|
|
195
|
-
if (request.instructions !== void 0) if (typeof request.instructions === "string") {} else if (Array.isArray(request.instructions))
|
|
196
|
-
else pushIssue(issues, "instructions", "INSTRUCTIONS_INVALID", "instructions must be a string or
|
|
203
|
+
if (request.instructions !== void 0) if (typeof request.instructions === "string") {} else if (Array.isArray(request.instructions)) validateInstructionArray(request.instructions, "instructions", issues);
|
|
204
|
+
else pushIssue(issues, "instructions", "INSTRUCTIONS_INVALID", "instructions must be a string or InstructionBlock[]");
|
|
197
205
|
if (!Array.isArray(request.input) || request.input.length === 0) pushIssue(issues, "input", "INPUT_EMPTY", "input must be a non-empty array");
|
|
198
206
|
if (Array.isArray(request.input)) for (let i = 0; i < request.input.length; i++) validateInputItem(request.input[i], `input[${i}]`, issues);
|
|
199
207
|
if (request.temperature !== void 0) {
|
|
@@ -713,7 +721,7 @@ function contentBlocksToText(blocks) {
|
|
|
713
721
|
return blocks.map(blockToText).join("\n");
|
|
714
722
|
}
|
|
715
723
|
/**
|
|
716
|
-
* 将 instructions(string |
|
|
724
|
+
* 将 instructions(string | InstructionBlock[])归一化为纯文本。
|
|
717
725
|
*/
|
|
718
726
|
function instructionsToText(instructions) {
|
|
719
727
|
return typeof instructions === "string" ? instructions : contentBlocksToText(instructions);
|
|
@@ -1003,6 +1011,93 @@ function mergeWarnings(...groups) {
|
|
|
1003
1011
|
return merged.length > 0 ? merged : void 0;
|
|
1004
1012
|
}
|
|
1005
1013
|
//#endregion
|
|
1014
|
+
//#region src/helpers/usage-mapping.ts
|
|
1015
|
+
function num(value) {
|
|
1016
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1017
|
+
}
|
|
1018
|
+
function record(obj) {
|
|
1019
|
+
const out = {};
|
|
1020
|
+
for (const [key, value] of Object.entries(obj)) if (value !== void 0) out[key] = value;
|
|
1021
|
+
return out;
|
|
1022
|
+
}
|
|
1023
|
+
function billableFromOpenAIStyle(inputTokens, outputTokens, cachedInputTokens, reasoningTokens) {
|
|
1024
|
+
let billableInputTokens;
|
|
1025
|
+
if (inputTokens !== void 0) billableInputTokens = cachedInputTokens !== void 0 ? Math.max(0, inputTokens - cachedInputTokens) : inputTokens;
|
|
1026
|
+
let billableOutputTokens;
|
|
1027
|
+
if (outputTokens !== void 0) billableOutputTokens = reasoningTokens !== void 0 ? Math.max(0, outputTokens - reasoningTokens) : outputTokens;
|
|
1028
|
+
return record({
|
|
1029
|
+
billableInputTokens,
|
|
1030
|
+
billableOutputTokens
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
/** OpenAI Chat Completions `usage` */
|
|
1034
|
+
function usageFromChatCompletions(raw) {
|
|
1035
|
+
const inputTokens = num(raw.prompt_tokens);
|
|
1036
|
+
const outputTokens = num(raw.completion_tokens);
|
|
1037
|
+
const cachedInputTokens = num(raw.prompt_tokens_details?.cached_tokens);
|
|
1038
|
+
const reasoningTokens = num(raw.completion_tokens_details?.reasoning_tokens);
|
|
1039
|
+
return record({
|
|
1040
|
+
inputTokens,
|
|
1041
|
+
outputTokens,
|
|
1042
|
+
totalTokens: num(raw.total_tokens) ?? (inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0),
|
|
1043
|
+
cachedInputTokens,
|
|
1044
|
+
reasoningTokens,
|
|
1045
|
+
...billableFromOpenAIStyle(inputTokens, outputTokens, cachedInputTokens, reasoningTokens)
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
/** OpenAI Responses API `usage` */
|
|
1049
|
+
function usageFromOpenAIResponses(raw) {
|
|
1050
|
+
const inputTokens = num(raw.input_tokens);
|
|
1051
|
+
const outputTokens = num(raw.output_tokens);
|
|
1052
|
+
const cachedInputTokens = num(raw.input_tokens_details?.cached_tokens);
|
|
1053
|
+
const reasoningTokens = num(raw.output_tokens_details?.reasoning_tokens);
|
|
1054
|
+
return record({
|
|
1055
|
+
inputTokens,
|
|
1056
|
+
outputTokens,
|
|
1057
|
+
totalTokens: num(raw.total_tokens) ?? (inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0),
|
|
1058
|
+
cachedInputTokens,
|
|
1059
|
+
reasoningTokens,
|
|
1060
|
+
...billableFromOpenAIStyle(inputTokens, outputTokens, cachedInputTokens, reasoningTokens)
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
/** Anthropic Messages `usage`(message_start / message_delta) */
|
|
1064
|
+
function usageFromAnthropicMessages(raw) {
|
|
1065
|
+
const inputTokens = num(raw.input_tokens);
|
|
1066
|
+
const outputTokens = num(raw.output_tokens);
|
|
1067
|
+
const cacheWriteInputTokens = num(raw.cache_creation_input_tokens);
|
|
1068
|
+
const cachedInputTokens = num(raw.cache_read_input_tokens);
|
|
1069
|
+
const inputParts = [
|
|
1070
|
+
inputTokens,
|
|
1071
|
+
cacheWriteInputTokens,
|
|
1072
|
+
cachedInputTokens
|
|
1073
|
+
].filter((n) => n !== void 0);
|
|
1074
|
+
const summedInput = inputParts.length > 0 ? inputParts.reduce((sum, n) => sum + n, 0) : void 0;
|
|
1075
|
+
const totalTokens = summedInput !== void 0 && outputTokens !== void 0 ? summedInput + outputTokens : void 0;
|
|
1076
|
+
let billableInputTokens;
|
|
1077
|
+
if (inputTokens !== void 0 || cacheWriteInputTokens !== void 0) billableInputTokens = (inputTokens ?? 0) + (cacheWriteInputTokens ?? 0);
|
|
1078
|
+
return record({
|
|
1079
|
+
inputTokens,
|
|
1080
|
+
outputTokens,
|
|
1081
|
+
totalTokens,
|
|
1082
|
+
cachedInputTokens,
|
|
1083
|
+
cacheWriteInputTokens,
|
|
1084
|
+
billableInputTokens,
|
|
1085
|
+
billableOutputTokens: outputTokens
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
/** Ollama 流式 chunk(无 cache / reasoning 细分时仅填基础与 billable 镜像) */
|
|
1089
|
+
function usageFromOllama(raw) {
|
|
1090
|
+
const inputTokens = num(raw.prompt_eval_count);
|
|
1091
|
+
const outputTokens = num(raw.eval_count);
|
|
1092
|
+
return record({
|
|
1093
|
+
inputTokens,
|
|
1094
|
+
outputTokens,
|
|
1095
|
+
totalTokens: inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0,
|
|
1096
|
+
billableInputTokens: inputTokens,
|
|
1097
|
+
billableOutputTokens: outputTokens
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
//#endregion
|
|
1006
1101
|
//#region src/helpers/sse-parser.ts
|
|
1007
1102
|
/**
|
|
1008
1103
|
* 将 SSE 文本块解析为事件数组。
|
|
@@ -1305,11 +1400,7 @@ var ResponsesAdapter = class extends AdapterBase {
|
|
|
1305
1400
|
let rawResponseId;
|
|
1306
1401
|
if (completedResponse) {
|
|
1307
1402
|
rawResponseId = completedResponse.id;
|
|
1308
|
-
if (completedResponse.usage) auxiliary.recordUsage(
|
|
1309
|
-
inputTokens: completedResponse.usage.input_tokens,
|
|
1310
|
-
outputTokens: completedResponse.usage.output_tokens,
|
|
1311
|
-
totalTokens: completedResponse.usage.total_tokens
|
|
1312
|
-
}, "final", completedResponse.usage);
|
|
1403
|
+
if (completedResponse.usage) auxiliary.recordUsage(usageFromOpenAIResponses(completedResponse.usage), "final", completedResponse.usage);
|
|
1313
1404
|
}
|
|
1314
1405
|
const replay = [...replayFromOutput(output)];
|
|
1315
1406
|
if (completedResponse?.id) replay.push(opaqueItem("responses", "replay", { id: completedResponse.id }));
|
|
@@ -1380,6 +1471,10 @@ function parseMessagesSSE(chunk) {
|
|
|
1380
1471
|
function rollbackTrailingAssistantMessages$2(messages) {
|
|
1381
1472
|
while (messages.length > 0 && messages[messages.length - 1]?.role === "assistant") messages.pop();
|
|
1382
1473
|
}
|
|
1474
|
+
/** 用 response 级别的命名空间合成 content block 的 item ID,避免多轮工具循环 ID 碰撞 */
|
|
1475
|
+
function synthesizeItemId(kind, blockIndex, responseId) {
|
|
1476
|
+
return `${kind}-${blockIndex}-${responseId}`;
|
|
1477
|
+
}
|
|
1383
1478
|
function parseToolUseInput(input) {
|
|
1384
1479
|
try {
|
|
1385
1480
|
const parsed = JSON.parse(input);
|
|
@@ -1447,11 +1542,6 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
1447
1542
|
if (request.instructions) systemPrompt = instructionsToMessagesText(request.instructions);
|
|
1448
1543
|
for (const item of request.input) switch (item.type) {
|
|
1449
1544
|
case "message": {
|
|
1450
|
-
if (item.role === "system" || item.role === "developer") {
|
|
1451
|
-
const text = contentBlocksToText(ensureMessagesTextBlocks(item.content, `input message (${item.role}) content`));
|
|
1452
|
-
systemPrompt = systemPrompt ? `${systemPrompt}\n${text}` : text;
|
|
1453
|
-
break;
|
|
1454
|
-
}
|
|
1455
1545
|
const role = item.role === "user" ? "user" : "assistant";
|
|
1456
1546
|
const supportedContent = ensureMessagesTextBlocks(item.content, `input message (${item.role}) content`);
|
|
1457
1547
|
if (supportedContent.length === 1 && supportedContent[0]?.type === "text") messages.push({
|
|
@@ -1581,7 +1671,7 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
1581
1671
|
let argsBuffer = "";
|
|
1582
1672
|
let stopReason;
|
|
1583
1673
|
let stopSequence;
|
|
1584
|
-
let rawResponseId;
|
|
1674
|
+
let rawResponseId = "";
|
|
1585
1675
|
if (request.include?.providerMetadata !== "off") {
|
|
1586
1676
|
const headerMetadata = pickProviderHeaders(response.headers);
|
|
1587
1677
|
auxiliary.recordProviderMetadata("header", Object.keys(headerMetadata).length > 0 ? { headers: headerMetadata } : void 0);
|
|
@@ -1618,14 +1708,14 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
1618
1708
|
switch (block.type) {
|
|
1619
1709
|
case "text":
|
|
1620
1710
|
currentItemType = "message";
|
|
1621
|
-
currentItemId =
|
|
1711
|
+
currentItemId = synthesizeItemId("msg", currentContentBlockIndex, rawResponseId);
|
|
1622
1712
|
textBuffer = "";
|
|
1623
1713
|
yield factory.messageStarted(currentItemId);
|
|
1624
1714
|
break;
|
|
1625
1715
|
case "thinking":
|
|
1626
1716
|
hasStreamedReasoning = true;
|
|
1627
1717
|
currentItemType = "reasoning";
|
|
1628
|
-
currentItemId =
|
|
1718
|
+
currentItemId = synthesizeItemId("reason", currentContentBlockIndex, rawResponseId);
|
|
1629
1719
|
currentThinkingVisibility = "full";
|
|
1630
1720
|
thinkingBuffer = "";
|
|
1631
1721
|
yield factory.reasoningStarted(currentItemId, "full");
|
|
@@ -1633,7 +1723,7 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
1633
1723
|
case "redacted_thinking": {
|
|
1634
1724
|
hasStreamedReasoning = true;
|
|
1635
1725
|
currentItemType = "reasoning";
|
|
1636
|
-
currentItemId =
|
|
1726
|
+
currentItemId = synthesizeItemId("reason-redacted", currentContentBlockIndex, rawResponseId);
|
|
1637
1727
|
currentThinkingVisibility = "redacted";
|
|
1638
1728
|
const data = block.data;
|
|
1639
1729
|
yield factory.reasoningStarted(currentItemId, "redacted");
|
|
@@ -1721,11 +1811,7 @@ var MessagesAdapter = class extends AdapterBase {
|
|
|
1721
1811
|
stopReason = sseEvent.data.delta.stop_reason;
|
|
1722
1812
|
stopSequence = sseEvent.data.delta.stop_sequence;
|
|
1723
1813
|
const u = sseEvent.data.usage;
|
|
1724
|
-
if (u) auxiliary.recordUsage(
|
|
1725
|
-
inputTokens: u.input_tokens,
|
|
1726
|
-
outputTokens: u.output_tokens,
|
|
1727
|
-
totalTokens: u.input_tokens + u.output_tokens
|
|
1728
|
-
}, "stream", u);
|
|
1814
|
+
if (u) auxiliary.recordUsage(usageFromAnthropicMessages(u), "stream", u);
|
|
1729
1815
|
continue;
|
|
1730
1816
|
}
|
|
1731
1817
|
case "message_stop": break;
|
|
@@ -1899,7 +1985,7 @@ var ChatCompletionsAdapter = class extends AdapterBase {
|
|
|
1899
1985
|
}
|
|
1900
1986
|
for (const item of request.input) switch (item.type) {
|
|
1901
1987
|
case "message": {
|
|
1902
|
-
const role = item.role
|
|
1988
|
+
const role = item.role;
|
|
1903
1989
|
const text = contentBlocksToChatText(item.content, `input message (${item.role}) content`);
|
|
1904
1990
|
messages.push({
|
|
1905
1991
|
role,
|
|
@@ -2060,11 +2146,7 @@ var ChatCompletionsAdapter = class extends AdapterBase {
|
|
|
2060
2146
|
if (malformedWarning) yield malformedWarning;
|
|
2061
2147
|
for (const chunk of chunks) {
|
|
2062
2148
|
responseId = chunk.id;
|
|
2063
|
-
if (chunk.usage) auxiliary.recordUsage(
|
|
2064
|
-
inputTokens: chunk.usage.prompt_tokens,
|
|
2065
|
-
outputTokens: chunk.usage.completion_tokens,
|
|
2066
|
-
totalTokens: chunk.usage.total_tokens
|
|
2067
|
-
}, "final", chunk.usage);
|
|
2149
|
+
if (chunk.usage) auxiliary.recordUsage(usageFromChatCompletions(chunk.usage), "final", chunk.usage);
|
|
2068
2150
|
for (const choice of chunk.choices) {
|
|
2069
2151
|
if (choice.index !== 0) continue;
|
|
2070
2152
|
const delta = choice.delta;
|
|
@@ -2289,7 +2371,7 @@ var OllamaAdapter = class extends AdapterBase {
|
|
|
2289
2371
|
});
|
|
2290
2372
|
for (const item of request.input) switch (item.type) {
|
|
2291
2373
|
case "message": {
|
|
2292
|
-
const role = item.role
|
|
2374
|
+
const role = item.role;
|
|
2293
2375
|
messages.push({
|
|
2294
2376
|
role,
|
|
2295
2377
|
content: contentBlocksToText(ensureOllamaTextBlocks(item.content, `input message (${item.role}) content`))
|
|
@@ -2434,11 +2516,10 @@ var OllamaAdapter = class extends AdapterBase {
|
|
|
2434
2516
|
yield factory.toolCallCompleted(toolCall);
|
|
2435
2517
|
output.push(toolCall);
|
|
2436
2518
|
}
|
|
2437
|
-
if (request.include?.usage !== "off" && (chunk.prompt_eval_count !== void 0 || chunk.eval_count !== void 0)) auxiliary.recordUsage({
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
}, "final", {
|
|
2519
|
+
if (request.include?.usage !== "off" && (chunk.prompt_eval_count !== void 0 || chunk.eval_count !== void 0)) auxiliary.recordUsage(usageFromOllama({
|
|
2520
|
+
prompt_eval_count: chunk.prompt_eval_count,
|
|
2521
|
+
eval_count: chunk.eval_count
|
|
2522
|
+
}), "final", {
|
|
2442
2523
|
prompt_eval_count: chunk.prompt_eval_count,
|
|
2443
2524
|
eval_count: chunk.eval_count
|
|
2444
2525
|
});
|
|
@@ -3003,6 +3084,6 @@ function* emitToolCallEvents(item, factory) {
|
|
|
3003
3084
|
yield factory.toolCallCompleted(item);
|
|
3004
3085
|
}
|
|
3005
3086
|
//#endregion
|
|
3006
|
-
export { AIError, AIMappingError, AIProviderError, AIRequestError, AIStreamError, AdapterAuxiliaryState, AdapterBase, AuxiliaryCollector, ChatCompletionsAdapter, MessagesAdapter, MockAdapter, OllamaAdapter, ResponsesAdapter, WarningCode, aggregateEvents, assertMockRequest, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createEventFactory, emitMalformedStreamWarning, extractText, imageBlock, instructionsToText, jsonBlock, mapReasoningVisibility, mapStopReason, messageItem, metadataSourceList, normalizeRequest, opaqueBlock, opaqueItem, parseSSEEvents, reasoningItem, replayFromOutput, syntheticStream, textBlock, toolCallItem, toolResultItem, validateRequest, withMockStreaming };
|
|
3087
|
+
export { AIError, AIMappingError, AIProviderError, AIRequestError, AIStreamError, AdapterAuxiliaryState, AdapterBase, AuxiliaryCollector, ChatCompletionsAdapter, MessagesAdapter, MockAdapter, OllamaAdapter, ResponsesAdapter, WarningCode, aggregateEvents, assertMockRequest, assertValidRequest, blockToText, collectStream, contentBlocksToText, createAIClient, createEventFactory, emitMalformedStreamWarning, extractText, imageBlock, instructionsToText, jsonBlock, mapReasoningVisibility, mapStopReason, messageItem, metadataSourceList, normalizeRequest, opaqueBlock, opaqueItem, parseSSEEvents, reasoningItem, replayFromOutput, syntheticStream, textBlock, toolCallItem, toolResultItem, usageFromAnthropicMessages, usageFromChatCompletions, usageFromOllama, usageFromOpenAIResponses, validateRequest, withMockStreaming };
|
|
3007
3088
|
|
|
3008
3089
|
//# sourceMappingURL=index.mjs.map
|