@tonyclaw/agent-inspector 2.0.37 → 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.
Files changed (85) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-nEHCEVP4.js → CompareDrawer-hc5OoAls.js} +1 -1
  3. package/.output/public/assets/{ProxyViewerContainer-BstBIX2B.js → ProxyViewerContainer-BMKBs8Qz.js} +14 -14
  4. package/.output/public/assets/{ReplayDialog-CUnBdt1Q.js → ReplayDialog-CN-KM2nu.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-BU9VT2Sw.js → RequestAnatomy-B1kTlAUk.js} +1 -1
  6. package/.output/public/assets/{ResponseView-amxuKPKY.js → ResponseView-BchUjKjt.js} +1 -1
  7. package/.output/public/assets/{StreamingChunkSequence-DpscrQM2.js → StreamingChunkSequence-BQOxI9Hi.js} +1 -1
  8. package/.output/public/assets/_sessionId-CVw5e8TK.js +1 -0
  9. package/.output/public/assets/index-BdUTMQL6.js +1 -0
  10. package/.output/public/assets/{main-D56QvEyw.js → main-Blykwzsn.js} +2 -2
  11. package/.output/server/{_sessionId-ChwEDyI4.mjs → _sessionId-BUNZz2zZ.mjs} +2 -2
  12. package/.output/server/_ssr/{CompareDrawer-Ce2590rK.mjs → CompareDrawer-VaDYPM5G.mjs} +2 -2
  13. package/.output/server/_ssr/{ProxyViewerContainer-D6xM8A0S.mjs → ProxyViewerContainer-CpdWs7Pk.mjs} +9 -9
  14. package/.output/server/_ssr/{ReplayDialog-CB4KOlLe.mjs → ReplayDialog-DbfIjJhb.mjs} +3 -3
  15. package/.output/server/_ssr/{RequestAnatomy-CsWV3W03.mjs → RequestAnatomy-CrD8h6As.mjs} +2 -2
  16. package/.output/server/_ssr/{ResponseView-BuCCV3LU.mjs → ResponseView-BalvDwtU.mjs} +2 -2
  17. package/.output/server/_ssr/{StreamingChunkSequence-C5dE7V1d.mjs → StreamingChunkSequence-RxatDbPV.mjs} +2 -2
  18. package/.output/server/_ssr/{index-BeIi0CPv.mjs → index-11qAtV9d.mjs} +2 -2
  19. package/.output/server/_ssr/index.mjs +2 -2
  20. package/.output/server/_ssr/{router-Ca2MCyUX.mjs → router-C4OdRnqX.mjs} +69 -76
  21. package/.output/server/{_tanstack-start-manifest_v-CBAJfSAX.mjs → _tanstack-start-manifest_v-F6bwcl33.mjs} +1 -1
  22. package/.output/server/index.mjs +61 -61
  23. package/README.md +1 -1
  24. package/package.json +1 -1
  25. package/src/components/ProxyViewer.tsx +1 -1
  26. package/src/components/ProxyViewerContainer.tsx +1 -1
  27. package/src/components/providers/ProviderForm.tsx +2 -2
  28. package/src/components/proxy-viewer/AgentTraceSummary.tsx +1 -1
  29. package/src/components/proxy-viewer/CompareDrawer.tsx +1 -1
  30. package/src/components/proxy-viewer/ConversationGroup.tsx +1 -1
  31. package/src/components/proxy-viewer/ConversationGroupList.tsx +1 -1
  32. package/src/components/proxy-viewer/ConversationHeader.tsx +1 -1
  33. package/src/components/proxy-viewer/LogEntry.tsx +1 -1
  34. package/src/components/proxy-viewer/LogEntryHeader.tsx +1 -1
  35. package/src/components/proxy-viewer/ReplayDialog.tsx +1 -1
  36. package/src/components/proxy-viewer/ResponseView.tsx +2 -2
  37. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +1 -1
  38. package/src/components/proxy-viewer/TurnGroup.tsx +1 -1
  39. package/src/components/proxy-viewer/anatomy/sessionContextSummary.ts +1 -1
  40. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +1 -1
  41. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +2 -2
  42. package/src/components/proxy-viewer/formats/index.tsx +5 -3
  43. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +1 -1
  44. package/src/components/proxy-viewer/log-formats/anthropic.ts +1 -4
  45. package/src/components/proxy-viewer/log-formats/index.ts +6 -6
  46. package/src/components/proxy-viewer/log-formats/openai.ts +1 -1
  47. package/src/components/proxy-viewer/log-formats/types.ts +2 -2
  48. package/src/components/proxy-viewer/viewerState.ts +1 -1
  49. package/src/contracts/anthropic.ts +235 -0
  50. package/src/contracts/index.ts +27 -0
  51. package/src/contracts/json.ts +32 -0
  52. package/src/contracts/log.ts +72 -0
  53. package/src/contracts/openai.ts +176 -0
  54. package/src/knowledge/distiller.ts +1 -1
  55. package/src/lib/export-logs.ts +1 -1
  56. package/src/lib/groupContract.ts +1 -1
  57. package/src/lib/objectUtils.ts +3 -3
  58. package/src/lib/providerTestContract.ts +1 -1
  59. package/src/lib/runContract.ts +1 -1
  60. package/src/lib/stopReason.ts +1 -1
  61. package/src/mcp/previewExtractor.ts +4 -7
  62. package/src/mcp/server.ts +1 -1
  63. package/src/mcp/toolHandlers.ts +1 -1
  64. package/src/proxy/formats/anthropic/anthropicProvider.ts +2 -2
  65. package/src/proxy/formats/anthropic/schemas.ts +12 -235
  66. package/src/proxy/formats/handler.ts +2 -2
  67. package/src/proxy/formats/index.ts +1 -1
  68. package/src/proxy/formats/jsonSchema.ts +2 -36
  69. package/src/proxy/formats/openai/alibabaProvider.ts +2 -2
  70. package/src/proxy/formats/openai/provider.ts +2 -2
  71. package/src/proxy/formats/openai/schemas.ts +14 -187
  72. package/src/proxy/formats/openai/zhipuProvider.ts +2 -2
  73. package/src/proxy/formats/{protocol.ts → providerAdapter.ts} +5 -5
  74. package/src/proxy/formats/providerRegistry.ts +7 -7
  75. package/src/proxy/formats/providers/index.ts +1 -1
  76. package/src/proxy/formats/registry.ts +16 -13
  77. package/src/proxy/handler.ts +1 -1
  78. package/src/proxy/openaiOrphanToolStrip.ts +1 -1
  79. package/src/proxy/providers.ts +1 -1
  80. package/src/proxy/schemas.ts +18 -80
  81. package/src/proxy/store.ts +2 -2
  82. package/src/proxy/upstream.ts +1 -1
  83. package/src/routes/api/logs.stream.ts +1 -1
  84. package/.output/public/assets/_sessionId-7c9bsOFT.js +0 -1
  85. package/.output/public/assets/index-B7a5OmIO.js +0 -1
@@ -3,7 +3,7 @@ import { AlertTriangle, ChevronRight, Clock, Zap } from "lucide-react";
3
3
  import { isTurnBoundary } from "../../lib/stopReason";
4
4
  import type { TimeDisplayFormat } from "../../lib/runtimeConfig";
5
5
  import { cn, formatTokens } from "../../lib/utils";
6
- import type { CapturedLog } from "../../proxy/schemas";
6
+ import type { CapturedLog } from "../../contracts";
7
7
  import { getCrabVariant } from "../ui/crab-variants";
8
8
  import { ProviderLogo, detectProvider, type Provider } from "../providers/ProviderLogo";
9
9
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip";
@@ -1,5 +1,5 @@
1
1
  import type { ProviderConfig } from "../../../lib/providerContract";
2
- import type { CapturedLog } from "../../../proxy/schemas";
2
+ import type { CapturedLog } from "../../../contracts";
3
3
  import { getLogFormatAdapter, resolveLogFormat } from "../log-formats";
4
4
  import {
5
5
  analyzeContextIntelligence,
@@ -1,6 +1,6 @@
1
1
  import { Brain, ChevronDown, ChevronRight, Terminal } from "lucide-react";
2
2
  import { type JSX, memo, useState } from "react";
3
- import type { ResponseContentBlockType } from "../../../../proxy/schemas";
3
+ import type { ResponseContentBlockType } from "../../../../contracts/anthropic";
4
4
  import { AnswerMarkdown } from "../../AnswerMarkdown";
5
5
  import { Badge } from "../../../ui/badge";
6
6
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../../ui/collapsible";
@@ -1,6 +1,6 @@
1
1
  import { StopCircle, Zap } from "lucide-react";
2
2
  import { memo, type JSX } from "react";
3
- import type { InspectorResponse } from "../../../../proxy/schemas";
3
+ import type { AnthropicResponse } from "../../../../contracts/anthropic";
4
4
  import { formatTokens } from "../../../../lib/utils";
5
5
  import { Badge } from "../../../ui/badge";
6
6
  import { Separator } from "../../../ui/separator";
@@ -9,7 +9,7 @@ import { ResponseContentBlockRenderer } from "./ContentBlocks";
9
9
  export const StructuredResponseViewAnthropic = memo(function StructuredResponseViewAnthropic({
10
10
  response,
11
11
  }: {
12
- response: InspectorResponse;
12
+ response: AnthropicResponse;
13
13
  }): JSX.Element {
14
14
  return (
15
15
  <div className="space-y-3">
@@ -1,5 +1,7 @@
1
1
  import type { JSX } from "react";
2
- import type { InspectorResponse, OpenAIResponse, RequestFormat } from "../../../proxy/schemas";
2
+ import type { ApiFormat } from "../../../contracts";
3
+ import type { AnthropicResponse } from "../../../contracts/anthropic";
4
+ import type { OpenAIResponse } from "../../../contracts/openai";
3
5
  import { StructuredResponseViewAnthropic } from "./anthropic/ResponseView";
4
6
  import { OpenAIResponseView } from "./openai/ResponseView";
5
7
 
@@ -15,12 +17,12 @@ function isOpenAIResponse(response: unknown): response is OpenAIResponse {
15
17
  return isRecord(response) && response.object === "chat.completion";
16
18
  }
17
19
 
18
- function isAnthropicResponse(response: unknown): response is InspectorResponse {
20
+ function isAnthropicResponse(response: unknown): response is AnthropicResponse {
19
21
  return isRecord(response) && response.type === "message" && Array.isArray(response.content);
20
22
  }
21
23
 
22
24
  export function formatViewFor(
23
- apiFormat: RequestFormat | undefined,
25
+ apiFormat: ApiFormat | undefined,
24
26
  response: unknown,
25
27
  ): JSX.Element | null {
26
28
  if (apiFormat === "openai" && isOpenAIResponse(response)) {
@@ -1,6 +1,6 @@
1
1
  import { StopCircle, Terminal, Zap } from "lucide-react";
2
2
  import { memo, useState, type JSX } from "react";
3
- import type { OpenAIResponse, OpenAIToolCall } from "../../../../proxy/schemas";
3
+ import type { OpenAIResponse, OpenAIToolCall } from "../../../../contracts/openai";
4
4
  import { formatTokens } from "../../../../lib/utils";
5
5
  import { AnswerMarkdown } from "../../AnswerMarkdown";
6
6
  import { Badge } from "../../../ui/badge";
@@ -1,7 +1,4 @@
1
- import {
2
- AnthropicRequestSchema,
3
- AnthropicResponseSchema,
4
- } from "../../../proxy/formats/anthropic/schemas";
1
+ import { AnthropicRequestSchema, AnthropicResponseSchema } from "../../../contracts/anthropic";
5
2
  import type { AnatomySegment } from "../anatomy/types";
6
3
  import { countCharacters, estimateTokens } from "../anatomy/tokenEstimate";
7
4
  import type { LogFormatAdapter } from "./types";
@@ -1,22 +1,22 @@
1
- import { requestFormatForPath } from "../../../proxy/formats";
2
- import type { CapturedLog, RequestFormat } from "../../../proxy/schemas";
1
+ import { apiFormatForPath } from "../../../proxy/formats";
2
+ import type { ApiFormat, CapturedLog } from "../../../contracts";
3
3
  import { anthropicLogFormatAdapter } from "./anthropic";
4
4
  import { openAILogFormatAdapter } from "./openai";
5
5
  import type { LogFormatAdapter } from "./types";
6
6
  import { unknownLogFormatAdapter } from "./unknown";
7
7
 
8
- const ADAPTERS: Record<RequestFormat, LogFormatAdapter> = {
8
+ const ADAPTERS: Record<ApiFormat, LogFormatAdapter> = {
9
9
  anthropic: anthropicLogFormatAdapter,
10
10
  openai: openAILogFormatAdapter,
11
11
  unknown: unknownLogFormatAdapter,
12
12
  };
13
13
 
14
- export function getLogFormatAdapter(format: RequestFormat): LogFormatAdapter {
14
+ export function getLogFormatAdapter(format: ApiFormat): LogFormatAdapter {
15
15
  return ADAPTERS[format];
16
16
  }
17
17
 
18
- export function resolveLogFormat(log: Pick<CapturedLog, "path" | "apiFormat">): RequestFormat {
19
- const pathFormat = requestFormatForPath(log.path);
18
+ export function resolveLogFormat(log: Pick<CapturedLog, "path" | "apiFormat">): ApiFormat {
19
+ const pathFormat = apiFormatForPath(log.path);
20
20
  return pathFormat === "unknown" ? log.apiFormat : pathFormat;
21
21
  }
22
22
 
@@ -1,4 +1,4 @@
1
- import { OpenAIRequestSchema, parseOpenAIResponse } from "../../../proxy/formats/openai/schemas";
1
+ import { OpenAIRequestSchema, parseOpenAIResponse } from "../../../contracts/openai";
2
2
  import type { AnatomySegment } from "../anatomy/types";
3
3
  import { countCharacters, estimateTokens } from "../anatomy/tokenEstimate";
4
4
  import type { LogFormatAdapter } from "./types";
@@ -1,4 +1,4 @@
1
- import type { RequestFormat } from "../../../proxy/schemas";
1
+ import type { ApiFormat } from "../../../contracts";
2
2
  import type { AnatomySegment } from "../anatomy/types";
3
3
 
4
4
  export type RequestAnalysis = {
@@ -14,7 +14,7 @@ export type ResponseAnalysis = {
14
14
  };
15
15
 
16
16
  export type LogFormatAdapter = {
17
- readonly format: RequestFormat;
17
+ readonly format: ApiFormat;
18
18
  analyzeRequest(rawBody: string | null): RequestAnalysis;
19
19
  analyzeResponse(responseText: string | null): ResponseAnalysis;
20
20
  /**
@@ -1,6 +1,6 @@
1
1
  import { extractStopReason, isTurnBoundary, type StopReason } from "../../lib/stopReason";
2
2
  import { safeGetOwnProperty } from "../../lib/objectUtils";
3
- import type { CapturedLog } from "../../proxy/schemas";
3
+ import type { CapturedLog } from "../../contracts";
4
4
  import { resolveLogFormat } from "./log-formats";
5
5
 
6
6
  export type TurnEntry = {
@@ -0,0 +1,235 @@
1
+ import { z } from "zod";
2
+ import { JsonValueSchema } from "./json";
3
+
4
+ const CacheControl = z.object({
5
+ type: z.string(),
6
+ ttl: z.string().optional(),
7
+ scope: z.string().optional(),
8
+ });
9
+
10
+ const TextContentBlock = z.object({
11
+ type: z.literal("text"),
12
+ text: z.string(),
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();
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();
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;
@@ -0,0 +1,27 @@
1
+ export { JsonValueSchema, trustAsJsonValue } from "./json";
2
+ export type { JsonValue } from "./json";
3
+
4
+ export { CapturedLogSchema, StreamingChunkSchema } from "./log";
5
+ export type { ApiFormat, CapturedLog, RequestFormat, StreamingChunk, TokenUsage } from "./log";
6
+
7
+ export {
8
+ AnthropicRequestSchema,
9
+ AnthropicResponseSchema,
10
+ SseEventSchema,
11
+ } from "./anthropic";
12
+ export type { AnthropicResponse, ResponseContentBlockType } from "./anthropic";
13
+
14
+ export {
15
+ OpenAIChoice,
16
+ OpenAIChoiceDelta,
17
+ OpenAIFunctionCall,
18
+ OpenAIMessage,
19
+ OpenAIMessageContent,
20
+ OpenAIRequestSchema,
21
+ OpenAIResponseSchema,
22
+ OpenAISSERawChunkSchema,
23
+ OpenAIToolCallSchema,
24
+ OpenAIToolDefinition,
25
+ parseOpenAIResponse,
26
+ } from "./openai";
27
+ export type { OpenAIResponse, OpenAIToolCall } from "./openai";
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Shared JSON value type for API payload fragments and streaming chunks.
5
+ */
6
+ export type JsonValue =
7
+ | string
8
+ | number
9
+ | boolean
10
+ | null
11
+ | JsonValue[]
12
+ | { [key: string]: JsonValue };
13
+
14
+ export const JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>
15
+ z.union([
16
+ z.string(),
17
+ z.number(),
18
+ z.boolean(),
19
+ z.null(),
20
+ z.array(JsonValueSchema),
21
+ z.record(z.string(), JsonValueSchema),
22
+ ]),
23
+ );
24
+
25
+ /**
26
+ * Re-types a value as `JsonValue` without re-walking it. Use this ONLY when
27
+ * the value has already been validated and originated from `JSON.parse`.
28
+ */
29
+ export function trustAsJsonValue<T>(value: T): JsonValue {
30
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
31
+ return value as unknown as JsonValue;
32
+ }
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+ import { JsonValueSchema } from "./json";
3
+
4
+ export type ApiFormat = "anthropic" | "openai" | "unknown";
5
+ export type RequestFormat = ApiFormat;
6
+
7
+ /**
8
+ * A single SSE event from a streaming response.
9
+ */
10
+ export const StreamingChunkSchema = z.object({
11
+ index: z.number(),
12
+ timestamp: z.number(),
13
+ type: z.string(),
14
+ data: JsonValueSchema,
15
+ });
16
+
17
+ export type StreamingChunk = z.infer<typeof StreamingChunkSchema>;
18
+
19
+ const StreamingChunksArraySchema = z.object({
20
+ chunks: z.array(StreamingChunkSchema),
21
+ truncated: z.boolean().optional().default(false),
22
+ });
23
+
24
+ export const CapturedLogSchema = z.object({
25
+ id: z.number(),
26
+ timestamp: z.string(),
27
+ method: z.string(),
28
+ path: z.string(),
29
+ model: z.string().nullable(),
30
+ sessionId: z.string().nullable(),
31
+ rawRequestBody: z.string().nullable(),
32
+ responseStatus: z.number().nullable(),
33
+ responseText: z.string().nullable(),
34
+ inputTokens: z.number().nullable(),
35
+ outputTokens: z.number().nullable(),
36
+ cacheCreationInputTokens: z.number().nullable(),
37
+ cacheReadInputTokens: z.number().nullable(),
38
+ elapsedMs: z.number().nullable(),
39
+ firstChunkMs: z.number().nullable().optional(),
40
+ totalStreamMs: z.number().nullable().optional(),
41
+ tokensPerSecond: z.number().nullable().optional(),
42
+ streaming: z.boolean(),
43
+ userAgent: z.string().nullable(),
44
+ origin: z.string().nullable(),
45
+ rawHeaders: z.record(z.string(), z.string()).optional(),
46
+ /** Headers sent to the upstream LLM */
47
+ headers: z.record(z.string(), z.string()).optional(),
48
+ apiFormat: z.enum(["anthropic", "openai", "unknown"]).default("unknown"),
49
+ isTest: z.boolean().optional().default(false),
50
+ replayOfLogId: z.number().nullable().optional(),
51
+ providerName: z.string().nullable().optional(),
52
+ clientPort: z.number().nullable().optional(),
53
+ clientPid: z.number().nullable().optional(),
54
+ clientCwd: z.string().nullable().optional(),
55
+ clientProjectFolder: z.string().nullable().optional(),
56
+ streamingChunks: StreamingChunksArraySchema.optional(),
57
+ streamingChunksPath: z.string().nullable().optional(),
58
+ rawRequestBodyBytes: z.number().int().nonnegative().nullable().optional(),
59
+ responseTextBytes: z.number().int().nonnegative().nullable().optional(),
60
+ bodyContentMode: z.enum(["full", "compact", "truncated"]).optional(),
61
+ /** Error message from streaming response (e.g., SSE error event) */
62
+ error: z.string().nullable().optional(),
63
+ });
64
+
65
+ export type CapturedLog = z.infer<typeof CapturedLogSchema>;
66
+
67
+ export type TokenUsage = {
68
+ inputTokens: number | null;
69
+ outputTokens: number | null;
70
+ cacheCreationInputTokens: number | null;
71
+ cacheReadInputTokens: number | null;
72
+ };