@tonyclaw/agent-inspector 3.0.24 → 3.0.25

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 (34) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-BC52FYwn.js → CompareDrawer-BnvOPwpe.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-DcqFqo1m.js +127 -0
  4. package/.output/public/assets/{ReplayDialog-BcKsarKt.js → ReplayDialog-BJgoQWdW.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-DR0uGpCj.js → RequestAnatomy-CpBZEHnM.js} +1 -1
  6. package/.output/public/assets/{ResponseView-kxAAPfmn.js → ResponseView-CWmyRb2M.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-YQR0PjQj.js → StreamingChunkSequence-BWhC8bwx.js} +1 -1
  8. package/.output/public/assets/{_sessionId-DRl-Y9om.js → _sessionId-Cq-2OqUU.js} +1 -1
  9. package/.output/public/assets/{index-CQbrc-hi.js → index-BKi9IRtV.js} +3 -3
  10. package/.output/public/assets/index-BMYuDL5X.css +1 -0
  11. package/.output/public/assets/{index-CcSIBI4L.js → index-Cf8O0Oos.js} +1 -1
  12. package/.output/public/assets/{index-ZrMgyEZV.js → index-DdgTJ4QJ.js} +1 -1
  13. package/.output/public/assets/{json-viewer-CS5pwnEA.js → json-viewer-Bqu_4hmm.js} +1 -1
  14. package/.output/server/_libs/lucide-react.mjs +245 -217
  15. package/.output/server/{_sessionId-BLk2xPkR.mjs → _sessionId-Ba7H3Gjw.mjs} +2 -2
  16. package/.output/server/_ssr/{CompareDrawer-Cw7Dseo3.mjs → CompareDrawer-aH59Ab6x.mjs} +3 -3
  17. package/.output/server/_ssr/{ProxyViewerContainer-D8SB0zyQ.mjs → ProxyViewerContainer-By-I0tJv.mjs} +539 -254
  18. package/.output/server/_ssr/{ReplayDialog-B-YMhZkE.mjs → ReplayDialog-BO4Vy0et.mjs} +4 -4
  19. package/.output/server/_ssr/{RequestAnatomy-a9d8UTYZ.mjs → RequestAnatomy-FtOr7vSS.mjs} +3 -3
  20. package/.output/server/_ssr/{ResponseView-PzaZS4CN.mjs → ResponseView-cvw6ajue.mjs} +3 -3
  21. package/.output/server/_ssr/{StreamingChunkSequence-C21_TCXk.mjs → StreamingChunkSequence-Oc8S2kD6.mjs} +3 -3
  22. package/.output/server/_ssr/{index-CrCeNP7H.mjs → index-BDRlQheR.mjs} +2 -2
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-Di2gxs9H.mjs → json-viewer-Cd6trhQr.mjs} +3 -3
  25. package/.output/server/_ssr/{router-BJzdUbcH.mjs → router-bofP-Ekl.mjs} +4 -4
  26. package/.output/server/{_tanstack-start-manifest_v-CGBTdAYC.mjs → _tanstack-start-manifest_v-BPuf86qB.mjs} +1 -1
  27. package/.output/server/index.mjs +70 -70
  28. package/package.json +1 -1
  29. package/src/components/ProxyViewer.tsx +2 -280
  30. package/src/components/inspector-pet/InspectorPet.tsx +390 -0
  31. package/src/components/inspector-pet/inspectorPetLogic.ts +273 -0
  32. package/styles/globals.css +98 -1
  33. package/.output/public/assets/ProxyViewerContainer-WuChOrSS.js +0 -127
  34. package/.output/public/assets/index-DQeXi4Rv.css +0 -1
@@ -1,5 +1,5 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, R as React } from "../_libs/react.mjs";
2
- import { C as CapturedLogSchema, z as DeleteInspectorGroupsResponseSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, g as readStoredUiScalePreference, h as persistUiScalePreference, i as applyUiScalePreference, w as extractStopReason, p as packageJson, P as ProviderConfigSchema, U as UI_SCALE_STORAGE_KEY, j as normalizeUiScalePreference, q as apiFormatForPath, B as GroupEvidenceExportResultSchema, E as DeleteInspectorGroupResponseSchema, $ as PiAgentResponseSchema, v as isTurnBoundary, r as readStoredThemeMode, e as applyThemeMode, f as persistThemeMode, a2 as formatUiScale, x as AlertSummarySchema, y as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, V as createPendingProviderTestResults, W as ProviderTestResultsSchema, X as createFailedProviderTestResults, Y as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, Z as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, _ as TimeDisplayFormatSchema, T as THEME_MODE_STORAGE_KEY, n as normalizeThemeMode, H as maskApiKey, M as PATH_V1_MESSAGES, N as PATH_V1_CHAT_COMPLETIONS, Q as PATH_V1_RESPONSES, F as providerHasContextMetadata, l as parseOpenAIResponse, m as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, o as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, k as AnthropicRequestSchema, s as safeGetOwnProperty, a0 as resolveProviderContextWindow, t as getSessionPath, J as findProviderModelMetadata, S as previewUpstreamUrl, K as KnowledgeCandidateSchema, a1 as isPlainRecord, u as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-BJzdUbcH.mjs";
2
+ import { C as CapturedLogSchema, z as DeleteInspectorGroupsResponseSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, g as readStoredUiScalePreference, h as persistUiScalePreference, i as applyUiScalePreference, w as extractStopReason, p as packageJson, P as ProviderConfigSchema, U as UI_SCALE_STORAGE_KEY, j as normalizeUiScalePreference, q as apiFormatForPath, B as GroupEvidenceExportResultSchema, E as DeleteInspectorGroupResponseSchema, $ as PiAgentResponseSchema, v as isTurnBoundary, r as readStoredThemeMode, e as applyThemeMode, f as persistThemeMode, a2 as formatUiScale, x as AlertSummarySchema, y as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, V as createPendingProviderTestResults, W as ProviderTestResultsSchema, X as createFailedProviderTestResults, Y as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, Z as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, _ as TimeDisplayFormatSchema, T as THEME_MODE_STORAGE_KEY, n as normalizeThemeMode, H as maskApiKey, M as PATH_V1_MESSAGES, N as PATH_V1_CHAT_COMPLETIONS, Q as PATH_V1_RESPONSES, F as providerHasContextMetadata, l as parseOpenAIResponse, m as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, o as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, k as AnthropicRequestSchema, s as safeGetOwnProperty, a0 as resolveProviderContextWindow, t as getSessionPath, J as findProviderModelMetadata, S as previewUpstreamUrl, K as KnowledgeCandidateSchema, a1 as isPlainRecord, u as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-bofP-Ekl.mjs";
3
3
  import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
4
4
  import { J as JSZip } from "../_libs/jszip.mjs";
5
5
  import { c as clsx } from "../_libs/clsx.mjs";
@@ -7,7 +7,7 @@ import { t as twMerge } from "../_libs/tailwind-merge.mjs";
7
7
  import { c as cva } from "../_libs/class-variance-authority.mjs";
8
8
  import { u as useWindowVirtualizer, a as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
9
9
  import { d as diffJson, a as diffLines } from "../_libs/diff.mjs";
10
- import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, P as PanelRightOpen, c as PanelRightClose, S as Search, U as Upload, D as Download, F as FileBraces, R as RefreshCw, d as Trash2, e as Plus, B as BrainCircuit, L as LoaderCircle, f as Send, A as ArrowLeft, g as ChevronUp, h as Copy, i as ChevronsLeft, j as ChevronLeft, k as ChevronRight, l as ChevronsRight, m as Clapperboard, n as Flag, o as Siren, p as Timer, G as Gauge, q as Sun, E as Eye, M as Moon, r as ALargeSmall, s as Layers, t as FlaskConical, u as Sparkles, v as Activity, w as Beaker, N as Network, x as Terminal, y as Settings, z as Monitor, H as Rocket, J as PackageCheck, K as History, O as Scan, Q as CircleAlert, V as ArrowUpRight, W as ArrowDownRight, Y as Cpu, Z as FolderOpen, _ as Bell, $ as Clock3, a0 as ShieldAlert, a1 as EyeOff, a2 as ExternalLink, a3 as Clock, a4 as RotateCw, a5 as Pencil, a6 as MessageSquare, a7 as Zap, a8 as Wrench, a9 as Brain, aa as CircleCheckBig, ab as Minus, ac as CircleX, ad as ShieldCheck, ae as Save, af as FileSearch, ag as CloudUpload, ah as CircleQuestionMark, ai as Server, aj as Lock, ak as Wifi, al as WifiOff, am as OctagonAlert, an as Radio, ao as Globe, ap as FileTerminal, aq as ChevronsUp, ar as ChevronsDown, as as FileDiff, at as RotateCcw, au as GitCompareArrows, av as ArrowUp, aw as ArrowDown, ax as Ellipsis, ay as CodeXml, az as Blocks, aA as MousePointerClick, aB as FileText, aC as Rows3, aD as Columns2 } from "../_libs/lucide-react.mjs";
10
+ import { T as TriangleAlert, C as CircleCheck, X, I as Info, a as ChevronDown, b as Check, P as PanelRightOpen, c as PanelRightClose, S as Search, U as Upload, D as Download, F as FileBraces, R as RefreshCw, d as Trash2, H as Heart, e as Pause, f as Play, g as Plus, B as BrainCircuit, L as LoaderCircle, h as Send, A as ArrowLeft, i as ChevronUp, j as Copy, k as ChevronsLeft, l as ChevronLeft, m as ChevronRight, n as ChevronsRight, o as Clapperboard, p as Flag, q as Siren, r as Timer, G as Gauge, s as Sun, E as Eye, M as Moon, t as ALargeSmall, u as Layers, v as FlaskConical, w as Sparkles, x as Activity, y as Beaker, N as Network, z as Terminal, J as Settings, K as Monitor, O as Rocket, Q as PackageCheck, V as History, W as Scan, Y as CircleAlert, Z as ArrowUpRight, _ as ArrowDownRight, $ as Cpu, a0 as FolderOpen, a1 as Bell, a2 as Clock3, a3 as ShieldAlert, a4 as EyeOff, a5 as ExternalLink, a6 as Clock, a7 as RotateCw, a8 as Pencil, a9 as MessageSquare, aa as Zap, ab as Wrench, ac as Brain, ad as CircleCheckBig, ae as Minus, af as CircleX, ag as ShieldCheck, ah as Save, ai as FileSearch, aj as CloudUpload, ak as CircleQuestionMark, al as Server, am as Lock, an as Wifi, ao as WifiOff, ap as OctagonAlert, aq as Radio, ar as Globe, as as FileTerminal, at as ChevronsUp, au as ChevronsDown, av as FileDiff, aw as RotateCcw, ax as GitCompareArrows, ay as ArrowUp, az as ArrowDown, aA as Ellipsis, aB as CodeXml, aC as Blocks, aD as MousePointerClick, aE as FileText, aF as Rows3, aG as Columns2 } from "../_libs/lucide-react.mjs";
11
11
  import { u as union, o as object, e as array, l as literal, n as number, d as boolean, b as string, _ as _enum } from "../_libs/zod.mjs";
12
12
  import { S as Select$1, a as SelectTrigger$1, b as SelectIcon, c as SelectValue$1, d as SelectPortal, e as SelectContent$1, f as SelectViewport, g as SelectItem$1, h as SelectItemIndicator, i as SelectItemText, j as SelectScrollUpButton$1, k as SelectScrollDownButton$1 } from "../_libs/radix-ui__react-select.mjs";
13
13
  import { D as Dialog$1, a as DialogContent$1, b as DialogClose, c as DialogTitle$1, d as DialogDescription$1, e as DialogPortal$1, f as DialogOverlay$1, g as DialogTrigger$1 } from "../_libs/radix-ui__react-dialog.mjs";
@@ -2525,27 +2525,27 @@ function useCopyFeedback(text) {
2525
2525
  return { copied, copy };
2526
2526
  }
2527
2527
  const LazyCompareDrawer = reactExports.lazy(
2528
- () => import("./CompareDrawer-Cw7Dseo3.mjs").then((m) => ({ default: m.CompareDrawer }))
2528
+ () => import("./CompareDrawer-aH59Ab6x.mjs").then((m) => ({ default: m.CompareDrawer }))
2529
2529
  );
2530
2530
  const LazyReplayDialog = reactExports.lazy(
2531
- () => import("./ReplayDialog-B-YMhZkE.mjs").then((m) => ({ default: m.ReplayDialog }))
2531
+ () => import("./ReplayDialog-BO4Vy0et.mjs").then((m) => ({ default: m.ReplayDialog }))
2532
2532
  );
2533
2533
  const LazyRequestAnatomy = reactExports.lazy(
2534
- () => import("./RequestAnatomy-a9d8UTYZ.mjs").then((m) => ({ default: m.RequestAnatomy }))
2534
+ () => import("./RequestAnatomy-FtOr7vSS.mjs").then((m) => ({ default: m.RequestAnatomy }))
2535
2535
  );
2536
2536
  const LazyResponseView = reactExports.lazy(
2537
- () => import("./ResponseView-PzaZS4CN.mjs").then((m) => ({ default: m.ResponseView }))
2537
+ () => import("./ResponseView-cvw6ajue.mjs").then((m) => ({ default: m.ResponseView }))
2538
2538
  );
2539
2539
  const LazyStreamingChunkSequence = reactExports.lazy(
2540
- () => import("./StreamingChunkSequence-C21_TCXk.mjs").then((m) => ({
2540
+ () => import("./StreamingChunkSequence-Oc8S2kD6.mjs").then((m) => ({
2541
2541
  default: m.StreamingChunkSequence
2542
2542
  }))
2543
2543
  );
2544
2544
  const LazyJsonViewer = reactExports.lazy(
2545
- () => import("./json-viewer-Di2gxs9H.mjs").then((m) => ({ default: m.JsonViewer }))
2545
+ () => import("./json-viewer-Cd6trhQr.mjs").then((m) => ({ default: m.JsonViewer }))
2546
2546
  );
2547
2547
  const LazyJsonViewerFromString = reactExports.lazy(
2548
- () => import("./json-viewer-Di2gxs9H.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2548
+ () => import("./json-viewer-Cd6trhQr.mjs").then((m) => ({ default: m.JsonViewerFromString }))
2549
2549
  );
2550
2550
  const HIGHLIGHT_DURATION_MS = 1200;
2551
2551
  const MAX_HIGHLIGHT_ATTEMPTS = 12;
@@ -12134,6 +12134,535 @@ function AgentLabDialog({ currentSessionId, logCount }) {
12134
12134
  ] })
12135
12135
  ] });
12136
12136
  }
12137
+ const INSPECTOR_PET_SIZE = 56;
12138
+ const INSPECTOR_PET_MARGIN = 14;
12139
+ const INSPECTOR_PET_EDGE_PEEK = 18;
12140
+ const INSPECTOR_PET_MIN_STEP = 72;
12141
+ const INSPECTOR_PET_MAX_STEP = 156;
12142
+ const INSPECTOR_PET_SLEEP_AFTER_MS = 45e3;
12143
+ const INSPECTOR_PET_PANEL_WIDTH = 192;
12144
+ const INSPECTOR_PET_PANEL_HEIGHT = 68;
12145
+ const INSPECTOR_PET_PANEL_GAP = 10;
12146
+ const INSPECTOR_PET_VERTICAL_SAFE_MARGIN = 78;
12147
+ function viewportScale(viewport) {
12148
+ const scale = viewport.scale ?? 1;
12149
+ return Number.isFinite(scale) && scale > 0 ? scale : 1;
12150
+ }
12151
+ function scaledMetric(value, viewport) {
12152
+ return value * viewportScale(viewport);
12153
+ }
12154
+ function clampUnit(value) {
12155
+ return Math.min(Math.max(value, 0), 1);
12156
+ }
12157
+ function maximumPetX(viewport) {
12158
+ const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
12159
+ return Math.max(
12160
+ -edgePeek,
12161
+ viewport.width - scaledMetric(INSPECTOR_PET_SIZE, viewport) + edgePeek
12162
+ );
12163
+ }
12164
+ function maximumPetY(viewport) {
12165
+ const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
12166
+ return Math.max(
12167
+ -edgePeek,
12168
+ viewport.height - scaledMetric(INSPECTOR_PET_SIZE, viewport) + edgePeek
12169
+ );
12170
+ }
12171
+ function clampInspectorPetPosition(position, viewport) {
12172
+ const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
12173
+ return {
12174
+ x: Math.min(Math.max(position.x, -edgePeek), maximumPetX(viewport)),
12175
+ y: Math.min(Math.max(position.y, -edgePeek), maximumPetY(viewport))
12176
+ };
12177
+ }
12178
+ function nearestInspectorPetEdge(position, viewport) {
12179
+ const clamped = clampInspectorPetPosition(position, viewport);
12180
+ const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
12181
+ const distances = [
12182
+ { edge: "left", distance: clamped.x + edgePeek },
12183
+ { edge: "right", distance: maximumPetX(viewport) - clamped.x },
12184
+ { edge: "top", distance: clamped.y + INSPECTOR_PET_EDGE_PEEK },
12185
+ { edge: "bottom", distance: maximumPetY(viewport) - clamped.y }
12186
+ ];
12187
+ return distances.reduce((best, current) => current.distance < best.distance ? current : best).edge;
12188
+ }
12189
+ function snapInspectorPetToEdge(position, viewport) {
12190
+ const clamped = clampInspectorPetPosition(position, viewport);
12191
+ const edge = nearestInspectorPetEdge(clamped, viewport);
12192
+ const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
12193
+ switch (edge) {
12194
+ case "left":
12195
+ return { x: -edgePeek, y: clamped.y };
12196
+ case "right":
12197
+ return { x: maximumPetX(viewport), y: clamped.y };
12198
+ case "top":
12199
+ return { x: clamped.x, y: -edgePeek };
12200
+ case "bottom":
12201
+ return { x: clamped.x, y: maximumPetY(viewport) };
12202
+ }
12203
+ }
12204
+ function randomInspectorPetEdgePosition(viewport, edgeSample, ySample) {
12205
+ const maxX = maximumPetX(viewport);
12206
+ const maxY = maximumPetY(viewport);
12207
+ const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
12208
+ const minimumSafeY = Math.min(scaledMetric(INSPECTOR_PET_VERTICAL_SAFE_MARGIN, viewport), maxY);
12209
+ const randomY = minimumSafeY + clampUnit(ySample) * (maxY - minimumSafeY);
12210
+ const edgeIndex = Math.min(1, Math.floor(clampUnit(edgeSample) * 2));
12211
+ switch (edgeIndex) {
12212
+ case 0:
12213
+ return { x: -edgePeek, y: randomY };
12214
+ case 1:
12215
+ return { x: maxX, y: randomY };
12216
+ default:
12217
+ return { x: maxX, y: maxY };
12218
+ }
12219
+ }
12220
+ function nextInspectorPetWalkingPosition(position, viewport, stepSample, directionSample) {
12221
+ const clamped = snapInspectorPetToEdge(position, viewport);
12222
+ const step = scaledMetric(INSPECTOR_PET_MIN_STEP, viewport) + clampUnit(stepSample) * scaledMetric(INSPECTOR_PET_MAX_STEP - INSPECTOR_PET_MIN_STEP, viewport);
12223
+ const direction = directionSample >= 0.5 ? 1 : -1;
12224
+ const edge = nearestInspectorPetEdge(clamped, viewport);
12225
+ const maxX = maximumPetX(viewport);
12226
+ const maxY = maximumPetY(viewport);
12227
+ const edgePeek = scaledMetric(INSPECTOR_PET_EDGE_PEEK, viewport);
12228
+ const minimumSafeY = Math.min(scaledMetric(INSPECTOR_PET_VERTICAL_SAFE_MARGIN, viewport), maxY);
12229
+ switch (edge) {
12230
+ case "left":
12231
+ return {
12232
+ x: -edgePeek,
12233
+ y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
12234
+ };
12235
+ case "right":
12236
+ return {
12237
+ x: maxX,
12238
+ y: Math.min(Math.max(clamped.y + step * direction, minimumSafeY), maxY)
12239
+ };
12240
+ case "top":
12241
+ return {
12242
+ x: Math.min(Math.max(clamped.x + step * direction, -edgePeek), maxX),
12243
+ y: -edgePeek
12244
+ };
12245
+ case "bottom":
12246
+ return {
12247
+ x: Math.min(Math.max(clamped.x + step * direction, -edgePeek), maxX),
12248
+ y: maxY
12249
+ };
12250
+ }
12251
+ }
12252
+ function inspectorPetPanelPosition(position, viewport) {
12253
+ const edge = nearestInspectorPetEdge(position, viewport);
12254
+ const petSize = scaledMetric(INSPECTOR_PET_SIZE, viewport);
12255
+ const panelWidth = scaledMetric(INSPECTOR_PET_PANEL_WIDTH, viewport);
12256
+ const panelHeight = scaledMetric(INSPECTOR_PET_PANEL_HEIGHT, viewport);
12257
+ const panelGap = scaledMetric(INSPECTOR_PET_PANEL_GAP, viewport);
12258
+ const margin = scaledMetric(INSPECTOR_PET_MARGIN, viewport);
12259
+ let x = position.x + petSize / 2 - panelWidth / 2;
12260
+ let y = position.y + petSize / 2 - panelHeight / 2;
12261
+ switch (edge) {
12262
+ case "left":
12263
+ x = position.x + petSize + panelGap;
12264
+ break;
12265
+ case "right":
12266
+ x = position.x - panelWidth - panelGap;
12267
+ break;
12268
+ case "top":
12269
+ y = position.y + petSize + panelGap;
12270
+ break;
12271
+ case "bottom":
12272
+ y = position.y - panelHeight - panelGap;
12273
+ break;
12274
+ }
12275
+ return {
12276
+ x: Math.min(Math.max(x, margin), Math.max(margin, viewport.width - panelWidth - margin)),
12277
+ y: Math.min(Math.max(y, margin), Math.max(margin, viewport.height - panelHeight - margin))
12278
+ };
12279
+ }
12280
+ function latestCapturedLog(logs) {
12281
+ let latest = null;
12282
+ for (const log of logs) {
12283
+ if (latest === null || log.id > latest.id) latest = log;
12284
+ }
12285
+ return latest;
12286
+ }
12287
+ function logNeedsAttention(log) {
12288
+ const hasHttpError = log.responseStatus !== null && log.responseStatus >= 400;
12289
+ const hasStreamError = log.error !== null && log.error !== void 0 && log.error !== "";
12290
+ return hasHttpError || hasStreamError;
12291
+ }
12292
+ function resolveInspectorPetStatus(logs, nowMs) {
12293
+ const pendingCount = logs.filter((log) => log.responseStatus === null).length;
12294
+ const capturedCount = logs.length;
12295
+ if (pendingCount > 0) {
12296
+ return {
12297
+ mood: "active",
12298
+ label: `${String(pendingCount)} request${pendingCount === 1 ? "" : "s"} in flight`,
12299
+ pendingCount,
12300
+ capturedCount
12301
+ };
12302
+ }
12303
+ const latest = latestCapturedLog(logs);
12304
+ if (latest !== null && logNeedsAttention(latest)) {
12305
+ return {
12306
+ mood: "attention",
12307
+ label: "Latest request needs attention",
12308
+ pendingCount,
12309
+ capturedCount
12310
+ };
12311
+ }
12312
+ if (latest === null) {
12313
+ return {
12314
+ mood: "idle",
12315
+ label: "Waiting for traffic",
12316
+ pendingCount,
12317
+ capturedCount
12318
+ };
12319
+ }
12320
+ const latestTimestamp = Date.parse(latest.timestamp);
12321
+ if (Number.isFinite(latestTimestamp) && nowMs - latestTimestamp >= INSPECTOR_PET_SLEEP_AFTER_MS) {
12322
+ return {
12323
+ mood: "sleeping",
12324
+ label: "All quiet",
12325
+ pendingCount,
12326
+ capturedCount
12327
+ };
12328
+ }
12329
+ return {
12330
+ mood: "idle",
12331
+ label: "Watching the session",
12332
+ pendingCount,
12333
+ capturedCount
12334
+ };
12335
+ }
12336
+ const INSPECTOR_PET_ROAMING_STORAGE_KEY = "agent-inspector.pet.roaming";
12337
+ const INSPECTOR_PET_MIN_DRIFT_MS = 5200;
12338
+ const INSPECTOR_PET_DRIFT_WINDOW_MS = 2400;
12339
+ const INSPECTOR_PET_PANEL_DISMISS_MS = 6e3;
12340
+ const INSPECTOR_PET_REACTION_MS = 760;
12341
+ const INSPECTOR_PET_DRAG_THRESHOLD = 4;
12342
+ function readViewport() {
12343
+ if (typeof window === "undefined") return { width: 1280, height: 720, scale: 1 };
12344
+ const rawScale = window.getComputedStyle(document.documentElement).getPropertyValue("--inspector-ui-scale");
12345
+ const parsedScale = Number.parseFloat(rawScale);
12346
+ const scale = Number.isFinite(parsedScale) && parsedScale > 0 ? parsedScale : 1;
12347
+ return {
12348
+ width: Math.max(window.innerWidth, INSPECTOR_PET_MARGIN * 2),
12349
+ height: Math.max(window.innerHeight, INSPECTOR_PET_MARGIN * 2),
12350
+ scale
12351
+ };
12352
+ }
12353
+ function readStoredRoaming() {
12354
+ if (typeof window === "undefined") return true;
12355
+ try {
12356
+ return window.localStorage.getItem(INSPECTOR_PET_ROAMING_STORAGE_KEY) !== "0";
12357
+ } catch {
12358
+ return true;
12359
+ }
12360
+ }
12361
+ function moodDotClass(mood) {
12362
+ switch (mood) {
12363
+ case "active":
12364
+ return "bg-cyan-400 shadow-[0_0_9px_rgba(34,211,238,0.65)]";
12365
+ case "attention":
12366
+ return "bg-red-500 shadow-[0_0_9px_rgba(239,68,68,0.55)]";
12367
+ case "idle":
12368
+ return "bg-amber-400 shadow-[0_0_8px_rgba(251,191,36,0.45)]";
12369
+ case "sleeping":
12370
+ return "bg-muted-foreground/45";
12371
+ }
12372
+ }
12373
+ function moodMotionClass(mood) {
12374
+ switch (mood) {
12375
+ case "active":
12376
+ return "inspector-pet-active";
12377
+ case "attention":
12378
+ return "inspector-pet-attention";
12379
+ case "idle":
12380
+ return "";
12381
+ case "sleeping":
12382
+ return "inspector-pet-sleeping";
12383
+ }
12384
+ }
12385
+ function InspectorPet({ logs }) {
12386
+ const [viewport, setViewport] = reactExports.useState(readViewport);
12387
+ const [position, setPosition] = reactExports.useState({
12388
+ x: INSPECTOR_PET_MARGIN,
12389
+ y: INSPECTOR_PET_MARGIN
12390
+ });
12391
+ const [clockMs, setClockMs] = reactExports.useState(() => Date.now());
12392
+ const [motionTick, setMotionTick] = reactExports.useState(0);
12393
+ const [panelTick, setPanelTick] = reactExports.useState(0);
12394
+ const [panelVisible, setPanelVisible] = reactExports.useState(false);
12395
+ const [reactionTick, setReactionTick] = reactExports.useState(0);
12396
+ const [reactionVisible, setReactionVisible] = reactExports.useState(false);
12397
+ const [dragging, setDragging] = reactExports.useState(false);
12398
+ const [roaming, setRoaming] = reactExports.useState(readStoredRoaming);
12399
+ const [reduceMotion, setReduceMotion] = reactExports.useState(false);
12400
+ const dragStateRef = reactExports.useRef(null);
12401
+ const dragOccurredRef = reactExports.useRef(false);
12402
+ const status = reactExports.useMemo(() => resolveInspectorPetStatus(logs, clockMs), [clockMs, logs]);
12403
+ const panelPosition = reactExports.useMemo(
12404
+ () => inspectorPetPanelPosition(position, viewport),
12405
+ [position, viewport]
12406
+ );
12407
+ reactExports.useEffect(() => {
12408
+ const nextViewport = readViewport();
12409
+ setViewport(nextViewport);
12410
+ setPosition(randomInspectorPetEdgePosition(nextViewport, Math.random(), Math.random()));
12411
+ }, []);
12412
+ reactExports.useEffect(() => {
12413
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
12414
+ const handleChange = (event) => setReduceMotion(event.matches);
12415
+ setReduceMotion(mediaQuery.matches);
12416
+ mediaQuery.addEventListener("change", handleChange);
12417
+ return () => mediaQuery.removeEventListener("change", handleChange);
12418
+ }, []);
12419
+ reactExports.useEffect(() => {
12420
+ const intervalId = window.setInterval(() => setClockMs(Date.now()), 15e3);
12421
+ return () => window.clearInterval(intervalId);
12422
+ }, []);
12423
+ reactExports.useEffect(() => {
12424
+ try {
12425
+ window.localStorage.setItem(INSPECTOR_PET_ROAMING_STORAGE_KEY, roaming ? "1" : "0");
12426
+ } catch {
12427
+ }
12428
+ }, [roaming]);
12429
+ reactExports.useEffect(() => {
12430
+ if (!roaming || dragging || reduceMotion) return void 0;
12431
+ let timeoutId = null;
12432
+ const scheduleDrift = () => {
12433
+ const delay = INSPECTOR_PET_MIN_DRIFT_MS + Math.random() * INSPECTOR_PET_DRIFT_WINDOW_MS;
12434
+ timeoutId = window.setTimeout(() => {
12435
+ setMotionTick((current) => current + 1);
12436
+ setPosition(
12437
+ (current) => nextInspectorPetWalkingPosition(current, viewport, Math.random(), Math.random())
12438
+ );
12439
+ scheduleDrift();
12440
+ }, delay);
12441
+ };
12442
+ scheduleDrift();
12443
+ return () => {
12444
+ if (timeoutId !== null) window.clearTimeout(timeoutId);
12445
+ };
12446
+ }, [dragging, reduceMotion, roaming, viewport]);
12447
+ reactExports.useEffect(() => {
12448
+ const handleResize = () => {
12449
+ const nextViewport = readViewport();
12450
+ setViewport(nextViewport);
12451
+ setPosition((current) => snapInspectorPetToEdge(current, nextViewport));
12452
+ };
12453
+ window.addEventListener("resize", handleResize);
12454
+ return () => window.removeEventListener("resize", handleResize);
12455
+ }, []);
12456
+ reactExports.useEffect(() => {
12457
+ if (!panelVisible) return void 0;
12458
+ const timeoutId = window.setTimeout(
12459
+ () => setPanelVisible(false),
12460
+ INSPECTOR_PET_PANEL_DISMISS_MS
12461
+ );
12462
+ return () => window.clearTimeout(timeoutId);
12463
+ }, [panelTick, panelVisible]);
12464
+ reactExports.useEffect(() => {
12465
+ if (!reactionVisible) return void 0;
12466
+ const timeoutId = window.setTimeout(() => setReactionVisible(false), INSPECTOR_PET_REACTION_MS);
12467
+ return () => window.clearTimeout(timeoutId);
12468
+ }, [reactionTick, reactionVisible]);
12469
+ const handlePet = reactExports.useCallback(() => {
12470
+ if (dragOccurredRef.current) {
12471
+ dragOccurredRef.current = false;
12472
+ return;
12473
+ }
12474
+ setClockMs(Date.now());
12475
+ setPanelTick((current) => current + 1);
12476
+ setPanelVisible(true);
12477
+ setReactionTick((current) => current + 1);
12478
+ setReactionVisible(true);
12479
+ }, []);
12480
+ const handlePointerDown = reactExports.useCallback((event) => {
12481
+ const rect = event.currentTarget.getBoundingClientRect();
12482
+ dragOccurredRef.current = false;
12483
+ dragStateRef.current = {
12484
+ pointerId: event.pointerId,
12485
+ offsetX: event.clientX - rect.left,
12486
+ offsetY: event.clientY - rect.top,
12487
+ startX: event.clientX,
12488
+ startY: event.clientY,
12489
+ moved: false
12490
+ };
12491
+ event.currentTarget.setPointerCapture(event.pointerId);
12492
+ setPanelVisible(false);
12493
+ setDragging(true);
12494
+ }, []);
12495
+ const handlePointerMove = reactExports.useCallback(
12496
+ (event) => {
12497
+ const dragState = dragStateRef.current;
12498
+ if (dragState === null || dragState.pointerId !== event.pointerId) return;
12499
+ const moved = dragState.moved || Math.abs(event.clientX - dragState.startX) >= INSPECTOR_PET_DRAG_THRESHOLD || Math.abs(event.clientY - dragState.startY) >= INSPECTOR_PET_DRAG_THRESHOLD;
12500
+ dragState.moved = moved;
12501
+ dragOccurredRef.current = moved;
12502
+ setPosition(
12503
+ clampInspectorPetPosition(
12504
+ {
12505
+ x: event.clientX - dragState.offsetX,
12506
+ y: event.clientY - dragState.offsetY
12507
+ },
12508
+ viewport
12509
+ )
12510
+ );
12511
+ },
12512
+ [viewport]
12513
+ );
12514
+ const handlePointerUp = reactExports.useCallback(
12515
+ (event) => {
12516
+ const dragState = dragStateRef.current;
12517
+ if (dragState === null || dragState.pointerId !== event.pointerId) return;
12518
+ if (event.currentTarget.hasPointerCapture(event.pointerId)) {
12519
+ event.currentTarget.releasePointerCapture(event.pointerId);
12520
+ }
12521
+ dragOccurredRef.current = dragState.moved;
12522
+ dragStateRef.current = null;
12523
+ setDragging(false);
12524
+ setPosition((current) => snapInspectorPetToEdge(current, viewport));
12525
+ },
12526
+ [viewport]
12527
+ );
12528
+ const handlePointerCancel = reactExports.useCallback((event) => {
12529
+ if (event.currentTarget.hasPointerCapture(event.pointerId)) {
12530
+ event.currentTarget.releasePointerCapture(event.pointerId);
12531
+ }
12532
+ dragStateRef.current = null;
12533
+ dragOccurredRef.current = false;
12534
+ setDragging(false);
12535
+ }, []);
12536
+ const petStyle = reactExports.useMemo(
12537
+ () => ({
12538
+ transform: `translate3d(${String(position.x)}px, ${String(position.y)}px, 0) rotate(${motionTick % 2 === 0 ? "-4deg" : "5deg"}) scale(${dragging ? "1.08" : "1"})`,
12539
+ transition: dragging ? "none" : "transform 4800ms cubic-bezier(0.33, 1, 0.68, 1)",
12540
+ touchAction: "none"
12541
+ }),
12542
+ [dragging, motionTick, position.x, position.y]
12543
+ );
12544
+ const panelStyle = reactExports.useMemo(
12545
+ () => ({ left: panelPosition.x, top: panelPosition.y }),
12546
+ [panelPosition.x, panelPosition.y]
12547
+ );
12548
+ const roamingLabel = roaming ? "Pause pet roaming" : "Resume pet roaming";
12549
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
12550
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12551
+ "button",
12552
+ {
12553
+ type: "button",
12554
+ className: cn(
12555
+ "fixed left-0 top-0 z-30 flex size-14 items-center justify-center bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_24px_rgba(245,158,11,0.36)] focus-visible:drop-shadow-[0_0_12px_rgba(251,191,36,0.72)]",
12556
+ dragging ? "cursor-grabbing" : "cursor-grab"
12557
+ ),
12558
+ style: petStyle,
12559
+ "data-pet-mood": status.mood,
12560
+ onClick: handlePet,
12561
+ onPointerDown: handlePointerDown,
12562
+ onPointerMove: handlePointerMove,
12563
+ onPointerUp: handlePointerUp,
12564
+ onPointerCancel: handlePointerCancel,
12565
+ "aria-label": `Inspector pet: ${status.label}`,
12566
+ title: status.label,
12567
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
12568
+ "span",
12569
+ {
12570
+ className: cn(
12571
+ "relative flex size-12 items-center justify-center",
12572
+ reactionVisible && "inspector-pet-patted"
12573
+ ),
12574
+ "aria-hidden": "true",
12575
+ children: [
12576
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12577
+ "span",
12578
+ {
12579
+ className: cn(
12580
+ "relative flex size-12 items-center justify-center",
12581
+ moodMotionClass(status.mood)
12582
+ ),
12583
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
12584
+ "span",
12585
+ {
12586
+ className: cn(
12587
+ "relative flex size-12 items-center justify-center",
12588
+ !dragging && "floating-crab-body"
12589
+ ),
12590
+ children: [
12591
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "relative z-10 size-11 text-amber-500 drop-shadow-[0_0_15px_rgba(245,158,11,0.30)]" }),
12592
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "pointer-events-none absolute inset-x-0 bottom-0 z-0 flex items-end justify-center gap-1 text-amber-400/80", children: [0, 1, 2, 3, 4, 5].map((leg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
12593
+ "span",
12594
+ {
12595
+ className: cn(
12596
+ "floating-crab-leg h-2 w-0.5 rounded-full bg-current shadow-[0_0_7px_rgba(245,158,11,0.24)]",
12597
+ leg < 3 ? "floating-crab-leg-left" : "floating-crab-leg-right",
12598
+ dragging && "animate-none"
12599
+ ),
12600
+ style: { animationDelay: `${String(leg % 2 === 0 ? 0 : 180)}ms` }
12601
+ },
12602
+ leg
12603
+ )) })
12604
+ ]
12605
+ }
12606
+ )
12607
+ }
12608
+ ),
12609
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12610
+ "span",
12611
+ {
12612
+ className: cn(
12613
+ "absolute right-0 top-1 size-2 rounded-full border border-background/90",
12614
+ moodDotClass(status.mood),
12615
+ status.mood === "active" && !reduceMotion && "animate-pulse"
12616
+ )
12617
+ }
12618
+ ),
12619
+ reactionVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(
12620
+ Heart,
12621
+ {
12622
+ className: "inspector-pet-heart absolute -right-1 -top-2 size-3.5 fill-amber-400 text-amber-400"
12623
+ },
12624
+ reactionTick
12625
+ )
12626
+ ]
12627
+ }
12628
+ )
12629
+ }
12630
+ ),
12631
+ panelVisible && /* @__PURE__ */ jsxRuntimeExports.jsxs(
12632
+ "div",
12633
+ {
12634
+ className: "fixed z-50 w-48 rounded-md border border-border/80 bg-popover/95 px-3 py-2 text-popover-foreground shadow-[0_14px_34px_rgba(0,0,0,0.28)] backdrop-blur",
12635
+ style: panelStyle,
12636
+ role: "status",
12637
+ "aria-live": "polite",
12638
+ children: [
12639
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
12640
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("size-2 shrink-0 rounded-full", moodDotClass(status.mood)) }),
12641
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 truncate text-xs font-medium", children: status.label }),
12642
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
12643
+ "button",
12644
+ {
12645
+ type: "button",
12646
+ className: "inline-flex size-6 shrink-0 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
12647
+ onClick: () => setRoaming((current) => !current),
12648
+ "aria-label": roamingLabel,
12649
+ title: roamingLabel,
12650
+ children: roaming ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { className: "size-3.5" })
12651
+ }
12652
+ )
12653
+ ] }),
12654
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center justify-between gap-3 font-mono text-[10px] text-muted-foreground", children: [
12655
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
12656
+ String(status.capturedCount),
12657
+ " captured"
12658
+ ] }),
12659
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: status.pendingCount > 0 ? `${String(status.pendingCount)} active` : roaming ? "Roaming" : "Resting" })
12660
+ ] })
12661
+ ]
12662
+ }
12663
+ )
12664
+ ] });
12665
+ }
12137
12666
  const DEFAULT_QUESTION = "Analyze the current Inspector session. What looks abnormal, slow, or likely to hang?";
12138
12667
  function providerSupportsPiAgent(provider) {
12139
12668
  return provider.openaiResponsesBaseUrl !== void 0 || provider.openaiBaseUrl !== void 0 || provider.anthropicBaseUrl !== void 0;
@@ -14561,256 +15090,12 @@ function BrandHeader({
14561
15090
  ] })
14562
15091
  ] });
14563
15092
  }
14564
- const FLOATING_LOGO_SIZE = 56;
14565
- const FLOATING_LOGO_MARGIN = 14;
14566
- const FLOATING_LOGO_MIN_DRIFT_MS = 5200;
14567
- const FLOATING_LOGO_DRIFT_WINDOW_MS = 2400;
14568
- const FLOATING_LOGO_MIN_STEP = 72;
14569
- const FLOATING_LOGO_MAX_STEP = 156;
14570
15093
  const DETAILS_PANEL_COLLAPSED_STORAGE_KEY = "agent-inspector.detailsPanelCollapsed";
14571
15094
  function readStoredDetailsPanelCollapsed() {
14572
15095
  if (typeof window === "undefined") return true;
14573
15096
  const stored = window.localStorage.getItem(DETAILS_PANEL_COLLAPSED_STORAGE_KEY);
14574
15097
  return stored === null || stored === "1";
14575
15098
  }
14576
- function clampFloatingLogoPosition(position) {
14577
- const maxX = Math.max(
14578
- FLOATING_LOGO_MARGIN,
14579
- window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14580
- );
14581
- const maxY = Math.max(
14582
- FLOATING_LOGO_MARGIN,
14583
- window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14584
- );
14585
- return {
14586
- x: Math.min(Math.max(position.x, FLOATING_LOGO_MARGIN), maxX),
14587
- y: Math.min(Math.max(position.y, FLOATING_LOGO_MARGIN), maxY)
14588
- };
14589
- }
14590
- function snapFloatingLogoToEdge(position) {
14591
- const clamped = clampFloatingLogoPosition(position);
14592
- const maxX = Math.max(
14593
- FLOATING_LOGO_MARGIN,
14594
- window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14595
- );
14596
- const maxY = Math.max(
14597
- FLOATING_LOGO_MARGIN,
14598
- window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14599
- );
14600
- const leftDistance = clamped.x - FLOATING_LOGO_MARGIN;
14601
- const rightDistance = maxX - clamped.x;
14602
- const topDistance = clamped.y - FLOATING_LOGO_MARGIN;
14603
- const bottomDistance = maxY - clamped.y;
14604
- const nearestDistance = Math.min(leftDistance, rightDistance, topDistance, bottomDistance);
14605
- if (nearestDistance === leftDistance) return { x: FLOATING_LOGO_MARGIN, y: clamped.y };
14606
- if (nearestDistance === rightDistance) return { x: maxX, y: clamped.y };
14607
- if (nearestDistance === topDistance) return { x: clamped.x, y: FLOATING_LOGO_MARGIN };
14608
- return { x: clamped.x, y: maxY };
14609
- }
14610
- function randomFloatingLogoEdgePosition() {
14611
- const maxX = Math.max(
14612
- FLOATING_LOGO_MARGIN,
14613
- window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14614
- );
14615
- const maxY = Math.max(
14616
- FLOATING_LOGO_MARGIN,
14617
- window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14618
- );
14619
- const randomX = FLOATING_LOGO_MARGIN + Math.random() * (maxX - FLOATING_LOGO_MARGIN);
14620
- const randomY = FLOATING_LOGO_MARGIN + Math.random() * (maxY - FLOATING_LOGO_MARGIN);
14621
- const edgeIndex = Math.floor(Math.random() * 4);
14622
- switch (edgeIndex) {
14623
- case 0:
14624
- return { x: FLOATING_LOGO_MARGIN, y: randomY };
14625
- case 1:
14626
- return { x: maxX, y: randomY };
14627
- case 2:
14628
- return { x: randomX, y: FLOATING_LOGO_MARGIN };
14629
- case 3:
14630
- return { x: randomX, y: maxY };
14631
- default:
14632
- return { x: maxX, y: FLOATING_LOGO_MARGIN };
14633
- }
14634
- }
14635
- function nearestFloatingLogoEdge(position) {
14636
- const clamped = clampFloatingLogoPosition(position);
14637
- const maxX = Math.max(
14638
- FLOATING_LOGO_MARGIN,
14639
- window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14640
- );
14641
- const maxY = Math.max(
14642
- FLOATING_LOGO_MARGIN,
14643
- window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14644
- );
14645
- const distances = [
14646
- { edge: "left", distance: clamped.x - FLOATING_LOGO_MARGIN },
14647
- { edge: "right", distance: maxX - clamped.x },
14648
- { edge: "top", distance: clamped.y - FLOATING_LOGO_MARGIN },
14649
- { edge: "bottom", distance: maxY - clamped.y }
14650
- ];
14651
- return distances.reduce((best, current) => current.distance < best.distance ? current : best).edge;
14652
- }
14653
- function nextFloatingLogoWalkingPosition(position) {
14654
- const clamped = snapFloatingLogoToEdge(position);
14655
- const maxX = Math.max(
14656
- FLOATING_LOGO_MARGIN,
14657
- window.innerWidth - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14658
- );
14659
- const maxY = Math.max(
14660
- FLOATING_LOGO_MARGIN,
14661
- window.innerHeight - FLOATING_LOGO_SIZE - FLOATING_LOGO_MARGIN
14662
- );
14663
- const step = FLOATING_LOGO_MIN_STEP + Math.random() * (FLOATING_LOGO_MAX_STEP - FLOATING_LOGO_MIN_STEP);
14664
- const direction = Math.random() > 0.5 ? 1 : -1;
14665
- const edge = nearestFloatingLogoEdge(clamped);
14666
- switch (edge) {
14667
- case "left": {
14668
- const nextY = clamped.y + step * direction;
14669
- if (nextY <= FLOATING_LOGO_MARGIN)
14670
- return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
14671
- if (nextY >= maxY) return { x: FLOATING_LOGO_MARGIN, y: maxY };
14672
- return { x: FLOATING_LOGO_MARGIN, y: nextY };
14673
- }
14674
- case "right": {
14675
- const nextY = clamped.y + step * direction;
14676
- if (nextY <= FLOATING_LOGO_MARGIN) return { x: maxX, y: FLOATING_LOGO_MARGIN };
14677
- if (nextY >= maxY) return { x: maxX, y: maxY };
14678
- return { x: maxX, y: nextY };
14679
- }
14680
- case "top": {
14681
- const nextX = clamped.x + step * direction;
14682
- if (nextX <= FLOATING_LOGO_MARGIN)
14683
- return { x: FLOATING_LOGO_MARGIN, y: FLOATING_LOGO_MARGIN };
14684
- if (nextX >= maxX) return { x: maxX, y: FLOATING_LOGO_MARGIN };
14685
- return { x: nextX, y: FLOATING_LOGO_MARGIN };
14686
- }
14687
- case "bottom": {
14688
- const nextX = clamped.x + step * direction;
14689
- if (nextX <= FLOATING_LOGO_MARGIN) return { x: FLOATING_LOGO_MARGIN, y: maxY };
14690
- if (nextX >= maxX) return { x: maxX, y: maxY };
14691
- return { x: nextX, y: maxY };
14692
- }
14693
- }
14694
- }
14695
- function FloatingInspectorLogo() {
14696
- const [position, setPosition] = reactExports.useState({
14697
- x: FLOATING_LOGO_MARGIN,
14698
- y: FLOATING_LOGO_MARGIN
14699
- });
14700
- const [motionTick, setMotionTick] = reactExports.useState(0);
14701
- const [dragging, setDragging] = reactExports.useState(false);
14702
- const dragStateRef = reactExports.useRef(null);
14703
- reactExports.useEffect(() => {
14704
- setPosition(randomFloatingLogoEdgePosition());
14705
- }, []);
14706
- reactExports.useEffect(() => {
14707
- if (dragging) return void 0;
14708
- let timeoutId = null;
14709
- const scheduleDrift = () => {
14710
- const delay = FLOATING_LOGO_MIN_DRIFT_MS + Math.random() * FLOATING_LOGO_DRIFT_WINDOW_MS;
14711
- timeoutId = window.setTimeout(() => {
14712
- setMotionTick((current) => current + 1);
14713
- setPosition((current) => nextFloatingLogoWalkingPosition(current));
14714
- scheduleDrift();
14715
- }, delay);
14716
- };
14717
- scheduleDrift();
14718
- return () => {
14719
- if (timeoutId !== null) {
14720
- window.clearTimeout(timeoutId);
14721
- }
14722
- };
14723
- }, [dragging]);
14724
- reactExports.useEffect(() => {
14725
- const handleResize = () => {
14726
- setPosition((current) => snapFloatingLogoToEdge(current));
14727
- };
14728
- window.addEventListener("resize", handleResize);
14729
- return () => window.removeEventListener("resize", handleResize);
14730
- }, []);
14731
- const handlePointerDown = reactExports.useCallback((event) => {
14732
- const rect = event.currentTarget.getBoundingClientRect();
14733
- dragStateRef.current = {
14734
- pointerId: event.pointerId,
14735
- offsetX: event.clientX - rect.left,
14736
- offsetY: event.clientY - rect.top
14737
- };
14738
- event.currentTarget.setPointerCapture(event.pointerId);
14739
- setDragging(true);
14740
- }, []);
14741
- const handlePointerMove = reactExports.useCallback((event) => {
14742
- const dragState = dragStateRef.current;
14743
- if (dragState === null || dragState.pointerId !== event.pointerId) return;
14744
- setPosition(
14745
- clampFloatingLogoPosition({
14746
- x: event.clientX - dragState.offsetX,
14747
- y: event.clientY - dragState.offsetY
14748
- })
14749
- );
14750
- }, []);
14751
- const handlePointerUp = reactExports.useCallback((event) => {
14752
- const dragState = dragStateRef.current;
14753
- if (dragState === null || dragState.pointerId !== event.pointerId) return;
14754
- if (event.currentTarget.hasPointerCapture(event.pointerId)) {
14755
- event.currentTarget.releasePointerCapture(event.pointerId);
14756
- }
14757
- dragStateRef.current = null;
14758
- setDragging(false);
14759
- setPosition((current) => snapFloatingLogoToEdge(current));
14760
- }, []);
14761
- const style = reactExports.useMemo(
14762
- () => ({
14763
- transform: `translate3d(${position.x}px, ${position.y}px, 0) rotate(${motionTick % 2 === 0 ? "-4deg" : "5deg"}) scale(${dragging ? "1.08" : "1"})`,
14764
- transition: dragging ? "none" : "transform 4800ms cubic-bezier(0.33, 1, 0.68, 1)",
14765
- touchAction: "none"
14766
- }),
14767
- [dragging, motionTick, position.x, position.y]
14768
- );
14769
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
14770
- "button",
14771
- {
14772
- type: "button",
14773
- className: cn(
14774
- "fixed left-0 top-0 z-40 flex size-14 items-center justify-center rounded-full bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_24px_rgba(245,158,11,0.36)] focus-visible:ring-1 focus-visible:ring-amber-300/55",
14775
- dragging ? "cursor-grabbing" : "cursor-grab"
14776
- ),
14777
- style,
14778
- onPointerDown: handlePointerDown,
14779
- onPointerMove: handlePointerMove,
14780
- onPointerUp: handlePointerUp,
14781
- onPointerCancel: handlePointerUp,
14782
- "aria-label": "Floating Inspector logo",
14783
- title: "Drag Inspector logo",
14784
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
14785
- "span",
14786
- {
14787
- className: cn(
14788
- "relative flex size-12 items-center justify-center",
14789
- !dragging && "floating-crab-body"
14790
- ),
14791
- "aria-hidden": "true",
14792
- children: [
14793
- /* @__PURE__ */ jsxRuntimeExports.jsx(CrabLogo, { className: "relative z-10 size-11 text-amber-500 drop-shadow-[0_0_15px_rgba(245,158,11,0.30)]" }),
14794
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "pointer-events-none absolute inset-x-0 bottom-0 z-0 flex items-end justify-center gap-1 text-amber-400/80", children: [0, 1, 2, 3, 4, 5].map((leg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
14795
- "span",
14796
- {
14797
- className: cn(
14798
- "floating-crab-leg h-2 w-0.5 rounded-full bg-current shadow-[0_0_7px_rgba(245,158,11,0.24)]",
14799
- leg < 3 ? "floating-crab-leg-left" : "floating-crab-leg-right",
14800
- dragging && "animate-none"
14801
- ),
14802
- style: {
14803
- animationDelay: `${leg % 2 === 0 ? 0 : 180}ms`
14804
- }
14805
- },
14806
- leg
14807
- )) })
14808
- ]
14809
- }
14810
- )
14811
- }
14812
- );
14813
- }
14814
15099
  function SessionContextLogButton({ label, logId }) {
14815
15100
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
14816
15101
  "button",
@@ -15379,7 +15664,7 @@ function ProxyViewer({
15379
15664
  ]
15380
15665
  }
15381
15666
  ),
15382
- detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(FloatingInspectorLogo, {}),
15667
+ detailsPanelCollapsed && /* @__PURE__ */ jsxRuntimeExports.jsx(InspectorPet, { logs }),
15383
15668
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
15384
15669
  "div",
15385
15670
  {