@tonyclaw/agent-inspector 2.0.37 → 2.0.39
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/cli.js +528 -24
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-nEHCEVP4.js → CompareDrawer-Jfe6M6DQ.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-BstBIX2B.js → ProxyViewerContainer-CQKV0Bqq.js} +15 -15
- package/.output/public/assets/{ReplayDialog-CUnBdt1Q.js → ReplayDialog-B58TbTtY.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-BU9VT2Sw.js → RequestAnatomy-d4P6JNiP.js} +1 -1
- package/.output/public/assets/{ResponseView-amxuKPKY.js → ResponseView-Bum1a3tG.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-DpscrQM2.js → StreamingChunkSequence-CjBDp5E9.js} +1 -1
- package/.output/public/assets/_sessionId-BupV2gtf.js +1 -0
- package/.output/public/assets/index-DHSww5em.js +1 -0
- package/.output/public/assets/{main-D56QvEyw.js → main-DK9PoBjx.js} +2 -2
- package/.output/server/{_sessionId-ChwEDyI4.mjs → _sessionId-DjarbXpT.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-Ce2590rK.mjs → CompareDrawer-C5Z6AlUk.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-D6xM8A0S.mjs → ProxyViewerContainer-4pXsBywn.mjs} +37 -9
- package/.output/server/_ssr/{ReplayDialog-CB4KOlLe.mjs → ReplayDialog-w1vc1p5e.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-CsWV3W03.mjs → RequestAnatomy-2HaBhsNV.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-BuCCV3LU.mjs → ResponseView-SO_Y_W85.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-C5dE7V1d.mjs → StreamingChunkSequence-CXEa2DkO.mjs} +2 -2
- package/.output/server/_ssr/{index-BeIi0CPv.mjs → index-DuCGt4a2.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-Ca2MCyUX.mjs → router-D0BaSzkZ.mjs} +69 -76
- package/.output/server/{_tanstack-start-manifest_v-CBAJfSAX.mjs → _tanstack-start-manifest_v-6N4SODyd.mjs} +1 -1
- package/.output/server/index.mjs +62 -62
- package/README.md +8 -1
- package/package.json +1 -1
- package/src/cli/onboard.ts +629 -21
- package/src/components/ProxyViewer.tsx +1 -1
- package/src/components/ProxyViewerContainer.tsx +1 -1
- package/src/components/providers/ProviderForm.tsx +2 -2
- package/src/components/providers/SettingsDialog.tsx +30 -0
- 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 +1 -1
- 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 +16 -13
- 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 +2 -2
- package/src/proxy/upstream.ts +1 -1
- package/src/routes/api/logs.stream.ts +1 -1
- package/.output/public/assets/_sessionId-7c9bsOFT.js +0 -1
- package/.output/public/assets/index-B7a5OmIO.js +0 -1
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
Trash2,
|
|
12
12
|
} from "lucide-react";
|
|
13
13
|
|
|
14
|
-
import type { CapturedLog } from "../
|
|
14
|
+
import type { CapturedLog } from "../contracts";
|
|
15
15
|
import { exportLogsAsZip, type ExportMode } from "../lib/export-logs";
|
|
16
16
|
import type { CaptureMode, TimeDisplayFormat } from "../lib/runtimeConfig";
|
|
17
17
|
import { formatTimestampRange } from "../lib/timeDisplay";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useEffect, useCallback, useRef, useMemo, type JSX } from "react";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { CapturedLogSchema, type CapturedLog } from "../
|
|
3
|
+
import { CapturedLogSchema, type CapturedLog } from "../contracts";
|
|
4
4
|
import { useStripConfig } from "../lib/useStripConfig";
|
|
5
5
|
import { OnboardingBanner } from "./OnboardingBanner";
|
|
6
6
|
import { ProxyViewer } from "./ProxyViewer";
|
|
@@ -845,7 +845,7 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
845
845
|
Anthropic Format
|
|
846
846
|
</button>
|
|
847
847
|
</TooltipTrigger>
|
|
848
|
-
<TooltipContent>Anthropic Messages API
|
|
848
|
+
<TooltipContent>Anthropic Messages API format</TooltipContent>
|
|
849
849
|
</Tooltip>
|
|
850
850
|
</TooltipProvider>
|
|
851
851
|
<TooltipProvider>
|
|
@@ -863,7 +863,7 @@ export function ProviderForm({ provider, onSubmit, onCancel }: ProviderFormProps
|
|
|
863
863
|
OpenAI Format
|
|
864
864
|
</button>
|
|
865
865
|
</TooltipTrigger>
|
|
866
|
-
<TooltipContent>OpenAI Chat Completions API
|
|
866
|
+
<TooltipContent>OpenAI Chat Completions API format</TooltipContent>
|
|
867
867
|
</Tooltip>
|
|
868
868
|
</TooltipProvider>
|
|
869
869
|
</div>
|
|
@@ -293,6 +293,18 @@ function OnboardingSettingsTab(): JSX.Element {
|
|
|
293
293
|
label: "Codex prompt",
|
|
294
294
|
value: "Use the agent-inspector-onboard skill",
|
|
295
295
|
},
|
|
296
|
+
{
|
|
297
|
+
id: "opencode-config",
|
|
298
|
+
label: "OpenCode config",
|
|
299
|
+
value: "agent-inspector onboard --opencode-only",
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: "opencode-status",
|
|
303
|
+
label: "OpenCode status",
|
|
304
|
+
value: "agent-inspector onboard --status --opencode-only",
|
|
305
|
+
},
|
|
306
|
+
{ id: "opencode-verify", label: "OpenCode verify", value: "opencode mcp list" },
|
|
307
|
+
{ id: "opencode-proxy", label: "OpenCode proxy", value: `LLM_BASE_URL=${origin}/proxy` },
|
|
296
308
|
{ id: "mcp", label: "MCP URL", value: `${origin}/api/mcp` },
|
|
297
309
|
{ id: "proxy", label: "Proxy URL", value: `${origin}/proxy` },
|
|
298
310
|
{ id: "anthropic", label: "Anthropic base", value: `ANTHROPIC_BASE_URL=${origin}/proxy` },
|
|
@@ -345,6 +357,24 @@ function OnboardingSettingsTab(): JSX.Element {
|
|
|
345
357
|
instead. Configure only one entry for the same Inspector.
|
|
346
358
|
</span>
|
|
347
359
|
</div>
|
|
360
|
+
<div className="flex items-start gap-2">
|
|
361
|
+
<Check className="mt-0.5 size-3.5 text-emerald-500" />
|
|
362
|
+
<span>
|
|
363
|
+
OpenCode onboarding safely merges{" "}
|
|
364
|
+
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px] text-foreground">
|
|
365
|
+
mcp.agent-inspector
|
|
366
|
+
</code>{" "}
|
|
367
|
+
into{" "}
|
|
368
|
+
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px] text-foreground">
|
|
369
|
+
opencode.json
|
|
370
|
+
</code>
|
|
371
|
+
, then verify with{" "}
|
|
372
|
+
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[11px] text-foreground">
|
|
373
|
+
opencode mcp list
|
|
374
|
+
</code>
|
|
375
|
+
.
|
|
376
|
+
</span>
|
|
377
|
+
</div>
|
|
348
378
|
<div className="flex items-start gap-2">
|
|
349
379
|
<Check className="mt-0.5 size-3.5 text-emerald-500" />
|
|
350
380
|
<span>
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
type KnowledgeCandidate,
|
|
30
30
|
type KnowledgeCandidateStatus,
|
|
31
31
|
} from "../../knowledge/types";
|
|
32
|
-
import type { CapturedLog } from "../../
|
|
32
|
+
import type { CapturedLog } from "../../contracts";
|
|
33
33
|
import { Badge } from "../ui/badge";
|
|
34
34
|
import { Button } from "../ui/button";
|
|
35
35
|
import { buildTraceSummary, extractToolTraceEvents, type TraceSummary } from "./viewerState";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState, memo, useCallback, useEffect, useMemo } from "react";
|
|
2
2
|
import type { JSX } from "react";
|
|
3
3
|
import type { TimeDisplayFormat } from "../../lib/runtimeConfig";
|
|
4
|
-
import type { CapturedLog } from "../../
|
|
4
|
+
import type { CapturedLog } from "../../contracts";
|
|
5
5
|
import {
|
|
6
6
|
ConversationHeader,
|
|
7
7
|
getGroupApiFormat,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type JSX, useCallback, useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { useWindowVirtualizer } from "@tanstack/react-virtual";
|
|
3
|
-
import type { CapturedLog } from "../../
|
|
3
|
+
import type { CapturedLog } from "../../contracts";
|
|
4
4
|
import { ConversationGroup, type ConversationGroupProps } from "./ConversationGroup";
|
|
5
5
|
import type { ConversationGroupData } from "./ConversationHeader";
|
|
6
6
|
import { LOG_FOCUS_REQUEST_EVENT, readLogFocusRequest } from "./logFocus";
|
|
@@ -15,7 +15,7 @@ import { getSessionPath } from "../../lib/sessionUrl";
|
|
|
15
15
|
import type { TimeDisplayFormat } from "../../lib/runtimeConfig";
|
|
16
16
|
import { formatTimestampRange } from "../../lib/timeDisplay";
|
|
17
17
|
import { cn, formatTokens } from "../../lib/utils";
|
|
18
|
-
import type { CapturedLog } from "../../
|
|
18
|
+
import type { CapturedLog } from "../../contracts";
|
|
19
19
|
import { Badge } from "../ui/badge";
|
|
20
20
|
import { ConfirmDialog } from "../ui/confirm-dialog";
|
|
21
21
|
import { resolveLogFormat } from "./log-formats";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { GitCompareArrows } from "lucide-react";
|
|
2
2
|
import { Suspense, type JSX } from "react";
|
|
3
3
|
import { useEffect, useMemo, useRef, useState, memo } from "react";
|
|
4
|
-
import type { CapturedLog } from "../../
|
|
4
|
+
import type { CapturedLog } from "../../contracts";
|
|
5
5
|
import type { TimeDisplayFormat } from "../../lib/runtimeConfig";
|
|
6
6
|
import { stripClaudeCodeBillingHeader } from "../../proxy/claudeCodeStrip";
|
|
7
7
|
import { Button } from "../ui/button";
|
|
@@ -27,7 +27,7 @@ import { memo } from "react";
|
|
|
27
27
|
import type { TimeDisplayFormat } from "../../lib/runtimeConfig";
|
|
28
28
|
import { formatTimestamp } from "../../lib/timeDisplay";
|
|
29
29
|
import { cn, formatTokens, getStatusCategory, type StatusCategory } from "../../lib/utils";
|
|
30
|
-
import type { CapturedLog } from "../../
|
|
30
|
+
import type { CapturedLog } from "../../contracts";
|
|
31
31
|
import { Badge } from "../ui/badge";
|
|
32
32
|
import { Button } from "../ui/button";
|
|
33
33
|
import { ProviderLogo, detectProvider } from "../providers/ProviderLogo";
|
|
@@ -8,7 +8,7 @@ import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/
|
|
|
8
8
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog";
|
|
9
9
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
|
|
10
10
|
import { ResponseView } from "./ResponseView";
|
|
11
|
-
import { CapturedLogSchema, type CapturedLog } from "../../
|
|
11
|
+
import { CapturedLogSchema, type CapturedLog } from "../../contracts";
|
|
12
12
|
import { dispatchLogFocusRequest } from "./logFocus";
|
|
13
13
|
import {
|
|
14
14
|
buildReplayComparisons,
|
|
@@ -3,7 +3,7 @@ import type { JSX } from "react";
|
|
|
3
3
|
import { memo } from "react";
|
|
4
4
|
import { useMemo } from "react";
|
|
5
5
|
import { cn, formatTokens, getStatusCategory, type StatusCategory } from "../../lib/utils";
|
|
6
|
-
import type {
|
|
6
|
+
import type { ApiFormat } from "../../contracts";
|
|
7
7
|
import { AnswerMarkdown } from "./AnswerMarkdown";
|
|
8
8
|
import { formatViewFor } from "./formats";
|
|
9
9
|
import { getLogFormatAdapter } from "./log-formats";
|
|
@@ -16,7 +16,7 @@ export type ResponseViewProps = {
|
|
|
16
16
|
outputTokens: number | null;
|
|
17
17
|
cacheCreationInputTokens?: number | null;
|
|
18
18
|
cacheReadInputTokens?: number | null;
|
|
19
|
-
apiFormat?:
|
|
19
|
+
apiFormat?: ApiFormat;
|
|
20
20
|
/** SSE error message from streaming response */
|
|
21
21
|
error?: string | null;
|
|
22
22
|
};
|
|
@@ -3,7 +3,7 @@ import { ChevronDown, ChevronRight, Loader2 } from "lucide-react";
|
|
|
3
3
|
import { Badge } from "../ui/badge";
|
|
4
4
|
import { JsonViewer } from "../ui/json-viewer";
|
|
5
5
|
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
|
|
6
|
-
import type { StreamingChunk } from "../../
|
|
6
|
+
import type { StreamingChunk } from "../../contracts";
|
|
7
7
|
|
|
8
8
|
export type StreamingChunkSequenceProps = {
|
|
9
9
|
logId: number;
|
|
@@ -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 "../../
|
|
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 "../../../
|
|
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 "../../../../
|
|
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 {
|
|
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:
|
|
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 {
|
|
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
|
|
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:
|
|
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 "../../../../
|
|
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 {
|
|
2
|
-
import type {
|
|
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<
|
|
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:
|
|
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">):
|
|
19
|
-
const pathFormat =
|
|
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 "../../../
|
|
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 {
|
|
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:
|
|
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 "../../
|
|
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
|
+
}
|