@nice-code/action 0.2.19 → 0.3.1

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.
@@ -1957,7 +1957,7 @@ class ActionDevtoolsCore {
1957
1957
  }
1958
1958
  }
1959
1959
  // src/devtools/browser/NiceActionDevtools.tsx
1960
- import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState9 } from "react";
1960
+ import { useEffect as useEffect4, useMemo as useMemo3, useState as useState9 } from "react";
1961
1961
 
1962
1962
  // src/devtools/core/devtools_colors.ts
1963
1963
  var DEVTOOL_COLOR_SEMANTIC_ERROR = "#FF5C5C";
@@ -2074,7 +2074,7 @@ import { useMemo, useState as useState7 } from "react";
2074
2074
  function getSizeValue(size) {
2075
2075
  switch (size) {
2076
2076
  case "sm" /* sm */:
2077
- return 0.8;
2077
+ return 0.75;
2078
2078
  case "md" /* md */:
2079
2079
  return 1;
2080
2080
  case "lg" /* lg */:
@@ -3295,8 +3295,7 @@ function Chip({
3295
3295
  size = "md" /* md */,
3296
3296
  rounded = false,
3297
3297
  tooltip,
3298
- children,
3299
- style
3298
+ children
3300
3299
  }) {
3301
3300
  const [anchor, setAnchor] = useState3(null);
3302
3301
  const hasTooltip = tooltip != null;
@@ -3310,6 +3309,8 @@ function Chip({
3310
3309
  onMouseEnter: hasTooltip ? (e) => setAnchor(e.currentTarget.getBoundingClientRect()) : undefined,
3311
3310
  onMouseLeave: hasTooltip ? () => setAnchor(null) : undefined,
3312
3311
  style: {
3312
+ display: "flex",
3313
+ alignItems: "center",
3313
3314
  color: resolvedColor,
3314
3315
  fontSize,
3315
3316
  background: DEVTOOL_LIST_BASE_BACKGROUND,
@@ -3318,8 +3319,7 @@ function Chip({
3318
3319
  borderRadius: rounded ? "0.6rem" : "3px",
3319
3320
  flexShrink: 0,
3320
3321
  whiteSpace: "nowrap",
3321
- cursor: hasTooltip ? "default" : undefined,
3322
- ...style
3322
+ cursor: hasTooltip ? "default" : undefined
3323
3323
  },
3324
3324
  children
3325
3325
  }, undefined, false, undefined, this),
@@ -3334,23 +3334,24 @@ function Chip({
3334
3334
  // src/devtools/browser/components/Icon.tsx
3335
3335
  import { useState as useState4 } from "react";
3336
3336
  import { jsxDEV as jsxDEV8, Fragment as Fragment3 } from "react/jsx-dev-runtime";
3337
- var ICON_SIZE_PX = {
3338
- ["sm" /* sm */]: 13,
3339
- ["md" /* md */]: 16,
3340
- ["lg" /* lg */]: 18
3341
- };
3337
+ var BASE_ICON_SIDE_LENGTH_EM = 1.6;
3338
+ var ICON_GAP_EM = 0.3;
3342
3339
  function Icon({
3343
3340
  icon: IconComponent,
3344
3341
  color,
3345
3342
  size = "md" /* md */,
3346
3343
  subtle = false,
3347
3344
  tooltip,
3348
- style
3345
+ style,
3346
+ noBackground = false
3349
3347
  }) {
3350
3348
  const [anchor, setAnchor] = useState4(null);
3351
3349
  const hasTooltip = tooltip != null;
3352
3350
  const colorEntry = SEMANTIC_COLORS[color];
3353
3351
  const resolvedColor = subtle ? colorEntry.subtle?.color ?? colorEntry.color : colorEntry.color;
3352
+ const finalIcons = Array.isArray(IconComponent) ? IconComponent : [IconComponent];
3353
+ const fullIconWidthEm = (finalIcons.length - 1) * ICON_GAP_EM + finalIcons.length * BASE_ICON_SIDE_LENGTH_EM * getSizeValue(size);
3354
+ const iconSideLengthEm = `${BASE_ICON_SIDE_LENGTH_EM * getSizeValue(size)}em`;
3354
3355
  return /* @__PURE__ */ jsxDEV8(Fragment3, {
3355
3356
  children: [
3356
3357
  /* @__PURE__ */ jsxDEV8("div", {
@@ -3358,20 +3359,24 @@ function Icon({
3358
3359
  onMouseLeave: hasTooltip ? () => setAnchor(null) : undefined,
3359
3360
  style: {
3360
3361
  borderRadius: "0.4em",
3361
- height: `${1.65 * getSizeValue(size)}em`,
3362
- width: `${1.65 * getSizeValue(size)}em`,
3362
+ width: `${fullIconWidthEm}em`,
3363
+ height: iconSideLengthEm,
3364
+ padding: "0.15em",
3363
3365
  display: "flex",
3364
3366
  alignItems: "center",
3365
3367
  justifyContent: "center",
3366
- background: "rgba(0,0,0,0.4)",
3368
+ background: noBackground ? "none" : "rgba(0,0,0,0.4)",
3367
3369
  color: resolvedColor,
3368
3370
  flexShrink: 0,
3369
3371
  cursor: hasTooltip ? "default" : undefined,
3370
3372
  ...style
3371
3373
  },
3372
- children: /* @__PURE__ */ jsxDEV8(IconComponent, {
3373
- size: ICON_SIZE_PX[size],
3374
- strokeWidth: 1.5
3374
+ children: /* @__PURE__ */ jsxDEV8("div", {
3375
+ style: { display: "flex", alignItems: "center", gap: `${ICON_GAP_EM}em` },
3376
+ children: finalIcons.map((Comp, i) => /* @__PURE__ */ jsxDEV8(Comp, {
3377
+ size: iconSideLengthEm,
3378
+ strokeWidth: 2.6
3379
+ }, `${Comp.name}-${i}`, false, undefined, this))
3375
3380
  }, undefined, false, undefined, this)
3376
3381
  }, undefined, false, undefined, this),
3377
3382
  anchor != null && hasTooltip && /* @__PURE__ */ jsxDEV8(Tooltip, {
@@ -3455,26 +3460,28 @@ function DomainChip({
3455
3460
  title: "Action Domain",
3456
3461
  align: "edge"
3457
3462
  },
3458
- style: { display: "flex", alignItems: "center", gap: "0.4em" },
3459
- children: [
3460
- /* @__PURE__ */ jsxDEV9("span", {
3461
- style: {
3462
- height: "1.2em",
3463
- width: "1.2em",
3464
- display: "flex",
3465
- alignItems: "center",
3466
- justifyContent: "center"
3467
- },
3468
- children: /* @__PURE__ */ jsxDEV9(Component, {
3469
- height: "1.2em",
3470
- width: "1.2em"
3463
+ children: /* @__PURE__ */ jsxDEV9("div", {
3464
+ style: { display: "flex", alignItems: "center", gap: "0.4em" },
3465
+ children: [
3466
+ /* @__PURE__ */ jsxDEV9("span", {
3467
+ style: {
3468
+ height: "1.2em",
3469
+ width: "1.2em",
3470
+ display: "flex",
3471
+ alignItems: "center",
3472
+ justifyContent: "center"
3473
+ },
3474
+ children: /* @__PURE__ */ jsxDEV9(Component, {
3475
+ height: "1.2em",
3476
+ width: "1.2em"
3477
+ }, undefined, false, undefined, this)
3478
+ }, undefined, false, undefined, this),
3479
+ /* @__PURE__ */ jsxDEV9("span", {
3480
+ children: domain
3471
3481
  }, undefined, false, undefined, this)
3472
- }, undefined, false, undefined, this),
3473
- /* @__PURE__ */ jsxDEV9("span", {
3474
- children: domain
3475
- }, undefined, false, undefined, this)
3476
- ]
3477
- }, undefined, true, undefined, this);
3482
+ ]
3483
+ }, undefined, true, undefined, this)
3484
+ }, undefined, false, undefined, this);
3478
3485
  }
3479
3486
 
3480
3487
  // src/devtools/browser/components/HandlerChips.tsx
@@ -4197,19 +4204,18 @@ function ActionDetailPanel({
4197
4204
  }, undefined, true, undefined, this);
4198
4205
  }
4199
4206
 
4207
+ // src/devtools/browser/components/action_list/ActionList.tsx
4208
+ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2 } from "react";
4209
+
4200
4210
  // src/devtools/browser/components/action_list/ActionEntryRow.tsx
4201
- import { Box, CircleX as CircleX2, Variable } from "lucide-react";
4202
- import { Fragment as Fragment7, useState as useState8 } from "react";
4203
- import { jsxDEV as jsxDEV17, Fragment as Fragment8 } from "react/jsx-dev-runtime";
4204
- function getLatestChipColor(status) {
4205
- if (status === "failed")
4206
- return "failed" /* failed */;
4207
- if (status === "action-error")
4208
- return "action_error" /* action_error */;
4209
- if (status === "aborted")
4210
- return "aborted" /* aborted */;
4211
- return "success" /* success */;
4212
- }
4211
+ import { CircleX as CircleX3, PackageCheck as PackageCheck2, Variable as Variable2 } from "lucide-react";
4212
+ import { Fragment as Fragment8, useState as useState8 } from "react";
4213
+
4214
+ // src/devtools/browser/components/action_list/ActionInputAndOutputChip.tsx
4215
+ import { CircleX as CircleX2, PackageCheck, Sparkle, Variable } from "lucide-react";
4216
+
4217
+ // src/devtools/browser/components/action_list/IoTooltipContent.tsx
4218
+ import { jsxDEV as jsxDEV17, Fragment as Fragment7 } from "react/jsx-dev-runtime";
4213
4219
  var JSON_TOKEN_RE2 = /("(?:\\.|[^"\\])*")(\s*:)?|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b|\bnull\b|\bundefined\b)|([{}[\],])/g;
4214
4220
  function renderColoredJson2(text) {
4215
4221
  const nodes = [];
@@ -4281,6 +4287,118 @@ function IoTooltipContent({ value }) {
4281
4287
  children: renderColoredJson2(text)
4282
4288
  }, undefined, false, undefined, this);
4283
4289
  }
4290
+
4291
+ // src/devtools/browser/components/action_list/ActionInputAndOutputChip.tsx
4292
+ import { jsxDEV as jsxDEV18 } from "react/jsx-dev-runtime";
4293
+ var ActionInputAndOutputChip = ({
4294
+ entry,
4295
+ breakReasons,
4296
+ subtle,
4297
+ size = "md" /* md */
4298
+ }) => {
4299
+ const firstHop = entry.meta.routing[0];
4300
+ const localEnvId = firstHop != null ? firstHop.runtime.envId : null;
4301
+ const externalLabel = firstHop != null ? getExternalLabel(firstHop) : null;
4302
+ const firstHopIsLocal = firstHop != null && firstHop.handlerType === "local";
4303
+ const isLocal = localEnvId != null && (firstHopIsLocal || externalLabel == null);
4304
+ const color = isLocal ? "handler_local" /* handler_local */ : "handler_external" /* handler_external */;
4305
+ const isNewInput = breakReasons.includes("new_input" /* new_input */);
4306
+ const isNewOutput = breakReasons.includes("new_output" /* new_output */);
4307
+ const hasError = entry.error != null || entry.abortReason != null;
4308
+ const sizeNum = getSizeValue(size);
4309
+ const newIconSizeEm = `${sizeNum * 0.9}em`;
4310
+ const label = `${(isLocal ? localEnvId : externalLabel) ?? "unknown"}`;
4311
+ const newSparkleComp = /* @__PURE__ */ jsxDEV18("div", {
4312
+ style: {
4313
+ opacity: 0.9,
4314
+ alignSelf: "start",
4315
+ marginLeft: "-0.6em"
4316
+ },
4317
+ children: /* @__PURE__ */ jsxDEV18(Sparkle, {
4318
+ strokeWidth: "0.2em",
4319
+ color: "rgba(243, 250, 140, 1)",
4320
+ width: newIconSizeEm,
4321
+ height: newIconSizeEm
4322
+ }, undefined, false, undefined, this)
4323
+ }, undefined, false, undefined, this);
4324
+ return /* @__PURE__ */ jsxDEV18(Chip, {
4325
+ color,
4326
+ size,
4327
+ subtle,
4328
+ children: /* @__PURE__ */ jsxDEV18("div", {
4329
+ style: { display: "flex", alignItems: "center", gap: "0.4em" },
4330
+ children: [
4331
+ /* @__PURE__ */ jsxDEV18(Icon, {
4332
+ noBackground: true,
4333
+ icon: Variable,
4334
+ color,
4335
+ subtle: subtle || entry.input === undefined,
4336
+ tooltip: {
4337
+ content: entry.input !== undefined ? /* @__PURE__ */ jsxDEV18(IoTooltipContent, {
4338
+ value: entry.input
4339
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV18("span", {
4340
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4341
+ children: "No input required or given"
4342
+ }, undefined, false, undefined, this),
4343
+ title: isNewInput ? "New Input" : "Input"
4344
+ }
4345
+ }, undefined, false, undefined, this),
4346
+ isNewInput && newSparkleComp,
4347
+ /* @__PURE__ */ jsxDEV18("span", {
4348
+ style: { opacity: 0.6 },
4349
+ color,
4350
+ children: "→"
4351
+ }, undefined, false, undefined, this),
4352
+ /* @__PURE__ */ jsxDEV18("span", {
4353
+ style: { opacity: 0.8 },
4354
+ children: label
4355
+ }, undefined, false, undefined, this),
4356
+ /* @__PURE__ */ jsxDEV18("span", {
4357
+ style: { opacity: 0.6 },
4358
+ color,
4359
+ children: "→"
4360
+ }, undefined, false, undefined, this),
4361
+ entry.status === "success" && entry.output !== undefined && /* @__PURE__ */ jsxDEV18(Icon, {
4362
+ noBackground: true,
4363
+ icon: PackageCheck,
4364
+ color: !hasError ? color : "default" /* default */,
4365
+ tooltip: {
4366
+ content: /* @__PURE__ */ jsxDEV18(IoTooltipContent, {
4367
+ value: entry.output
4368
+ }, undefined, false, undefined, this),
4369
+ title: isNewOutput ? "New Output" : "Output"
4370
+ }
4371
+ }, undefined, false, undefined, this),
4372
+ isNewOutput && newSparkleComp,
4373
+ (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV18(Icon, {
4374
+ noBackground: true,
4375
+ icon: CircleX2,
4376
+ color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4377
+ tooltip: {
4378
+ content: /* @__PURE__ */ jsxDEV18(ActionErrorDisplay, {
4379
+ entry,
4380
+ compact: true
4381
+ }, undefined, false, undefined, this),
4382
+ title: entry.status === "aborted" ? "Aborted" : "Error",
4383
+ maxWidth: 340
4384
+ }
4385
+ }, undefined, false, undefined, this)
4386
+ ]
4387
+ }, undefined, true, undefined, this)
4388
+ }, undefined, false, undefined, this);
4389
+ };
4390
+
4391
+ // src/devtools/browser/components/action_list/ActionEntryRow.tsx
4392
+ import { jsxDEV as jsxDEV19, Fragment as Fragment9 } from "react/jsx-dev-runtime";
4393
+ function getLatestChipColor(status) {
4394
+ if (status === "failed")
4395
+ return "failed" /* failed */;
4396
+ if (status === "action-error")
4397
+ return "action_error" /* action_error */;
4398
+ if (status === "aborted")
4399
+ return "aborted" /* aborted */;
4400
+ return "success" /* success */;
4401
+ }
4284
4402
  function GroupDotTooltip({
4285
4403
  entry,
4286
4404
  index,
@@ -4293,14 +4411,14 @@ function GroupDotTooltip({
4293
4411
  const deltaMs = refTime - entry.startTime;
4294
4412
  const relStr = index === 0 ? "latest run" : `−${formatRelativeAge(deltaMs)} from latest`;
4295
4413
  const durationStr = entry.endTime != null ? `${entry.endTime - entry.startTime}ms` : "running…";
4296
- return /* @__PURE__ */ jsxDEV17(Tooltip, {
4414
+ return /* @__PURE__ */ jsxDEV19(Tooltip, {
4297
4415
  anchor,
4298
4416
  config: {
4299
4417
  align: "center",
4300
4418
  maxWidth: 240,
4301
- content: /* @__PURE__ */ jsxDEV17(Fragment8, {
4419
+ content: /* @__PURE__ */ jsxDEV19(Fragment9, {
4302
4420
  children: [
4303
- /* @__PURE__ */ jsxDEV17("div", {
4421
+ /* @__PURE__ */ jsxDEV19("div", {
4304
4422
  style: { color: dotColor, marginBottom: "1px" },
4305
4423
  children: [
4306
4424
  symbol,
@@ -4310,15 +4428,15 @@ function GroupDotTooltip({
4310
4428
  total
4311
4429
  ]
4312
4430
  }, undefined, true, undefined, this),
4313
- /* @__PURE__ */ jsxDEV17("div", {
4431
+ /* @__PURE__ */ jsxDEV19("div", {
4314
4432
  style: { color: DEVTOOL_COLOR_TEXT_SECONDARY },
4315
4433
  children: formatTimestamp(entry.startTime)
4316
4434
  }, undefined, false, undefined, this),
4317
- /* @__PURE__ */ jsxDEV17("div", {
4435
+ /* @__PURE__ */ jsxDEV19("div", {
4318
4436
  style: { color: DEVTOOL_COLOR_TEXT_MUTED },
4319
4437
  children: durationStr
4320
4438
  }, undefined, false, undefined, this),
4321
- index > 0 && /* @__PURE__ */ jsxDEV17("div", {
4439
+ index > 0 && /* @__PURE__ */ jsxDEV19("div", {
4322
4440
  style: {
4323
4441
  color: DEVTOOL_COLOR_TEXT_MUTED,
4324
4442
  marginTop: "3px",
@@ -4343,9 +4461,9 @@ function GroupDot({
4343
4461
  const [anchor, setAnchor] = useState8(null);
4344
4462
  const dotColor = STATUS_COLOR[entry.status];
4345
4463
  const hovered = anchor != null;
4346
- return /* @__PURE__ */ jsxDEV17(Fragment8, {
4464
+ return /* @__PURE__ */ jsxDEV19(Fragment9, {
4347
4465
  children: [
4348
- /* @__PURE__ */ jsxDEV17("button", {
4466
+ /* @__PURE__ */ jsxDEV19("button", {
4349
4467
  "data-cuid": entry.cuid,
4350
4468
  onClick: (e) => {
4351
4469
  e.stopPropagation();
@@ -4367,7 +4485,7 @@ function GroupDot({
4367
4485
  transition: "transform 0.1s ease, opacity 0.1s ease, border-color 0.1s ease"
4368
4486
  }
4369
4487
  }, undefined, false, undefined, this),
4370
- hovered && anchor != null && /* @__PURE__ */ jsxDEV17(GroupDotTooltip, {
4488
+ hovered && anchor != null && /* @__PURE__ */ jsxDEV19(GroupDotTooltip, {
4371
4489
  entry,
4372
4490
  index,
4373
4491
  total,
@@ -4392,8 +4510,8 @@ function ActionEntryRow({
4392
4510
  }) {
4393
4511
  const timestamp = formatTimestamp(entry.startTime);
4394
4512
  const hasGroup = groupEntries != null && groupEntries.length > 1;
4395
- const hasBottomContent = childEntries != null && childEntries.length > 0 || (breakReasons?.some((r) => r !== "new input" && r !== "new output") ?? false) || entry.error != null || entry.abortReason != null;
4396
- return /* @__PURE__ */ jsxDEV17("div", {
4513
+ const hasBottomContent = childEntries != null && childEntries.length > 0 || (breakReasons?.some((r) => r !== "new_input" /* new_input */ && r !== "new_output" /* new_output */) ?? false) || entry.error != null || entry.abortReason != null;
4514
+ return /* @__PURE__ */ jsxDEV19("div", {
4397
4515
  "data-cuid": entry.cuid,
4398
4516
  onClick,
4399
4517
  style: {
@@ -4410,7 +4528,7 @@ function ActionEntryRow({
4410
4528
  margin: "2px 4px"
4411
4529
  },
4412
4530
  children: [
4413
- /* @__PURE__ */ jsxDEV17("div", {
4531
+ /* @__PURE__ */ jsxDEV19("div", {
4414
4532
  style: {
4415
4533
  position: "absolute",
4416
4534
  left: "2em",
@@ -4422,10 +4540,10 @@ function ActionEntryRow({
4422
4540
  zIndex: 0
4423
4541
  }
4424
4542
  }, undefined, false, undefined, this),
4425
- /* @__PURE__ */ jsxDEV17("div", {
4543
+ /* @__PURE__ */ jsxDEV19("div", {
4426
4544
  style: { display: "flex", alignItems: "center", gap: "8px" },
4427
4545
  children: [
4428
- /* @__PURE__ */ jsxDEV17("div", {
4546
+ /* @__PURE__ */ jsxDEV19("div", {
4429
4547
  style: {
4430
4548
  position: "relative",
4431
4549
  zIndex: 1,
@@ -4435,11 +4553,11 @@ function ActionEntryRow({
4435
4553
  alignItems: "center",
4436
4554
  justifyContent: "flex-start"
4437
4555
  },
4438
- children: isLatest ? /* @__PURE__ */ jsxDEV17(Chip, {
4556
+ children: isLatest ? /* @__PURE__ */ jsxDEV19(Chip, {
4439
4557
  size: "sm" /* sm */,
4440
4558
  color: getLatestChipColor(entry.status),
4441
4559
  children: "latest"
4442
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17(Chip, {
4560
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19(Chip, {
4443
4561
  size: "sm" /* sm */,
4444
4562
  color: getLatestChipColor(entry.status),
4445
4563
  children: [
@@ -4448,10 +4566,10 @@ function ActionEntryRow({
4448
4566
  ]
4449
4567
  }, undefined, true, undefined, this)
4450
4568
  }, undefined, false, undefined, this),
4451
- /* @__PURE__ */ jsxDEV17("div", {
4569
+ /* @__PURE__ */ jsxDEV19("div", {
4452
4570
  style: { flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: "0.5em" },
4453
4571
  children: [
4454
- /* @__PURE__ */ jsxDEV17("span", {
4572
+ /* @__PURE__ */ jsxDEV19("span", {
4455
4573
  style: {
4456
4574
  color: DEVTOOL_COLOR_TEXT_SECONDARY,
4457
4575
  fontSize: "1em",
@@ -4465,47 +4583,14 @@ function ActionEntryRow({
4465
4583
  },
4466
4584
  children: entry.actionId
4467
4585
  }, undefined, false, undefined, this),
4468
- /* @__PURE__ */ jsxDEV17(Icon, {
4469
- icon: Variable,
4470
- color: entry.input !== undefined ? "io_input" /* io_input */ : "default" /* default */,
4471
- subtle: entry.input === undefined,
4472
- tooltip: {
4473
- content: entry.input !== undefined ? /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4474
- value: entry.input
4475
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17("span", {
4476
- style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4477
- children: "No input required or given"
4478
- }, undefined, false, undefined, this),
4479
- title: "Input"
4480
- }
4586
+ /* @__PURE__ */ jsxDEV19(ActionInputAndOutputChip, {
4587
+ breakReasons,
4588
+ entry
4481
4589
  }, undefined, false, undefined, this),
4482
- /* @__PURE__ */ jsxDEV17(HandlerChips, {
4483
- entry,
4484
- size: "sm" /* sm */
4485
- }, undefined, false, undefined, this),
4486
- entry.status === "success" && entry.output !== undefined && /* @__PURE__ */ jsxDEV17(Icon, {
4487
- icon: Box,
4488
- color: "io_output" /* io_output */,
4489
- tooltip: { content: /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4490
- value: entry.output
4491
- }, undefined, false, undefined, this), title: "Output" }
4492
- }, undefined, false, undefined, this),
4493
- (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV17(Icon, {
4494
- icon: CircleX2,
4495
- color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4496
- tooltip: {
4497
- content: /* @__PURE__ */ jsxDEV17(ActionErrorDisplay, {
4498
- entry,
4499
- compact: true
4500
- }, undefined, false, undefined, this),
4501
- title: entry.status === "aborted" ? "Aborted" : "Error",
4502
- maxWidth: 340
4503
- }
4504
- }, undefined, false, undefined, this),
4505
- /* @__PURE__ */ jsxDEV17("div", {
4590
+ /* @__PURE__ */ jsxDEV19("div", {
4506
4591
  style: { flex: 1 }
4507
4592
  }, undefined, false, undefined, this),
4508
- /* @__PURE__ */ jsxDEV17("span", {
4593
+ /* @__PURE__ */ jsxDEV19("span", {
4509
4594
  style: {
4510
4595
  color: DEVTOOL_COLOR_SEMANTIC_METADATA,
4511
4596
  fontSize: "10px",
@@ -4515,9 +4600,9 @@ function ActionEntryRow({
4515
4600
  },
4516
4601
  children: timestamp
4517
4602
  }, undefined, false, undefined, this),
4518
- /* @__PURE__ */ jsxDEV17("span", {
4603
+ /* @__PURE__ */ jsxDEV19("span", {
4519
4604
  style: { color: DEVTOOL_COLOR_SEMANTIC_WARNING, fontSize: "11px", flexShrink: 0 },
4520
- children: /* @__PURE__ */ jsxDEV17(DurationDisplay, {
4605
+ children: /* @__PURE__ */ jsxDEV19(DurationDisplay, {
4521
4606
  entry
4522
4607
  }, undefined, false, undefined, this)
4523
4608
  }, undefined, false, undefined, this)
@@ -4525,7 +4610,7 @@ function ActionEntryRow({
4525
4610
  }, undefined, true, undefined, this)
4526
4611
  ]
4527
4612
  }, undefined, true, undefined, this),
4528
- hasBottomContent && /* @__PURE__ */ jsxDEV17("div", {
4613
+ hasBottomContent && /* @__PURE__ */ jsxDEV19("div", {
4529
4614
  style: {
4530
4615
  display: "flex",
4531
4616
  flexWrap: "wrap",
@@ -4534,33 +4619,35 @@ function ActionEntryRow({
4534
4619
  paddingLeft: "4.5em"
4535
4620
  },
4536
4621
  children: [
4537
- childEntries?.map((child) => /* @__PURE__ */ jsxDEV17(Fragment7, {
4622
+ childEntries?.map((child) => /* @__PURE__ */ jsxDEV19(Fragment8, {
4538
4623
  children: [
4539
- /* @__PURE__ */ jsxDEV17(Icon, {
4540
- icon: Variable,
4624
+ /* @__PURE__ */ jsxDEV19(Icon, {
4625
+ size: "sm" /* sm */,
4626
+ icon: Variable2,
4541
4627
  color: "io_input" /* io_input */,
4542
4628
  subtle: true,
4543
4629
  tooltip: {
4544
- content: child.input !== undefined ? /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4630
+ content: child.input !== undefined ? /* @__PURE__ */ jsxDEV19(IoTooltipContent, {
4545
4631
  value: child.input
4546
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17("span", {
4632
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19("span", {
4547
4633
  style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4548
4634
  children: "No input required or given"
4549
4635
  }, undefined, false, undefined, this),
4550
4636
  title: `Input · ${child.actionId}`
4551
4637
  }
4552
4638
  }, undefined, false, undefined, this),
4553
- /* @__PURE__ */ jsxDEV17(HandlerChips, {
4639
+ /* @__PURE__ */ jsxDEV19(HandlerChips, {
4554
4640
  entry: child,
4555
4641
  size: "sm" /* sm */,
4556
4642
  subtle: true
4557
4643
  }, undefined, false, undefined, this),
4558
- child.status === "success" && child.output !== undefined && /* @__PURE__ */ jsxDEV17(Icon, {
4559
- icon: Box,
4644
+ child.status === "success" && child.output !== undefined && /* @__PURE__ */ jsxDEV19(Icon, {
4645
+ size: "sm" /* sm */,
4646
+ icon: PackageCheck2,
4560
4647
  color: "io_output" /* io_output */,
4561
4648
  subtle: true,
4562
4649
  tooltip: {
4563
- content: /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4650
+ content: /* @__PURE__ */ jsxDEV19(IoTooltipContent, {
4564
4651
  value: child.output
4565
4652
  }, undefined, false, undefined, this),
4566
4653
  title: `Output · ${child.actionId}`
@@ -4568,17 +4655,18 @@ function ActionEntryRow({
4568
4655
  }, undefined, false, undefined, this)
4569
4656
  ]
4570
4657
  }, child.actionId, true, undefined, this)),
4571
- breakReasons?.filter((r) => r !== "new input" && r !== "new output").map((reason) => /* @__PURE__ */ jsxDEV17(Chip, {
4658
+ breakReasons?.filter((r) => r !== "new_input" /* new_input */ && r !== "new_output" /* new_output */).map((reason) => /* @__PURE__ */ jsxDEV19(Chip, {
4572
4659
  color: "default" /* default */,
4573
4660
  subtle: true,
4574
4661
  children: reason
4575
4662
  }, reason, false, undefined, this)),
4576
- (childEntries?.length ?? 0) > 0 && (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV17(Icon, {
4577
- icon: CircleX2,
4663
+ (childEntries?.length ?? 0) > 0 && (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV19(Icon, {
4664
+ size: "sm" /* sm */,
4665
+ icon: CircleX3,
4578
4666
  color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4579
4667
  subtle: true,
4580
4668
  tooltip: {
4581
- content: /* @__PURE__ */ jsxDEV17(ActionErrorDisplay, {
4669
+ content: /* @__PURE__ */ jsxDEV19(ActionErrorDisplay, {
4582
4670
  entry,
4583
4671
  compact: true
4584
4672
  }, undefined, false, undefined, this),
@@ -4588,7 +4676,7 @@ function ActionEntryRow({
4588
4676
  }, undefined, false, undefined, this)
4589
4677
  ]
4590
4678
  }, undefined, true, undefined, this),
4591
- hasGroup && /* @__PURE__ */ jsxDEV17("div", {
4679
+ hasGroup && /* @__PURE__ */ jsxDEV19("div", {
4592
4680
  style: {
4593
4681
  display: "flex",
4594
4682
  flexWrap: "wrap",
@@ -4597,7 +4685,7 @@ function ActionEntryRow({
4597
4685
  paddingLeft: "4.6em",
4598
4686
  paddingBottom: "2px"
4599
4687
  },
4600
- children: groupEntries.map((e, i) => /* @__PURE__ */ jsxDEV17(GroupDot, {
4688
+ children: groupEntries.map((e, i) => /* @__PURE__ */ jsxDEV19(GroupDot, {
4601
4689
  entry: e,
4602
4690
  index: i,
4603
4691
  total: groupEntries.length,
@@ -4610,8 +4698,130 @@ function ActionEntryRow({
4610
4698
  }, undefined, true, undefined, this);
4611
4699
  }
4612
4700
 
4701
+ // src/devtools/browser/components/action_list/ActionList.tsx
4702
+ import { jsxDEV as jsxDEV20 } from "react/jsx-dev-runtime";
4703
+ function getBreakReasons(current, previous) {
4704
+ const reasons = [];
4705
+ const inputChanged = current.inputHash != null && previous.inputHash != null ? current.inputHash !== previous.inputHash : safeStringify(current.input, 0) !== safeStringify(previous.input, 0);
4706
+ if (inputChanged)
4707
+ reasons.push("new_input" /* new_input */);
4708
+ const outputChanged = current.outputHash != null && previous.outputHash != null && current.outputHash !== previous.outputHash;
4709
+ if (outputChanged)
4710
+ reasons.push("new_output" /* new_output */);
4711
+ return reasons;
4712
+ }
4713
+ function getGroupChildEntries(group, childEntriesMap) {
4714
+ const seen = new Set;
4715
+ const result = [];
4716
+ for (const e of [group.representative, ...group.rest]) {
4717
+ for (const child of childEntriesMap.get(e.cuid) ?? []) {
4718
+ if (!seen.has(child.actionId)) {
4719
+ seen.add(child.actionId);
4720
+ result.push(child);
4721
+ }
4722
+ }
4723
+ }
4724
+ return result.length > 0 ? result.sort((a, b) => a.startTime - b.startTime) : undefined;
4725
+ }
4726
+ function getFlatItemKey(item) {
4727
+ const oldestCuid = item.group.rest[item.group.rest.length - 1]?.cuid ?? item.group.representative.cuid;
4728
+ return `g:${oldestCuid}`;
4729
+ }
4730
+ function ActionList({
4731
+ groups,
4732
+ selectedCuid,
4733
+ onGroupClick,
4734
+ onSubClick,
4735
+ childEntriesMap,
4736
+ style
4737
+ }) {
4738
+ const containerRef = useRef2(null);
4739
+ const latestTime = groups[0]?.representative.startTime;
4740
+ const flatItems = useMemo2(() => {
4741
+ return groups.map((group, gi) => {
4742
+ const prevGroup = groups[gi + 1];
4743
+ let breakReasons = [];
4744
+ if (prevGroup != null && prevGroup.representative.actionId === group.representative.actionId && prevGroup.representative.domain === group.representative.domain) {
4745
+ const reasons = getBreakReasons(group.representative, prevGroup.representative);
4746
+ if (reasons.length > 0)
4747
+ breakReasons = reasons;
4748
+ }
4749
+ return { group, groupIndex: gi, breakReasons };
4750
+ });
4751
+ }, [groups]);
4752
+ const prevSelectedRef = useRef2(selectedCuid);
4753
+ useEffect3(() => {
4754
+ if (selectedCuid === prevSelectedRef.current)
4755
+ return;
4756
+ prevSelectedRef.current = selectedCuid;
4757
+ if (selectedCuid == null)
4758
+ return;
4759
+ let repCuid = selectedCuid;
4760
+ for (const item of flatItems) {
4761
+ if (item.group.rest.some((e) => e.cuid === selectedCuid)) {
4762
+ repCuid = item.group.representative.cuid;
4763
+ break;
4764
+ }
4765
+ }
4766
+ containerRef.current?.querySelector(`[data-cuid="${repCuid}"]`)?.scrollIntoView({ block: "nearest" });
4767
+ }, [selectedCuid, flatItems]);
4768
+ if (groups.length === 0) {
4769
+ return /* @__PURE__ */ jsxDEV20("div", {
4770
+ style,
4771
+ children: /* @__PURE__ */ jsxDEV20("div", {
4772
+ style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
4773
+ children: "No actions recorded yet"
4774
+ }, undefined, false, undefined, this)
4775
+ }, undefined, false, undefined, this);
4776
+ }
4777
+ return /* @__PURE__ */ jsxDEV20("div", {
4778
+ ref: containerRef,
4779
+ style,
4780
+ children: [
4781
+ flatItems.map((item) => {
4782
+ const key = getFlatItemKey(item);
4783
+ const { group } = item;
4784
+ return /* @__PURE__ */ jsxDEV20("div", {
4785
+ style: {
4786
+ borderBottom: `1px solid ${DEVTOOL_LIST_GROUP_DIVIDER}`,
4787
+ position: "relative",
4788
+ overflow: "hidden"
4789
+ },
4790
+ children: [
4791
+ /* @__PURE__ */ jsxDEV20("div", {
4792
+ style: {
4793
+ position: "absolute",
4794
+ inset: 0,
4795
+ pointerEvents: "none",
4796
+ background: "linear-gradient(90deg, transparent 0%, rgba(148, 210, 255, 0.13) 50%, transparent 100%)",
4797
+ animation: "__nice-action-shine 0.65s ease-out forwards"
4798
+ }
4799
+ }, group.representative.cuid, false, undefined, this),
4800
+ /* @__PURE__ */ jsxDEV20(ActionEntryRow, {
4801
+ entry: group.representative,
4802
+ isSelected: selectedCuid === group.representative.cuid || group.rest.some((e) => e.cuid === selectedCuid),
4803
+ isLatest: item.groupIndex === 0,
4804
+ latestTime,
4805
+ childEntries: getGroupChildEntries(group, childEntriesMap),
4806
+ breakReasons: item.breakReasons,
4807
+ groupEntries: group.rest.length > 0 ? [group.representative, ...group.rest] : undefined,
4808
+ selectedGroupCuid: selectedCuid,
4809
+ onSelectGroupEntry: (cuid) => onSubClick(cuid, selectedCuid === cuid),
4810
+ onClick: () => onGroupClick(group)
4811
+ }, undefined, false, undefined, this)
4812
+ ]
4813
+ }, key, true, undefined, this);
4814
+ }),
4815
+ /* @__PURE__ */ jsxDEV20("div", {
4816
+ style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
4817
+ children: "Start of action history"
4818
+ }, undefined, false, undefined, this)
4819
+ ]
4820
+ }, undefined, true, undefined, this);
4821
+ }
4822
+
4613
4823
  // src/devtools/browser/components/PanelChrome.tsx
4614
- import { jsxDEV as jsxDEV18 } from "react/jsx-dev-runtime";
4824
+ import { jsxDEV as jsxDEV21 } from "react/jsx-dev-runtime";
4615
4825
  var DOCKED_SIZE_MIN = 140;
4616
4826
  var POSITION_GRID = [
4617
4827
  ["top-left", "dock-top", "top-right"],
@@ -4635,7 +4845,7 @@ function PanelHeader({
4635
4845
  onClose,
4636
4846
  onClear
4637
4847
  }) {
4638
- return /* @__PURE__ */ jsxDEV18("div", {
4848
+ return /* @__PURE__ */ jsxDEV21("div", {
4639
4849
  style: {
4640
4850
  display: "flex",
4641
4851
  alignItems: "center",
@@ -4646,18 +4856,18 @@ function PanelHeader({
4646
4856
  flexShrink: 0
4647
4857
  },
4648
4858
  children: [
4649
- /* @__PURE__ */ jsxDEV18("span", {
4859
+ /* @__PURE__ */ jsxDEV21("span", {
4650
4860
  style: { color: DEVTOOL_COLOR_SEMANTIC_SYSTEM, fontWeight: "bold", fontSize: "11px" },
4651
4861
  children: "⚡ nice-action devtools"
4652
4862
  }, undefined, false, undefined, this),
4653
- /* @__PURE__ */ jsxDEV18("div", {
4863
+ /* @__PURE__ */ jsxDEV21("div", {
4654
4864
  style: { display: "flex", gap: "10px", alignItems: "center" },
4655
4865
  children: [
4656
- /* @__PURE__ */ jsxDEV18(PositionPicker, {
4866
+ /* @__PURE__ */ jsxDEV21(PositionPicker, {
4657
4867
  position,
4658
4868
  onChange: onPositionChange
4659
4869
  }, undefined, false, undefined, this),
4660
- onClear != null && /* @__PURE__ */ jsxDEV18("button", {
4870
+ onClear != null && /* @__PURE__ */ jsxDEV21("button", {
4661
4871
  onClick: onClear,
4662
4872
  style: {
4663
4873
  background: "none",
@@ -4669,7 +4879,7 @@ function PanelHeader({
4669
4879
  },
4670
4880
  children: "clear"
4671
4881
  }, undefined, false, undefined, this),
4672
- /* @__PURE__ */ jsxDEV18("button", {
4882
+ /* @__PURE__ */ jsxDEV21("button", {
4673
4883
  onClick: onClose,
4674
4884
  style: {
4675
4885
  background: "none",
@@ -4691,18 +4901,18 @@ function PositionPicker({
4691
4901
  position,
4692
4902
  onChange
4693
4903
  }) {
4694
- return /* @__PURE__ */ jsxDEV18("div", {
4904
+ return /* @__PURE__ */ jsxDEV21("div", {
4695
4905
  title: "Move / dock panel",
4696
4906
  style: { display: "grid", gridTemplateColumns: "repeat(3, 9px)", gap: "2px", padding: "2px" },
4697
4907
  children: POSITION_GRID.flat().map((pos) => {
4698
4908
  if (pos == null)
4699
- return /* @__PURE__ */ jsxDEV18("div", {
4909
+ return /* @__PURE__ */ jsxDEV21("div", {
4700
4910
  style: { width: "9px", height: "9px" }
4701
4911
  }, "center-empty", false, undefined, this);
4702
4912
  const isDock = pos.startsWith("dock-");
4703
4913
  const isTopBottom = pos === "dock-top" || pos === "dock-bottom";
4704
4914
  const isActive = pos === position;
4705
- return /* @__PURE__ */ jsxDEV18("div", {
4915
+ return /* @__PURE__ */ jsxDEV21("div", {
4706
4916
  title: pos,
4707
4917
  onClick: () => onChange(pos),
4708
4918
  style: {
@@ -4713,7 +4923,7 @@ function PositionPicker({
4713
4923
  justifyContent: "center",
4714
4924
  cursor: "pointer"
4715
4925
  },
4716
- children: /* @__PURE__ */ jsxDEV18("div", {
4926
+ children: /* @__PURE__ */ jsxDEV21("div", {
4717
4927
  style: {
4718
4928
  width: isDock ? isTopBottom ? "9px" : "3px" : "7px",
4719
4929
  height: isDock ? isTopBottom ? "3px" : "9px" : "7px",
@@ -4749,7 +4959,7 @@ function ResizeHandle({
4749
4959
  window.addEventListener("mouseup", onUp);
4750
4960
  };
4751
4961
  const edgeStyle = dockSide === "bottom" ? { top: 0, left: 0, right: 0, height: "5px", cursor: "ns-resize" } : dockSide === "top" ? { bottom: 0, left: 0, right: 0, height: "5px", cursor: "ns-resize" } : dockSide === "right" ? { top: 0, bottom: 0, left: 0, width: "5px", cursor: "ew-resize" } : { top: 0, bottom: 0, right: 0, width: "5px", cursor: "ew-resize" };
4752
- return /* @__PURE__ */ jsxDEV18("div", {
4962
+ return /* @__PURE__ */ jsxDEV21("div", {
4753
4963
  onMouseDown,
4754
4964
  style: {
4755
4965
  position: "absolute",
@@ -4761,7 +4971,7 @@ function ResizeHandle({
4761
4971
  }
4762
4972
 
4763
4973
  // src/devtools/browser/NiceActionDevtools.tsx
4764
- import { jsxDEV as jsxDEV19, Fragment as Fragment9 } from "react/jsx-dev-runtime";
4974
+ import { jsxDEV as jsxDEV22, Fragment as Fragment10 } from "react/jsx-dev-runtime";
4765
4975
  if (typeof document !== "undefined" && !document.getElementById("__nice-action-devtools-styles")) {
4766
4976
  const style = document.createElement("style");
4767
4977
  style.id = "__nice-action-devtools-styles";
@@ -4854,7 +5064,7 @@ function groupEntries(entries) {
4854
5064
  }
4855
5065
  function NiceActionDevtools(props) {
4856
5066
  if (false) {}
4857
- return /* @__PURE__ */ jsxDEV19(NiceActionDevtools_Panel, {
5067
+ return /* @__PURE__ */ jsxDEV22(NiceActionDevtools_Panel, {
4858
5068
  ...props
4859
5069
  }, undefined, false, undefined, this);
4860
5070
  }
@@ -4866,13 +5076,13 @@ function NiceActionDevtools_Panel({
4866
5076
  const [prefs, setPrefsRaw] = useState9(() => readPrefs(defaultPosition, initialOpen));
4867
5077
  const [entries, setEntries] = useState9([]);
4868
5078
  const [selectedCuid, setSelectedCuid] = useState9(null);
4869
- useEffect3(() => core.subscribe(setEntries), [core]);
4870
- const groups = useMemo2(() => {
5079
+ useEffect4(() => core.subscribe(setEntries), [core]);
5080
+ const groups = useMemo3(() => {
4871
5081
  const byCuid = new Map(entries.map((e) => [e.cuid, e]));
4872
5082
  const roots = entries.filter((e) => e.status !== "running" && (e.parentCuid == null || !byCuid.has(e.parentCuid)));
4873
5083
  return groupEntries(roots);
4874
5084
  }, [entries]);
4875
- const childEntriesMap = useMemo2(() => {
5085
+ const childEntriesMap = useMemo3(() => {
4876
5086
  const map = new Map;
4877
5087
  for (const entry of entries) {
4878
5088
  if (entry.parentCuid == null)
@@ -4908,7 +5118,7 @@ function NiceActionDevtools_Panel({
4908
5118
  const dockedSize = isHorizDock ? dockedHeight : dockedWidth;
4909
5119
  const selectedEntry = selectedCuid != null ? entries.find((e) => e.cuid === selectedCuid) : null;
4910
5120
  const runningCount = entries.filter((e) => e.status === "running").length;
4911
- useEffect3(() => {
5121
+ useEffect4(() => {
4912
5122
  const sides = ["top", "bottom", "left", "right"];
4913
5123
  const clearAll = () => {
4914
5124
  sides.forEach((s) => {
@@ -4947,7 +5157,7 @@ function NiceActionDevtools_Panel({
4947
5157
  fontSize: "12px"
4948
5158
  };
4949
5159
  if (!isOpen) {
4950
- return /* @__PURE__ */ jsxDEV19("button", {
5160
+ return /* @__PURE__ */ jsxDEV22("button", {
4951
5161
  onClick: () => setPrefs({ isOpen: true }),
4952
5162
  style: {
4953
5163
  ...baseStyle,
@@ -4962,7 +5172,7 @@ function NiceActionDevtools_Panel({
4962
5172
  },
4963
5173
  children: [
4964
5174
  "⚡ actions",
4965
- runningCount > 0 && /* @__PURE__ */ jsxDEV19("span", {
5175
+ runningCount > 0 && /* @__PURE__ */ jsxDEV22("span", {
4966
5176
  style: {
4967
5177
  marginLeft: "6px",
4968
5178
  color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
@@ -5035,16 +5245,16 @@ function NiceActionDevtools_Panel({
5035
5245
  },
5036
5246
  childEntriesMap
5037
5247
  };
5038
- return /* @__PURE__ */ jsxDEV19("div", {
5248
+ return /* @__PURE__ */ jsxDEV22("div", {
5039
5249
  id: "__nice-action-devtools-panel",
5040
5250
  style: panelStyle,
5041
5251
  children: [
5042
- dockSide != null && /* @__PURE__ */ jsxDEV19(ResizeHandle, {
5252
+ dockSide != null && /* @__PURE__ */ jsxDEV22(ResizeHandle, {
5043
5253
  dockSide,
5044
5254
  dockedSize,
5045
5255
  onChange: (size) => setPrefs(isHorizDock ? { dockedHeight: size } : { dockedWidth: size })
5046
5256
  }, undefined, false, undefined, this),
5047
- /* @__PURE__ */ jsxDEV19(PanelHeader, {
5257
+ /* @__PURE__ */ jsxDEV22(PanelHeader, {
5048
5258
  position,
5049
5259
  onPositionChange: (p) => setPrefs({ position: p }),
5050
5260
  onClose: () => setPrefs({ isOpen: false }),
@@ -5053,17 +5263,17 @@ function NiceActionDevtools_Panel({
5053
5263
  setSelectedCuid(null);
5054
5264
  } : undefined
5055
5265
  }, undefined, false, undefined, this),
5056
- isHorizDock ? /* @__PURE__ */ jsxDEV19("div", {
5266
+ isHorizDock ? /* @__PURE__ */ jsxDEV22("div", {
5057
5267
  style: { flex: 1, display: "flex", overflow: "hidden" },
5058
5268
  children: [
5059
- /* @__PURE__ */ jsxDEV19("div", {
5269
+ /* @__PURE__ */ jsxDEV22("div", {
5060
5270
  style: { position: "relative", width: "340px", flexShrink: 0 },
5061
5271
  children: [
5062
- /* @__PURE__ */ jsxDEV19(ActionList, {
5272
+ /* @__PURE__ */ jsxDEV22(ActionList, {
5063
5273
  ...virtualListProps,
5064
5274
  style: { width: "100%", height: "100%", overflowY: "auto" }
5065
5275
  }, undefined, false, undefined, this),
5066
- /* @__PURE__ */ jsxDEV19("div", {
5276
+ /* @__PURE__ */ jsxDEV22("div", {
5067
5277
  style: {
5068
5278
  position: "absolute",
5069
5279
  top: 0,
@@ -5076,7 +5286,7 @@ function NiceActionDevtools_Panel({
5076
5286
  }, undefined, false, undefined, this)
5077
5287
  ]
5078
5288
  }, undefined, true, undefined, this),
5079
- /* @__PURE__ */ jsxDEV19("div", {
5289
+ /* @__PURE__ */ jsxDEV22("div", {
5080
5290
  style: {
5081
5291
  flex: 1,
5082
5292
  display: "flex",
@@ -5085,12 +5295,12 @@ function NiceActionDevtools_Panel({
5085
5295
  borderLeft: `1px solid ${DEVTOOL_PANEL_DIVIDER_BORDER}`,
5086
5296
  boxShadow: "inset 18px 0 36px -14px rgba(0,0,0,0.8)"
5087
5297
  },
5088
- children: selectedEntry != null ? /* @__PURE__ */ jsxDEV19(ActionDetailPanel, {
5298
+ children: selectedEntry != null ? /* @__PURE__ */ jsxDEV22(ActionDetailPanel, {
5089
5299
  entry: selectedEntry,
5090
5300
  parent: selectedEntryParent,
5091
5301
  childEntries: selectedEntryChildren,
5092
5302
  onSelectEntry: (cuid) => setSelectedCuid(cuid)
5093
- }, selectedEntry.cuid, false, undefined, this) : /* @__PURE__ */ jsxDEV19("div", {
5303
+ }, selectedEntry.cuid, false, undefined, this) : /* @__PURE__ */ jsxDEV22("div", {
5094
5304
  style: {
5095
5305
  padding: "24px",
5096
5306
  textAlign: "center",
@@ -5101,16 +5311,16 @@ function NiceActionDevtools_Panel({
5101
5311
  }, undefined, false, undefined, this)
5102
5312
  }, undefined, false, undefined, this)
5103
5313
  ]
5104
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV19(Fragment9, {
5314
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV22(Fragment10, {
5105
5315
  children: [
5106
- /* @__PURE__ */ jsxDEV19("div", {
5316
+ /* @__PURE__ */ jsxDEV22("div", {
5107
5317
  style: { position: "relative", flex: 1, minHeight: "80px" },
5108
5318
  children: [
5109
- /* @__PURE__ */ jsxDEV19(ActionList, {
5319
+ /* @__PURE__ */ jsxDEV22(ActionList, {
5110
5320
  ...virtualListProps,
5111
5321
  style: { overflowY: "auto", height: "100%" }
5112
5322
  }, undefined, false, undefined, this),
5113
- selectedEntry != null && /* @__PURE__ */ jsxDEV19("div", {
5323
+ selectedEntry != null && /* @__PURE__ */ jsxDEV22("div", {
5114
5324
  style: {
5115
5325
  position: "absolute",
5116
5326
  bottom: 0,
@@ -5123,7 +5333,7 @@ function NiceActionDevtools_Panel({
5123
5333
  }, undefined, false, undefined, this)
5124
5334
  ]
5125
5335
  }, undefined, true, undefined, this),
5126
- selectedEntry != null && /* @__PURE__ */ jsxDEV19("div", {
5336
+ selectedEntry != null && /* @__PURE__ */ jsxDEV22("div", {
5127
5337
  style: {
5128
5338
  flexShrink: 0,
5129
5339
  maxHeight: "55%",
@@ -5133,7 +5343,7 @@ function NiceActionDevtools_Panel({
5133
5343
  borderTop: `1px solid ${DEVTOOL_PANEL_DIVIDER_BORDER}`,
5134
5344
  boxShadow: "inset 0 18px 36px -14px rgba(0,0,0,0.8)"
5135
5345
  },
5136
- children: /* @__PURE__ */ jsxDEV19(ActionDetailPanel, {
5346
+ children: /* @__PURE__ */ jsxDEV22(ActionDetailPanel, {
5137
5347
  entry: selectedEntry,
5138
5348
  parent: selectedEntryParent,
5139
5349
  childEntries: selectedEntryChildren,
@@ -5145,119 +5355,6 @@ function NiceActionDevtools_Panel({
5145
5355
  ]
5146
5356
  }, undefined, true, undefined, this);
5147
5357
  }
5148
- function getBreakReasons(current, previous) {
5149
- const reasons = [];
5150
- const inputChanged = current.inputHash != null && previous.inputHash != null ? current.inputHash !== previous.inputHash : safeStringify(current.input, 0) !== safeStringify(previous.input, 0);
5151
- if (inputChanged)
5152
- reasons.push("new input");
5153
- const outputChanged = current.outputHash != null && previous.outputHash != null && current.outputHash !== previous.outputHash;
5154
- if (outputChanged)
5155
- reasons.push("new output");
5156
- return reasons;
5157
- }
5158
- function getGroupChildEntries(group, childEntriesMap) {
5159
- const seen = new Set;
5160
- const result = [];
5161
- for (const e of [group.representative, ...group.rest]) {
5162
- for (const child of childEntriesMap.get(e.cuid) ?? []) {
5163
- if (!seen.has(child.actionId)) {
5164
- seen.add(child.actionId);
5165
- result.push(child);
5166
- }
5167
- }
5168
- }
5169
- return result.length > 0 ? result.sort((a, b) => a.startTime - b.startTime) : undefined;
5170
- }
5171
- function getFlatItemKey(item) {
5172
- const oldestCuid = item.group.rest[item.group.rest.length - 1]?.cuid ?? item.group.representative.cuid;
5173
- return `g:${oldestCuid}`;
5174
- }
5175
- function ActionList({
5176
- groups,
5177
- selectedCuid,
5178
- onGroupClick,
5179
- onSubClick,
5180
- childEntriesMap,
5181
- style
5182
- }) {
5183
- const containerRef = useRef2(null);
5184
- const latestTime = groups[0]?.representative.startTime;
5185
- const flatItems = useMemo2(() => {
5186
- return groups.map((group, gi) => {
5187
- const prevGroup = groups[gi + 1];
5188
- let breakReasons;
5189
- if (prevGroup != null && prevGroup.representative.actionId === group.representative.actionId && prevGroup.representative.domain === group.representative.domain) {
5190
- const reasons = getBreakReasons(group.representative, prevGroup.representative);
5191
- if (reasons.length > 0)
5192
- breakReasons = reasons;
5193
- }
5194
- return { group, groupIndex: gi, breakReasons };
5195
- });
5196
- }, [groups]);
5197
- const prevSelectedRef = useRef2(selectedCuid);
5198
- useEffect3(() => {
5199
- if (selectedCuid === prevSelectedRef.current)
5200
- return;
5201
- prevSelectedRef.current = selectedCuid;
5202
- if (selectedCuid == null)
5203
- return;
5204
- let repCuid = selectedCuid;
5205
- for (const item of flatItems) {
5206
- if (item.group.rest.some((e) => e.cuid === selectedCuid)) {
5207
- repCuid = item.group.representative.cuid;
5208
- break;
5209
- }
5210
- }
5211
- containerRef.current?.querySelector(`[data-cuid="${repCuid}"]`)?.scrollIntoView({ block: "nearest" });
5212
- }, [selectedCuid, flatItems]);
5213
- if (groups.length === 0) {
5214
- return /* @__PURE__ */ jsxDEV19("div", {
5215
- style,
5216
- children: /* @__PURE__ */ jsxDEV19("div", {
5217
- style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
5218
- children: "No actions recorded yet"
5219
- }, undefined, false, undefined, this)
5220
- }, undefined, false, undefined, this);
5221
- }
5222
- return /* @__PURE__ */ jsxDEV19("div", {
5223
- ref: containerRef,
5224
- style,
5225
- children: flatItems.map((item) => {
5226
- const key = getFlatItemKey(item);
5227
- const { group } = item;
5228
- return /* @__PURE__ */ jsxDEV19("div", {
5229
- style: {
5230
- borderBottom: `1px solid ${DEVTOOL_LIST_GROUP_DIVIDER}`,
5231
- position: "relative",
5232
- overflow: "hidden"
5233
- },
5234
- children: [
5235
- /* @__PURE__ */ jsxDEV19("div", {
5236
- style: {
5237
- position: "absolute",
5238
- inset: 0,
5239
- pointerEvents: "none",
5240
- background: "linear-gradient(90deg, transparent 0%, rgba(148, 210, 255, 0.13) 50%, transparent 100%)",
5241
- animation: "__nice-action-shine 0.65s ease-out forwards"
5242
- }
5243
- }, group.representative.cuid, false, undefined, this),
5244
- /* @__PURE__ */ jsxDEV19(ActionEntryRow, {
5245
- entry: group.representative,
5246
- isSelected: selectedCuid === group.representative.cuid || group.rest.some((e) => e.cuid === selectedCuid),
5247
- isLatest: item.groupIndex === 0,
5248
- latestTime,
5249
- childEntries: getGroupChildEntries(group, childEntriesMap),
5250
- breakReasons: item.breakReasons,
5251
- groupEntries: group.rest.length > 0 ? [group.representative, ...group.rest] : undefined,
5252
- selectedGroupCuid: selectedCuid,
5253
- onSelectGroupEntry: (cuid) => onSubClick(cuid, selectedCuid === cuid),
5254
- onClick: () => onGroupClick(group)
5255
- }, undefined, false, undefined, this)
5256
- ]
5257
- }, key, true, undefined, this);
5258
- })
5259
- }, undefined, false, undefined, this);
5260
- }
5261
5358
  export {
5262
5359
  NiceActionDevtools,
5263
5360
  ActionDevtoolsCore
@@ -1,8 +1,12 @@
1
- import type { TDevtoolsPosition } from "../core/ActionDevtools.types";
1
+ import type { IDevtoolsActionEntry, TDevtoolsPosition } from "../core/ActionDevtools.types";
2
2
  import type { ActionDevtoolsCore } from "../core/ActionDevtoolsCore";
3
3
  export interface INiceActionDevtoolsProps {
4
4
  core: ActionDevtoolsCore;
5
5
  position?: TDevtoolsPosition;
6
6
  initialOpen?: boolean;
7
7
  }
8
+ export interface IEntryGroup {
9
+ representative: IDevtoolsActionEntry;
10
+ rest: IDevtoolsActionEntry[];
11
+ }
8
12
  export declare function NiceActionDevtools(props: INiceActionDevtoolsProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1,4 +1,4 @@
1
- import { type CSSProperties, type ReactNode } from "react";
1
+ import { type ReactNode } from "react";
2
2
  import { type ESemanticThing } from "../../core/devtools_colors";
3
3
  import { ESize } from "../ui_util/size";
4
4
  import { type ITooltipConfig } from "./Tooltip";
@@ -17,7 +17,6 @@ interface IChipProps {
17
17
  rounded?: boolean;
18
18
  tooltip?: ITooltipConfig;
19
19
  children: ReactNode;
20
- style?: CSSProperties;
21
20
  }
22
- export declare function Chip({ color, subtle, size, rounded, tooltip, children, style, }: IChipProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare function Chip({ color, subtle, size, rounded, tooltip, children, }: IChipProps): import("react/jsx-runtime").JSX.Element;
23
22
  export {};
@@ -4,12 +4,13 @@ import { type ESemanticThing } from "../../core/devtools_colors";
4
4
  import { ESize } from "../ui_util/size";
5
5
  import { type ITooltipConfig } from "./Tooltip";
6
6
  interface IIconProps {
7
- icon: LucideIcon;
7
+ icon: LucideIcon | LucideIcon[];
8
8
  color: ESemanticThing;
9
9
  size?: ESize;
10
10
  subtle?: boolean;
11
11
  tooltip?: ITooltipConfig;
12
12
  style?: CSSProperties;
13
+ noBackground?: boolean;
13
14
  }
14
- export declare function Icon({ icon: IconComponent, color, size, subtle, tooltip, style, }: IIconProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function Icon({ icon: IconComponent, color, size, subtle, tooltip, style, noBackground, }: IIconProps): import("react/jsx-runtime").JSX.Element;
15
16
  export {};
@@ -1,4 +1,5 @@
1
1
  import type { IDevtoolsActionEntry } from "../../../core/ActionDevtools.types";
2
+ import { EBreakGroupReason } from "./action_list.types";
2
3
  export declare function ActionEntryRow({ entry, isSelected, onClick, isLatest, latestTime, childEntries, breakReasons, groupEntries, selectedGroupCuid, onSelectGroupEntry, }: {
3
4
  entry: IDevtoolsActionEntry;
4
5
  isSelected: boolean;
@@ -6,7 +7,7 @@ export declare function ActionEntryRow({ entry, isSelected, onClick, isLatest, l
6
7
  isLatest?: boolean;
7
8
  latestTime?: number;
8
9
  childEntries?: IDevtoolsActionEntry[];
9
- breakReasons?: string[];
10
+ breakReasons: EBreakGroupReason[];
10
11
  groupEntries?: IDevtoolsActionEntry[];
11
12
  selectedGroupCuid?: string | null;
12
13
  onSelectGroupEntry?: (cuid: string) => void;
@@ -0,0 +1,11 @@
1
+ import type { IDevtoolsActionEntry } from "../../../core/ActionDevtools.types";
2
+ import { ESize } from "../../ui_util/size";
3
+ import { EBreakGroupReason } from "./action_list.types";
4
+ interface IActionInputAndOutputChipProps {
5
+ entry: IDevtoolsActionEntry;
6
+ breakReasons: EBreakGroupReason[];
7
+ subtle?: boolean;
8
+ size?: ESize;
9
+ }
10
+ export declare const ActionInputAndOutputChip: ({ entry, breakReasons, subtle, size, }: IActionInputAndOutputChipProps) => import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { IDevtoolsActionEntry } from "../../../server";
2
+ import type { IEntryGroup } from "../../NiceActionDevtools";
3
+ export declare function ActionList({ groups, selectedCuid, onGroupClick, onSubClick, childEntriesMap, style, }: {
4
+ groups: IEntryGroup[];
5
+ selectedCuid: string | null;
6
+ onGroupClick: (group: IEntryGroup) => void;
7
+ onSubClick: (cuid: string, isSelected: boolean) => void;
8
+ childEntriesMap: Map<string, IDevtoolsActionEntry[]>;
9
+ style?: React.CSSProperties;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ export declare const _IoTooltipContent: ({ value }: {
2
+ value: unknown;
3
+ }) => import("react/jsx-runtime").JSX.Element;
4
+ export declare function IoTooltipContent({ value }: {
5
+ value: unknown;
6
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare enum EBreakGroupReason {
2
+ new_input = "new_input",
3
+ new_output = "new_output"
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nice-code/action",
3
- "version": "0.2.19",
3
+ "version": "0.3.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,9 +44,9 @@
44
44
  "build-types": "tsc --project tsconfig.build.json"
45
45
  },
46
46
  "dependencies": {
47
- "@nice-code/common-errors": "0.2.19",
48
- "@nice-code/error": "0.2.19",
49
- "@nice-code/util": "0.2.19",
47
+ "@nice-code/common-errors": "0.3.1",
48
+ "@nice-code/error": "0.3.1",
49
+ "@nice-code/util": "0.3.1",
50
50
  "@standard-schema/spec": "^1.1.0",
51
51
  "@tanstack/react-virtual": "^3.13.26",
52
52
  "http-status-codes": "^2.3.0",