@tonyclaw/agent-inspector 3.0.14 → 3.0.15
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-DDfwHQUi.js → CompareDrawer-UaIxykqz.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-DlpfcX56.js +106 -0
- package/.output/public/assets/{ReplayDialog-D-26DMBt.js → ReplayDialog-BFFomU1m.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-B6zNFqNX.js → RequestAnatomy-DKQJBt_c.js} +1 -1
- package/.output/public/assets/{ResponseView-Ccy95rWI.js → ResponseView-D7yotmne.js} +2 -2
- package/.output/public/assets/{StreamingChunkSequence-yIiscGuE.js → StreamingChunkSequence-Da-6WNFG.js} +1 -1
- package/.output/public/assets/{_sessionId-BnMB0zab.js → _sessionId-ByTXLS-w.js} +1 -1
- package/.output/public/assets/{index-BbtAIxbg.js → index-BrM8t5mc.js} +1 -1
- package/.output/public/assets/index-CGpPRty8.js +1 -0
- package/.output/public/assets/index-HRfrFVYw.css +1 -0
- package/.output/public/assets/{json-viewer-C838cVmD.js → json-viewer-DyjXQdVu.js} +1 -1
- package/.output/public/assets/{main-BfN4culo.js → main-Zv_gjZMb.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +215 -201
- package/.output/server/{_sessionId-DoprmwZV.mjs → _sessionId-GcFhWT0i.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-YMLJNxXR.mjs → CompareDrawer-BV7dw1TN.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-C62eZnva.mjs → ProxyViewerContainer-CcgfvaS4.mjs} +725 -378
- package/.output/server/_ssr/{ReplayDialog-NmN7Ukjo.mjs → ReplayDialog-B7sBKxIO.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-Dawm2qxe.mjs → RequestAnatomy-s_9Veje2.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-BHyAY83t.mjs → ResponseView-DsOFPCvF.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-C4qgcJbg.mjs → StreamingChunkSequence-CyA1XtiF.mjs} +3 -3
- package/.output/server/_ssr/{index-B2Pf6W_T.mjs → index-CDDRt201.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-u67BASf8.mjs → json-viewer-BFV-xtRM.mjs} +3 -3
- package/.output/server/_ssr/{router-CZhFVMGN.mjs → router-B2Q7vHPM.mjs} +58 -14
- package/.output/server/{_tanstack-start-manifest_v-Dk2HfOoe.mjs → _tanstack-start-manifest_v-Dm_GmuRz.mjs} +1 -1
- package/.output/server/index.mjs +73 -73
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +470 -197
- package/src/components/ProxyViewerContainer.tsx +145 -17
- package/src/components/proxy-viewer/ToolTraceEvents.tsx +36 -10
- package/src/components/proxy-viewer/TurnGroup.tsx +4 -1
- package/src/proxy/formats/openai/codexMetadata.ts +61 -0
- package/src/proxy/formats/openai/handler.ts +8 -2
- package/styles/globals.css +54 -0
- package/.output/public/assets/ProxyViewerContainer-CbNsaoQw.js +0 -106
- package/.output/public/assets/index-49RC4dlD.js +0 -1
- package/.output/public/assets/index-DXKupW0r.css +0 -1
|
@@ -2,7 +2,11 @@ import { useState, useEffect, useCallback, useRef, useMemo, useTransition, type
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { CapturedLogSchema, type CapturedLog } from "../contracts";
|
|
4
4
|
import { fetchJson, fetchJsonWithTimeout } from "../lib/apiClient";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
DeleteInspectorGroupsResponseSchema,
|
|
7
|
+
InspectorGroupsListResponseSchema,
|
|
8
|
+
type InspectorGroup,
|
|
9
|
+
} from "../lib/groupContract";
|
|
6
10
|
import { ImportLogsResponseSchema, type ImportLogsResponse } from "../lib/logImportContract";
|
|
7
11
|
import { useStripConfig } from "../lib/useStripConfig";
|
|
8
12
|
import { OnboardingBanner } from "./OnboardingBanner";
|
|
@@ -58,6 +62,11 @@ const DeleteLogsResponseSchema = z.object({
|
|
|
58
62
|
sessionArchiveLogsDeleted: z.number().int().nonnegative().optional(),
|
|
59
63
|
});
|
|
60
64
|
|
|
65
|
+
type GroupCleanupResult = {
|
|
66
|
+
deleted: number;
|
|
67
|
+
ok: boolean;
|
|
68
|
+
};
|
|
69
|
+
|
|
61
70
|
type SessionPageRequest =
|
|
62
71
|
| { kind: "newest" }
|
|
63
72
|
| { kind: "oldest" }
|
|
@@ -190,6 +199,50 @@ function fetchSessionLogsPage(
|
|
|
190
199
|
);
|
|
191
200
|
}
|
|
192
201
|
|
|
202
|
+
type SessionLogIdCollection = {
|
|
203
|
+
ids: number[];
|
|
204
|
+
truncated: boolean;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
async function collectSessionLogIds(
|
|
208
|
+
sessionId: string,
|
|
209
|
+
onProgress: (logCount: number, pageCount: number) => void,
|
|
210
|
+
): Promise<SessionLogIdCollection> {
|
|
211
|
+
const ids = new Set<number>();
|
|
212
|
+
let page = await fetchSessionLogsPage(sessionId, { kind: "oldest" }, SESSION_RELOAD_PAGE_LIMIT);
|
|
213
|
+
for (const log of page.logs) {
|
|
214
|
+
ids.add(log.id);
|
|
215
|
+
}
|
|
216
|
+
onProgress(ids.size, 1);
|
|
217
|
+
|
|
218
|
+
let loadedPages = 1;
|
|
219
|
+
while (page.hasNewer && page.newestLogId !== null && loadedPages < MAX_SESSION_RELOAD_PAGES) {
|
|
220
|
+
page = await fetchSessionLogsPage(
|
|
221
|
+
sessionId,
|
|
222
|
+
{ kind: "newer", afterLogId: page.newestLogId },
|
|
223
|
+
SESSION_RELOAD_PAGE_LIMIT,
|
|
224
|
+
);
|
|
225
|
+
for (const log of page.logs) {
|
|
226
|
+
ids.add(log.id);
|
|
227
|
+
}
|
|
228
|
+
loadedPages += 1;
|
|
229
|
+
onProgress(ids.size, loadedPages);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return { ids: [...ids], truncated: page.hasNewer };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function deleteAllGroupsForFullHistoryDelete(): Promise<GroupCleanupResult> {
|
|
236
|
+
try {
|
|
237
|
+
const result = await fetchJson("/api/groups", DeleteInspectorGroupsResponseSchema, {
|
|
238
|
+
method: "DELETE",
|
|
239
|
+
});
|
|
240
|
+
return { deleted: result.deleted, ok: true };
|
|
241
|
+
} catch {
|
|
242
|
+
return { deleted: 0, ok: false };
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
193
246
|
export function mergeLogsById(
|
|
194
247
|
previousLogs: readonly CapturedLog[],
|
|
195
248
|
incomingLogs: readonly CapturedLog[],
|
|
@@ -685,27 +738,88 @@ export function ProxyViewerContainer({
|
|
|
685
738
|
[showToast],
|
|
686
739
|
);
|
|
687
740
|
|
|
688
|
-
const handleDeleteCurrentView = useCallback(
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
741
|
+
const handleDeleteCurrentView = useCallback(async (): Promise<void> => {
|
|
742
|
+
const deleteRequestId = sessionPageRequestIdRef.current + 1;
|
|
743
|
+
sessionPageRequestIdRef.current = deleteRequestId;
|
|
744
|
+
setSessionPageLoading(true);
|
|
745
|
+
stopSessionLoadProgress();
|
|
746
|
+
dismissToast();
|
|
747
|
+
|
|
748
|
+
try {
|
|
749
|
+
if (selectedSession === "__all__") {
|
|
750
|
+
startSessionLoadProgress("Deleting stored history", deleteRequestId);
|
|
751
|
+
const result = await fetchJson("/api/logs", DeleteLogsResponseSchema, {
|
|
752
|
+
method: "DELETE",
|
|
753
|
+
});
|
|
754
|
+
const groupCleanup = await deleteAllGroupsForFullHistoryDelete();
|
|
755
|
+
if (sessionPageRequestIdRef.current !== deleteRequestId) return;
|
|
756
|
+
setAllLogs([]);
|
|
757
|
+
logIndexRef.current.clear();
|
|
758
|
+
setLogPage(null);
|
|
759
|
+
setKnownSessions([]);
|
|
760
|
+
setSessionMemberships([]);
|
|
761
|
+
setSessionPageLoading(false);
|
|
762
|
+
stopSessionLoadProgress();
|
|
763
|
+
const groupMessage = groupCleanup.ok
|
|
764
|
+
? ` Cleared ${groupCleanup.deleted.toString()} group${
|
|
765
|
+
groupCleanup.deleted === 1 ? "" : "s"
|
|
766
|
+
}.`
|
|
767
|
+
: " Group cleanup failed; open Groups to retry Clear.";
|
|
768
|
+
showToast({
|
|
769
|
+
message: `Deleted ${result.cleared.toString()} stored log${
|
|
770
|
+
result.cleared === 1 ? "" : "s"
|
|
771
|
+
} across all sessions.${groupMessage}`,
|
|
772
|
+
tone: groupCleanup.ok ? "success" : "error",
|
|
773
|
+
});
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
const sessionId = selectedSession;
|
|
778
|
+
startSessionLoadProgress("Deleting session history", deleteRequestId);
|
|
779
|
+
const collected = await collectSessionLogIds(sessionId, (logCount, pageCount) => {
|
|
780
|
+
updateSessionLoadProgress("Deleting session history", deleteRequestId, logCount, pageCount);
|
|
781
|
+
});
|
|
782
|
+
const idSet = new Set(collected.ids);
|
|
783
|
+
for (const log of allLogs) {
|
|
784
|
+
if (log.sessionId === sessionId) {
|
|
785
|
+
idSet.add(log.id);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
const persistedIds = [...idSet].filter((id) => Number.isInteger(id) && id >= 0);
|
|
692
789
|
if (persistedIds.length === 0) {
|
|
790
|
+
if (sessionPageRequestIdRef.current !== deleteRequestId) return;
|
|
791
|
+
setAllLogs((prev) => {
|
|
792
|
+
const remaining = prev.filter((log) => log.sessionId !== sessionId);
|
|
793
|
+
logIndexRef.current = buildLogIndex(remaining);
|
|
794
|
+
return remaining;
|
|
795
|
+
});
|
|
796
|
+
setLogPage((prev) =>
|
|
797
|
+
prev === null
|
|
798
|
+
? null
|
|
799
|
+
: {
|
|
800
|
+
...prev,
|
|
801
|
+
logs: prev.logs.filter((log) => log.sessionId !== sessionId),
|
|
802
|
+
},
|
|
803
|
+
);
|
|
804
|
+
setKnownSessions((prev) => prev.filter((session) => session !== sessionId));
|
|
805
|
+
setSessionPageLoading(false);
|
|
806
|
+
stopSessionLoadProgress();
|
|
693
807
|
showToast({
|
|
694
|
-
message: "No
|
|
695
|
-
tone: "
|
|
808
|
+
message: "No stored log records were found for this session.",
|
|
809
|
+
tone: "success",
|
|
696
810
|
});
|
|
697
811
|
return;
|
|
698
812
|
}
|
|
699
|
-
|
|
700
|
-
const removed = allLogs.filter((log) => idSet.has(log.id));
|
|
813
|
+
|
|
701
814
|
const result = await fetchJson("/api/logs", DeleteLogsResponseSchema, {
|
|
702
815
|
method: "DELETE",
|
|
703
816
|
headers: { "content-type": "application/json" },
|
|
704
817
|
body: JSON.stringify({ ids: persistedIds }),
|
|
705
818
|
});
|
|
706
819
|
|
|
820
|
+
if (sessionPageRequestIdRef.current !== deleteRequestId) return;
|
|
707
821
|
setAllLogs((prev) => {
|
|
708
|
-
const remaining = prev.filter((log) =>
|
|
822
|
+
const remaining = prev.filter((log) => log.sessionId !== sessionId);
|
|
709
823
|
logIndexRef.current = buildLogIndex(remaining);
|
|
710
824
|
return remaining;
|
|
711
825
|
});
|
|
@@ -714,19 +828,33 @@ export function ProxyViewerContainer({
|
|
|
714
828
|
? null
|
|
715
829
|
: {
|
|
716
830
|
...prev,
|
|
717
|
-
logs: prev.logs.filter((log) =>
|
|
831
|
+
logs: prev.logs.filter((log) => log.sessionId !== sessionId),
|
|
718
832
|
},
|
|
719
833
|
);
|
|
720
|
-
setKnownSessions((prev) =>
|
|
834
|
+
setKnownSessions((prev) => prev.filter((session) => session !== sessionId));
|
|
835
|
+
setSessionPageLoading(false);
|
|
836
|
+
stopSessionLoadProgress();
|
|
721
837
|
showToast({
|
|
722
838
|
message: `Deleted ${result.cleared.toString()} stored log${
|
|
723
839
|
result.cleared === 1 ? "" : "s"
|
|
724
|
-
}
|
|
725
|
-
tone: "success",
|
|
840
|
+
} for this session${collected.truncated ? ". More history may remain." : "."}`,
|
|
841
|
+
tone: collected.truncated ? "error" : "success",
|
|
726
842
|
});
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
|
|
843
|
+
} finally {
|
|
844
|
+
if (sessionPageRequestIdRef.current === deleteRequestId) {
|
|
845
|
+
setSessionPageLoading(false);
|
|
846
|
+
stopSessionLoadProgress();
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}, [
|
|
850
|
+
allLogs,
|
|
851
|
+
dismissToast,
|
|
852
|
+
selectedSession,
|
|
853
|
+
showToast,
|
|
854
|
+
startSessionLoadProgress,
|
|
855
|
+
stopSessionLoadProgress,
|
|
856
|
+
updateSessionLoadProgress,
|
|
857
|
+
]);
|
|
730
858
|
|
|
731
859
|
const handleReloadSession = useCallback(() => {
|
|
732
860
|
if (initialSessionId !== undefined) {
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { type JSX } from "react";
|
|
2
|
-
import { Wrench } from "lucide-react";
|
|
2
|
+
import { AlertTriangle, Wrench } from "lucide-react";
|
|
3
3
|
import type { ToolTraceEvent } from "./viewerState";
|
|
4
4
|
import { dispatchLogFocusRequest } from "./logFocus";
|
|
5
5
|
|
|
6
6
|
type ToolTraceEventsProps = {
|
|
7
7
|
events: ToolTraceEvent[];
|
|
8
|
+
warnings?: readonly string[];
|
|
8
9
|
};
|
|
9
10
|
|
|
11
|
+
const VISIBLE_TOOL_LIMIT = 4;
|
|
12
|
+
|
|
10
13
|
function ToolTraceEventChip({ event }: { event: ToolTraceEvent }): JSX.Element {
|
|
11
14
|
return (
|
|
12
15
|
<button
|
|
13
16
|
type="button"
|
|
14
17
|
key={event.id}
|
|
15
|
-
className="inline-flex min-w-0 items-center gap-1
|
|
18
|
+
className="inline-flex h-6 max-w-[11rem] min-w-0 items-center gap-1 rounded-md bg-white/[0.028] px-1.5 text-[11px] text-muted-foreground transition-colors hover:bg-sky-400/[0.08] hover:text-sky-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
16
19
|
onClick={() =>
|
|
17
20
|
dispatchLogFocusRequest({
|
|
18
21
|
logId: event.logId,
|
|
@@ -21,21 +24,44 @@ function ToolTraceEventChip({ event }: { event: ToolTraceEvent }): JSX.Element {
|
|
|
21
24
|
})
|
|
22
25
|
}
|
|
23
26
|
aria-label={`Open response tool call ${event.name}`}
|
|
24
|
-
title={`Open ${event.name} in Response`}
|
|
25
27
|
>
|
|
26
|
-
<Wrench className="size-3
|
|
28
|
+
<Wrench className="size-3 shrink-0 text-sky-400/65" />
|
|
27
29
|
<span className="min-w-0 truncate font-mono font-semibold">{event.name}</span>
|
|
28
30
|
</button>
|
|
29
31
|
);
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
export function ToolTraceEvents({
|
|
33
|
-
|
|
34
|
+
export function ToolTraceEvents({
|
|
35
|
+
events,
|
|
36
|
+
warnings = [],
|
|
37
|
+
}: ToolTraceEventsProps): JSX.Element | null {
|
|
38
|
+
if (events.length === 0 && warnings.length === 0) return null;
|
|
39
|
+
const visibleEvents = events.slice(0, VISIBLE_TOOL_LIMIT);
|
|
40
|
+
const hiddenCount = Math.max(0, events.length - visibleEvents.length);
|
|
34
41
|
return (
|
|
35
|
-
<div className="mx-3 mb-2 flex
|
|
36
|
-
{events.
|
|
37
|
-
<
|
|
38
|
-
|
|
42
|
+
<div className="mx-3 mb-2 flex min-w-0 items-center gap-1.5 overflow-hidden rounded-md bg-black/[0.10] px-2 py-1 shadow-[inset_0_1px_0_rgba(255,255,255,0.025)]">
|
|
43
|
+
{events.length > 0 && (
|
|
44
|
+
<span className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md px-1.5 font-mono text-[10px] font-semibold uppercase tracking-[0.12em] text-sky-300/70">
|
|
45
|
+
<Wrench className="size-3" />
|
|
46
|
+
{events.length}
|
|
47
|
+
</span>
|
|
48
|
+
)}
|
|
49
|
+
{warnings.length > 0 && (
|
|
50
|
+
<span className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-amber-300/20 bg-amber-300/[0.08] px-1.5 font-mono text-[10px] font-semibold text-amber-100">
|
|
51
|
+
<AlertTriangle className="size-3" />
|
|
52
|
+
{warnings.length}
|
|
53
|
+
</span>
|
|
54
|
+
)}
|
|
55
|
+
<div className="flex min-w-0 flex-1 items-center gap-1 overflow-hidden">
|
|
56
|
+
{visibleEvents.map((event) => (
|
|
57
|
+
<ToolTraceEventChip key={event.id} event={event} />
|
|
58
|
+
))}
|
|
59
|
+
{hiddenCount > 0 && (
|
|
60
|
+
<span className="inline-flex h-6 shrink-0 items-center rounded-md bg-white/[0.025] px-1.5 font-mono text-[11px] font-semibold text-muted-foreground">
|
|
61
|
+
+{hiddenCount}
|
|
62
|
+
</span>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
39
65
|
</div>
|
|
40
66
|
);
|
|
41
67
|
}
|
|
@@ -361,7 +361,10 @@ export const TurnGroup = memo(function TurnGroup({
|
|
|
361
361
|
comparisonPredecessors.has(log.id) ? onCompareWithPrevious : undefined
|
|
362
362
|
}
|
|
363
363
|
/>
|
|
364
|
-
<ToolTraceEvents
|
|
364
|
+
<ToolTraceEvents
|
|
365
|
+
events={toolEventsByLogId.get(log.id) ?? []}
|
|
366
|
+
warnings={log.warnings ?? []}
|
|
367
|
+
/>
|
|
365
368
|
</div>
|
|
366
369
|
</div>
|
|
367
370
|
);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
type CodexClientMetadata = {
|
|
2
|
+
sessionId: string | null;
|
|
3
|
+
threadId: string | null;
|
|
4
|
+
turnId: string | null;
|
|
5
|
+
installationId: string | null;
|
|
6
|
+
windowId: string | null;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const EMPTY_CODEX_CLIENT_METADATA: CodexClientMetadata = {
|
|
10
|
+
sessionId: null,
|
|
11
|
+
threadId: null,
|
|
12
|
+
turnId: null,
|
|
13
|
+
installationId: null,
|
|
14
|
+
windowId: null,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function readObjectField(value: unknown, field: string): unknown {
|
|
18
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return undefined;
|
|
19
|
+
return Object.getOwnPropertyDescriptor(value, field)?.value;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function readStringField(value: unknown, field: string): string | null {
|
|
23
|
+
const fieldValue = readObjectField(value, field);
|
|
24
|
+
return typeof fieldValue === "string" && fieldValue.length > 0 ? fieldValue : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function parseNestedTurnMetadata(value: unknown): unknown {
|
|
28
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(value);
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function extractCodexClientMetadata(rawRequest: unknown): CodexClientMetadata {
|
|
37
|
+
const clientMetadata = readObjectField(rawRequest, "client_metadata");
|
|
38
|
+
if (clientMetadata === undefined) return EMPTY_CODEX_CLIENT_METADATA;
|
|
39
|
+
|
|
40
|
+
const turnMetadata = parseNestedTurnMetadata(
|
|
41
|
+
readObjectField(clientMetadata, "x-codex-turn-metadata"),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
sessionId:
|
|
46
|
+
readStringField(clientMetadata, "session_id") ?? readStringField(turnMetadata, "session_id"),
|
|
47
|
+
threadId:
|
|
48
|
+
readStringField(clientMetadata, "thread_id") ?? readStringField(turnMetadata, "thread_id"),
|
|
49
|
+
turnId: readStringField(clientMetadata, "turn_id") ?? readStringField(turnMetadata, "turn_id"),
|
|
50
|
+
installationId:
|
|
51
|
+
readStringField(clientMetadata, "x-codex-installation-id") ??
|
|
52
|
+
readStringField(turnMetadata, "installation_id"),
|
|
53
|
+
windowId:
|
|
54
|
+
readStringField(clientMetadata, "x-codex-window-id") ??
|
|
55
|
+
readStringField(turnMetadata, "window_id"),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function extractCodexSessionId(rawRequest: unknown): string | null {
|
|
60
|
+
return extractCodexClientMetadata(rawRequest).sessionId;
|
|
61
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
parseOpenAIResponse,
|
|
8
8
|
} from "./schemas";
|
|
9
9
|
import { extractOpenAIStream } from "./stream";
|
|
10
|
+
import { extractCodexSessionId } from "./codexMetadata";
|
|
10
11
|
|
|
11
12
|
function emptyTokens(): TokenUsage {
|
|
12
13
|
return {
|
|
@@ -17,6 +18,11 @@ function emptyTokens(): TokenUsage {
|
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
function headerSessionId(headers: Headers | undefined): string | null {
|
|
22
|
+
if (headers === undefined) return null;
|
|
23
|
+
return headers.get("x-agent-inspector-session-id") ?? headers.get("x-session-affinity");
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
export const OpenAIFormatHandler: FormatHandler = {
|
|
21
27
|
format: "openai",
|
|
22
28
|
|
|
@@ -27,14 +33,14 @@ export const OpenAIFormatHandler: FormatHandler = {
|
|
|
27
33
|
if (result.success) {
|
|
28
34
|
return {
|
|
29
35
|
model: result.data.model,
|
|
30
|
-
sessionId:
|
|
36
|
+
sessionId: extractCodexSessionId(json) ?? headerSessionId(headers),
|
|
31
37
|
};
|
|
32
38
|
}
|
|
33
39
|
const responsesResult = OpenAIResponsesRequestSchema.safeParse(json);
|
|
34
40
|
if (responsesResult.success) {
|
|
35
41
|
return {
|
|
36
42
|
model: responsesResult.data.model,
|
|
37
|
-
sessionId:
|
|
43
|
+
sessionId: extractCodexSessionId(json) ?? headerSessionId(headers),
|
|
38
44
|
};
|
|
39
45
|
}
|
|
40
46
|
return null;
|
package/styles/globals.css
CHANGED
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
--animate-crab-appear: crab-appear 300ms ease-out;
|
|
45
45
|
--animate-crab-settle: crab-settle 400ms ease-in-out;
|
|
46
46
|
--animate-crab-piano-pop: crab-piano-pop 400ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
|
|
47
|
+
--animate-crab-short-leg-body: crab-short-leg-body 720ms ease-in-out infinite;
|
|
48
|
+
--animate-crab-short-leg-step: crab-short-leg-step 360ms ease-in-out infinite;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
:root {
|
|
@@ -165,10 +167,42 @@
|
|
|
165
167
|
}
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
@keyframes crab-short-leg-body {
|
|
171
|
+
0%,
|
|
172
|
+
100% {
|
|
173
|
+
transform: translateY(0) rotate(-1deg);
|
|
174
|
+
}
|
|
175
|
+
25% {
|
|
176
|
+
transform: translateY(1px) rotate(1.5deg);
|
|
177
|
+
}
|
|
178
|
+
50% {
|
|
179
|
+
transform: translateY(-1px) rotate(-1.5deg);
|
|
180
|
+
}
|
|
181
|
+
75% {
|
|
182
|
+
transform: translateY(1px) rotate(1deg);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@keyframes crab-short-leg-step {
|
|
187
|
+
0%,
|
|
188
|
+
100% {
|
|
189
|
+
transform: translateY(0) scaleY(0.72) rotate(var(--crab-leg-rest, 0deg));
|
|
190
|
+
opacity: 0.42;
|
|
191
|
+
}
|
|
192
|
+
50% {
|
|
193
|
+
transform: translateY(3px) scaleY(1.15) rotate(var(--crab-leg-step, 0deg));
|
|
194
|
+
opacity: 0.9;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
168
198
|
@media (prefers-reduced-motion: reduce) {
|
|
169
199
|
.animate-crab-piano-pop {
|
|
170
200
|
animation: none !important;
|
|
171
201
|
}
|
|
202
|
+
.floating-crab-body,
|
|
203
|
+
.floating-crab-leg {
|
|
204
|
+
animation: none !important;
|
|
205
|
+
}
|
|
172
206
|
}
|
|
173
207
|
|
|
174
208
|
[data-deep-link-highlight="true"] {
|
|
@@ -205,6 +239,26 @@
|
|
|
205
239
|
}
|
|
206
240
|
|
|
207
241
|
@layer utilities {
|
|
242
|
+
.floating-crab-body {
|
|
243
|
+
animation: var(--animate-crab-short-leg-body);
|
|
244
|
+
transform-origin: 50% 74%;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.floating-crab-leg {
|
|
248
|
+
animation: var(--animate-crab-short-leg-step);
|
|
249
|
+
transform-origin: 50% 0%;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.floating-crab-leg-left {
|
|
253
|
+
--crab-leg-rest: -10deg;
|
|
254
|
+
--crab-leg-step: 14deg;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.floating-crab-leg-right {
|
|
258
|
+
--crab-leg-rest: 10deg;
|
|
259
|
+
--crab-leg-step: -14deg;
|
|
260
|
+
}
|
|
261
|
+
|
|
208
262
|
.inspector-scrollbar {
|
|
209
263
|
scrollbar-color: color-mix(in srgb, var(--muted-foreground) 32%, transparent) transparent;
|
|
210
264
|
scrollbar-width: thin;
|