@tonyclaw/agent-inspector 2.0.36 → 2.0.38
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/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-Bg2mo0NZ.js → CompareDrawer-hc5OoAls.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-C_Lq5T5V.js → ProxyViewerContainer-BMKBs8Qz.js} +35 -35
- package/.output/public/assets/{ReplayDialog-Bns-ayOg.js → ReplayDialog-CN-KM2nu.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-BBcPAIWx.js → RequestAnatomy-B1kTlAUk.js} +1 -1
- package/.output/public/assets/{ResponseView-DSRS3rHt.js → ResponseView-BchUjKjt.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-CzZxKE5-.js → StreamingChunkSequence-BQOxI9Hi.js} +1 -1
- package/.output/public/assets/_sessionId-CVw5e8TK.js +1 -0
- package/.output/public/assets/index-BdUTMQL6.js +1 -0
- package/.output/public/assets/{main-BVKRHBUl.js → main-Blykwzsn.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +114 -94
- package/.output/server/{_sessionId-Dsd36Yhc.mjs → _sessionId-BUNZz2zZ.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-BbJ5UdYD.mjs → CompareDrawer-VaDYPM5G.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-7igCY291.mjs → ProxyViewerContainer-CpdWs7Pk.mjs} +801 -785
- package/.output/server/_ssr/{ReplayDialog-CgWweshq.mjs → ReplayDialog-DbfIjJhb.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-BAyM_j7a.mjs → RequestAnatomy-CrD8h6As.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-iZQH7EYu.mjs → ResponseView-BalvDwtU.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-BU6hyHMg.mjs → StreamingChunkSequence-RxatDbPV.mjs} +2 -2
- package/.output/server/_ssr/{index-D7QF4E6v.mjs → index-11qAtV9d.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-DLLY6gv_.mjs → router-C4OdRnqX.mjs} +138 -138
- package/.output/server/{_tanstack-start-manifest_v-CHmIZaVV.mjs → _tanstack-start-manifest_v-F6bwcl33.mjs} +1 -1
- package/.output/server/index.mjs +60 -60
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +43 -9
- package/src/components/ProxyViewerContainer.tsx +1 -1
- package/src/components/providers/ProviderForm.tsx +2 -2
- package/src/components/proxy-viewer/AgentTraceSummary.tsx +1 -1
- package/src/components/proxy-viewer/CompareDrawer.tsx +1 -1
- package/src/components/proxy-viewer/ConversationGroup.tsx +1 -1
- package/src/components/proxy-viewer/ConversationGroupList.tsx +1 -1
- package/src/components/proxy-viewer/ConversationHeader.tsx +11 -7
- package/src/components/proxy-viewer/LogEntry.tsx +1 -1
- package/src/components/proxy-viewer/LogEntryHeader.tsx +1 -1
- package/src/components/proxy-viewer/ReplayDialog.tsx +1 -1
- package/src/components/proxy-viewer/ResponseView.tsx +2 -2
- package/src/components/proxy-viewer/StreamingChunkSequence.tsx +1 -1
- package/src/components/proxy-viewer/TurnGroup.tsx +1 -1
- package/src/components/proxy-viewer/anatomy/sessionContextSummary.ts +1 -1
- package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +1 -1
- package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +2 -2
- package/src/components/proxy-viewer/formats/index.tsx +5 -3
- package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +1 -1
- package/src/components/proxy-viewer/log-formats/anthropic.ts +1 -4
- package/src/components/proxy-viewer/log-formats/index.ts +6 -6
- package/src/components/proxy-viewer/log-formats/openai.ts +1 -1
- package/src/components/proxy-viewer/log-formats/types.ts +2 -2
- package/src/components/proxy-viewer/viewerState.ts +1 -1
- package/src/contracts/anthropic.ts +235 -0
- package/src/contracts/index.ts +27 -0
- package/src/contracts/json.ts +32 -0
- package/src/contracts/log.ts +72 -0
- package/src/contracts/openai.ts +176 -0
- package/src/knowledge/distiller.ts +1 -1
- package/src/lib/export-logs.ts +1 -1
- package/src/lib/groupContract.ts +1 -1
- package/src/lib/objectUtils.ts +3 -3
- package/src/lib/providerTestContract.ts +1 -1
- package/src/lib/runContract.ts +1 -1
- package/src/lib/stopReason.ts +1 -1
- package/src/mcp/previewExtractor.ts +4 -7
- package/src/mcp/server.ts +1 -1
- package/src/mcp/toolHandlers.ts +1 -1
- package/src/proxy/formats/anthropic/anthropicProvider.ts +2 -2
- package/src/proxy/formats/anthropic/schemas.ts +12 -235
- package/src/proxy/formats/handler.ts +2 -2
- package/src/proxy/formats/index.ts +1 -1
- package/src/proxy/formats/jsonSchema.ts +2 -36
- package/src/proxy/formats/openai/alibabaProvider.ts +2 -2
- package/src/proxy/formats/openai/provider.ts +2 -2
- package/src/proxy/formats/openai/schemas.ts +14 -187
- package/src/proxy/formats/openai/zhipuProvider.ts +2 -2
- package/src/proxy/formats/{protocol.ts → providerAdapter.ts} +5 -5
- package/src/proxy/formats/providerRegistry.ts +7 -7
- package/src/proxy/formats/providers/index.ts +1 -1
- package/src/proxy/formats/registry.ts +20 -11
- package/src/proxy/handler.ts +1 -1
- package/src/proxy/openaiOrphanToolStrip.ts +1 -1
- package/src/proxy/providers.ts +1 -1
- package/src/proxy/schemas.ts +18 -80
- package/src/proxy/store.ts +14 -11
- package/src/proxy/upstream.ts +1 -1
- package/src/routes/api/logs.stream.ts +1 -1
- package/.output/public/assets/_sessionId-DurHDwM1.js +0 -1
- package/.output/public/assets/index-sGphugFR.js +0 -1
|
@@ -1,235 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
cache_control: CacheControl.optional(),
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const ThinkingContentBlock = z.object({
|
|
17
|
-
type: z.literal("thinking"),
|
|
18
|
-
thinking: z.string(),
|
|
19
|
-
signature: z.string().optional(),
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const ThinkContentBlock = z.object({
|
|
23
|
-
type: z.literal("think"),
|
|
24
|
-
thinking: z.string(),
|
|
25
|
-
signature: z.string().optional(),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const ImageSourceBlock = z.object({
|
|
29
|
-
type: z.literal("base64"),
|
|
30
|
-
media_type: z.string(),
|
|
31
|
-
data: z.string(),
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const ImageContentBlock = z.object({
|
|
35
|
-
type: z.literal("image"),
|
|
36
|
-
source: ImageSourceBlock,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const ToolUseContentBlock = z.object({
|
|
40
|
-
type: z.literal("tool_use"),
|
|
41
|
-
id: z.string(),
|
|
42
|
-
name: z.string(),
|
|
43
|
-
input: z.record(z.string(), JsonValueSchema),
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const ToolResultContentItem = z.discriminatedUnion("type", [TextContentBlock, ImageContentBlock]);
|
|
47
|
-
|
|
48
|
-
const ToolResultContentBlock = z.object({
|
|
49
|
-
type: z.literal("tool_result"),
|
|
50
|
-
tool_use_id: z.string().optional(),
|
|
51
|
-
content: z.union([z.string(), z.array(ToolResultContentItem)]),
|
|
52
|
-
is_error: z.boolean().optional(),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const ContentBlock = z.discriminatedUnion("type", [
|
|
56
|
-
TextContentBlock,
|
|
57
|
-
ThinkingContentBlock,
|
|
58
|
-
ImageContentBlock,
|
|
59
|
-
ToolUseContentBlock,
|
|
60
|
-
ToolResultContentBlock,
|
|
61
|
-
]);
|
|
62
|
-
|
|
63
|
-
const MessageContent = z.union([z.string(), z.array(ContentBlock)]);
|
|
64
|
-
|
|
65
|
-
const Message = z.object({
|
|
66
|
-
role: z.enum(["user", "assistant"]),
|
|
67
|
-
content: MessageContent,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const SystemBlock = z.object({
|
|
71
|
-
type: z.literal("text"),
|
|
72
|
-
text: z.string(),
|
|
73
|
-
cache_control: CacheControl.optional(),
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const InputSchema = z.object({
|
|
77
|
-
type: z.string(),
|
|
78
|
-
properties: z.record(z.string(), z.record(z.string(), JsonValueSchema)).optional(),
|
|
79
|
-
required: z.array(z.string()).optional(),
|
|
80
|
-
additionalProperties: z.boolean().optional(),
|
|
81
|
-
$schema: z.string().optional(),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const ToolDefinition = z.object({
|
|
85
|
-
name: z.string(),
|
|
86
|
-
description: z.string().optional(),
|
|
87
|
-
input_schema: InputSchema.optional(),
|
|
88
|
-
cache_control: CacheControl.optional(),
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const ThinkingConfig = z.discriminatedUnion("type", [
|
|
92
|
-
z.object({ type: z.literal("enabled"), budget_tokens: z.number() }),
|
|
93
|
-
z.object({ type: z.literal("disabled") }),
|
|
94
|
-
z.object({ type: z.literal("adaptive") }),
|
|
95
|
-
]);
|
|
96
|
-
|
|
97
|
-
export const AnthropicRequestSchema = z.object({
|
|
98
|
-
model: z.string(),
|
|
99
|
-
messages: z.array(Message),
|
|
100
|
-
system: z.array(SystemBlock).optional(),
|
|
101
|
-
tools: z.array(ToolDefinition).optional(),
|
|
102
|
-
max_tokens: z.number().optional(),
|
|
103
|
-
temperature: z.number().optional(),
|
|
104
|
-
stream: z.boolean().optional(),
|
|
105
|
-
thinking: ThinkingConfig.optional(),
|
|
106
|
-
metadata: z
|
|
107
|
-
.object({
|
|
108
|
-
user_id: z.string().optional(),
|
|
109
|
-
})
|
|
110
|
-
.optional(),
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
const ResponseContentBlock = z.discriminatedUnion("type", [
|
|
114
|
-
TextContentBlock,
|
|
115
|
-
ThinkingContentBlock,
|
|
116
|
-
ThinkContentBlock,
|
|
117
|
-
ToolUseContentBlock,
|
|
118
|
-
]);
|
|
119
|
-
|
|
120
|
-
const ResponseUsageSchema = z
|
|
121
|
-
.object({
|
|
122
|
-
input_tokens: z.number().nullable().optional(),
|
|
123
|
-
output_tokens: z.number().nullable().optional(),
|
|
124
|
-
cache_creation_input_tokens: z.number().nullable().optional(),
|
|
125
|
-
cache_read_input_tokens: z.number().nullable().optional(),
|
|
126
|
-
})
|
|
127
|
-
.passthrough(); // Allow extra fields from different providers
|
|
128
|
-
|
|
129
|
-
export const AnthropicResponseSchema = z
|
|
130
|
-
.object({
|
|
131
|
-
id: z.string(),
|
|
132
|
-
type: z.literal("message"),
|
|
133
|
-
model: z.string(),
|
|
134
|
-
role: z.literal("assistant"),
|
|
135
|
-
content: z.array(ResponseContentBlock),
|
|
136
|
-
stop_reason: z.string().nullable(),
|
|
137
|
-
stop_sequence: z.string().nullable().optional(),
|
|
138
|
-
usage: ResponseUsageSchema,
|
|
139
|
-
})
|
|
140
|
-
.passthrough(); // Allow extra unknown fields
|
|
141
|
-
|
|
142
|
-
const SseMessageStartEvent = z.object({
|
|
143
|
-
type: z.literal("message_start"),
|
|
144
|
-
message: z.object({
|
|
145
|
-
id: z.string(),
|
|
146
|
-
type: z.literal("message"),
|
|
147
|
-
model: z.string(),
|
|
148
|
-
role: z.literal("assistant"),
|
|
149
|
-
content: z.array(ResponseContentBlock),
|
|
150
|
-
stop_reason: z.null(),
|
|
151
|
-
stop_sequence: z.null(),
|
|
152
|
-
usage: z
|
|
153
|
-
.object({
|
|
154
|
-
input_tokens: z.number(),
|
|
155
|
-
cache_creation_input_tokens: z.number().optional(),
|
|
156
|
-
cache_read_input_tokens: z.number().optional(),
|
|
157
|
-
})
|
|
158
|
-
.passthrough(),
|
|
159
|
-
}),
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
const SseContentBlockStartEvent = z.object({
|
|
163
|
-
type: z.literal("content_block_start"),
|
|
164
|
-
index: z.number(),
|
|
165
|
-
content_block: ResponseContentBlock,
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
const SseDeltaBlock = z.discriminatedUnion("type", [
|
|
169
|
-
z.object({ type: z.literal("text_delta"), text: z.string() }),
|
|
170
|
-
z.object({ type: z.literal("input_json_delta"), partial_json: z.string() }),
|
|
171
|
-
z.object({ type: z.literal("thinking_delta"), thinking: z.string() }),
|
|
172
|
-
z.object({ type: z.literal("signature_delta"), signature: z.string() }),
|
|
173
|
-
]);
|
|
174
|
-
|
|
175
|
-
const SseContentBlockDeltaEvent = z.object({
|
|
176
|
-
type: z.literal("content_block_delta"),
|
|
177
|
-
index: z.number(),
|
|
178
|
-
delta: SseDeltaBlock,
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
const SseContentBlockStopEvent = z.object({
|
|
182
|
-
type: z.literal("content_block_stop"),
|
|
183
|
-
index: z.number(),
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
const SseMessageDeltaEvent = z.object({
|
|
187
|
-
type: z.literal("message_delta"),
|
|
188
|
-
delta: z.object({
|
|
189
|
-
stop_reason: z.string().nullable(),
|
|
190
|
-
stop_sequence: z.string().nullable().optional(),
|
|
191
|
-
}),
|
|
192
|
-
usage: z
|
|
193
|
-
.object({
|
|
194
|
-
output_tokens: z.number(),
|
|
195
|
-
input_tokens: z.number().optional(),
|
|
196
|
-
cache_creation_input_tokens: z.number().optional(),
|
|
197
|
-
cache_read_input_tokens: z.number().optional(),
|
|
198
|
-
})
|
|
199
|
-
.passthrough(),
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
const SseMessageStopEvent = z.object({
|
|
203
|
-
type: z.literal("message_stop"),
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const SsePingEvent = z.object({
|
|
207
|
-
type: z.literal("ping"),
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const SseErrorEvent = z.object({
|
|
211
|
-
type: z.literal("error"),
|
|
212
|
-
error: z.object({
|
|
213
|
-
type: z.string(),
|
|
214
|
-
message: z.string(),
|
|
215
|
-
}),
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
export const SseEventSchema = z.discriminatedUnion("type", [
|
|
219
|
-
SseMessageStartEvent,
|
|
220
|
-
SseContentBlockStartEvent,
|
|
221
|
-
SseContentBlockDeltaEvent,
|
|
222
|
-
SseContentBlockStopEvent,
|
|
223
|
-
SseMessageDeltaEvent,
|
|
224
|
-
SseMessageStopEvent,
|
|
225
|
-
SsePingEvent,
|
|
226
|
-
SseErrorEvent,
|
|
227
|
-
]);
|
|
228
|
-
|
|
229
|
-
export type AnthropicResponse = z.infer<typeof AnthropicResponseSchema>;
|
|
230
|
-
export type ResponseContentBlockType = z.infer<typeof ResponseContentBlock>;
|
|
231
|
-
|
|
232
|
-
// Backward-compatible aliases (originally named Inspector*)
|
|
233
|
-
export const InspectorRequestSchema = AnthropicRequestSchema;
|
|
234
|
-
export const InspectorResponseSchema = AnthropicResponseSchema;
|
|
235
|
-
export type InspectorResponse = AnthropicResponse;
|
|
1
|
+
export {
|
|
2
|
+
AnthropicRequestSchema,
|
|
3
|
+
AnthropicResponseSchema,
|
|
4
|
+
InspectorRequestSchema,
|
|
5
|
+
InspectorResponseSchema,
|
|
6
|
+
SseEventSchema,
|
|
7
|
+
} from "../../../contracts/anthropic";
|
|
8
|
+
export type {
|
|
9
|
+
AnthropicResponse,
|
|
10
|
+
InspectorResponse,
|
|
11
|
+
ResponseContentBlockType,
|
|
12
|
+
} from "../../../contracts/anthropic";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiFormat, CapturedLog, TokenUsage } from "../schemas";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Structured result of parsing a raw request body.
|
|
@@ -17,7 +17,7 @@ export type ParsedRequest = {
|
|
|
17
17
|
*/
|
|
18
18
|
export type FormatHandler = {
|
|
19
19
|
/** The format identifier */
|
|
20
|
-
readonly format:
|
|
20
|
+
readonly format: ApiFormat;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Parse a raw request body to extract model name and metadata.
|
|
@@ -9,5 +9,5 @@ import "./openai/zhipuProvider";
|
|
|
9
9
|
import "./openai/alibabaProvider";
|
|
10
10
|
|
|
11
11
|
export type { FormatHandler, ParsedRequest } from "./handler";
|
|
12
|
-
export { formatRegistry, formatForPath, requestFormatForPath } from "./registry";
|
|
12
|
+
export { apiFormatForPath, formatRegistry, formatForPath, requestFormatForPath } from "./registry";
|
|
13
13
|
export { registry } from "./providers";
|
|
@@ -1,36 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shared JSON value type for streaming chunks.
|
|
5
|
-
* Defined in a separate file to avoid circular dependencies.
|
|
6
|
-
*/
|
|
7
|
-
export type JsonValue =
|
|
8
|
-
| string
|
|
9
|
-
| number
|
|
10
|
-
| boolean
|
|
11
|
-
| null
|
|
12
|
-
| JsonValue[]
|
|
13
|
-
| { [key: string]: JsonValue };
|
|
14
|
-
|
|
15
|
-
export const JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>
|
|
16
|
-
z.union([
|
|
17
|
-
z.string(),
|
|
18
|
-
z.number(),
|
|
19
|
-
z.boolean(),
|
|
20
|
-
z.null(),
|
|
21
|
-
z.array(JsonValueSchema),
|
|
22
|
-
z.record(z.string(), JsonValueSchema),
|
|
23
|
-
]),
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Re-types a value as `JsonValue` without re-walking it. Use this ONLY when
|
|
28
|
-
* the value has already been validated (e.g., via `SseEventSchema.safeParse`)
|
|
29
|
-
* AND originated from `JSON.parse`. Skipping the recursive `JsonValueSchema`
|
|
30
|
-
* walk avoids a second full-tree zod parse on every event of every streaming
|
|
31
|
-
* response. Centralized here so the eslint-disable is one site, not two.
|
|
32
|
-
*/
|
|
33
|
-
export function trustAsJsonValue<T>(value: T): JsonValue {
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
35
|
-
return value as unknown as JsonValue;
|
|
36
|
-
}
|
|
1
|
+
export { JsonValueSchema, trustAsJsonValue } from "../../contracts/json";
|
|
2
|
+
export type { JsonValue } from "../../contracts/json";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CapturedLog } from "../../schemas";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderAdapter } from "../providerAdapter";
|
|
3
3
|
import { registry } from "../providers";
|
|
4
4
|
import { extractOpenAIStream } from "./stream";
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ const DEFAULT_ALIBABA_UPSTREAM = "https://dashscope.aliyuncs.com/compatible-mode
|
|
|
8
8
|
/**
|
|
9
9
|
* Alibaba Provider Implementation (DashScope)
|
|
10
10
|
*/
|
|
11
|
-
export const alibabaProvider:
|
|
11
|
+
export const alibabaProvider: ProviderAdapter = {
|
|
12
12
|
name: "alibaba",
|
|
13
13
|
|
|
14
14
|
matches(model: string): boolean {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CapturedLog } from "../../schemas";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderAdapter } from "../providerAdapter";
|
|
3
3
|
import { registry } from "../providers";
|
|
4
4
|
import { extractOpenAIStream } from "./stream";
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ const DEFAULT_OPENAI_UPSTREAM = "https://api.openai.com/v1";
|
|
|
8
8
|
/**
|
|
9
9
|
* OpenAI Provider Implementation
|
|
10
10
|
*/
|
|
11
|
-
export const openaiProvider:
|
|
11
|
+
export const openaiProvider: ProviderAdapter = {
|
|
12
12
|
name: "openai",
|
|
13
13
|
|
|
14
14
|
matches(model: string): boolean {
|
|
@@ -1,187 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
]),
|
|
16
|
-
),
|
|
17
|
-
]);
|
|
18
|
-
|
|
19
|
-
export const OpenAIMessage = z.object({
|
|
20
|
-
role: z.enum(["system", "user", "assistant", "tool"]),
|
|
21
|
-
content: OpenAIMessageContent,
|
|
22
|
-
name: z.string().optional(),
|
|
23
|
-
reasoning_content: z.string().optional(),
|
|
24
|
-
thinking: z.string().optional(), // Some providers use 'thinking' field
|
|
25
|
-
think: z.string().optional(), // MiniMax uses 'think' field
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
export const OpenAIFunctionCall = z.object({
|
|
29
|
-
name: z.string(),
|
|
30
|
-
arguments: z.string(),
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
/** A single OpenAI tool_call (the modern multi-tool form, returned by most
|
|
34
|
-
* providers in `choices[].message.tool_calls`). `function.arguments` is
|
|
35
|
-
* a JSON-encoded string per the OpenAI spec — we keep it as a string at
|
|
36
|
-
* parse time and let the renderer decide whether to JSON-parse it for
|
|
37
|
-
* display. */
|
|
38
|
-
export const OpenAIToolCallSchema = z.object({
|
|
39
|
-
index: z.number().optional(),
|
|
40
|
-
id: z.string().optional(),
|
|
41
|
-
type: z.literal("function").optional(),
|
|
42
|
-
function: z.object({
|
|
43
|
-
name: z.string().optional(),
|
|
44
|
-
arguments: z.string().optional(),
|
|
45
|
-
}),
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
export type OpenAIToolCall = z.infer<typeof OpenAIToolCallSchema>;
|
|
49
|
-
|
|
50
|
-
const OpenAIMessageWithFunctionCall = OpenAIMessage.extend({
|
|
51
|
-
content: z
|
|
52
|
-
.union([z.string(), z.array(z.object({ type: z.literal("text"), text: z.string() }))])
|
|
53
|
-
.optional(),
|
|
54
|
-
function_call: OpenAIFunctionCall.optional(),
|
|
55
|
-
tool_calls: z.array(OpenAIToolCallSchema).optional(),
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
export const OpenAIToolDefinition = z.object({
|
|
59
|
-
type: z.literal("function"),
|
|
60
|
-
function: z.object({
|
|
61
|
-
name: z.string(),
|
|
62
|
-
description: z.string().optional(),
|
|
63
|
-
parameters: z.record(z.string(), JsonValueSchema),
|
|
64
|
-
}),
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
export const OpenAIRequestSchema = z.object({
|
|
68
|
-
model: z.string(),
|
|
69
|
-
messages: z.array(OpenAIMessage),
|
|
70
|
-
temperature: z.number().optional(),
|
|
71
|
-
max_tokens: z.number().optional(),
|
|
72
|
-
stream: z.boolean().optional(),
|
|
73
|
-
tools: z.array(OpenAIToolDefinition).optional(),
|
|
74
|
-
tool_choice: z
|
|
75
|
-
.union([
|
|
76
|
-
z.enum(["auto", "none", "required"]),
|
|
77
|
-
z.object({ type: z.literal("auto") }),
|
|
78
|
-
z.object({ type: z.literal("none") }),
|
|
79
|
-
z.object({ type: z.literal("function"), function: z.object({ name: z.string() }) }),
|
|
80
|
-
])
|
|
81
|
-
.optional(),
|
|
82
|
-
user: z.string().optional(),
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
export const OpenAIChoiceDelta = z.object({
|
|
86
|
-
role: z.enum(["assistant"]).optional(),
|
|
87
|
-
content: z.string().nullable().optional(),
|
|
88
|
-
reasoning_content: z.string().nullable().optional(),
|
|
89
|
-
thinking: z.string().nullable().optional(), // Some providers use 'thinking' field
|
|
90
|
-
think: z.string().nullable().optional(), // MiniMax uses 'think' field
|
|
91
|
-
function_call: z
|
|
92
|
-
.object({ name: z.string().optional(), arguments: z.string().optional() })
|
|
93
|
-
.nullable()
|
|
94
|
-
.optional(),
|
|
95
|
-
tool_calls: z
|
|
96
|
-
.array(
|
|
97
|
-
z.object({
|
|
98
|
-
index: z.number(),
|
|
99
|
-
id: z.string().optional(),
|
|
100
|
-
type: z.literal("function").optional(),
|
|
101
|
-
function: z.object({
|
|
102
|
-
name: z.string().optional(),
|
|
103
|
-
arguments: z.string().optional(),
|
|
104
|
-
}),
|
|
105
|
-
}),
|
|
106
|
-
)
|
|
107
|
-
.nullable()
|
|
108
|
-
.optional(),
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
export const OpenAIChoice = z.object({
|
|
112
|
-
index: z.number(),
|
|
113
|
-
message: z
|
|
114
|
-
.object({
|
|
115
|
-
role: z.enum(["assistant"]),
|
|
116
|
-
content: z.string().nullable(),
|
|
117
|
-
reasoning_content: z.string().optional(),
|
|
118
|
-
thinking: z.string().optional(), // Some providers use 'thinking' field in message
|
|
119
|
-
think: z.string().optional(), // MiniMax uses 'think' field in message
|
|
120
|
-
function_call: z.object({ name: z.string(), arguments: z.string() }).nullable().optional(),
|
|
121
|
-
tool_calls: z.array(OpenAIToolCallSchema).optional(),
|
|
122
|
-
})
|
|
123
|
-
.optional(),
|
|
124
|
-
delta: OpenAIChoiceDelta.optional(),
|
|
125
|
-
finish_reason: z.string().nullable(),
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
export const OpenAIResponseSchema = z
|
|
129
|
-
.object({
|
|
130
|
-
id: z.string(),
|
|
131
|
-
object: z.literal("chat.completion"),
|
|
132
|
-
created: z.number(),
|
|
133
|
-
model: z.string(),
|
|
134
|
-
choices: z.array(OpenAIChoice),
|
|
135
|
-
usage: z
|
|
136
|
-
.object({
|
|
137
|
-
prompt_tokens: z.number().nullable().optional(),
|
|
138
|
-
completion_tokens: z.number().nullable().optional(),
|
|
139
|
-
total_tokens: z.number().nullable().optional(),
|
|
140
|
-
})
|
|
141
|
-
.passthrough(), // Allow extra fields like prompt_tokens_details, completion_tokens_details
|
|
142
|
-
service_tier: z.string().nullable().optional(),
|
|
143
|
-
system_fingerprint: z.string().nullable().optional(),
|
|
144
|
-
})
|
|
145
|
-
.passthrough(); // Allow extra fields like refusal, annotations, audio
|
|
146
|
-
|
|
147
|
-
// Schema for actual OpenAI SSE chunk format (not wrapped in event/data)
|
|
148
|
-
export const OpenAISSERawChunkSchema = z
|
|
149
|
-
.object({
|
|
150
|
-
id: z.string(),
|
|
151
|
-
object: z.literal("chat.completion.chunk"),
|
|
152
|
-
created: z.number(),
|
|
153
|
-
model: z.string(),
|
|
154
|
-
choices: z.array(
|
|
155
|
-
z.object({
|
|
156
|
-
index: z.number(),
|
|
157
|
-
delta: OpenAIChoiceDelta,
|
|
158
|
-
finish_reason: z.string().nullable().optional(),
|
|
159
|
-
}),
|
|
160
|
-
),
|
|
161
|
-
usage: z
|
|
162
|
-
.object({
|
|
163
|
-
prompt_tokens: z.number().nullable().optional(),
|
|
164
|
-
completion_tokens: z.number().nullable().optional(),
|
|
165
|
-
total_tokens: z.number().nullable().optional(),
|
|
166
|
-
})
|
|
167
|
-
.passthrough()
|
|
168
|
-
.nullable()
|
|
169
|
-
.optional(),
|
|
170
|
-
})
|
|
171
|
-
.passthrough(); // Allow extra fields in chunks
|
|
172
|
-
|
|
173
|
-
export type OpenAIResponse = z.infer<typeof OpenAIResponseSchema>;
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Parse an OpenAI response body.
|
|
177
|
-
*/
|
|
178
|
-
export function parseOpenAIResponse(rawBody: string): OpenAIResponse | null {
|
|
179
|
-
try {
|
|
180
|
-
const json: unknown = JSON.parse(rawBody);
|
|
181
|
-
const result = OpenAIResponseSchema.safeParse(json);
|
|
182
|
-
if (result.success) return result.data;
|
|
183
|
-
return null;
|
|
184
|
-
} catch {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
1
|
+
export {
|
|
2
|
+
OpenAIChoice,
|
|
3
|
+
OpenAIChoiceDelta,
|
|
4
|
+
OpenAIFunctionCall,
|
|
5
|
+
OpenAIMessage,
|
|
6
|
+
OpenAIMessageContent,
|
|
7
|
+
OpenAIRequestSchema,
|
|
8
|
+
OpenAIResponseSchema,
|
|
9
|
+
OpenAISSERawChunkSchema,
|
|
10
|
+
OpenAIToolCallSchema,
|
|
11
|
+
OpenAIToolDefinition,
|
|
12
|
+
parseOpenAIResponse,
|
|
13
|
+
} from "../../../contracts/openai";
|
|
14
|
+
export type { OpenAIResponse, OpenAIToolCall } from "../../../contracts/openai";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { CapturedLog } from "../../schemas";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ProviderAdapter } from "../providerAdapter";
|
|
3
3
|
import { registry } from "../providers";
|
|
4
4
|
import { extractOpenAIStream } from "./stream";
|
|
5
5
|
|
|
6
6
|
const DEFAULT_ZHIPU_UPSTREAM = "https://open.bigmodel.cn/api/paas/v4";
|
|
7
7
|
const ZHIPU_MODEL_PREFIXES = ["glm-", "charglm-", "cogview-", "embedding-", "rerank-"];
|
|
8
8
|
|
|
9
|
-
export const zhipuProvider:
|
|
9
|
+
export const zhipuProvider: ProviderAdapter = {
|
|
10
10
|
name: "zhipu",
|
|
11
11
|
|
|
12
12
|
matches(model: string): boolean {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiFormat, CapturedLog } from "../../contracts";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Provider
|
|
4
|
+
* Provider Adapter Interface
|
|
5
5
|
*
|
|
6
|
-
* Defines the contract that all
|
|
6
|
+
* Defines the contract that all provider adapters must implement to support
|
|
7
7
|
* different LLM APIs (Anthropic, OpenAI, etc.).
|
|
8
8
|
*/
|
|
9
|
-
export type
|
|
9
|
+
export type ProviderAdapter = {
|
|
10
10
|
/** Provider identifier (e.g., "anthropic", "openai") */
|
|
11
11
|
name: string;
|
|
12
12
|
|
|
@@ -46,5 +46,5 @@ export type ProviderProtocol = {
|
|
|
46
46
|
* @param apiFormat - Request format (anthropic/openai/unknown)
|
|
47
47
|
* @returns Transformed body or null to use original
|
|
48
48
|
*/
|
|
49
|
-
transformRequest?(body: string, apiFormat:
|
|
49
|
+
transformRequest?(body: string, apiFormat: ApiFormat): string | null;
|
|
50
50
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProviderAdapter } from "./providerAdapter";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Provider Registry
|
|
@@ -7,13 +7,13 @@ import type { ProviderProtocol } from "./protocol";
|
|
|
7
7
|
* Providers register themselves at module load time.
|
|
8
8
|
*/
|
|
9
9
|
class ProviderRegistryImpl {
|
|
10
|
-
private providers:
|
|
10
|
+
private providers: ProviderAdapter[] = [];
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Register a provider with the registry.
|
|
14
14
|
* @param provider - Provider implementation to register
|
|
15
15
|
*/
|
|
16
|
-
register(provider:
|
|
16
|
+
register(provider: ProviderAdapter): void {
|
|
17
17
|
this.providers.push(provider);
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -22,8 +22,8 @@ class ProviderRegistryImpl {
|
|
|
22
22
|
* @param model - Model name to match
|
|
23
23
|
* @returns Matching provider or null if none found
|
|
24
24
|
*/
|
|
25
|
-
findProvider(model: string):
|
|
26
|
-
let fallback:
|
|
25
|
+
findProvider(model: string): ProviderAdapter | null {
|
|
26
|
+
let fallback: ProviderAdapter | null = null;
|
|
27
27
|
|
|
28
28
|
for (const provider of this.providers) {
|
|
29
29
|
if (provider.matches(model)) {
|
|
@@ -31,7 +31,7 @@ class ProviderRegistryImpl {
|
|
|
31
31
|
if (provider.name !== "anthropic") {
|
|
32
32
|
return provider;
|
|
33
33
|
}
|
|
34
|
-
// Anthropic is the fallback
|
|
34
|
+
// Anthropic is the fallback; only use if nothing else matches
|
|
35
35
|
fallback = provider;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -42,7 +42,7 @@ class ProviderRegistryImpl {
|
|
|
42
42
|
* Get all registered providers.
|
|
43
43
|
* @returns Array of all registered providers
|
|
44
44
|
*/
|
|
45
|
-
getAll():
|
|
45
|
+
getAll(): ProviderAdapter[] {
|
|
46
46
|
return [...this.providers];
|
|
47
47
|
}
|
|
48
48
|
}
|