@tonyclaw/agent-inspector 3.0.25 → 3.0.26

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 (37) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-BnvOPwpe.js → CompareDrawer-SZRUDQc9.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-BJvwOrSi.js +4234 -0
  4. package/.output/public/assets/{ReplayDialog-BJgoQWdW.js → ReplayDialog-DgfmqiM3.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-CpBZEHnM.js → RequestAnatomy-CS6c7Qfn.js} +1 -1
  6. package/.output/public/assets/{ResponseView-CWmyRb2M.js → ResponseView-C0Ri_5gm.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-BWhC8bwx.js → StreamingChunkSequence-7dYcHWyZ.js} +1 -1
  8. package/.output/public/assets/{_sessionId-Cq-2OqUU.js → _sessionId-D-V84cgw.js} +1 -1
  9. package/.output/public/assets/{index-BKi9IRtV.js → index-CSIL7-MK.js} +3 -3
  10. package/.output/public/assets/index-CmeF5XXS.css +1 -0
  11. package/.output/public/assets/{index-Cf8O0Oos.js → index-DgFWCxOs.js} +1 -1
  12. package/.output/public/assets/{index-DdgTJ4QJ.js → index-DrVJsks2.js} +1 -1
  13. package/.output/public/assets/{json-viewer-Bqu_4hmm.js → json-viewer-C9Ji3gYN.js} +1 -1
  14. package/.output/server/_libs/three.mjs +26016 -0
  15. package/.output/server/{_sessionId-Ba7H3Gjw.mjs → _sessionId-BQ6YQOO1.mjs} +7 -6
  16. package/.output/server/_ssr/{CompareDrawer-aH59Ab6x.mjs → CompareDrawer-CqNzIeMR.mjs} +7 -6
  17. package/.output/server/_ssr/{ProxyViewerContainer-By-I0tJv.mjs → ProxyViewerContainer-CMC7Vsbw.mjs} +785 -311
  18. package/.output/server/_ssr/{ReplayDialog-BO4Vy0et.mjs → ReplayDialog-D9p_LaTr.mjs} +8 -7
  19. package/.output/server/_ssr/{RequestAnatomy-FtOr7vSS.mjs → RequestAnatomy-B4ge3qNZ.mjs} +7 -6
  20. package/.output/server/_ssr/{ResponseView-cvw6ajue.mjs → ResponseView-BCqMKApI.mjs} +7 -6
  21. package/.output/server/_ssr/{StreamingChunkSequence-Oc8S2kD6.mjs → StreamingChunkSequence-BA4zTLE4.mjs} +7 -6
  22. package/.output/server/_ssr/{index-BDRlQheR.mjs → index-CzxhDjlq.mjs} +7 -6
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-Cd6trhQr.mjs → json-viewer-B3qV6iEJ.mjs} +7 -6
  25. package/.output/server/_ssr/{router-bofP-Ekl.mjs → router-CZe_R31M.mjs} +4 -4
  26. package/.output/server/{_tanstack-start-manifest_v-BPuf86qB.mjs → _tanstack-start-manifest_v-B50VTLrH.mjs} +1 -1
  27. package/.output/server/index.mjs +68 -68
  28. package/package.json +3 -1
  29. package/src/components/inspector-pet/InspectorPet.tsx +66 -51
  30. package/src/components/inspector-pet/InspectorPetCrab3D.tsx +455 -0
  31. package/src/components/inspector-pet/inspectorPetLogic.ts +28 -43
  32. package/src/components/providers/ProviderForm.tsx +238 -163
  33. package/src/components/providers/ProvidersPanel.tsx +16 -6
  34. package/src/components/providers/providerFormCapabilities.ts +36 -0
  35. package/styles/globals.css +0 -61
  36. package/.output/public/assets/ProxyViewerContainer-DcqFqo1m.js +0 -127
  37. package/.output/public/assets/index-BMYuDL5X.css +0 -1
@@ -8,10 +8,10 @@ import {
8
8
  useRef,
9
9
  useState,
10
10
  } from "react";
11
+ import { createPortal } from "react-dom";
11
12
  import { Heart, Pause, Play } from "lucide-react";
12
13
  import type { CapturedLog } from "../../contracts";
13
14
  import { cn } from "../../lib/utils";
14
- import { CrabLogo } from "../ui/crab-logo";
15
15
  import {
16
16
  INSPECTOR_PET_MARGIN,
17
17
  type InspectorPetMood,
@@ -24,6 +24,7 @@ import {
24
24
  resolveInspectorPetStatus,
25
25
  snapInspectorPetToEdge,
26
26
  } from "./inspectorPetLogic";
27
+ import { InspectorPetCrab3D } from "./InspectorPetCrab3D";
27
28
 
28
29
  type InspectorPetProps = {
29
30
  logs: readonly CapturedLog[];
@@ -39,11 +40,13 @@ type InspectorPetDragState = {
39
40
  };
40
41
 
41
42
  const INSPECTOR_PET_ROAMING_STORAGE_KEY = "agent-inspector.pet.roaming";
42
- const INSPECTOR_PET_MIN_DRIFT_MS = 5200;
43
- const INSPECTOR_PET_DRIFT_WINDOW_MS = 2400;
43
+ const INSPECTOR_PET_MIN_PAUSE_MS = 11_000;
44
+ const INSPECTOR_PET_PAUSE_WINDOW_MS = 9000;
45
+ const INSPECTOR_PET_SCUTTLE_MS = 7200;
44
46
  const INSPECTOR_PET_PANEL_DISMISS_MS = 6000;
45
47
  const INSPECTOR_PET_REACTION_MS = 760;
46
48
  const INSPECTOR_PET_DRAG_THRESHOLD = 4;
49
+ const INSPECTOR_PET_TOP_LAYER_Z_INDEX = 2_147_483_647;
47
50
 
48
51
  function readViewport(): InspectorPetViewport {
49
52
  if (typeof window === "undefined") return { width: 1280, height: 720, scale: 1 };
@@ -95,13 +98,14 @@ function moodMotionClass(mood: InspectorPetMood): string {
95
98
  }
96
99
 
97
100
  export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
101
+ const [portalHost, setPortalHost] = useState<HTMLElement | null>(null);
98
102
  const [viewport, setViewport] = useState<InspectorPetViewport>(readViewport);
99
103
  const [position, setPosition] = useState<InspectorPetPosition>({
100
104
  x: INSPECTOR_PET_MARGIN,
101
105
  y: INSPECTOR_PET_MARGIN,
102
106
  });
103
107
  const [clockMs, setClockMs] = useState(() => Date.now());
104
- const [motionTick, setMotionTick] = useState(0);
108
+ const [scuttling, setScuttling] = useState(false);
105
109
  const [panelTick, setPanelTick] = useState(0);
106
110
  const [panelVisible, setPanelVisible] = useState(false);
107
111
  const [reactionTick, setReactionTick] = useState(0);
@@ -117,11 +121,12 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
117
121
  () => inspectorPetPanelPosition(position, viewport),
118
122
  [position, viewport],
119
123
  );
124
+ useEffect(() => setPortalHost(document.body), []);
120
125
 
121
126
  useEffect(() => {
122
127
  const nextViewport = readViewport();
123
128
  setViewport(nextViewport);
124
- setPosition(randomInspectorPetEdgePosition(nextViewport, Math.random(), Math.random()));
129
+ setPosition(randomInspectorPetEdgePosition(nextViewport, Math.random()));
125
130
  }, []);
126
131
 
127
132
  useEffect(() => {
@@ -147,28 +152,34 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
147
152
 
148
153
  useEffect(() => {
149
154
  if (!roaming || dragging || reduceMotion) return undefined;
150
- let timeoutId: number | null = null;
155
+ let pauseTimeoutId: number | null = null;
156
+ let scuttleTimeoutId: number | null = null;
151
157
 
152
- const scheduleDrift = (): void => {
153
- const delay = INSPECTOR_PET_MIN_DRIFT_MS + Math.random() * INSPECTOR_PET_DRIFT_WINDOW_MS;
154
- timeoutId = window.setTimeout(() => {
155
- setMotionTick((current) => current + 1);
158
+ const scheduleScuttle = (): void => {
159
+ const delay = INSPECTOR_PET_MIN_PAUSE_MS + Math.random() * INSPECTOR_PET_PAUSE_WINDOW_MS;
160
+ pauseTimeoutId = window.setTimeout(() => {
161
+ setScuttling(true);
156
162
  setPosition((current) =>
157
163
  nextInspectorPetWalkingPosition(current, viewport, Math.random(), Math.random()),
158
164
  );
159
- scheduleDrift();
165
+ scuttleTimeoutId = window.setTimeout(() => {
166
+ setScuttling(false);
167
+ scheduleScuttle();
168
+ }, INSPECTOR_PET_SCUTTLE_MS);
160
169
  }, delay);
161
170
  };
162
171
 
163
- scheduleDrift();
172
+ scheduleScuttle();
164
173
  return () => {
165
- if (timeoutId !== null) window.clearTimeout(timeoutId);
174
+ if (pauseTimeoutId !== null) window.clearTimeout(pauseTimeoutId);
175
+ if (scuttleTimeoutId !== null) window.clearTimeout(scuttleTimeoutId);
166
176
  };
167
177
  }, [dragging, reduceMotion, roaming, viewport]);
168
178
 
169
179
  useEffect(() => {
170
180
  const handleResize = (): void => {
171
181
  const nextViewport = readViewport();
182
+ setScuttling(false);
172
183
  setViewport(nextViewport);
173
184
  setPosition((current) => snapInspectorPetToEdge(current, nextViewport));
174
185
  };
@@ -215,6 +226,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
215
226
  moved: false,
216
227
  };
217
228
  event.currentTarget.setPointerCapture(event.pointerId);
229
+ setScuttling(false);
218
230
  setPanelVisible(false);
219
231
  setDragging(true);
220
232
  }, []);
@@ -266,15 +278,22 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
266
278
  setDragging(false);
267
279
  }, []);
268
280
 
281
+ const handleToggleRoaming = useCallback(() => {
282
+ setScuttling(false);
283
+ setRoaming((current) => !current);
284
+ }, []);
285
+
269
286
  const petStyle = useMemo<CSSProperties>(
270
287
  () => ({
271
- transform: `translate3d(${String(position.x)}px, ${String(position.y)}px, 0) rotate(${
272
- motionTick % 2 === 0 ? "-4deg" : "5deg"
273
- }) scale(${dragging ? "1.08" : "1"})`,
274
- transition: dragging ? "none" : "transform 4800ms cubic-bezier(0.33, 1, 0.68, 1)",
288
+ transform: `translate3d(${String(position.x)}px, ${String(position.y)}px, 0) scale(${dragging ? "1.04" : "1"})`,
289
+ transition: dragging
290
+ ? "none"
291
+ : scuttling
292
+ ? `transform ${String(INSPECTOR_PET_SCUTTLE_MS)}ms cubic-bezier(0.22, 0.72, 0.32, 1)`
293
+ : "transform 900ms cubic-bezier(0.22, 0.72, 0.32, 1)",
275
294
  touchAction: "none",
276
295
  }),
277
- [dragging, motionTick, position.x, position.y],
296
+ [dragging, position.x, position.y, scuttling],
278
297
  );
279
298
 
280
299
  const panelStyle = useMemo<CSSProperties>(
@@ -284,16 +303,23 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
284
303
 
285
304
  const roamingLabel = roaming ? "Pause pet roaming" : "Resume pet roaming";
286
305
 
287
- return (
288
- <>
306
+ if (portalHost === null) return <></>;
307
+
308
+ return createPortal(
309
+ <div
310
+ className="pointer-events-none fixed inset-0 isolate"
311
+ style={{ zIndex: INSPECTOR_PET_TOP_LAYER_Z_INDEX }}
312
+ data-inspector-pet-layer="true"
313
+ >
289
314
  <button
290
315
  type="button"
291
316
  className={cn(
292
- "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)]",
317
+ "pointer-events-auto fixed left-0 top-0 z-10 flex size-28 items-center justify-center bg-transparent text-foreground outline-none transition-[filter,opacity] duration-200 hover:opacity-95 hover:drop-shadow-[0_0_28px_rgba(245,158,11,0.32)] focus-visible:drop-shadow-[0_0_14px_rgba(251,191,36,0.72)]",
293
318
  dragging ? "cursor-grabbing" : "cursor-grab",
294
319
  )}
295
320
  style={petStyle}
296
321
  data-pet-mood={status.mood}
322
+ data-pet-moving={scuttling ? "true" : "false"}
297
323
  onClick={handlePet}
298
324
  onPointerDown={handlePointerDown}
299
325
  onPointerMove={handlePointerMove}
@@ -304,42 +330,28 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
304
330
  >
305
331
  <span
306
332
  className={cn(
307
- "relative flex size-12 items-center justify-center",
333
+ "relative z-10 flex size-24 items-center justify-center",
308
334
  reactionVisible && "inspector-pet-patted",
309
335
  )}
310
336
  aria-hidden="true"
311
337
  >
312
338
  <span
313
339
  className={cn(
314
- "relative flex size-12 items-center justify-center",
340
+ "relative flex size-24 items-center justify-center",
315
341
  moodMotionClass(status.mood),
316
342
  )}
317
343
  >
318
- <span
319
- className={cn(
320
- "relative flex size-12 items-center justify-center",
321
- !dragging && "floating-crab-body",
322
- )}
323
- >
324
- <CrabLogo className="relative z-10 size-11 text-amber-500 drop-shadow-[0_0_15px_rgba(245,158,11,0.30)]" />
325
- <span className="pointer-events-none absolute inset-x-0 bottom-0 z-0 flex items-end justify-center gap-1 text-amber-400/80">
326
- {[0, 1, 2, 3, 4, 5].map((leg) => (
327
- <span
328
- key={leg}
329
- className={cn(
330
- "floating-crab-leg h-2 w-0.5 rounded-full bg-current shadow-[0_0_7px_rgba(245,158,11,0.24)]",
331
- leg < 3 ? "floating-crab-leg-left" : "floating-crab-leg-right",
332
- dragging && "animate-none",
333
- )}
334
- style={{ animationDelay: `${String(leg % 2 === 0 ? 0 : 180)}ms` }}
335
- />
336
- ))}
337
- </span>
344
+ <span className="relative flex size-24 items-center justify-center">
345
+ <InspectorPetCrab3D
346
+ mood={status.mood}
347
+ moving={scuttling && !dragging}
348
+ reduceMotion={reduceMotion}
349
+ />
338
350
  </span>
339
351
  </span>
340
352
  <span
341
353
  className={cn(
342
- "absolute right-0 top-1 size-2 rounded-full border border-background/90",
354
+ "absolute right-0 top-2 size-3 rounded-full border border-background/90",
343
355
  moodDotClass(status.mood),
344
356
  status.mood === "active" && !reduceMotion && "animate-pulse",
345
357
  )}
@@ -347,7 +359,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
347
359
  {reactionVisible && (
348
360
  <Heart
349
361
  key={reactionTick}
350
- className="inspector-pet-heart absolute -right-1 -top-2 size-3.5 fill-amber-400 text-amber-400"
362
+ className="inspector-pet-heart absolute -right-2 -top-3 size-5 fill-amber-400 text-amber-400"
351
363
  />
352
364
  )}
353
365
  </span>
@@ -355,7 +367,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
355
367
 
356
368
  {panelVisible && (
357
369
  <div
358
- 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"
370
+ className="pointer-events-auto fixed z-20 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"
359
371
  style={panelStyle}
360
372
  role="status"
361
373
  aria-live="polite"
@@ -366,7 +378,7 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
366
378
  <button
367
379
  type="button"
368
380
  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"
369
- onClick={() => setRoaming((current) => !current)}
381
+ onClick={handleToggleRoaming}
370
382
  aria-label={roamingLabel}
371
383
  title={roamingLabel}
372
384
  >
@@ -378,13 +390,16 @@ export function InspectorPet({ logs }: InspectorPetProps): JSX.Element {
378
390
  <span>
379
391
  {status.pendingCount > 0
380
392
  ? `${String(status.pendingCount)} active`
381
- : roaming
382
- ? "Roaming"
383
- : "Resting"}
393
+ : scuttling
394
+ ? "Scuttling"
395
+ : roaming
396
+ ? "Resting"
397
+ : "Paused"}
384
398
  </span>
385
399
  </div>
386
400
  </div>
387
401
  )}
388
- </>
402
+ </div>,
403
+ portalHost,
389
404
  );
390
405
  }