@nice-code/action 0.2.16 → 0.2.18

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 (28) hide show
  1. package/build/devtools/browser/index.js +2257 -1405
  2. package/build/devtools/server/index.js +35 -7
  3. package/build/index.js +113 -22
  4. package/build/types/ActionDefinition/Action/Payload/ActionPayload.types.d.ts +3 -1
  5. package/build/types/ActionDefinition/Action/Payload/ActionPayload_Request.d.ts +1 -0
  6. package/build/types/ActionDefinition/Action/Payload/ActionPayload_Result.d.ts +1 -0
  7. package/build/types/ActionDefinition/Action/RunningAction.d.ts +1 -0
  8. package/build/types/ActionDefinition/Domain/ActionDomain.d.ts +2 -1
  9. package/build/types/ActionDefinition/Domain/ActionRootDomain.d.ts +1 -1
  10. package/build/types/ActionDefinition/Schema/ActionSchema.d.ts +0 -18
  11. package/build/types/devtools/browser/components/ActionErrorDisplay.d.ts +5 -0
  12. package/build/types/devtools/browser/components/ChildDispatchChips.d.ts +5 -3
  13. package/build/types/devtools/browser/components/Chip.d.ts +17 -5
  14. package/build/types/devtools/browser/components/DomainChip.d.ts +3 -11
  15. package/build/types/devtools/browser/components/HandlerChips.d.ts +4 -2
  16. package/build/types/devtools/browser/components/Icon.d.ts +15 -0
  17. package/build/types/devtools/browser/components/NiceErrorDisplay.d.ts +19 -0
  18. package/build/types/devtools/browser/components/StackTraceSection.d.ts +3 -1
  19. package/build/types/devtools/browser/components/Tooltip.d.ts +14 -0
  20. package/build/types/devtools/browser/components/{ActionDetailPanel.d.ts → action_detail/ActionDetailPanel.d.ts} +1 -1
  21. package/build/types/devtools/browser/components/action_list/ActionEntryRow.d.ts +13 -0
  22. package/build/types/devtools/browser/components/utils.d.ts +4 -0
  23. package/build/types/devtools/browser/ui_util/size.d.ts +6 -0
  24. package/build/types/devtools/core/ActionDevtools.types.d.ts +4 -1
  25. package/build/types/devtools/core/devtools_colors.d.ts +58 -0
  26. package/build/types/utils/hashPayloadData.d.ts +5 -0
  27. package/package.json +4 -3
  28. package/build/types/devtools/browser/components/ActionEntryRow.d.ts +0 -11
@@ -1827,6 +1827,12 @@ var require_source_node = __commonJS((exports) => {
1827
1827
  });
1828
1828
 
1829
1829
  // src/devtools/core/ActionDevtoolsCore.ts
1830
+ function serializeErrorForDisplay(error) {
1831
+ if (error != null && typeof error === "object" && error.name === "NiceError" && typeof error.toJsonObject === "function") {
1832
+ return error.toJsonObject();
1833
+ }
1834
+ return error;
1835
+ }
1830
1836
  function extractRouting(context) {
1831
1837
  return (context?.routing ?? []).map((item) => {
1832
1838
  const handler = item.handler;
@@ -1876,6 +1882,7 @@ class ActionDevtoolsCore {
1876
1882
  status: "running",
1877
1883
  startTime: time,
1878
1884
  input: runningAction.state?.request?.input,
1885
+ inputHash: runningAction.state?.request?.inputHash,
1879
1886
  progressUpdates: [],
1880
1887
  meta: extractMeta(runningAction.context),
1881
1888
  parentCuid: runningAction.parentCuid,
@@ -1898,16 +1905,29 @@ class ActionDevtoolsCore {
1898
1905
  };
1899
1906
  const finishType = update.finishType;
1900
1907
  if (finishType === "success" /* success */) {
1901
- return { ...base, status: "success", output: update.response?.result?.output };
1908
+ const result = update.response?.result;
1909
+ const outputHash = update.response?.outputHash;
1910
+ if (result != null && !result.ok) {
1911
+ const rawError = result.error;
1912
+ const errorStack2 = rawError instanceof Error ? rawError.stack : undefined;
1913
+ return {
1914
+ ...base,
1915
+ status: "action-error",
1916
+ outputHash,
1917
+ error: serializeErrorForDisplay(rawError),
1918
+ errorStack: errorStack2
1919
+ };
1920
+ }
1921
+ return { ...base, status: "success", output: result?.output, outputHash };
1902
1922
  }
1903
1923
  if (finishType === "failed" /* failed */) {
1904
1924
  const rawError = update.error;
1905
1925
  const errorStack2 = rawError instanceof Error ? rawError.stack : undefined;
1906
- return { ...base, status: "failed", error: rawError, errorStack: errorStack2 };
1926
+ return { ...base, status: "failed", error: serializeErrorForDisplay(rawError), errorStack: errorStack2 };
1907
1927
  }
1908
1928
  const abortReason = update.reason;
1909
1929
  const errorStack = abortReason instanceof Error ? abortReason.stack : undefined;
1910
- return { ...base, status: "aborted", abortReason, errorStack };
1930
+ return { ...base, status: "aborted", abortReason: serializeErrorForDisplay(abortReason), errorStack };
1911
1931
  });
1912
1932
  }
1913
1933
  });
@@ -1937,204 +1957,183 @@ class ActionDevtoolsCore {
1937
1957
  }
1938
1958
  }
1939
1959
  // src/devtools/browser/NiceActionDevtools.tsx
1940
- import { useCallback, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState6 } from "react";
1941
-
1942
- // src/devtools/browser/components/ActionDetailPanel.tsx
1943
- import { useMemo, useState as useState5 } from "react";
1960
+ import { useEffect as useEffect3, useMemo as useMemo2, useRef, useState as useState9 } from "react";
1944
1961
 
1945
1962
  // src/devtools/core/devtools_colors.ts
1963
+ var DEVTOOL_COLOR_SEMANTIC_ERROR = "#FF5C5C";
1964
+ var DEVTOOL_COLOR_SEMANTIC_SUCCESS = "#A3E635";
1965
+ var DEVTOOL_COLOR_SEMANTIC_SYSTEM = "#38BDF8";
1966
+ var DEVTOOL_COLOR_SEMANTIC_WARNING = "#FB923C";
1967
+ var DEVTOOL_COLOR_SEMANTIC_METADATA = "#A1A1AA";
1946
1968
  var DEVTOOL_COLOR_HANDLER_LOCAL_TEXT = "#34bb89";
1947
1969
  var DEVTOOL_COLOR_HANDLER_LOCAL_BORDER = "#144427";
1948
1970
  var DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT = "#cfa12a";
1949
1971
  var DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER = "#723917";
1972
+ var DEVTOOL_COLOR_TEXT_EMPHASIS = "#f1f5f9";
1973
+ var DEVTOOL_COLOR_TEXT_SECONDARY = "#cbd5e1";
1974
+ var DEVTOOL_COLOR_TEXT_MUTED = "#64748b";
1975
+ var DEVTOOL_COLOR_TEXT_FAINT = "#334155";
1976
+ var DEVTOOL_LIST_BASE_BACKGROUND = "#0f172a";
1977
+ var DEVTOOL_LIST_HEADER_SELECTED_BACKGROUND = "#1d2942";
1978
+ var DEVTOOL_LIST_GROUP_DIVIDER = "#101109";
1979
+ var DEVTOOL_DETAIL_BASE_BACKGROUND = "#0d1729";
1980
+ var DEVTOOL_DETAIL_HEADER_BACKGROUND = "#131f35";
1981
+ var DEVTOOL_SECTION_BACKGROUND = "#1e293b";
1982
+ var DEVTOOL_SECTION_STRING_BACKGROUND = "#0d131f";
1983
+ var DEVTOOL_STACK_TRACE_BACKGROUND = "#040a13";
1984
+ var DEVTOOL_PANEL_BORDER = "#1e293b";
1985
+ var DEVTOOL_PANEL_DIVIDER_BORDER = "#1d3352";
1986
+ var DEVTOOL_ERROR_BACKGROUND = "#1e0a0a";
1987
+ var DEVTOOL_ERROR_BADGE_BACKGROUND = "#2d0f0f";
1988
+ var DEVTOOL_TOOLTIP_BACKGROUND = "#0c1526";
1989
+ var DEVTOOL_TOOLTIP_TITLE_BACKGROUND = "#101b2e";
1990
+ var DEVTOOL_TOOLTIP_TITLE_BOTTOM_BORDER = "#211f5f";
1991
+ var DEVTOOL_TOOLTIP_BORDER = "#312e81";
1992
+ var DEVTOOL_COLOR_CALL_STACK_DIVIDER = "#0a1120";
1993
+ var DEVTOOL_JSON_KEY = "#a5b4fc";
1994
+ var DEVTOOL_JSON_STRING = "#fbbf24";
1995
+ var DEVTOOL_JSON_NUMBER = "#34d399";
1996
+ var DEVTOOL_JSON_KEYWORD = "#a78bfa";
1997
+ var DEVTOOL_JSON_PUNCTUATION = "#475569";
1998
+ var DEVTOOL_STACK_FRAME_USER_NUMBER = "#64748b";
1999
+ var DEVTOOL_STACK_FRAME_USER_FUNCTION = "#e2e8f0";
2000
+ var DEVTOOL_STACK_FRAME_USER_FOLDER = "#596b83";
2001
+ var DEVTOOL_STACK_FRAME_USER_FILE = "#8a9ebb";
2002
+ var DEVTOOL_STACK_FRAME_USER_LINE = "#4a7fa8";
2003
+ var DEVTOOL_STACK_FRAME_INTERNAL_NUMBER = "#2d3f53";
2004
+ var DEVTOOL_STACK_FRAME_INTERNAL_FUNCTION = "#50698b";
2005
+ var DEVTOOL_STACK_FRAME_INTERNAL_FOLDER = "#2d3f53";
2006
+ var DEVTOOL_STACK_FRAME_INTERNAL_FILE = "#425979";
2007
+ var DEVTOOL_STACK_FRAME_INTERNAL_LINE = "#2d4a63";
2008
+ var SEMANTIC_COLORS = {
2009
+ running_action: {
2010
+ color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
2011
+ borderColor: `${DEVTOOL_COLOR_SEMANTIC_SYSTEM}55`
2012
+ },
2013
+ success: {
2014
+ color: DEVTOOL_COLOR_SEMANTIC_SUCCESS,
2015
+ borderColor: `${DEVTOOL_COLOR_SEMANTIC_SUCCESS}55`
2016
+ },
2017
+ action_error: {
2018
+ color: DEVTOOL_COLOR_SEMANTIC_WARNING,
2019
+ borderColor: `${DEVTOOL_COLOR_SEMANTIC_WARNING}55`
2020
+ },
2021
+ failed: {
2022
+ color: DEVTOOL_COLOR_SEMANTIC_ERROR,
2023
+ borderColor: `${DEVTOOL_COLOR_SEMANTIC_ERROR}55`
2024
+ },
2025
+ aborted: {
2026
+ color: DEVTOOL_COLOR_SEMANTIC_METADATA,
2027
+ borderColor: DEVTOOL_COLOR_TEXT_FAINT
2028
+ },
2029
+ error: {
2030
+ color: DEVTOOL_COLOR_SEMANTIC_ERROR,
2031
+ borderColor: DEVTOOL_COLOR_SEMANTIC_ERROR,
2032
+ subtle: { color: "#FF5C5C9f", borderColor: "transparent" }
2033
+ },
2034
+ domain: {
2035
+ color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
2036
+ borderColor: `${DEVTOOL_COLOR_SEMANTIC_SYSTEM}55`,
2037
+ subtle: { color: "#4b5563", borderColor: "transparent" }
2038
+ },
2039
+ handler_local: {
2040
+ color: DEVTOOL_COLOR_HANDLER_LOCAL_TEXT,
2041
+ borderColor: DEVTOOL_COLOR_HANDLER_LOCAL_BORDER,
2042
+ subtle: { color: "#4b5563", borderColor: "transparent" }
2043
+ },
2044
+ handler_external: {
2045
+ color: DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT,
2046
+ borderColor: DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER,
2047
+ subtle: { color: "#cfa12a9f", borderColor: "transparent" }
2048
+ },
2049
+ age: {
2050
+ color: DEVTOOL_COLOR_SEMANTIC_METADATA,
2051
+ borderColor: DEVTOOL_SECTION_BACKGROUND,
2052
+ subtle: { color: "#4b5563", borderColor: "transparent" }
2053
+ },
2054
+ io_input: {
2055
+ color: "#fbbf24",
2056
+ subtle: { color: "#fbbe249f", borderColor: "transparent" },
2057
+ borderColor: "#78350f"
2058
+ },
2059
+ io_output: {
2060
+ color: "#a78bfa",
2061
+ subtle: { color: "#a78bfa9f", borderColor: "transparent" },
2062
+ borderColor: "#4c1d95"
2063
+ },
2064
+ default: {
2065
+ color: DEVTOOL_COLOR_TEXT_MUTED,
2066
+ borderColor: DEVTOOL_COLOR_TEXT_FAINT
2067
+ }
2068
+ };
1950
2069
 
1951
- // src/devtools/browser/components/DomainChip.tsx
1952
- import { createContext, useContext, useRef } from "react";
1953
- import { jsxDEV } from "react/jsx-dev-runtime";
1954
- var DomainTooltipCtx = createContext(null);
1955
- function DomainHierarchyTooltip({
1956
- allDomains,
1957
- anchor
1958
- }) {
1959
- return /* @__PURE__ */ jsxDEV("div", {
1960
- style: {
1961
- position: "fixed",
1962
- left: anchor.left,
1963
- top: anchor.top - 6,
1964
- transform: "translateY(-100%)",
1965
- zIndex: 2147483647,
1966
- background: "#0c1526",
1967
- border: "1px solid #312e81",
1968
- borderRadius: "5px",
1969
- padding: "6px 8px",
1970
- fontFamily: "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace",
1971
- boxShadow: "0 4px 20px rgba(0,0,0,0.6)",
1972
- pointerEvents: "none",
1973
- minWidth: "80px"
1974
- },
1975
- children: allDomains.map((d, i) => {
1976
- const isCurrent = i === allDomains.length - 1;
1977
- return /* @__PURE__ */ jsxDEV("div", {
1978
- style: {
1979
- display: "flex",
1980
- alignItems: "center",
1981
- gap: "0.3rem",
1982
- paddingLeft: `${i * 10}px`,
1983
- paddingTop: i > 0 ? "0.1rem" : undefined
1984
- },
1985
- children: [
1986
- /* @__PURE__ */ jsxDEV("span", {
1987
- style: {
1988
- fontSize: "0.8rem",
1989
- height: "0.6em",
1990
- width: "0.6em",
1991
- overflow: "hidden",
1992
- color: isCurrent ? "#818cf8" : "#3730a3",
1993
- display: "flex",
1994
- alignItems: "center",
1995
- justifyContent: "center"
1996
- },
1997
- children: "⬢"
1998
- }, undefined, false, undefined, this),
1999
- /* @__PURE__ */ jsxDEV("span", {
2000
- style: {
2001
- color: isCurrent ? "#a5b4fc" : "#4b5563",
2002
- fontSize: "0.7rem",
2003
- fontWeight: isCurrent ? 500 : undefined
2004
- },
2005
- children: d
2006
- }, undefined, false, undefined, this)
2007
- ]
2008
- }, d, true, undefined, this);
2009
- })
2010
- }, undefined, false, undefined, this);
2011
- }
2012
- function DomainChip({
2013
- subtle = false,
2014
- domain,
2015
- allDomains,
2016
- size
2017
- }) {
2018
- const ctx = useContext(DomainTooltipCtx);
2019
- const chipRef = useRef(null);
2020
- const hasHierarchy = allDomains != null && allDomains.length > 1;
2021
- const fontSize = size === "md" ? "0.7rem" : "0.6rem";
2022
- const padding = size === "md" ? "1px 5px" : "1px 4px";
2023
- return /* @__PURE__ */ jsxDEV("span", {
2024
- ref: chipRef,
2025
- onMouseEnter: hasHierarchy && ctx != null ? () => {
2026
- if (chipRef.current != null)
2027
- ctx.show(chipRef.current.getBoundingClientRect(), allDomains);
2028
- } : undefined,
2029
- onMouseLeave: hasHierarchy && ctx != null ? () => ctx.hide() : undefined,
2030
- style: {
2031
- display: "flex",
2032
- alignItems: "center",
2033
- gap: "0.4em",
2034
- color: subtle ? "#4b5563" : "#818cf8",
2035
- fontSize,
2036
- background: "#0f172a",
2037
- border: !subtle ? "1px solid #312e81" : "1px solid transparent",
2038
- padding,
2039
- borderRadius: "0.6rem",
2040
- flexShrink: 0,
2041
- whiteSpace: "nowrap"
2042
- },
2043
- children: [
2044
- /* @__PURE__ */ jsxDEV("span", {
2045
- style: {
2046
- fontSize: size === "md" ? "0.9rem" : "0.8rem",
2047
- height: "0.6em",
2048
- width: "0.6em",
2049
- display: "flex",
2050
- alignItems: "center",
2051
- justifyContent: "center"
2052
- },
2053
- children: "⬢"
2054
- }, undefined, false, undefined, this),
2055
- /* @__PURE__ */ jsxDEV("span", {
2056
- children: domain
2057
- }, undefined, false, undefined, this)
2058
- ]
2059
- }, undefined, true, undefined, this);
2070
+ // src/devtools/browser/components/action_detail/ActionDetailPanel.tsx
2071
+ import { useMemo, useState as useState6 } from "react";
2072
+
2073
+ // src/devtools/browser/ui_util/size.ts
2074
+ function getSizeValue(size) {
2075
+ switch (size) {
2076
+ case "sm" /* sm */:
2077
+ return 0.8;
2078
+ case "md" /* md */:
2079
+ return 1;
2080
+ case "lg" /* lg */:
2081
+ return 1.2;
2082
+ default:
2083
+ return 1;
2084
+ }
2060
2085
  }
2061
2086
 
2062
- // src/devtools/browser/components/Chip.tsx
2063
- import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
2064
- function Chip({
2065
- color,
2066
- borderColor,
2067
- fontSize = "8px",
2068
- padding = "1px 4px",
2069
- children,
2070
- style
2071
- }) {
2072
- return /* @__PURE__ */ jsxDEV2("span", {
2087
+ // src/devtools/browser/components/DetailSection.tsx
2088
+ import { useState } from "react";
2089
+
2090
+ // src/devtools/browser/components/SectionLabel.tsx
2091
+ import { jsxDEV } from "react/jsx-dev-runtime";
2092
+ function SectionLabel({ label, color = DEVTOOL_COLOR_SEMANTIC_SYSTEM }) {
2093
+ return /* @__PURE__ */ jsxDEV("div", {
2073
2094
  style: {
2074
2095
  color,
2075
- fontSize,
2076
- background: "#0f172a",
2077
- border: `1px solid ${borderColor}`,
2078
- padding,
2079
- borderRadius: "3px",
2080
- flexShrink: 0,
2081
- whiteSpace: "nowrap",
2082
- ...style
2096
+ fontSize: "0.85em",
2097
+ marginBottom: "3px",
2098
+ textTransform: "uppercase",
2099
+ letterSpacing: "0.05em",
2100
+ fontWeight: 500,
2101
+ textAlign: "left"
2083
2102
  },
2084
- children
2103
+ children: label
2085
2104
  }, undefined, false, undefined, this);
2086
2105
  }
2087
2106
 
2088
- // src/devtools/browser/components/HandlerChips.tsx
2089
- import { jsxDEV as jsxDEV3, Fragment } from "react/jsx-dev-runtime";
2090
- function getExternalLabel(hop) {
2091
- if (hop.handlerType !== "external")
2092
- return null;
2093
- return hop.handlerClient != null ? `${hop.transport ?? "ext"} → ${hop.handlerClient.envId}` : `→ ${hop.transport ?? "ext"}`;
2094
- }
2095
- function HandlerChips({ entry, size }) {
2096
- const firstHop = entry.meta.routing[0];
2097
- const localEnvId = firstHop != null ? firstHop.runtime.envId : null;
2098
- const externalLabel = firstHop != null ? getExternalLabel(firstHop) : null;
2099
- const fontSize = size === "md" ? "1em" : "0.8em";
2100
- const padding = size === "md" ? "1px 5px" : "1px 4px";
2101
- const firstHopIsLocal = firstHop != null && firstHop.handlerType === "local";
2102
- return /* @__PURE__ */ jsxDEV3(Fragment, {
2103
- children: [
2104
- localEnvId != null && (firstHopIsLocal || externalLabel == null) && /* @__PURE__ */ jsxDEV3(Chip, {
2105
- color: DEVTOOL_COLOR_HANDLER_LOCAL_TEXT,
2106
- borderColor: DEVTOOL_COLOR_HANDLER_LOCAL_BORDER,
2107
- fontSize,
2108
- padding,
2109
- children: "local"
2110
- }, undefined, false, undefined, this),
2111
- externalLabel != null && /* @__PURE__ */ jsxDEV3(Chip, {
2112
- color: DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT,
2113
- borderColor: DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER,
2114
- fontSize,
2115
- padding,
2116
- children: externalLabel
2117
- }, undefined, false, undefined, this)
2118
- ]
2119
- }, undefined, true, undefined, this);
2120
- }
2121
-
2122
- // src/devtools/browser/components/RunningTimer.tsx
2123
- import { useEffect, useState } from "react";
2124
-
2125
2107
  // src/devtools/browser/components/utils.ts
2108
+ import { Circle, CircleAlert, CircleCheck, CircleX, Loader2 } from "lucide-react";
2126
2109
  var STATUS_COLOR = {
2127
- running: "#60a5fa",
2128
- success: "#4ade80",
2129
- failed: "#f87171",
2130
- aborted: "#9ca3af"
2110
+ running: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
2111
+ success: DEVTOOL_COLOR_SEMANTIC_SUCCESS,
2112
+ "action-error": DEVTOOL_COLOR_SEMANTIC_WARNING,
2113
+ failed: DEVTOOL_COLOR_SEMANTIC_ERROR,
2114
+ aborted: DEVTOOL_COLOR_SEMANTIC_METADATA
2115
+ };
2116
+ var STATUS_THING = {
2117
+ running: "running_action" /* running_action */,
2118
+ success: "success" /* success */,
2119
+ "action-error": "action_error" /* action_error */,
2120
+ failed: "failed" /* failed */,
2121
+ aborted: "aborted" /* aborted */
2131
2122
  };
2132
2123
  var STATUS_SYMBOL = {
2133
2124
  running: "●",
2134
2125
  success: "✓",
2126
+ "action-error": "!",
2135
2127
  failed: "✗",
2136
2128
  aborted: "○"
2137
2129
  };
2130
+ var STATUS_ICON = {
2131
+ running: Loader2,
2132
+ success: CircleCheck,
2133
+ "action-error": CircleAlert,
2134
+ failed: CircleX,
2135
+ aborted: Circle
2136
+ };
2138
2137
  function safeStringify(value, indent = 2) {
2139
2138
  if (value === undefined)
2140
2139
  return "undefined";
@@ -2165,214 +2164,406 @@ function formatTimestamp(startTime) {
2165
2164
  });
2166
2165
  }
2167
2166
 
2168
- // src/devtools/browser/components/RunningTimer.tsx
2169
- import { jsxDEV as jsxDEV4, Fragment as Fragment2 } from "react/jsx-dev-runtime";
2170
- function RunningTimer({ startTime }) {
2171
- const [elapsed, setElapsed] = useState(() => Date.now() - startTime);
2172
- useEffect(() => {
2173
- const interval = setInterval(() => setElapsed(Date.now() - startTime), 100);
2174
- return () => clearInterval(interval);
2175
- }, [startTime]);
2176
- return /* @__PURE__ */ jsxDEV4(Fragment2, {
2167
+ // src/devtools/browser/components/DetailSection.tsx
2168
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
2169
+ var COMPACT_CHAR_LIMIT = 120;
2170
+ var MONO = "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace";
2171
+ var JSON_TOKEN_RE = /("(?:\\.|[^"\\])*")(\s*:)?|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b|\bnull\b|\bundefined\b)|([{}[\],])/g;
2172
+ function renderColoredJson(text) {
2173
+ const nodes = [];
2174
+ let last = 0;
2175
+ let i = 0;
2176
+ JSON_TOKEN_RE.lastIndex = 0;
2177
+ for (let m = JSON_TOKEN_RE.exec(text);m !== null; m = JSON_TOKEN_RE.exec(text)) {
2178
+ if (m.index > last)
2179
+ nodes.push(text.slice(last, m.index));
2180
+ const [, str, colon, num, kw, punct] = m;
2181
+ if (str != null) {
2182
+ if (colon != null) {
2183
+ nodes.push(/* @__PURE__ */ jsxDEV2("span", {
2184
+ style: { color: DEVTOOL_JSON_KEY },
2185
+ children: str
2186
+ }, i++, false, undefined, this));
2187
+ nodes.push(/* @__PURE__ */ jsxDEV2("span", {
2188
+ style: { color: DEVTOOL_JSON_PUNCTUATION },
2189
+ children: colon
2190
+ }, i++, false, undefined, this));
2191
+ } else {
2192
+ nodes.push(/* @__PURE__ */ jsxDEV2("span", {
2193
+ style: { color: DEVTOOL_JSON_STRING },
2194
+ children: str
2195
+ }, i++, false, undefined, this));
2196
+ }
2197
+ } else if (num != null) {
2198
+ nodes.push(/* @__PURE__ */ jsxDEV2("span", {
2199
+ style: { color: DEVTOOL_JSON_NUMBER },
2200
+ children: num
2201
+ }, i++, false, undefined, this));
2202
+ } else if (kw != null) {
2203
+ nodes.push(/* @__PURE__ */ jsxDEV2("span", {
2204
+ style: { color: DEVTOOL_JSON_KEYWORD },
2205
+ children: kw
2206
+ }, i++, false, undefined, this));
2207
+ } else if (punct != null) {
2208
+ nodes.push(/* @__PURE__ */ jsxDEV2("span", {
2209
+ style: { color: DEVTOOL_JSON_PUNCTUATION },
2210
+ children: punct
2211
+ }, i++, false, undefined, this));
2212
+ }
2213
+ last = JSON_TOKEN_RE.lastIndex;
2214
+ }
2215
+ if (last < text.length)
2216
+ nodes.push(text.slice(last));
2217
+ return nodes;
2218
+ }
2219
+ function tryParseJson(s) {
2220
+ try {
2221
+ return JSON.parse(s);
2222
+ } catch {
2223
+ return null;
2224
+ }
2225
+ }
2226
+ function DetailSection({
2227
+ label,
2228
+ value,
2229
+ color = DEVTOOL_COLOR_SEMANTIC_SYSTEM
2230
+ }) {
2231
+ const parsedFromString = typeof value === "string" ? tryParseJson(value) : null;
2232
+ const isPlainString = typeof value === "string" && parsedFromString === null;
2233
+ const effectiveValue = parsedFromString !== null ? parsedFromString : value;
2234
+ const [expanded, setExpanded] = useState(false);
2235
+ const fullJson = isPlainString ? value : safeStringify(effectiveValue, 2);
2236
+ const compactJson = isPlainString ? value : safeStringify(effectiveValue, 0);
2237
+ const canExpand = fullJson !== compactJson || compactJson.length > COMPACT_CHAR_LIMIT;
2238
+ const compactDisplay = compactJson.length > COMPACT_CHAR_LIMIT ? `${compactJson.slice(0, COMPACT_CHAR_LIMIT)}…` : compactJson;
2239
+ const baseStyle = isPlainString ? { background: DEVTOOL_SECTION_STRING_BACKGROUND, color: DEVTOOL_COLOR_TEXT_MUTED } : { background: DEVTOOL_SECTION_BACKGROUND, color: DEVTOOL_COLOR_TEXT_SECONDARY };
2240
+ return /* @__PURE__ */ jsxDEV2("div", {
2177
2241
  children: [
2178
- elapsed,
2179
- "ms"
2242
+ /* @__PURE__ */ jsxDEV2("div", {
2243
+ style: {
2244
+ display: "flex",
2245
+ alignItems: "center",
2246
+ justifyContent: "space-between",
2247
+ marginBottom: "3px"
2248
+ },
2249
+ children: [
2250
+ /* @__PURE__ */ jsxDEV2(SectionLabel, {
2251
+ label,
2252
+ color
2253
+ }, undefined, false, undefined, this),
2254
+ canExpand && /* @__PURE__ */ jsxDEV2("span", {
2255
+ style: { color: DEVTOOL_COLOR_TEXT_FAINT, fontSize: "11px" },
2256
+ children: expanded ? "▾" : "▸"
2257
+ }, undefined, false, undefined, this)
2258
+ ]
2259
+ }, undefined, true, undefined, this),
2260
+ expanded ? /* @__PURE__ */ jsxDEV2("div", {
2261
+ onClick: canExpand ? () => setExpanded(false) : undefined,
2262
+ style: {
2263
+ margin: 0,
2264
+ padding: "6px 8px",
2265
+ borderRadius: "4px",
2266
+ fontSize: "11px",
2267
+ fontFamily: MONO,
2268
+ overflowX: "auto",
2269
+ textAlign: "left",
2270
+ whiteSpace: "pre-wrap",
2271
+ wordBreak: "break-all",
2272
+ cursor: canExpand ? "pointer" : "default",
2273
+ fontStyle: isPlainString ? "italic" : "normal",
2274
+ ...baseStyle
2275
+ },
2276
+ children: isPlainString ? fullJson : renderColoredJson(fullJson)
2277
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2("div", {
2278
+ onClick: canExpand ? () => setExpanded(true) : undefined,
2279
+ style: {
2280
+ padding: "5px 8px",
2281
+ borderRadius: "4px",
2282
+ fontSize: "11px",
2283
+ fontFamily: MONO,
2284
+ whiteSpace: "nowrap",
2285
+ overflow: "hidden",
2286
+ textOverflow: "ellipsis",
2287
+ cursor: canExpand ? "pointer" : "default",
2288
+ fontStyle: isPlainString ? "italic" : "normal",
2289
+ ...baseStyle
2290
+ },
2291
+ children: compactDisplay
2292
+ }, undefined, false, undefined, this)
2180
2293
  ]
2181
2294
  }, undefined, true, undefined, this);
2182
2295
  }
2183
- function DurationDisplay({ entry }) {
2184
- const d = formatDuration(entry);
2185
- return /* @__PURE__ */ jsxDEV4(Fragment2, {
2186
- children: d ?? /* @__PURE__ */ jsxDEV4(RunningTimer, {
2187
- startTime: entry.startTime
2188
- }, undefined, false, undefined, this)
2189
- }, undefined, false, undefined, this);
2190
- }
2191
-
2192
- // src/devtools/browser/components/SectionLabel.tsx
2193
- import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
2194
- function SectionLabel({ label, color = "#60a5fa" }) {
2195
- return /* @__PURE__ */ jsxDEV5("div", {
2196
- style: {
2197
- color,
2198
- fontSize: "10px",
2199
- marginBottom: "3px",
2200
- textTransform: "uppercase",
2201
- letterSpacing: "0.05em"
2202
- },
2203
- children: label
2204
- }, undefined, false, undefined, this);
2205
- }
2206
2296
 
2207
- // src/devtools/browser/components/CallStackSection.tsx
2208
- import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
2209
- function getCalledLabel(entry) {
2210
- const firstHop = entry.meta.routing[0];
2211
- if (firstHop == null)
2212
- return " call";
2213
- if (firstHop.handlerType === "local")
2214
- return "↳ local";
2215
- const label = getExternalLabel(firstHop);
2216
- return label != null ? `↳ ${label}` : "↳ call";
2217
- }
2218
- function getCalledColor(entry) {
2219
- const firstHop = entry.meta.routing[0];
2220
- if (firstHop == null)
2221
- return "#a78bfa";
2222
- if (firstHop.handlerType === "local")
2223
- return DEVTOOL_COLOR_HANDLER_LOCAL_TEXT;
2224
- return DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT;
2297
+ // src/devtools/browser/components/NiceErrorDisplay.tsx
2298
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
2299
+ var MONO2 = "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace";
2300
+ var SANS = "ui-sans-serif, system-ui, -apple-system, sans-serif";
2301
+ function isNiceErrorJson(value) {
2302
+ if (typeof value !== "object" || value == null)
2303
+ return false;
2304
+ const v = value;
2305
+ return v["name"] === "NiceError" && Array.isArray(v["ids"]) && typeof v["message"] === "string";
2225
2306
  }
2226
- function CallStackLink({
2227
- entry,
2228
- entryRole,
2229
- isFocused,
2230
- onClick
2231
- }) {
2232
- const color = STATUS_COLOR[entry.status];
2233
- const symbol = STATUS_SYMBOL[entry.status];
2234
- const labelColor = entryRole === "caller" ? "#94a3b8" : getCalledColor(entry);
2235
- const label = entryRole === "caller" ? "↑ from" : getCalledLabel(entry);
2236
- return /* @__PURE__ */ jsxDEV6("div", {
2237
- onClick,
2307
+ function NiceErrorBody({ error }) {
2308
+ return /* @__PURE__ */ jsxDEV3("div", {
2238
2309
  style: {
2239
- background: isFocused ? "#1e2e45" : "#1e293b",
2310
+ background: DEVTOOL_ERROR_BACKGROUND,
2311
+ border: `1px solid ${DEVTOOL_COLOR_SEMANTIC_ERROR}`,
2240
2312
  borderRadius: "4px",
2241
- borderLeft: isFocused ? "2px solid #a78bfa" : "2px solid transparent",
2242
- padding: isFocused ? "5px 8px 5px 6px" : "5px 8px",
2243
- display: "grid",
2244
- gridTemplateColumns: "30% 1fr 30%",
2245
- alignItems: "center",
2246
- columnGap: "8px",
2247
- cursor: "pointer"
2313
+ overflow: "hidden"
2248
2314
  },
2249
2315
  children: [
2250
- /* @__PURE__ */ jsxDEV6("span", {
2316
+ /* @__PURE__ */ jsxDEV3("div", {
2251
2317
  style: {
2252
- color: labelColor,
2253
- fontSize: "9px",
2254
- whiteSpace: "nowrap",
2255
- overflow: "hidden",
2256
- textOverflow: "ellipsis"
2318
+ padding: "12px 14px",
2319
+ color: DEVTOOL_COLOR_SEMANTIC_ERROR,
2320
+ fontSize: "1em",
2321
+ fontWeight: "700",
2322
+ lineHeight: "1.45",
2323
+ wordBreak: "break-word",
2324
+ fontFamily: SANS,
2325
+ textAlign: "left",
2326
+ borderBottom: `1px solid ${DEVTOOL_ERROR_BADGE_BACKGROUND}`
2257
2327
  },
2258
- children: label
2328
+ children: error.message
2259
2329
  }, undefined, false, undefined, this),
2260
- /* @__PURE__ */ jsxDEV6("span", {
2330
+ /* @__PURE__ */ jsxDEV3("div", {
2261
2331
  style: {
2332
+ padding: "6px 14px 8px",
2262
2333
  display: "flex",
2334
+ flexWrap: "wrap",
2335
+ gap: "10px",
2263
2336
  alignItems: "center",
2264
- justifyContent: "center",
2265
- gap: "5px",
2266
- overflow: "hidden"
2337
+ background: DEVTOOL_ERROR_BADGE_BACKGROUND
2267
2338
  },
2268
2339
  children: [
2269
- /* @__PURE__ */ jsxDEV6("span", {
2270
- style: { color, fontSize: "10px", flexShrink: 0 },
2271
- children: symbol
2272
- }, undefined, false, undefined, this),
2273
- /* @__PURE__ */ jsxDEV6("span", {
2340
+ error.ids.map((id) => /* @__PURE__ */ jsxDEV3("span", {
2274
2341
  style: {
2275
- color: "#cbd5e1",
2342
+ color: DEVTOOL_COLOR_SEMANTIC_ERROR,
2343
+ fontFamily: MONO2,
2276
2344
  fontSize: "11px",
2277
- overflow: "hidden",
2278
- textOverflow: "ellipsis",
2279
- whiteSpace: "nowrap"
2345
+ fontWeight: "600"
2280
2346
  },
2281
- children: entry.actionId
2282
- }, undefined, false, undefined, this),
2283
- /* @__PURE__ */ jsxDEV6(DomainChip, {
2284
- domain: entry.domain,
2285
- allDomains: entry.allDomains,
2286
- size: "sm"
2287
- }, undefined, false, undefined, this)
2347
+ children: id
2348
+ }, id, false, undefined, this)),
2349
+ /* @__PURE__ */ jsxDEV3("span", {
2350
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px", fontFamily: SANS },
2351
+ children: [
2352
+ "domain:",
2353
+ " ",
2354
+ /* @__PURE__ */ jsxDEV3("span", {
2355
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontFamily: MONO2 },
2356
+ children: error.def.domain
2357
+ }, undefined, false, undefined, this)
2358
+ ]
2359
+ }, undefined, true, undefined, this),
2360
+ /* @__PURE__ */ jsxDEV3("span", {
2361
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px", fontFamily: SANS },
2362
+ children: [
2363
+ "http:",
2364
+ " ",
2365
+ /* @__PURE__ */ jsxDEV3("span", {
2366
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontFamily: MONO2 },
2367
+ children: error.httpStatusCode
2368
+ }, undefined, false, undefined, this)
2369
+ ]
2370
+ }, undefined, true, undefined, this)
2288
2371
  ]
2289
- }, undefined, true, undefined, this),
2290
- /* @__PURE__ */ jsxDEV6("span", {
2291
- style: { color: "#475569", fontSize: "10px", textAlign: "right" },
2292
- children: /* @__PURE__ */ jsxDEV6(DurationDisplay, {
2293
- entry
2294
- }, undefined, false, undefined, this)
2295
- }, undefined, false, undefined, this)
2372
+ }, undefined, true, undefined, this)
2296
2373
  ]
2297
2374
  }, undefined, true, undefined, this);
2298
2375
  }
2299
- function CallStackSection({
2300
- parent,
2301
- childEntries,
2302
- focusedChildCuid,
2303
- onFocusChild,
2304
- onSelectParent
2376
+ function NiceErrorDisplay({
2377
+ error,
2378
+ label,
2379
+ color
2305
2380
  }) {
2306
- if (parent == null && childEntries.length === 0)
2307
- return null;
2308
- return /* @__PURE__ */ jsxDEV6("div", {
2381
+ return /* @__PURE__ */ jsxDEV3("div", {
2309
2382
  children: [
2310
- /* @__PURE__ */ jsxDEV6(SectionLabel, {
2311
- label: "Call Stack",
2312
- color: "#a78bfa"
2383
+ /* @__PURE__ */ jsxDEV3(SectionLabel, {
2384
+ label,
2385
+ color
2313
2386
  }, undefined, false, undefined, this),
2314
- /* @__PURE__ */ jsxDEV6("div", {
2315
- style: { display: "flex", flexDirection: "column", gap: "2px" },
2316
- children: [
2317
- parent != null && /* @__PURE__ */ jsxDEV6(CallStackLink, {
2318
- entry: parent,
2319
- entryRole: "caller",
2320
- isFocused: false,
2321
- onClick: () => onSelectParent(parent.cuid)
2322
- }, undefined, false, undefined, this),
2323
- childEntries.map((child) => /* @__PURE__ */ jsxDEV6(CallStackLink, {
2324
- entry: child,
2325
- entryRole: "called",
2326
- isFocused: focusedChildCuid === child.cuid,
2327
- onClick: () => onFocusChild(child.cuid)
2328
- }, child.cuid, false, undefined, this))
2329
- ]
2330
- }, undefined, true, undefined, this)
2387
+ /* @__PURE__ */ jsxDEV3(NiceErrorBody, {
2388
+ error
2389
+ }, undefined, false, undefined, this)
2331
2390
  ]
2332
2391
  }, undefined, true, undefined, this);
2333
2392
  }
2334
2393
 
2335
- // src/devtools/browser/components/ChildDispatchChips.tsx
2336
- import { jsxDEV as jsxDEV7, Fragment as Fragment3 } from "react/jsx-dev-runtime";
2337
- function ChildDispatchChips({
2338
- labels,
2339
- size = "sm"
2340
- }) {
2341
- if (labels == null || labels.length === 0)
2394
+ // src/devtools/browser/components/StackTraceSection.tsx
2395
+ import { useEffect, useState as useState2 } from "react";
2396
+
2397
+ // ../../node_modules/.bun/source-map-js@1.2.1/node_modules/source-map-js/source-map.js
2398
+ var $SourceMapGenerator = require_source_map_generator().SourceMapGenerator;
2399
+ var $SourceMapConsumer = require_source_map_consumer().SourceMapConsumer;
2400
+ var $SourceNode = require_source_node().SourceNode;
2401
+
2402
+ // src/devtools/browser/components/sourceMapResolver.ts
2403
+ var consumerCache = new Map;
2404
+ async function loadConsumer(fileUrl) {
2405
+ try {
2406
+ if (!fileUrl.startsWith("http://") && !fileUrl.startsWith("https://"))
2407
+ return null;
2408
+ const resp = await fetch(fileUrl);
2409
+ if (!resp.ok)
2410
+ return null;
2411
+ const text = await resp.text();
2412
+ const match = text.match(/\/\/[#@] sourceMappingURL=(\S+)/);
2413
+ if (match == null)
2414
+ return null;
2415
+ const mapRef = match[1];
2416
+ let mapJson;
2417
+ if (mapRef.startsWith("data:")) {
2418
+ const commaIdx = mapRef.indexOf(",");
2419
+ if (commaIdx === -1)
2420
+ return null;
2421
+ const header = mapRef.slice(5, commaIdx);
2422
+ const payload = mapRef.slice(commaIdx + 1);
2423
+ mapJson = header.includes("base64") ? atob(payload) : decodeURIComponent(payload);
2424
+ } else {
2425
+ const mapUrl = new URL(mapRef, fileUrl).href;
2426
+ const mapResp = await fetch(mapUrl);
2427
+ if (!mapResp.ok)
2428
+ return null;
2429
+ mapJson = await mapResp.text();
2430
+ }
2431
+ return new $SourceMapConsumer(JSON.parse(mapJson));
2432
+ } catch {
2342
2433
  return null;
2343
- const fontSize = size === "md" ? "1em" : "0.8em";
2344
- const padding = size === "md" ? "1px 4px" : "1px 3px";
2345
- return /* @__PURE__ */ jsxDEV7(Fragment3, {
2346
- children: labels.map((label) => /* @__PURE__ */ jsxDEV7(Chip, {
2347
- color: DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT,
2348
- borderColor: DEVTOOL_COLOR_HANDLER_EXTERNAL_BORDER,
2349
- fontSize,
2350
- padding,
2351
- children: [
2352
- "↳ ",
2353
- label
2354
- ]
2355
- }, label, true, undefined, this))
2356
- }, undefined, false, undefined, this);
2434
+ }
2435
+ }
2436
+ function getConsumer(fileUrl) {
2437
+ const key = fileUrl.split("?")[0] ?? fileUrl;
2438
+ if (!consumerCache.has(key)) {
2439
+ consumerCache.set(key, loadConsumer(fileUrl));
2440
+ }
2441
+ return consumerCache.get(key);
2442
+ }
2443
+ async function resolveCompiledPosition(fileUrl, line, col) {
2444
+ try {
2445
+ const consumer = await getConsumer(fileUrl);
2446
+ if (consumer == null)
2447
+ return null;
2448
+ const pos = consumer.originalPositionFor({ line, column: col });
2449
+ if (pos.source == null || pos.line == null)
2450
+ return null;
2451
+ return { file: pos.source, line: pos.line, col: pos.column ?? 0 };
2452
+ } catch {
2453
+ return null;
2454
+ }
2357
2455
  }
2358
2456
 
2359
- // src/devtools/browser/components/DetailSection.tsx
2360
- import { useState as useState2 } from "react";
2361
- import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
2362
- var COMPACT_CHAR_LIMIT = 120;
2363
- function DetailSection({
2457
+ // src/devtools/browser/components/StackTraceSection.tsx
2458
+ import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
2459
+ var INTERNAL_PATTERNS = [
2460
+ "/nice-action/",
2461
+ "@nice-code/action",
2462
+ "/nice-error/",
2463
+ "@nice-code/error",
2464
+ "node_modules/",
2465
+ "native code",
2466
+ "<anonymous>"
2467
+ ];
2468
+ function isInternalFrame(file) {
2469
+ return INTERNAL_PATTERNS.some((p) => file.includes(p));
2470
+ }
2471
+ function parseStackFrames(stack) {
2472
+ return stack.split(`
2473
+ `).slice(1).map((line) => {
2474
+ const raw = line.trim();
2475
+ if (raw === "")
2476
+ return null;
2477
+ const matchFn = raw.match(/^at (.+?) \((.+):(\d+):(\d+)\)$/);
2478
+ if (matchFn != null) {
2479
+ const file = matchFn[2];
2480
+ return {
2481
+ fn: matchFn[1],
2482
+ file,
2483
+ line: parseInt(matchFn[3], 10),
2484
+ col: parseInt(matchFn[4], 10),
2485
+ raw,
2486
+ isInternal: isInternalFrame(file)
2487
+ };
2488
+ }
2489
+ const matchUrl = raw.match(/^at (.+):(\d+):(\d+)$/);
2490
+ if (matchUrl != null) {
2491
+ const file = matchUrl[1];
2492
+ return {
2493
+ file,
2494
+ line: parseInt(matchUrl[2], 10),
2495
+ col: parseInt(matchUrl[3], 10),
2496
+ raw,
2497
+ isInternal: isInternalFrame(file)
2498
+ };
2499
+ }
2500
+ return { raw, isInternal: true };
2501
+ }).filter((f) => f != null);
2502
+ }
2503
+ async function resolveSourceMapPositions(frames) {
2504
+ return Promise.all(frames.map(async (frame) => {
2505
+ if (frame.isInternal || frame.file == null || frame.line == null)
2506
+ return frame;
2507
+ const resolved = await resolveCompiledPosition(frame.file, frame.line, frame.col ?? 0);
2508
+ if (resolved == null)
2509
+ return frame;
2510
+ return { ...frame, file: resolved.file, line: resolved.line, col: resolved.col };
2511
+ }));
2512
+ }
2513
+ function formatFrameFile(file) {
2514
+ if (file == null)
2515
+ return "?";
2516
+ let path = file;
2517
+ try {
2518
+ const url = new URL(file);
2519
+ path = url.pathname.split("?")[0] ?? url.pathname;
2520
+ if (path.startsWith("/@fs/"))
2521
+ path = path.slice(4);
2522
+ } catch {}
2523
+ const parts = path.replace(/\\/g, "/").split("/").filter(Boolean);
2524
+ const filtered = parts[0]?.match(/^[a-zA-Z]:$/) != null ? parts.slice(1) : parts;
2525
+ const tail = filtered.slice(-4);
2526
+ return tail.join("/") || file;
2527
+ }
2528
+ function countUserFrames(stack) {
2529
+ if (stack == null)
2530
+ return 0;
2531
+ return parseStackFrames(stack).filter((f) => !f.isInternal).length;
2532
+ }
2533
+ function StackTraceSection({
2364
2534
  label,
2365
- value,
2366
- color = "#60a5fa"
2535
+ stack,
2536
+ color = DEVTOOL_COLOR_SEMANTIC_SYSTEM,
2537
+ minFrameCount
2367
2538
  }) {
2368
- const [expanded, setExpanded] = useState2(false);
2369
- const fullJson = safeStringify(value, 2);
2370
- const compactJson = safeStringify(value, 0);
2371
- const canExpand = fullJson !== compactJson || compactJson.length > COMPACT_CHAR_LIMIT;
2372
- const compactDisplay = compactJson.length > COMPACT_CHAR_LIMIT ? `${compactJson.slice(0, COMPACT_CHAR_LIMIT)}…` : compactJson;
2373
- return /* @__PURE__ */ jsxDEV8("div", {
2539
+ const [showAll, setShowAll] = useState2(false);
2540
+ const [resolvedFrames, setResolvedFrames] = useState2(null);
2541
+ useEffect(() => {
2542
+ if (stack == null)
2543
+ return;
2544
+ setResolvedFrames(null);
2545
+ const parsed = parseStackFrames(stack);
2546
+ let cancelled = false;
2547
+ resolveSourceMapPositions(parsed).then((frames) => {
2548
+ if (!cancelled)
2549
+ setResolvedFrames(frames);
2550
+ });
2551
+ return () => {
2552
+ cancelled = true;
2553
+ };
2554
+ }, [stack]);
2555
+ if (stack == null)
2556
+ return null;
2557
+ const allFrames = resolvedFrames ?? parseStackFrames(stack);
2558
+ const userFrames = allFrames.filter((f) => !f.isInternal);
2559
+ const hasInternalFrames = allFrames.length > userFrames.length;
2560
+ const displayFrames = showAll ? allFrames : userFrames;
2561
+ const phantomFrameCount = !showAll ? Math.max(0, (minFrameCount ?? 0) - displayFrames.length) : 0;
2562
+ if (allFrames.length === 0)
2563
+ return null;
2564
+ return /* @__PURE__ */ jsxDEV4("div", {
2374
2565
  children: [
2375
- /* @__PURE__ */ jsxDEV8("div", {
2566
+ /* @__PURE__ */ jsxDEV4("div", {
2376
2567
  style: {
2377
2568
  display: "flex",
2378
2569
  alignItems: "center",
@@ -2380,469 +2571,744 @@ function DetailSection({
2380
2571
  marginBottom: "3px"
2381
2572
  },
2382
2573
  children: [
2383
- /* @__PURE__ */ jsxDEV8("div", {
2384
- style: {
2385
- color,
2386
- fontSize: "10px",
2387
- textTransform: "uppercase",
2388
- letterSpacing: "0.05em"
2389
- },
2390
- children: label
2574
+ /* @__PURE__ */ jsxDEV4(SectionLabel, {
2575
+ label,
2576
+ color
2391
2577
  }, undefined, false, undefined, this),
2392
- canExpand && /* @__PURE__ */ jsxDEV8("span", {
2393
- style: { color: "#334155", fontSize: "11px" },
2394
- children: expanded ? "" : "▸"
2578
+ hasInternalFrames && /* @__PURE__ */ jsxDEV4("span", {
2579
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "9px" },
2580
+ children: !showAll ? "user only" : `all (${allFrames.length})`
2395
2581
  }, undefined, false, undefined, this)
2396
2582
  ]
2397
2583
  }, undefined, true, undefined, this),
2398
- expanded ? /* @__PURE__ */ jsxDEV8("div", {
2399
- onClick: canExpand ? () => setExpanded(false) : undefined,
2400
- style: {
2401
- margin: 0,
2402
- padding: "6px 8px",
2403
- background: "#1e293b",
2404
- borderRadius: "4px",
2405
- fontSize: "11px",
2406
- color: "#cbd5e1",
2407
- overflowX: "auto",
2408
- textAlign: "left",
2409
- whiteSpace: "pre-wrap",
2410
- wordBreak: "break-all",
2411
- cursor: canExpand ? "pointer" : "default"
2412
- },
2413
- children: fullJson
2414
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("div", {
2415
- onClick: canExpand ? () => setExpanded(true) : undefined,
2584
+ /* @__PURE__ */ jsxDEV4("div", {
2585
+ onClick: () => setShowAll((s) => !s),
2416
2586
  style: {
2417
- padding: "5px 8px",
2418
- background: "#1e293b",
2587
+ background: DEVTOOL_STACK_TRACE_BACKGROUND,
2419
2588
  borderRadius: "4px",
2420
- fontSize: "11px",
2421
- color: "#94a3b8",
2422
- fontFamily: "inherit",
2423
- whiteSpace: "nowrap",
2589
+ padding: "2px",
2424
2590
  overflow: "hidden",
2425
- textOverflow: "ellipsis",
2426
- cursor: canExpand ? "pointer" : "default"
2427
- },
2428
- children: compactDisplay
2429
- }, undefined, false, undefined, this)
2430
- ]
2431
- }, undefined, true, undefined, this);
2432
- }
2433
-
2434
- // src/devtools/browser/components/MetaSection.tsx
2435
- import { useState as useState3 } from "react";
2436
- import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
2437
- function MetaChip({ label, value }) {
2438
- return /* @__PURE__ */ jsxDEV9("span", {
2439
- style: { whiteSpace: "nowrap" },
2440
- children: [
2441
- /* @__PURE__ */ jsxDEV9("span", {
2442
- style: { color: "#475569" },
2443
- children: [
2444
- label,
2445
- " "
2446
- ]
2447
- }, undefined, true, undefined, this),
2448
- /* @__PURE__ */ jsxDEV9("span", {
2449
- style: { color: "#cbd5e1" },
2450
- children: value
2451
- }, undefined, false, undefined, this)
2452
- ]
2453
- }, undefined, true, undefined, this);
2454
- }
2455
- function MetaSection({ entry }) {
2456
- const [expanded, setExpanded] = useState3(false);
2457
- const { meta, cuid } = entry;
2458
- const expandedRows = [
2459
- { label: "cuid", value: cuid },
2460
- { label: "origin", value: meta.originClient.envId },
2461
- ...meta.originClient.perId != null ? [{ label: "perId", value: meta.originClient.perId }] : [],
2462
- ...meta.originClient.insId != null ? [{ label: "insId", value: meta.originClient.insId }] : []
2463
- ];
2464
- return /* @__PURE__ */ jsxDEV9("div", {
2465
- children: [
2466
- /* @__PURE__ */ jsxDEV9("div", {
2467
- style: {
2468
- display: "flex",
2469
- alignItems: "center",
2470
- justifyContent: "space-between",
2471
- marginBottom: "3px"
2591
+ cursor: "pointer"
2472
2592
  },
2473
2593
  children: [
2474
- /* @__PURE__ */ jsxDEV9("div", {
2475
- style: {
2476
- color: "#60a5fa",
2477
- fontSize: "10px",
2478
- textTransform: "uppercase",
2479
- letterSpacing: "0.05em"
2480
- },
2481
- children: "Meta"
2482
- }, undefined, false, undefined, this),
2483
- /* @__PURE__ */ jsxDEV9("span", {
2484
- style: { color: "#334155", fontSize: "11px" },
2485
- children: expanded ? "▾" : "▸"
2486
- }, undefined, false, undefined, this)
2487
- ]
2488
- }, undefined, true, undefined, this),
2489
- expanded ? /* @__PURE__ */ jsxDEV9("div", {
2490
- onClick: () => setExpanded(false),
2491
- style: { background: "#1e293b", borderRadius: "4px", overflow: "hidden", cursor: "pointer" },
2492
- children: expandedRows.map(({ label, value }, i) => /* @__PURE__ */ jsxDEV9("div", {
2493
- style: {
2494
- display: "grid",
2495
- gridTemplateColumns: "52px 1fr",
2496
- columnGap: "8px",
2497
- padding: "4px 8px",
2498
- borderBottom: i < expandedRows.length - 1 ? "1px solid #0f172a" : "none",
2499
- alignItems: "start"
2500
- },
2501
- children: [
2502
- /* @__PURE__ */ jsxDEV9("span", {
2503
- style: { textAlign: "left", color: "#475569", fontSize: "10px", paddingTop: "1px" },
2504
- children: label
2505
- }, undefined, false, undefined, this),
2506
- /* @__PURE__ */ jsxDEV9("span", {
2507
- style: { textAlign: "left", color: "#cbd5e1", fontSize: "11px", wordBreak: "break-all" },
2508
- children: value
2509
- }, undefined, false, undefined, this)
2510
- ]
2511
- }, label, true, undefined, this))
2512
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("div", {
2513
- onClick: () => setExpanded(true),
2514
- style: {
2515
- background: "#1e293b",
2516
- borderRadius: "4px",
2517
- padding: "5px 8px",
2518
- fontSize: "11px",
2519
- display: "flex",
2520
- gap: "10px",
2521
- rowGap: "2px",
2522
- flexWrap: "wrap",
2523
- cursor: "pointer"
2524
- },
2525
- children: [
2526
- /* @__PURE__ */ jsxDEV9(MetaChip, {
2527
- label: "cuid",
2528
- value: `…${cuid.slice(-8)}`
2529
- }, undefined, false, undefined, this),
2530
- /* @__PURE__ */ jsxDEV9(MetaChip, {
2531
- label: "origin",
2532
- value: meta.originClient.envId
2533
- }, undefined, false, undefined, this),
2534
- meta.originClient.perId != null && /* @__PURE__ */ jsxDEV9(MetaChip, {
2535
- label: "perId",
2536
- value: meta.originClient.perId.length > 10 ? `${meta.originClient.perId.slice(0, 10)}…` : meta.originClient.perId
2537
- }, undefined, false, undefined, this),
2538
- meta.originClient.insId != null && /* @__PURE__ */ jsxDEV9(MetaChip, {
2539
- label: "insId",
2540
- value: meta.originClient.insId.length > 10 ? `${meta.originClient.insId.slice(0, 10)}…` : meta.originClient.insId
2541
- }, undefined, false, undefined, this)
2542
- ]
2543
- }, undefined, true, undefined, this)
2544
- ]
2545
- }, undefined, true, undefined, this);
2546
- }
2547
-
2548
- // src/devtools/browser/components/RoutingSection.tsx
2549
- import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
2550
- function RoutingSection({
2551
- entry,
2552
- minHopCount = 0
2553
- }) {
2554
- const { meta, startTime } = entry;
2555
- const hopCount = meta.routing.length;
2556
- const phantomCount = Math.max(0, minHopCount - hopCount);
2557
- if (hopCount === 0 && phantomCount === 0)
2558
- return null;
2559
- return /* @__PURE__ */ jsxDEV10("div", {
2560
- children: [
2561
- /* @__PURE__ */ jsxDEV10(SectionLabel, {
2562
- label: hopCount > 0 ? `Routing · ${hopCount} hop${hopCount !== 1 ? "s" : ""}` : "Routing"
2563
- }, undefined, false, undefined, this),
2564
- /* @__PURE__ */ jsxDEV10("div", {
2565
- style: { display: "flex", flexDirection: "column", gap: "2px" },
2566
- children: [
2567
- meta.routing.map((hop, i) => {
2568
- const isLocal = hop.handlerType === "local";
2569
- const isLast = i === hopCount - 1 && phantomCount === 0;
2570
- const badgeColor = isLocal ? "#34d399" : "#fbbf24";
2571
- const badgeText = isLocal ? "● exec" : `→ ${hop.transport ?? "ext"}`;
2572
- const runtimeTitle = [hop.runtime.perId, hop.runtime.insId].filter(Boolean).join(" · ") || undefined;
2573
- return /* @__PURE__ */ jsxDEV10("div", {
2594
+ displayFrames.length === 0 ? /* @__PURE__ */ jsxDEV4("div", {
2595
+ style: { padding: "6px 10px", color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px", fontStyle: "italic" },
2596
+ children: "no user frames captured"
2597
+ }, undefined, false, undefined, this) : displayFrames.map((frame, idx) => {
2598
+ const displayFile = formatFrameFile(frame.file);
2599
+ const slashIdx = displayFile.lastIndexOf("/");
2600
+ const folderPrefix = slashIdx >= 0 ? displayFile.slice(0, slashIdx + 1) : "";
2601
+ const bareFilename = slashIdx >= 0 ? displayFile.slice(slashIdx + 1) : displayFile;
2602
+ const titleStr = frame.file != null ? frame.file : frame.raw;
2603
+ const isUser = !frame.isInternal;
2604
+ return /* @__PURE__ */ jsxDEV4("div", {
2605
+ title: titleStr,
2574
2606
  style: {
2575
- background: "#1e293b",
2576
- borderRadius: "4px",
2577
- overflow: "hidden",
2578
- display: "grid",
2579
- gridTemplateColumns: "30% 1fr 30%",
2580
- alignItems: "center",
2581
- columnGap: "8px",
2582
- borderBottom: isLast ? undefined : "1px solid #0f172a",
2583
- padding: "4px 8px"
2607
+ display: "flex",
2608
+ flexDirection: "row",
2609
+ gap: "0.5em",
2610
+ padding: "4px",
2611
+ borderBottom: `1px solid ${DEVTOOL_LIST_BASE_BACKGROUND}`
2584
2612
  },
2585
2613
  children: [
2586
- /* @__PURE__ */ jsxDEV10("span", {
2587
- style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
2588
- children: [
2589
- /* @__PURE__ */ jsxDEV10("span", {
2590
- style: { color: "#334155", fontSize: "10px", width: "16px", textAlign: "right" },
2591
- children: i + 1
2592
- }, undefined, false, undefined, this),
2593
- /* @__PURE__ */ jsxDEV10("span", {
2594
- title: runtimeTitle,
2595
- style: {
2596
- color: "#94a3b8",
2597
- fontSize: "11px",
2598
- overflow: "hidden",
2599
- textOverflow: "ellipsis",
2600
- whiteSpace: "nowrap",
2601
- textAlign: "center"
2602
- },
2603
- children: hop.runtime.envId
2604
- }, undefined, false, undefined, this)
2605
- ]
2606
- }, undefined, true, undefined, this),
2607
- /* @__PURE__ */ jsxDEV10("span", {
2608
- style: { color: badgeColor, fontSize: "10px", whiteSpace: "nowrap" },
2609
- children: badgeText
2614
+ /* @__PURE__ */ jsxDEV4("span", {
2615
+ style: {
2616
+ color: isUser ? DEVTOOL_STACK_FRAME_USER_NUMBER : DEVTOOL_STACK_FRAME_INTERNAL_NUMBER,
2617
+ fontSize: "10px",
2618
+ minWidth: "10px",
2619
+ textAlign: "left",
2620
+ flexShrink: 0,
2621
+ fontVariantNumeric: "tabular-nums"
2622
+ },
2623
+ children: idx + 1
2610
2624
  }, undefined, false, undefined, this),
2611
- /* @__PURE__ */ jsxDEV10("span", {
2625
+ /* @__PURE__ */ jsxDEV4("div", {
2612
2626
  style: {
2613
2627
  display: "flex",
2614
- alignItems: "center",
2615
- justifyContent: "space-between",
2616
- paddingRight: "8px",
2617
- overflow: "hidden"
2628
+ flexDirection: "column",
2629
+ gap: "0.15em",
2630
+ lineHeight: 1.2
2618
2631
  },
2619
2632
  children: [
2620
- /* @__PURE__ */ jsxDEV10("span", {
2621
- style: {
2622
- color: "#475569",
2623
- fontSize: "10px",
2624
- whiteSpace: "nowrap",
2625
- overflow: "hidden",
2626
- textOverflow: "ellipsis"
2627
- },
2628
- children: hop.handlerClient != null ? `↳ ${hop.handlerClient.envId}` : ""
2633
+ /* @__PURE__ */ jsxDEV4("div", {
2634
+ style: { display: "flex", alignItems: "center" },
2635
+ children: /* @__PURE__ */ jsxDEV4("span", {
2636
+ style: {
2637
+ color: isUser ? DEVTOOL_STACK_FRAME_USER_FUNCTION : DEVTOOL_STACK_FRAME_INTERNAL_FUNCTION,
2638
+ fontSize: "12px",
2639
+ fontWeight: 500,
2640
+ overflow: "hidden",
2641
+ textOverflow: "ellipsis",
2642
+ whiteSpace: "nowrap"
2643
+ },
2644
+ children: frame.fn ?? "(anonymous)"
2645
+ }, undefined, false, undefined, this)
2629
2646
  }, undefined, false, undefined, this),
2630
- /* @__PURE__ */ jsxDEV10("span", {
2631
- style: { color: "#334155", fontSize: "10px", flexShrink: 0, marginLeft: "auto" },
2647
+ /* @__PURE__ */ jsxDEV4("div", {
2648
+ style: { display: "flex", alignItems: "baseline", overflow: "hidden" },
2632
2649
  children: [
2633
- "+",
2634
- hop.time - startTime,
2635
- "ms"
2650
+ folderPrefix !== "" && /* @__PURE__ */ jsxDEV4("span", {
2651
+ style: {
2652
+ color: isUser ? DEVTOOL_STACK_FRAME_USER_FOLDER : DEVTOOL_STACK_FRAME_INTERNAL_FOLDER,
2653
+ fontSize: "10px",
2654
+ overflow: "hidden",
2655
+ textOverflow: "ellipsis",
2656
+ whiteSpace: "nowrap",
2657
+ flexShrink: 1,
2658
+ minWidth: 0
2659
+ },
2660
+ children: folderPrefix
2661
+ }, undefined, false, undefined, this),
2662
+ /* @__PURE__ */ jsxDEV4("span", {
2663
+ style: {
2664
+ color: isUser ? DEVTOOL_STACK_FRAME_USER_FILE : DEVTOOL_STACK_FRAME_INTERNAL_FILE,
2665
+ fontSize: "10px",
2666
+ whiteSpace: "nowrap",
2667
+ flexShrink: 0
2668
+ },
2669
+ children: bareFilename
2670
+ }, undefined, false, undefined, this),
2671
+ frame.line != null && /* @__PURE__ */ jsxDEV4("span", {
2672
+ style: {
2673
+ color: isUser ? DEVTOOL_STACK_FRAME_USER_LINE : DEVTOOL_STACK_FRAME_INTERNAL_LINE,
2674
+ fontSize: "10px",
2675
+ whiteSpace: "nowrap",
2676
+ flexShrink: 0,
2677
+ fontVariantNumeric: "tabular-nums"
2678
+ },
2679
+ children: [
2680
+ ":",
2681
+ frame.line
2682
+ ]
2683
+ }, undefined, true, undefined, this)
2636
2684
  ]
2637
2685
  }, undefined, true, undefined, this)
2638
2686
  ]
2639
2687
  }, undefined, true, undefined, this)
2640
2688
  ]
2641
- }, `${hop.time}-${hop.runtime.envId}`, true, undefined, this);
2689
+ }, frame.raw, true, undefined, this);
2642
2690
  }),
2643
- Array.from({ length: phantomCount }, (_, i) => `routing-phantom-${hopCount + i}`).map((key) => /* @__PURE__ */ jsxDEV10("div", {
2691
+ Array.from({ length: phantomFrameCount }, (_, i) => i).map((i) => /* @__PURE__ */ jsxDEV4("div", {
2644
2692
  "aria-hidden": "true",
2645
2693
  style: {
2646
2694
  visibility: "hidden",
2647
- background: "#1e293b",
2648
- borderRadius: "4px",
2649
- display: "grid",
2650
- gridTemplateColumns: "30% 1fr 30%",
2651
- alignItems: "center",
2652
- columnGap: "8px",
2653
- padding: "4px 8px"
2695
+ display: "flex",
2696
+ flexDirection: "row",
2697
+ gap: "0.5em",
2698
+ padding: "4px",
2699
+ borderBottom: `1px solid ${DEVTOOL_LIST_BASE_BACKGROUND}`
2654
2700
  },
2655
2701
  children: [
2656
- /* @__PURE__ */ jsxDEV10("span", {
2657
- style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
2702
+ /* @__PURE__ */ jsxDEV4("span", {
2703
+ style: { fontSize: "10px", minWidth: "10px", flexShrink: 0 },
2704
+ children: "0"
2705
+ }, undefined, false, undefined, this),
2706
+ /* @__PURE__ */ jsxDEV4("div", {
2707
+ style: { display: "flex", flexDirection: "column", gap: "0.15em", lineHeight: 1.2 },
2658
2708
  children: [
2659
- /* @__PURE__ */ jsxDEV10("span", {
2660
- style: { fontSize: "10px", width: "16px" },
2661
- children: "0"
2662
- }, undefined, false, undefined, this),
2663
- /* @__PURE__ */ jsxDEV10("span", {
2664
- style: { fontSize: "11px" },
2709
+ /* @__PURE__ */ jsxDEV4("div", {
2710
+ style: { fontSize: "12px" },
2665
2711
  children: "placeholder"
2712
+ }, undefined, false, undefined, this),
2713
+ /* @__PURE__ */ jsxDEV4("div", {
2714
+ style: { fontSize: "10px" },
2715
+ children: "placeholder/file.ts:1"
2666
2716
  }, undefined, false, undefined, this)
2667
2717
  ]
2668
- }, undefined, true, undefined, this),
2669
- /* @__PURE__ */ jsxDEV10("span", {
2670
- style: { fontSize: "10px" },
2671
- children: "placeholder"
2672
- }, undefined, false, undefined, this),
2673
- /* @__PURE__ */ jsxDEV10("span", {}, undefined, false, undefined, this)
2718
+ }, undefined, true, undefined, this)
2674
2719
  ]
2675
- }, key, true, undefined, this))
2720
+ }, `phantom-${i}`, true, undefined, this))
2676
2721
  ]
2677
2722
  }, undefined, true, undefined, this)
2678
2723
  ]
2679
2724
  }, undefined, true, undefined, this);
2680
2725
  }
2681
2726
 
2682
- // src/devtools/browser/components/StackTraceSection.tsx
2683
- import { useEffect as useEffect2, useState as useState4 } from "react";
2684
-
2685
- // ../../node_modules/.bun/source-map-js@1.2.1/node_modules/source-map-js/source-map.js
2686
- var $SourceMapGenerator = require_source_map_generator().SourceMapGenerator;
2687
- var $SourceMapConsumer = require_source_map_consumer().SourceMapConsumer;
2688
- var $SourceNode = require_source_node().SourceNode;
2689
-
2690
- // src/devtools/browser/components/sourceMapResolver.ts
2691
- var consumerCache = new Map;
2692
- async function loadConsumer(fileUrl) {
2693
- try {
2694
- if (!fileUrl.startsWith("http://") && !fileUrl.startsWith("https://"))
2695
- return null;
2696
- const resp = await fetch(fileUrl);
2697
- if (!resp.ok)
2698
- return null;
2699
- const text = await resp.text();
2700
- const match = text.match(/\/\/[#@] sourceMappingURL=(\S+)/);
2701
- if (match == null)
2702
- return null;
2703
- const mapRef = match[1];
2704
- let mapJson;
2705
- if (mapRef.startsWith("data:")) {
2706
- const commaIdx = mapRef.indexOf(",");
2707
- if (commaIdx === -1)
2708
- return null;
2709
- const header = mapRef.slice(5, commaIdx);
2710
- const payload = mapRef.slice(commaIdx + 1);
2711
- mapJson = header.includes("base64") ? atob(payload) : decodeURIComponent(payload);
2712
- } else {
2713
- const mapUrl = new URL(mapRef, fileUrl).href;
2714
- const mapResp = await fetch(mapUrl);
2715
- if (!mapResp.ok)
2716
- return null;
2717
- mapJson = await mapResp.text();
2718
- }
2719
- return new $SourceMapConsumer(JSON.parse(mapJson));
2720
- } catch {
2721
- return null;
2722
- }
2727
+ // src/devtools/browser/components/ActionErrorDisplay.tsx
2728
+ import { jsxDEV as jsxDEV5, Fragment } from "react/jsx-dev-runtime";
2729
+ var MONO3 = "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace";
2730
+ var SANS2 = "ui-sans-serif, system-ui, -apple-system, sans-serif";
2731
+ function FullErrorContent({
2732
+ label,
2733
+ error,
2734
+ errorStack,
2735
+ color
2736
+ }) {
2737
+ return /* @__PURE__ */ jsxDEV5(Fragment, {
2738
+ children: [
2739
+ isNiceErrorJson(error) ? /* @__PURE__ */ jsxDEV5(NiceErrorDisplay, {
2740
+ error,
2741
+ label,
2742
+ color
2743
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV5(DetailSection, {
2744
+ label,
2745
+ value: error,
2746
+ color
2747
+ }, undefined, false, undefined, this),
2748
+ /* @__PURE__ */ jsxDEV5(StackTraceSection, {
2749
+ label: "Error Stack",
2750
+ stack: errorStack,
2751
+ color
2752
+ }, undefined, false, undefined, this)
2753
+ ]
2754
+ }, undefined, true, undefined, this);
2723
2755
  }
2724
- function getConsumer(fileUrl) {
2725
- const key = fileUrl.split("?")[0] ?? fileUrl;
2726
- if (!consumerCache.has(key)) {
2727
- consumerCache.set(key, loadConsumer(fileUrl));
2756
+ function CompactErrorContent({ value, color }) {
2757
+ if (isNiceErrorJson(value)) {
2758
+ return /* @__PURE__ */ jsxDEV5("div", {
2759
+ style: { display: "flex", flexDirection: "column", gap: "1em" },
2760
+ children: [
2761
+ /* @__PURE__ */ jsxDEV5("div", {
2762
+ style: {
2763
+ color,
2764
+ fontFamily: SANS2,
2765
+ fontSize: "12px",
2766
+ fontWeight: 600,
2767
+ lineHeight: "1.4",
2768
+ wordBreak: "break-word",
2769
+ textAlign: "left"
2770
+ },
2771
+ children: value.message
2772
+ }, undefined, false, undefined, this),
2773
+ /* @__PURE__ */ jsxDEV5("div", {
2774
+ style: { display: "flex", flexWrap: "wrap", gap: "6px", alignItems: "center" },
2775
+ children: [
2776
+ value.ids.map((id) => /* @__PURE__ */ jsxDEV5("span", {
2777
+ style: { color, fontFamily: MONO3, fontSize: "10px", opacity: 0.8 },
2778
+ children: id
2779
+ }, id, false, undefined, this)),
2780
+ /* @__PURE__ */ jsxDEV5("span", {
2781
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontFamily: MONO3, fontSize: "10px" },
2782
+ children: value.def.domain
2783
+ }, undefined, false, undefined, this)
2784
+ ]
2785
+ }, undefined, true, undefined, this)
2786
+ ]
2787
+ }, undefined, true, undefined, this);
2728
2788
  }
2729
- return consumerCache.get(key);
2730
- }
2731
- async function resolveCompiledPosition(fileUrl, line, col) {
2732
- try {
2733
- const consumer = await getConsumer(fileUrl);
2734
- if (consumer == null)
2735
- return null;
2736
- const pos = consumer.originalPositionFor({ line, column: col });
2737
- if (pos.source == null || pos.line == null)
2738
- return null;
2739
- return { file: pos.source, line: pos.line, col: pos.column ?? 0 };
2740
- } catch {
2789
+ const text = typeof value === "string" ? value : value != null ? String(value) : null;
2790
+ if (text == null)
2741
2791
  return null;
2792
+ return /* @__PURE__ */ jsxDEV5("div", {
2793
+ style: {
2794
+ color,
2795
+ fontFamily: SANS2,
2796
+ fontSize: "12px",
2797
+ lineHeight: "1.4",
2798
+ wordBreak: "break-word"
2799
+ },
2800
+ children: text
2801
+ }, undefined, false, undefined, this);
2802
+ }
2803
+ function ActionErrorDisplay({
2804
+ entry,
2805
+ compact
2806
+ }) {
2807
+ const { status, error, abortReason, errorStack } = entry;
2808
+ if (status === "action-error") {
2809
+ const color = DEVTOOL_COLOR_SEMANTIC_ERROR;
2810
+ if (compact)
2811
+ return /* @__PURE__ */ jsxDEV5(CompactErrorContent, {
2812
+ value: error,
2813
+ color
2814
+ }, undefined, false, undefined, this);
2815
+ return /* @__PURE__ */ jsxDEV5(FullErrorContent, {
2816
+ label: "Action Error",
2817
+ error,
2818
+ errorStack,
2819
+ color
2820
+ }, undefined, false, undefined, this);
2821
+ }
2822
+ if (status === "failed") {
2823
+ const color = DEVTOOL_COLOR_SEMANTIC_ERROR;
2824
+ if (compact)
2825
+ return /* @__PURE__ */ jsxDEV5(CompactErrorContent, {
2826
+ value: error,
2827
+ color
2828
+ }, undefined, false, undefined, this);
2829
+ return /* @__PURE__ */ jsxDEV5(FullErrorContent, {
2830
+ label: "Error",
2831
+ error,
2832
+ errorStack,
2833
+ color
2834
+ }, undefined, false, undefined, this);
2835
+ }
2836
+ if (status === "aborted") {
2837
+ const color = DEVTOOL_COLOR_SEMANTIC_METADATA;
2838
+ if (compact)
2839
+ return /* @__PURE__ */ jsxDEV5(CompactErrorContent, {
2840
+ value: abortReason,
2841
+ color
2842
+ }, undefined, false, undefined, this);
2843
+ return /* @__PURE__ */ jsxDEV5(Fragment, {
2844
+ children: [
2845
+ abortReason != null && (isNiceErrorJson(abortReason) ? /* @__PURE__ */ jsxDEV5(NiceErrorDisplay, {
2846
+ error: abortReason,
2847
+ label: "Abort Reason",
2848
+ color
2849
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV5(DetailSection, {
2850
+ label: "Abort Reason",
2851
+ value: abortReason,
2852
+ color
2853
+ }, undefined, false, undefined, this)),
2854
+ /* @__PURE__ */ jsxDEV5(StackTraceSection, {
2855
+ label: "Abort Stack",
2856
+ stack: errorStack,
2857
+ color
2858
+ }, undefined, false, undefined, this)
2859
+ ]
2860
+ }, undefined, true, undefined, this);
2742
2861
  }
2862
+ return null;
2743
2863
  }
2744
2864
 
2745
- // src/devtools/browser/components/StackTraceSection.tsx
2746
- import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
2747
- var INTERNAL_PATTERNS = [
2748
- "/nice-action/",
2749
- "@nice-code/action",
2750
- "node_modules/",
2751
- "native code",
2752
- "<anonymous>"
2753
- ];
2754
- function isInternalFrame(file) {
2755
- return INTERNAL_PATTERNS.some((p) => file.includes(p));
2756
- }
2757
- function parseStackFrames(stack) {
2758
- return stack.split(`
2759
- `).slice(1).map((line) => {
2760
- const raw = line.trim();
2761
- if (raw === "")
2762
- return null;
2763
- const matchFn = raw.match(/^at (.+?) \((.+):(\d+):(\d+)\)$/);
2764
- if (matchFn != null) {
2765
- const file = matchFn[2];
2766
- return {
2767
- fn: matchFn[1],
2768
- file,
2769
- line: parseInt(matchFn[3], 10),
2770
- col: parseInt(matchFn[4], 10),
2771
- raw,
2772
- isInternal: isInternalFrame(file)
2773
- };
2774
- }
2775
- const matchUrl = raw.match(/^at (.+):(\d+):(\d+)$/);
2776
- if (matchUrl != null) {
2777
- const file = matchUrl[1];
2778
- return {
2779
- file,
2780
- line: parseInt(matchUrl[2], 10),
2781
- col: parseInt(matchUrl[3], 10),
2782
- raw,
2783
- isInternal: isInternalFrame(file)
2784
- };
2865
+ // src/devtools/browser/components/Chip.tsx
2866
+ import { useState as useState3 } from "react";
2867
+
2868
+ // src/devtools/browser/components/Tooltip.tsx
2869
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
2870
+ function Tooltip({
2871
+ anchor,
2872
+ config,
2873
+ children
2874
+ }) {
2875
+ const resolvedTitle = config?.title;
2876
+ const resolvedAlign = config?.align;
2877
+ const resolvedMaxWidth = config?.maxWidth ?? 400;
2878
+ const resolvedContent = config != null ? config.content : children;
2879
+ const showAbove = anchor.top >= window.innerHeight - anchor.bottom;
2880
+ const gap = 6;
2881
+ const screenMargin = 16;
2882
+ const top = showAbove ? Math.round(anchor.top - gap) : Math.round(anchor.bottom + gap);
2883
+ const maxHeight = showAbove ? Math.round(anchor.top - gap - screenMargin) : Math.round(window.innerHeight - anchor.bottom - gap - screenMargin);
2884
+ let left;
2885
+ let right;
2886
+ let transform;
2887
+ if (resolvedAlign === "center") {
2888
+ const halfMax = resolvedMaxWidth != null ? resolvedMaxWidth / 2 : 120;
2889
+ const center = Math.round(anchor.left + anchor.width / 2);
2890
+ left = Math.max(halfMax + screenMargin, Math.min(center, window.innerWidth - halfMax - screenMargin));
2891
+ transform = showAbove ? "translateX(-50%) translateY(-100%)" : "translateX(-50%)";
2892
+ } else {
2893
+ const anchorMidX = anchor.left + anchor.width / 2;
2894
+ if (anchorMidX <= window.innerWidth / 2) {
2895
+ left = Math.max(screenMargin, anchor.left);
2896
+ } else {
2897
+ right = Math.max(screenMargin, window.innerWidth - anchor.right);
2785
2898
  }
2786
- return { raw, isInternal: true };
2787
- }).filter((f) => f != null);
2899
+ if (showAbove)
2900
+ transform = "translateY(-100%)";
2901
+ }
2902
+ return /* @__PURE__ */ jsxDEV6("div", {
2903
+ style: {
2904
+ position: "fixed",
2905
+ left,
2906
+ right,
2907
+ top,
2908
+ transform,
2909
+ zIndex: 2147483647,
2910
+ background: DEVTOOL_TOOLTIP_BACKGROUND,
2911
+ border: `1px solid ${DEVTOOL_TOOLTIP_BORDER}`,
2912
+ borderRadius: "5px",
2913
+ boxShadow: "0 4px 20px rgba(0,0,0,0.6)",
2914
+ pointerEvents: "none",
2915
+ maxWidth: resolvedMaxWidth != null ? `${resolvedMaxWidth}px` : undefined,
2916
+ maxHeight: `${maxHeight}px`,
2917
+ overflowY: "auto"
2918
+ },
2919
+ children: [
2920
+ resolvedTitle != null && /* @__PURE__ */ jsxDEV6("div", {
2921
+ style: {
2922
+ background: DEVTOOL_TOOLTIP_TITLE_BACKGROUND,
2923
+ padding: "6px 8px",
2924
+ alignSelf: "start",
2925
+ textAlign: "left",
2926
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
2927
+ fontSize: "0.75rem",
2928
+ fontWeight: 600,
2929
+ paddingBottom: "4px",
2930
+ marginBottom: "4px",
2931
+ borderBottom: `1px solid ${DEVTOOL_TOOLTIP_TITLE_BOTTOM_BORDER}`
2932
+ },
2933
+ children: resolvedTitle
2934
+ }, undefined, false, undefined, this),
2935
+ /* @__PURE__ */ jsxDEV6("div", {
2936
+ style: {
2937
+ padding: "6px 8px"
2938
+ },
2939
+ children: resolvedContent
2940
+ }, undefined, false, undefined, this)
2941
+ ]
2942
+ }, undefined, true, undefined, this);
2788
2943
  }
2789
- async function resolveSourceMapPositions(frames) {
2790
- return Promise.all(frames.map(async (frame) => {
2791
- if (frame.isInternal || frame.file == null || frame.line == null)
2792
- return frame;
2793
- const resolved = await resolveCompiledPosition(frame.file, frame.line, frame.col ?? 0);
2794
- if (resolved == null)
2795
- return frame;
2796
- return { ...frame, file: resolved.file, line: resolved.line, col: resolved.col };
2797
- }));
2944
+
2945
+ // src/devtools/browser/components/Chip.tsx
2946
+ import { jsxDEV as jsxDEV7, Fragment as Fragment2 } from "react/jsx-dev-runtime";
2947
+ var CHIP_SIZE_STYLES = {
2948
+ ["sm" /* sm */]: { fontSize: "0.8em", padding: "1px 3px" },
2949
+ ["md" /* md */]: { fontSize: "0.9em", padding: "1px 4px" },
2950
+ ["lg" /* lg */]: { fontSize: "1em", padding: "2px 6px" }
2951
+ };
2952
+ function Chip({
2953
+ color,
2954
+ subtle = false,
2955
+ size = "md" /* md */,
2956
+ rounded = false,
2957
+ tooltip,
2958
+ children,
2959
+ style
2960
+ }) {
2961
+ const [anchor, setAnchor] = useState3(null);
2962
+ const hasTooltip = tooltip != null;
2963
+ const { fontSize, padding } = CHIP_SIZE_STYLES[size];
2964
+ const colorEntry = SEMANTIC_COLORS[color];
2965
+ const resolvedColor = subtle ? colorEntry.subtle?.color ?? colorEntry.color : colorEntry.color;
2966
+ const resolvedBorderColor = subtle ? colorEntry.subtle?.borderColor ?? "transparent" : colorEntry.borderColor;
2967
+ return /* @__PURE__ */ jsxDEV7(Fragment2, {
2968
+ children: [
2969
+ /* @__PURE__ */ jsxDEV7("span", {
2970
+ onMouseEnter: hasTooltip ? (e) => setAnchor(e.currentTarget.getBoundingClientRect()) : undefined,
2971
+ onMouseLeave: hasTooltip ? () => setAnchor(null) : undefined,
2972
+ style: {
2973
+ color: resolvedColor,
2974
+ fontSize,
2975
+ background: DEVTOOL_LIST_BASE_BACKGROUND,
2976
+ border: `1px solid ${resolvedBorderColor}`,
2977
+ padding,
2978
+ borderRadius: rounded ? "0.6rem" : "3px",
2979
+ flexShrink: 0,
2980
+ whiteSpace: "nowrap",
2981
+ cursor: hasTooltip ? "default" : undefined,
2982
+ ...style
2983
+ },
2984
+ children
2985
+ }, undefined, false, undefined, this),
2986
+ anchor != null && hasTooltip && /* @__PURE__ */ jsxDEV7(Tooltip, {
2987
+ anchor,
2988
+ config: tooltip
2989
+ }, undefined, false, undefined, this)
2990
+ ]
2991
+ }, undefined, true, undefined, this);
2798
2992
  }
2799
- function formatFrameFile(file) {
2800
- if (file == null)
2801
- return "?";
2802
- let path = file;
2803
- try {
2804
- const url = new URL(file);
2805
- path = url.pathname.split("?")[0] ?? url.pathname;
2806
- if (path.startsWith("/@fs/"))
2807
- path = path.slice(4);
2808
- } catch {}
2809
- const parts = path.replace(/\\/g, "/").split("/").filter(Boolean);
2810
- const filtered = parts[0]?.match(/^[a-zA-Z]:$/) != null ? parts.slice(1) : parts;
2811
- const tail = filtered.slice(-4);
2812
- return tail.join("/") || file;
2993
+
2994
+ // src/devtools/browser/components/DomainChip.tsx
2995
+ import { jsxDEV as jsxDEV8, Fragment as Fragment3 } from "react/jsx-dev-runtime";
2996
+ function DomainHierarchyContent({ allDomains }) {
2997
+ return /* @__PURE__ */ jsxDEV8(Fragment3, {
2998
+ children: allDomains.map((d, i) => {
2999
+ const isCurrent = i === allDomains.length - 1;
3000
+ return /* @__PURE__ */ jsxDEV8("div", {
3001
+ style: {
3002
+ display: "flex",
3003
+ alignItems: "center",
3004
+ gap: "0.3rem",
3005
+ paddingLeft: `${i * 10}px`,
3006
+ paddingTop: i > 0 ? "0.1rem" : undefined
3007
+ },
3008
+ children: [
3009
+ /* @__PURE__ */ jsxDEV8("span", {
3010
+ style: {
3011
+ fontSize: "0.8rem",
3012
+ height: "0.6em",
3013
+ width: "0.6em",
3014
+ overflow: "hidden",
3015
+ color: isCurrent ? DEVTOOL_COLOR_SEMANTIC_SYSTEM : "#3730a3",
3016
+ display: "flex",
3017
+ alignItems: "center",
3018
+ justifyContent: "center"
3019
+ },
3020
+ children: "⬢"
3021
+ }, undefined, false, undefined, this),
3022
+ /* @__PURE__ */ jsxDEV8("span", {
3023
+ style: {
3024
+ color: isCurrent ? DEVTOOL_COLOR_SEMANTIC_SYSTEM : "#4b5563",
3025
+ fontSize: "0.7rem",
3026
+ fontWeight: isCurrent ? 500 : undefined
3027
+ },
3028
+ children: d
3029
+ }, undefined, false, undefined, this)
3030
+ ]
3031
+ }, d, true, undefined, this);
3032
+ })
3033
+ }, undefined, false, undefined, this);
2813
3034
  }
2814
- function StackTraceSection({
2815
- label,
2816
- stack,
2817
- color = "#60a5fa"
3035
+ function DomainChip({
3036
+ subtle = false,
3037
+ domain,
3038
+ allDomains,
3039
+ size
2818
3040
  }) {
2819
- const [showAll, setShowAll] = useState4(false);
2820
- const [resolvedFrames, setResolvedFrames] = useState4(null);
2821
- useEffect2(() => {
2822
- if (stack == null)
2823
- return;
2824
- setResolvedFrames(null);
2825
- const parsed = parseStackFrames(stack);
2826
- let cancelled = false;
2827
- resolveSourceMapPositions(parsed).then((frames) => {
2828
- if (!cancelled)
2829
- setResolvedFrames(frames);
2830
- });
2831
- return () => {
2832
- cancelled = true;
2833
- };
2834
- }, [stack]);
2835
- if (stack == null)
3041
+ return /* @__PURE__ */ jsxDEV8(Chip, {
3042
+ color: "domain" /* domain */,
3043
+ subtle,
3044
+ size,
3045
+ rounded: true,
3046
+ tooltip: {
3047
+ content: /* @__PURE__ */ jsxDEV8(DomainHierarchyContent, {
3048
+ allDomains
3049
+ }, undefined, false, undefined, this),
3050
+ title: "Action Domain",
3051
+ align: "edge"
3052
+ },
3053
+ style: { display: "flex", alignItems: "center", gap: "0.4em" },
3054
+ children: [
3055
+ /* @__PURE__ */ jsxDEV8("span", {
3056
+ style: {
3057
+ height: "0.6em",
3058
+ width: "0.6em",
3059
+ display: "flex",
3060
+ alignItems: "center",
3061
+ justifyContent: "center"
3062
+ },
3063
+ children: "⬢"
3064
+ }, undefined, false, undefined, this),
3065
+ /* @__PURE__ */ jsxDEV8("span", {
3066
+ children: domain
3067
+ }, undefined, false, undefined, this)
3068
+ ]
3069
+ }, undefined, true, undefined, this);
3070
+ }
3071
+
3072
+ // src/devtools/browser/components/HandlerChips.tsx
3073
+ import { jsxDEV as jsxDEV9, Fragment as Fragment4 } from "react/jsx-dev-runtime";
3074
+ function getExternalLabel(hop) {
3075
+ if (hop.handlerType !== "external")
2836
3076
  return null;
2837
- const allFrames = resolvedFrames ?? parseStackFrames(stack);
2838
- const userFrames = allFrames.filter((f) => !f.isInternal);
2839
- const hasInternalFrames = allFrames.length > userFrames.length;
2840
- const displayFrames = showAll ? allFrames : userFrames;
2841
- if (allFrames.length === 0)
3077
+ return hop.handlerClient != null ? `${hop.transport ?? "ext"} → ${hop.handlerClient.envId}` : `→ ${hop.transport ?? "ext"}`;
3078
+ }
3079
+ function HandlerChips({ entry, size, subtle }) {
3080
+ const firstHop = entry.meta.routing[0];
3081
+ const localEnvId = firstHop != null ? firstHop.runtime.envId : null;
3082
+ const externalLabel = firstHop != null ? getExternalLabel(firstHop) : null;
3083
+ const firstHopIsLocal = firstHop != null && firstHop.handlerType === "local";
3084
+ return /* @__PURE__ */ jsxDEV9(Fragment4, {
3085
+ children: [
3086
+ localEnvId != null && (firstHopIsLocal || externalLabel == null) && /* @__PURE__ */ jsxDEV9(Chip, {
3087
+ color: "handler_local" /* handler_local */,
3088
+ size,
3089
+ subtle,
3090
+ children: localEnvId
3091
+ }, undefined, false, undefined, this),
3092
+ externalLabel != null && /* @__PURE__ */ jsxDEV9(Chip, {
3093
+ color: "handler_external" /* handler_external */,
3094
+ size,
3095
+ subtle,
3096
+ children: externalLabel
3097
+ }, undefined, false, undefined, this)
3098
+ ]
3099
+ }, undefined, true, undefined, this);
3100
+ }
3101
+
3102
+ // src/devtools/browser/components/RunningTimer.tsx
3103
+ import { useEffect as useEffect2, useState as useState4 } from "react";
3104
+ import { jsxDEV as jsxDEV10, Fragment as Fragment5 } from "react/jsx-dev-runtime";
3105
+ function RunningTimer({ startTime }) {
3106
+ const [elapsed, setElapsed] = useState4(() => Date.now() - startTime);
3107
+ useEffect2(() => {
3108
+ const interval = setInterval(() => setElapsed(Date.now() - startTime), 100);
3109
+ return () => clearInterval(interval);
3110
+ }, [startTime]);
3111
+ return /* @__PURE__ */ jsxDEV10(Fragment5, {
3112
+ children: [
3113
+ elapsed,
3114
+ "ms"
3115
+ ]
3116
+ }, undefined, true, undefined, this);
3117
+ }
3118
+ function DurationDisplay({ entry }) {
3119
+ const d = formatDuration(entry);
3120
+ return /* @__PURE__ */ jsxDEV10(Fragment5, {
3121
+ children: d ?? /* @__PURE__ */ jsxDEV10(RunningTimer, {
3122
+ startTime: entry.startTime
3123
+ }, undefined, false, undefined, this)
3124
+ }, undefined, false, undefined, this);
3125
+ }
3126
+
3127
+ // src/devtools/browser/components/CallStackSection.tsx
3128
+ import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
3129
+ function getCalledLabel(entry) {
3130
+ const firstHop = entry.meta.routing[0];
3131
+ if (firstHop == null)
3132
+ return "↳ call";
3133
+ if (firstHop.handlerType === "local")
3134
+ return "↳ local";
3135
+ const label = getExternalLabel(firstHop);
3136
+ return label != null ? `↳ ${label}` : "↳ call";
3137
+ }
3138
+ function getCalledColor(entry) {
3139
+ const firstHop = entry.meta.routing[0];
3140
+ if (firstHop == null)
3141
+ return DEVTOOL_COLOR_SEMANTIC_SYSTEM;
3142
+ if (firstHop.handlerType === "local")
3143
+ return DEVTOOL_COLOR_HANDLER_LOCAL_TEXT;
3144
+ return DEVTOOL_COLOR_HANDLER_EXTERNAL_TEXT;
3145
+ }
3146
+ function CallStackLink({
3147
+ entry,
3148
+ entryRole,
3149
+ isFocused,
3150
+ onClick
3151
+ }) {
3152
+ const color = STATUS_COLOR[entry.status];
3153
+ const symbol = STATUS_SYMBOL[entry.status];
3154
+ const labelColor = entryRole === "caller" ? DEVTOOL_COLOR_TEXT_SECONDARY : getCalledColor(entry);
3155
+ const label = entryRole === "caller" ? "↑ from" : getCalledLabel(entry);
3156
+ return /* @__PURE__ */ jsxDEV11("div", {
3157
+ onClick,
3158
+ style: {
3159
+ background: isFocused ? DEVTOOL_SECTION_BACKGROUND : DEVTOOL_DETAIL_HEADER_BACKGROUND,
3160
+ borderBottom: `1px solid ${DEVTOOL_COLOR_CALL_STACK_DIVIDER}`,
3161
+ borderLeft: isFocused ? `2px solid ${DEVTOOL_COLOR_SEMANTIC_SYSTEM}` : "2px solid transparent",
3162
+ padding: "5px 12px 5px 10px",
3163
+ display: "grid",
3164
+ gridTemplateColumns: "1fr 1fr",
3165
+ alignItems: "center",
3166
+ columnGap: "6px",
3167
+ cursor: "pointer"
3168
+ },
3169
+ children: [
3170
+ /* @__PURE__ */ jsxDEV11("span", {
3171
+ style: { display: "flex", alignItems: "center", gap: "1em", flexShrink: 0 },
3172
+ children: [
3173
+ /* @__PURE__ */ jsxDEV11("span", {
3174
+ style: { color, fontSize: "10px", flexShrink: 0 },
3175
+ children: symbol
3176
+ }, undefined, false, undefined, this),
3177
+ /* @__PURE__ */ jsxDEV11("span", {
3178
+ style: { color: labelColor, fontSize: "9px", flexShrink: 0 },
3179
+ children: label
3180
+ }, undefined, false, undefined, this),
3181
+ /* @__PURE__ */ jsxDEV11("span", {
3182
+ style: { display: "flex", alignItems: "center", gap: "5px" },
3183
+ children: [
3184
+ /* @__PURE__ */ jsxDEV11("span", {
3185
+ style: {
3186
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
3187
+ fontSize: "11px",
3188
+ overflow: "hidden",
3189
+ textOverflow: "ellipsis",
3190
+ whiteSpace: "nowrap"
3191
+ },
3192
+ children: entry.actionId
3193
+ }, undefined, false, undefined, this),
3194
+ /* @__PURE__ */ jsxDEV11(DomainChip, {
3195
+ domain: entry.domain,
3196
+ allDomains: entry.allDomains,
3197
+ size: "sm" /* sm */
3198
+ }, undefined, false, undefined, this)
3199
+ ]
3200
+ }, undefined, true, undefined, this)
3201
+ ]
3202
+ }, undefined, true, undefined, this),
3203
+ /* @__PURE__ */ jsxDEV11("span", {
3204
+ style: {
3205
+ color: DEVTOOL_COLOR_TEXT_FAINT,
3206
+ fontSize: "10px",
3207
+ textAlign: "right",
3208
+ whiteSpace: "nowrap"
3209
+ },
3210
+ children: /* @__PURE__ */ jsxDEV11(DurationDisplay, {
3211
+ entry
3212
+ }, undefined, false, undefined, this)
3213
+ }, undefined, false, undefined, this)
3214
+ ]
3215
+ }, undefined, true, undefined, this);
3216
+ }
3217
+ function CallStackSection({
3218
+ parent,
3219
+ childEntries,
3220
+ focusedChildCuid,
3221
+ onFocusChild,
3222
+ onSelectParent
3223
+ }) {
3224
+ if (parent == null && childEntries.length === 0)
2842
3225
  return null;
2843
3226
  return /* @__PURE__ */ jsxDEV11("div", {
2844
3227
  children: [
2845
- /* @__PURE__ */ jsxDEV11("div", {
3228
+ parent != null && /* @__PURE__ */ jsxDEV11(CallStackLink, {
3229
+ entry: parent,
3230
+ entryRole: "caller",
3231
+ isFocused: false,
3232
+ onClick: () => onSelectParent(parent.cuid)
3233
+ }, undefined, false, undefined, this),
3234
+ childEntries.map((child) => /* @__PURE__ */ jsxDEV11(CallStackLink, {
3235
+ entry: child,
3236
+ entryRole: "called",
3237
+ isFocused: focusedChildCuid === child.cuid,
3238
+ onClick: () => onFocusChild(child.cuid)
3239
+ }, child.cuid, false, undefined, this))
3240
+ ]
3241
+ }, undefined, true, undefined, this);
3242
+ }
3243
+
3244
+ // src/devtools/browser/components/ChildDispatchChips.tsx
3245
+ import { jsxDEV as jsxDEV12 } from "react/jsx-dev-runtime";
3246
+ function ChildDispatchChips({
3247
+ childRouteItems,
3248
+ size = "sm" /* sm */
3249
+ }) {
3250
+ if (childRouteItems == null || childRouteItems.length === 0)
3251
+ return null;
3252
+ const groups = new Map;
3253
+ for (const item of childRouteItems) {
3254
+ const runtimeId = item.handlerClient?.envId ?? item.transport ?? "ext";
3255
+ const hasClient = item.handlerClient != null;
3256
+ if (!groups.has(runtimeId)) {
3257
+ groups.set(runtimeId, { runtimeId, transports: [], hasClient });
3258
+ }
3259
+ const transport = item.transport;
3260
+ const group = groups.get(runtimeId);
3261
+ if (transport != null && !group.transports.includes(transport)) {
3262
+ group.transports.push(transport);
3263
+ }
3264
+ }
3265
+ return /* @__PURE__ */ jsxDEV12("div", {
3266
+ style: { display: "flex", alignItems: "center", gap: "4px", flexWrap: "wrap" },
3267
+ children: Array.from(groups.values()).map((group) => {
3268
+ const transportStr = group.transports.length > 0 ? group.transports.join(", ") : "ext";
3269
+ const label = group.hasClient ? `${transportStr} → ${group.runtimeId}` : `→ ${transportStr}`;
3270
+ return /* @__PURE__ */ jsxDEV12(Chip, {
3271
+ color: "handler_external" /* handler_external */,
3272
+ size,
3273
+ children: label
3274
+ }, group.runtimeId, false, undefined, this);
3275
+ })
3276
+ }, undefined, false, undefined, this);
3277
+ }
3278
+
3279
+ // src/devtools/browser/components/MetaSection.tsx
3280
+ import { useState as useState5 } from "react";
3281
+ import { jsxDEV as jsxDEV13 } from "react/jsx-dev-runtime";
3282
+ function MetaChip({ label, value }) {
3283
+ return /* @__PURE__ */ jsxDEV13("span", {
3284
+ style: { whiteSpace: "nowrap" },
3285
+ children: [
3286
+ /* @__PURE__ */ jsxDEV13("span", {
3287
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED },
3288
+ children: [
3289
+ label,
3290
+ " "
3291
+ ]
3292
+ }, undefined, true, undefined, this),
3293
+ /* @__PURE__ */ jsxDEV13("span", {
3294
+ style: { color: DEVTOOL_COLOR_TEXT_SECONDARY },
3295
+ children: value
3296
+ }, undefined, false, undefined, this)
3297
+ ]
3298
+ }, undefined, true, undefined, this);
3299
+ }
3300
+ function MetaSection({ entry }) {
3301
+ const [expanded, setExpanded] = useState5(false);
3302
+ const { meta, cuid } = entry;
3303
+ const expandedRows = [
3304
+ { label: "cuid", value: cuid },
3305
+ { label: "runtime", value: meta.originClient.envId },
3306
+ ...meta.originClient.perId != null ? [{ label: "perId", value: meta.originClient.perId }] : [],
3307
+ ...meta.originClient.insId != null ? [{ label: "insId", value: meta.originClient.insId }] : []
3308
+ ];
3309
+ return /* @__PURE__ */ jsxDEV13("div", {
3310
+ children: [
3311
+ /* @__PURE__ */ jsxDEV13("div", {
2846
3312
  style: {
2847
3313
  display: "flex",
2848
3314
  alignItems: "center",
@@ -2850,235 +3316,377 @@ function StackTraceSection({
2850
3316
  marginBottom: "3px"
2851
3317
  },
2852
3318
  children: [
2853
- /* @__PURE__ */ jsxDEV11(SectionLabel, {
2854
- label,
2855
- color
3319
+ /* @__PURE__ */ jsxDEV13("div", {
3320
+ style: {
3321
+ color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
3322
+ fontSize: "10px",
3323
+ textTransform: "uppercase",
3324
+ letterSpacing: "0.05em"
3325
+ },
3326
+ children: "Meta"
2856
3327
  }, undefined, false, undefined, this),
2857
- hasInternalFrames && /* @__PURE__ */ jsxDEV11("span", {
2858
- style: { color: "#475569", fontSize: "9px" },
2859
- children: !showAll ? "user only" : `all (${allFrames.length})`
3328
+ /* @__PURE__ */ jsxDEV13("span", {
3329
+ style: { color: DEVTOOL_COLOR_TEXT_FAINT, fontSize: "11px" },
3330
+ children: expanded ? "" : "▸"
2860
3331
  }, undefined, false, undefined, this)
2861
3332
  ]
2862
3333
  }, undefined, true, undefined, this),
2863
- /* @__PURE__ */ jsxDEV11("div", {
2864
- onClick: () => setShowAll((s) => !s),
3334
+ expanded ? /* @__PURE__ */ jsxDEV13("div", {
3335
+ onClick: () => setExpanded(false),
2865
3336
  style: {
2866
- background: "#040a13",
3337
+ background: DEVTOOL_SECTION_BACKGROUND,
2867
3338
  borderRadius: "4px",
2868
- padding: "2px",
2869
3339
  overflow: "hidden",
2870
3340
  cursor: "pointer"
2871
3341
  },
2872
- children: displayFrames.length === 0 ? /* @__PURE__ */ jsxDEV11("div", {
2873
- style: { padding: "6px 10px", color: "#64748b", fontSize: "10px", fontStyle: "italic" },
2874
- children: "no user frames captured"
2875
- }, undefined, false, undefined, this) : displayFrames.map((frame, idx) => {
2876
- const displayFile = formatFrameFile(frame.file);
2877
- const slashIdx = displayFile.lastIndexOf("/");
2878
- const folderPrefix = slashIdx >= 0 ? displayFile.slice(0, slashIdx + 1) : "";
2879
- const bareFilename = slashIdx >= 0 ? displayFile.slice(slashIdx + 1) : displayFile;
2880
- const titleStr = frame.file != null ? frame.file : frame.raw;
2881
- const isUser = !frame.isInternal;
2882
- return /* @__PURE__ */ jsxDEV11("div", {
2883
- title: titleStr,
2884
- style: {
2885
- display: "flex",
2886
- flexDirection: "row",
2887
- gap: "0.5em",
2888
- padding: "4px",
2889
- borderBottom: idx < displayFrames.length - 1 ? "1px solid #0f172a" : undefined
2890
- },
2891
- children: [
2892
- /* @__PURE__ */ jsxDEV11("span", {
2893
- style: {
2894
- color: isUser ? "#64748b" : "#2d3f53",
2895
- fontSize: "10px",
2896
- minWidth: "10px",
2897
- textAlign: "left",
2898
- flexShrink: 0,
2899
- fontVariantNumeric: "tabular-nums"
2900
- },
2901
- children: idx + 1
2902
- }, undefined, false, undefined, this),
2903
- /* @__PURE__ */ jsxDEV11("div", {
2904
- style: { display: "flex", flexDirection: "column", gap: "0.15em", lineHeight: 1.2 },
2905
- children: [
2906
- /* @__PURE__ */ jsxDEV11("div", {
2907
- style: { display: "flex", alignItems: "center" },
2908
- children: /* @__PURE__ */ jsxDEV11("span", {
3342
+ children: expandedRows.map(({ label, value }, i) => /* @__PURE__ */ jsxDEV13("div", {
3343
+ style: {
3344
+ display: "grid",
3345
+ gridTemplateColumns: "52px 1fr",
3346
+ columnGap: "8px",
3347
+ padding: "4px 8px",
3348
+ borderBottom: i < expandedRows.length - 1 ? `1px solid ${DEVTOOL_LIST_BASE_BACKGROUND}` : "none",
3349
+ alignItems: "start"
3350
+ },
3351
+ children: [
3352
+ /* @__PURE__ */ jsxDEV13("span", {
3353
+ style: { textAlign: "left", color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px", paddingTop: "1px" },
3354
+ children: label
3355
+ }, undefined, false, undefined, this),
3356
+ /* @__PURE__ */ jsxDEV13("span", {
3357
+ style: {
3358
+ textAlign: "left",
3359
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
3360
+ fontSize: "11px",
3361
+ wordBreak: "break-all"
3362
+ },
3363
+ children: value
3364
+ }, undefined, false, undefined, this)
3365
+ ]
3366
+ }, label, true, undefined, this))
3367
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV13("div", {
3368
+ onClick: () => setExpanded(true),
3369
+ style: {
3370
+ background: DEVTOOL_SECTION_BACKGROUND,
3371
+ borderRadius: "4px",
3372
+ padding: "5px 8px",
3373
+ fontSize: "11px",
3374
+ display: "flex",
3375
+ gap: "10px",
3376
+ rowGap: "2px",
3377
+ flexWrap: "wrap",
3378
+ cursor: "pointer"
3379
+ },
3380
+ children: [
3381
+ /* @__PURE__ */ jsxDEV13(MetaChip, {
3382
+ label: "cuid",
3383
+ value: `…${cuid.slice(-8)}`
3384
+ }, undefined, false, undefined, this),
3385
+ /* @__PURE__ */ jsxDEV13(MetaChip, {
3386
+ label: "runtime",
3387
+ value: meta.originClient.envId
3388
+ }, undefined, false, undefined, this),
3389
+ meta.originClient.perId != null && /* @__PURE__ */ jsxDEV13(MetaChip, {
3390
+ label: "perId",
3391
+ value: meta.originClient.perId.length > 10 ? `${meta.originClient.perId.slice(0, 10)}…` : meta.originClient.perId
3392
+ }, undefined, false, undefined, this),
3393
+ meta.originClient.insId != null && /* @__PURE__ */ jsxDEV13(MetaChip, {
3394
+ label: "insId",
3395
+ value: meta.originClient.insId.length > 10 ? `${meta.originClient.insId.slice(0, 10)}…` : meta.originClient.insId
3396
+ }, undefined, false, undefined, this)
3397
+ ]
3398
+ }, undefined, true, undefined, this)
3399
+ ]
3400
+ }, undefined, true, undefined, this);
3401
+ }
3402
+
3403
+ // src/devtools/browser/components/RoutingSection.tsx
3404
+ import { jsxDEV as jsxDEV14 } from "react/jsx-dev-runtime";
3405
+ function RoutingSection({
3406
+ entry,
3407
+ minHopCount = 0
3408
+ }) {
3409
+ const { meta, startTime } = entry;
3410
+ const hopCount = meta.routing.length;
3411
+ const phantomCount = Math.max(0, minHopCount - hopCount);
3412
+ if (hopCount === 0 && phantomCount === 0)
3413
+ return null;
3414
+ return /* @__PURE__ */ jsxDEV14("div", {
3415
+ children: [
3416
+ /* @__PURE__ */ jsxDEV14(SectionLabel, {
3417
+ label: hopCount > 0 ? `Routing · ${hopCount} hop${hopCount !== 1 ? "s" : ""}` : "Routing"
3418
+ }, undefined, false, undefined, this),
3419
+ /* @__PURE__ */ jsxDEV14("div", {
3420
+ style: { display: "flex", flexDirection: "column", gap: "2px" },
3421
+ children: [
3422
+ meta.routing.map((hop, i) => {
3423
+ const isLocal = hop.handlerType === "local";
3424
+ const isLast = i === hopCount - 1 && phantomCount === 0;
3425
+ const badgeColor = isLocal ? DEVTOOL_COLOR_SEMANTIC_SUCCESS : DEVTOOL_COLOR_SEMANTIC_WARNING;
3426
+ const badgeText = isLocal ? "● exec" : `→ ${hop.transport ?? "ext"}`;
3427
+ const runtimeTitle = [hop.runtime.perId, hop.runtime.insId].filter(Boolean).join(" · ") || undefined;
3428
+ return /* @__PURE__ */ jsxDEV14("div", {
3429
+ style: {
3430
+ background: DEVTOOL_SECTION_BACKGROUND,
3431
+ borderRadius: "4px",
3432
+ overflow: "hidden",
3433
+ display: "grid",
3434
+ gridTemplateColumns: "30% 1fr 30%",
3435
+ alignItems: "center",
3436
+ columnGap: "8px",
3437
+ borderBottom: isLast ? undefined : `1px solid ${DEVTOOL_LIST_BASE_BACKGROUND}`,
3438
+ padding: "4px 8px"
3439
+ },
3440
+ children: [
3441
+ /* @__PURE__ */ jsxDEV14("span", {
3442
+ style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
3443
+ children: [
3444
+ /* @__PURE__ */ jsxDEV14("span", {
3445
+ style: { color: DEVTOOL_COLOR_TEXT_FAINT, fontSize: "10px", width: "16px", textAlign: "right" },
3446
+ children: i + 1
3447
+ }, undefined, false, undefined, this),
3448
+ /* @__PURE__ */ jsxDEV14("span", {
3449
+ title: runtimeTitle,
2909
3450
  style: {
2910
- color: isUser ? "#e2e8f0" : "#50698b",
2911
- fontSize: "12px",
2912
- fontWeight: 500,
3451
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
3452
+ fontSize: "11px",
2913
3453
  overflow: "hidden",
2914
3454
  textOverflow: "ellipsis",
2915
- whiteSpace: "nowrap"
3455
+ whiteSpace: "nowrap",
3456
+ textAlign: "center"
2916
3457
  },
2917
- children: frame.fn ?? "(anonymous)"
3458
+ children: hop.runtime.envId
2918
3459
  }, undefined, false, undefined, this)
3460
+ ]
3461
+ }, undefined, true, undefined, this),
3462
+ /* @__PURE__ */ jsxDEV14("span", {
3463
+ style: { color: badgeColor, fontSize: "10px", whiteSpace: "nowrap" },
3464
+ children: badgeText
3465
+ }, undefined, false, undefined, this),
3466
+ /* @__PURE__ */ jsxDEV14("span", {
3467
+ style: {
3468
+ display: "flex",
3469
+ alignItems: "center",
3470
+ justifyContent: "space-between",
3471
+ paddingRight: "8px",
3472
+ overflow: "hidden"
3473
+ },
3474
+ children: [
3475
+ /* @__PURE__ */ jsxDEV14("span", {
3476
+ style: {
3477
+ color: DEVTOOL_COLOR_TEXT_MUTED,
3478
+ fontSize: "10px",
3479
+ whiteSpace: "nowrap",
3480
+ overflow: "hidden",
3481
+ textOverflow: "ellipsis"
3482
+ },
3483
+ children: hop.handlerClient != null ? `↳ ${hop.handlerClient.envId}` : ""
3484
+ }, undefined, false, undefined, this),
3485
+ /* @__PURE__ */ jsxDEV14("span", {
3486
+ style: { color: DEVTOOL_COLOR_TEXT_FAINT, fontSize: "10px", flexShrink: 0, marginLeft: "auto" },
3487
+ children: [
3488
+ "+",
3489
+ hop.time - startTime,
3490
+ "ms"
3491
+ ]
3492
+ }, undefined, true, undefined, this)
3493
+ ]
3494
+ }, undefined, true, undefined, this)
3495
+ ]
3496
+ }, `${hop.time}-${hop.runtime.envId}`, true, undefined, this);
3497
+ }),
3498
+ Array.from({ length: phantomCount }, (_, i) => `routing-phantom-${hopCount + i}`).map((key) => /* @__PURE__ */ jsxDEV14("div", {
3499
+ "aria-hidden": "true",
3500
+ style: {
3501
+ visibility: "hidden",
3502
+ background: DEVTOOL_SECTION_BACKGROUND,
3503
+ borderRadius: "4px",
3504
+ display: "grid",
3505
+ gridTemplateColumns: "30% 1fr 30%",
3506
+ alignItems: "center",
3507
+ columnGap: "8px",
3508
+ padding: "4px 8px"
3509
+ },
3510
+ children: [
3511
+ /* @__PURE__ */ jsxDEV14("span", {
3512
+ style: { display: "flex", flexDirection: "row", alignItems: "center", gap: "10px" },
3513
+ children: [
3514
+ /* @__PURE__ */ jsxDEV14("span", {
3515
+ style: { fontSize: "10px", width: "16px" },
3516
+ children: "0"
2919
3517
  }, undefined, false, undefined, this),
2920
- /* @__PURE__ */ jsxDEV11("div", {
2921
- style: { display: "flex", alignItems: "baseline", overflow: "hidden" },
2922
- children: [
2923
- folderPrefix !== "" && /* @__PURE__ */ jsxDEV11("span", {
2924
- style: {
2925
- color: isUser ? "#596b83" : "#2d3f53",
2926
- fontSize: "10px",
2927
- overflow: "hidden",
2928
- textOverflow: "ellipsis",
2929
- whiteSpace: "nowrap",
2930
- flexShrink: 1,
2931
- minWidth: 0
2932
- },
2933
- children: folderPrefix
2934
- }, undefined, false, undefined, this),
2935
- /* @__PURE__ */ jsxDEV11("span", {
2936
- style: {
2937
- color: isUser ? "#8a9ebb" : "#425979",
2938
- fontSize: "10px",
2939
- whiteSpace: "nowrap",
2940
- flexShrink: 0
2941
- },
2942
- children: bareFilename
2943
- }, undefined, false, undefined, this),
2944
- frame.line != null && /* @__PURE__ */ jsxDEV11("span", {
2945
- style: {
2946
- color: isUser ? "#4a7fa8" : "#2d4a63",
2947
- fontSize: "10px",
2948
- whiteSpace: "nowrap",
2949
- flexShrink: 0,
2950
- fontVariantNumeric: "tabular-nums"
2951
- },
2952
- children: [
2953
- ":",
2954
- frame.line
2955
- ]
2956
- }, undefined, true, undefined, this)
2957
- ]
2958
- }, undefined, true, undefined, this)
3518
+ /* @__PURE__ */ jsxDEV14("span", {
3519
+ style: { fontSize: "11px" },
3520
+ children: "placeholder"
3521
+ }, undefined, false, undefined, this)
2959
3522
  ]
2960
- }, undefined, true, undefined, this)
3523
+ }, undefined, true, undefined, this),
3524
+ /* @__PURE__ */ jsxDEV14("span", {
3525
+ style: { fontSize: "10px" },
3526
+ children: "placeholder"
3527
+ }, undefined, false, undefined, this),
3528
+ /* @__PURE__ */ jsxDEV14("span", {}, undefined, false, undefined, this)
2961
3529
  ]
2962
- }, frame.raw, true, undefined, this);
2963
- })
2964
- }, undefined, false, undefined, this)
3530
+ }, key, true, undefined, this))
3531
+ ]
3532
+ }, undefined, true, undefined, this)
2965
3533
  ]
2966
3534
  }, undefined, true, undefined, this);
2967
3535
  }
2968
3536
 
2969
- // src/devtools/browser/components/ActionDetailPanel.tsx
2970
- import { jsxDEV as jsxDEV12, Fragment as Fragment4 } from "react/jsx-dev-runtime";
3537
+ // src/devtools/browser/components/action_detail/ActionDetailPanel.tsx
3538
+ import { jsxDEV as jsxDEV15 } from "react/jsx-dev-runtime";
3539
+ var STATUS_BADGE_LABEL = {
3540
+ running: "RUNNING",
3541
+ success: "SUCCESS",
3542
+ "action-error": "ERROR",
3543
+ failed: "FAILED",
3544
+ aborted: "ABORTED"
3545
+ };
3546
+ var STATUS_BADGE_BG = {
3547
+ running: STATUS_COLOR.running,
3548
+ success: STATUS_COLOR.success,
3549
+ "action-error": DEVTOOL_COLOR_SEMANTIC_ERROR,
3550
+ failed: DEVTOOL_COLOR_SEMANTIC_ERROR,
3551
+ aborted: DEVTOOL_COLOR_SEMANTIC_METADATA
3552
+ };
3553
+ var STATUS_BADGE_TEXT_COLOR = {
3554
+ running: "#0f172a",
3555
+ success: "#0f172a",
3556
+ "action-error": "#ffffff",
3557
+ failed: "#ffffff",
3558
+ aborted: "#0f172a"
3559
+ };
2971
3560
  function DetailHeader({
2972
3561
  entry,
2973
3562
  isActive,
2974
3563
  onClick,
2975
- childExternalLabels
3564
+ childExternalRouteItems
2976
3565
  }) {
2977
3566
  const color = STATUS_COLOR[entry.status];
2978
- const symbol = STATUS_SYMBOL[entry.status];
3567
+ const StatusIconComponent = STATUS_ICON[entry.status];
2979
3568
  const timestamp = formatTimestamp(entry.startTime);
2980
- return /* @__PURE__ */ jsxDEV12("div", {
3569
+ return /* @__PURE__ */ jsxDEV15("div", {
2981
3570
  onClick: !isActive ? onClick : undefined,
2982
3571
  style: {
2983
- padding: "10px 12px",
2984
- background: isActive ? "#1e293b" : "#131f35",
2985
- borderBottom: "1px solid #0f172a",
2986
- borderLeft: isActive ? "2px solid #60a5fa" : "2px solid transparent",
3572
+ padding: "0.5em 1em",
3573
+ background: isActive ? DEVTOOL_SECTION_BACKGROUND : DEVTOOL_DETAIL_HEADER_BACKGROUND,
3574
+ borderBottom: `1px solid ${DEVTOOL_LIST_BASE_BACKGROUND}`,
3575
+ borderLeft: isActive ? `2px solid ${color}` : "2px solid transparent",
2987
3576
  flexShrink: 0,
3577
+ flexDirection: "row",
2988
3578
  display: "flex",
2989
3579
  alignItems: "flex-start",
2990
- gap: "10px",
3580
+ gap: "1em",
2991
3581
  cursor: isActive ? "default" : "pointer"
2992
3582
  },
2993
- children: [
2994
- /* @__PURE__ */ jsxDEV12("span", {
2995
- style: {
2996
- color,
2997
- fontSize: "15px",
2998
- flexShrink: 0,
2999
- paddingTop: "1px",
3000
- animation: entry.status === "running" ? "__nice-action-pulse 1.2s ease-in-out infinite" : undefined
3001
- },
3002
- children: symbol
3003
- }, undefined, false, undefined, this),
3004
- /* @__PURE__ */ jsxDEV12("div", {
3005
- style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "0.5em" },
3006
- children: [
3007
- /* @__PURE__ */ jsxDEV12("div", {
3008
- style: { display: "flex", alignItems: "center", minWidth: 0, gap: "0.4em" },
3009
- children: [
3010
- /* @__PURE__ */ jsxDEV12("span", {
3011
- style: { fontSize: "1.2em" },
3012
- children: "⚡"
3013
- }, undefined, false, undefined, this),
3014
- /* @__PURE__ */ jsxDEV12("span", {
3015
- style: {
3016
- color: "#f1f5f9",
3017
- fontSize: "1.2em",
3018
- fontWeight: "600",
3019
- overflow: "hidden",
3020
- textOverflow: "ellipsis",
3021
- whiteSpace: "nowrap",
3022
- flexShrink: 1,
3023
- minWidth: "24px"
3024
- },
3025
- children: entry.actionId
3026
- }, undefined, false, undefined, this),
3027
- /* @__PURE__ */ jsxDEV12(DomainChip, {
3028
- domain: entry.domain,
3029
- allDomains: entry.allDomains,
3030
- size: "md"
3583
+ children: /* @__PURE__ */ jsxDEV15("div", {
3584
+ style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "0.5em" },
3585
+ children: [
3586
+ /* @__PURE__ */ jsxDEV15("div", {
3587
+ style: { display: "flex", alignItems: "center", minWidth: 0, gap: "0.5em" },
3588
+ children: [
3589
+ /* @__PURE__ */ jsxDEV15("span", {
3590
+ style: {
3591
+ color,
3592
+ flexShrink: 0,
3593
+ display: "flex",
3594
+ alignItems: "center",
3595
+ animation: entry.status === "running" ? "__nice-action-pulse 1.2s ease-in-out infinite" : undefined
3596
+ },
3597
+ children: /* @__PURE__ */ jsxDEV15(StatusIconComponent, {
3598
+ size: 20,
3599
+ strokeWidth: 1.75
3031
3600
  }, undefined, false, undefined, this)
3032
- ]
3033
- }, undefined, true, undefined, this),
3034
- /* @__PURE__ */ jsxDEV12("div", {
3035
- style: {
3036
- display: "flex",
3037
- alignItems: "center",
3038
- justifyContent: "space-between",
3039
- gap: "8px"
3040
- },
3041
- children: [
3042
- /* @__PURE__ */ jsxDEV12("div", {
3043
- style: {
3044
- display: "flex",
3045
- alignItems: "center",
3046
- gap: "6px",
3047
- minWidth: 0,
3048
- overflow: "hidden"
3049
- },
3050
- children: [
3051
- /* @__PURE__ */ jsxDEV12(HandlerChips, {
3052
- entry,
3053
- size: "md"
3054
- }, undefined, false, undefined, this),
3055
- /* @__PURE__ */ jsxDEV12(ChildDispatchChips, {
3056
- labels: childExternalLabels,
3057
- size: "md"
3058
- }, undefined, false, undefined, this)
3059
- ]
3060
- }, undefined, true, undefined, this),
3061
- /* @__PURE__ */ jsxDEV12("div", {
3062
- style: { display: "flex", alignItems: "center", gap: "8px", flexShrink: 0 },
3063
- children: [
3064
- /* @__PURE__ */ jsxDEV12("span", {
3065
- style: { color: "#334155", fontSize: "10px", letterSpacing: "0.02em" },
3066
- children: timestamp
3067
- }, undefined, false, undefined, this),
3068
- /* @__PURE__ */ jsxDEV12("span", {
3069
- style: { color, fontSize: "12px", fontWeight: "500" },
3070
- children: /* @__PURE__ */ jsxDEV12(DurationDisplay, {
3071
- entry
3072
- }, undefined, false, undefined, this)
3601
+ }, undefined, false, undefined, this),
3602
+ /* @__PURE__ */ jsxDEV15("span", {
3603
+ style: {
3604
+ color: DEVTOOL_COLOR_TEXT_EMPHASIS,
3605
+ fontSize: "1.2em",
3606
+ fontWeight: "600",
3607
+ fontFamily: "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace",
3608
+ overflow: "hidden",
3609
+ textOverflow: "ellipsis",
3610
+ whiteSpace: "nowrap",
3611
+ flexShrink: 1,
3612
+ minWidth: "2.5em"
3613
+ },
3614
+ children: entry.actionId
3615
+ }, undefined, false, undefined, this),
3616
+ /* @__PURE__ */ jsxDEV15("span", {
3617
+ style: {
3618
+ flexShrink: 0,
3619
+ padding: "2px 9px",
3620
+ borderRadius: "999px",
3621
+ background: STATUS_BADGE_BG[entry.status],
3622
+ color: STATUS_BADGE_TEXT_COLOR[entry.status],
3623
+ fontSize: "9px",
3624
+ fontWeight: "700",
3625
+ letterSpacing: "0.1em",
3626
+ textTransform: "uppercase",
3627
+ fontFamily: "ui-sans-serif, system-ui, sans-serif"
3628
+ },
3629
+ children: STATUS_BADGE_LABEL[entry.status]
3630
+ }, undefined, false, undefined, this),
3631
+ /* @__PURE__ */ jsxDEV15(DomainChip, {
3632
+ domain: entry.domain,
3633
+ allDomains: entry.allDomains,
3634
+ size: "md" /* md */
3635
+ }, undefined, false, undefined, this)
3636
+ ]
3637
+ }, undefined, true, undefined, this),
3638
+ /* @__PURE__ */ jsxDEV15("div", {
3639
+ style: {
3640
+ display: "flex",
3641
+ alignItems: "center",
3642
+ justifyContent: "space-between",
3643
+ gap: "8px"
3644
+ },
3645
+ children: [
3646
+ /* @__PURE__ */ jsxDEV15("div", {
3647
+ style: {
3648
+ display: "flex",
3649
+ alignItems: "center",
3650
+ gap: "6px",
3651
+ minWidth: 0,
3652
+ overflow: "hidden"
3653
+ },
3654
+ children: [
3655
+ /* @__PURE__ */ jsxDEV15(HandlerChips, {
3656
+ entry,
3657
+ size: "md" /* md */
3658
+ }, undefined, false, undefined, this),
3659
+ /* @__PURE__ */ jsxDEV15(ChildDispatchChips, {
3660
+ childRouteItems: childExternalRouteItems,
3661
+ size: "md" /* md */
3662
+ }, undefined, false, undefined, this)
3663
+ ]
3664
+ }, undefined, true, undefined, this),
3665
+ /* @__PURE__ */ jsxDEV15("div", {
3666
+ style: { display: "flex", alignItems: "center", gap: "8px", flexShrink: 0 },
3667
+ children: [
3668
+ /* @__PURE__ */ jsxDEV15("span", {
3669
+ style: {
3670
+ color: DEVTOOL_COLOR_SEMANTIC_METADATA,
3671
+ fontSize: "10px",
3672
+ letterSpacing: "0.02em",
3673
+ fontFamily: "ui-sans-serif, system-ui, sans-serif"
3674
+ },
3675
+ children: timestamp
3676
+ }, undefined, false, undefined, this),
3677
+ /* @__PURE__ */ jsxDEV15("span", {
3678
+ style: { color, fontSize: "12px", fontWeight: "500" },
3679
+ children: /* @__PURE__ */ jsxDEV15(DurationDisplay, {
3680
+ entry
3073
3681
  }, undefined, false, undefined, this)
3074
- ]
3075
- }, undefined, true, undefined, this)
3076
- ]
3077
- }, undefined, true, undefined, this)
3078
- ]
3079
- }, undefined, true, undefined, this)
3080
- ]
3081
- }, undefined, true, undefined, this);
3682
+ }, undefined, false, undefined, this)
3683
+ ]
3684
+ }, undefined, true, undefined, this)
3685
+ ]
3686
+ }, undefined, true, undefined, this)
3687
+ ]
3688
+ }, undefined, true, undefined, this)
3689
+ }, undefined, false, undefined, this);
3082
3690
  }
3083
3691
  function ActionDetailPanel({
3084
3692
  entry,
@@ -3086,44 +3694,52 @@ function ActionDetailPanel({
3086
3694
  childEntries,
3087
3695
  onSelectEntry
3088
3696
  }) {
3089
- const [focusedChildCuid, setFocusedChildCuid] = useState5(null);
3697
+ const [focusedChildCuid, setFocusedChildCuid] = useState6(null);
3090
3698
  const focusedEntry = focusedChildCuid != null ? childEntries.find((e) => e.cuid === focusedChildCuid) ?? entry : entry;
3091
3699
  const maxRoutingHops = Math.max(entry.meta.routing.length, ...childEntries.map((e) => e.meta.routing.length), 0);
3092
- const childExternalLabels = useMemo(() => {
3700
+ const maxCallSiteFrames = Math.max(countUserFrames(entry.callSite), ...childEntries.map((e) => countUserFrames(e.callSite)), 0);
3701
+ const childExternalRouteItems = useMemo(() => {
3093
3702
  const seen = new Set;
3094
3703
  const result = [];
3095
3704
  for (const child of childEntries) {
3096
3705
  const firstHop = child.meta.routing[0];
3097
- if (firstHop == null)
3706
+ if (firstHop == null || firstHop.handlerType !== "external")
3098
3707
  continue;
3099
- const label = getExternalLabel(firstHop);
3100
- if (label == null || seen.has(label))
3708
+ const key = `${firstHop.handlerClient?.envId ?? ""}:${firstHop.transport ?? ""}`;
3709
+ if (seen.has(key))
3101
3710
  continue;
3102
- seen.add(label);
3103
- result.push(label);
3711
+ seen.add(key);
3712
+ result.push(firstHop);
3104
3713
  }
3105
3714
  return result;
3106
3715
  }, [childEntries]);
3107
3716
  const handleFocusChild = (cuid) => {
3108
3717
  setFocusedChildCuid((prev) => prev === cuid ? null : cuid);
3109
3718
  };
3110
- return /* @__PURE__ */ jsxDEV12("div", {
3719
+ return /* @__PURE__ */ jsxDEV15("div", {
3111
3720
  style: {
3112
3721
  flex: 1,
3113
3722
  display: "flex",
3114
3723
  flexDirection: "column",
3115
3724
  overflow: "hidden",
3116
3725
  minHeight: 0,
3117
- background: "#0f172a"
3726
+ background: DEVTOOL_DETAIL_BASE_BACKGROUND
3118
3727
  },
3119
3728
  children: [
3120
- /* @__PURE__ */ jsxDEV12(DetailHeader, {
3729
+ /* @__PURE__ */ jsxDEV15(DetailHeader, {
3121
3730
  entry,
3122
3731
  isActive: focusedChildCuid === null,
3123
3732
  onClick: () => setFocusedChildCuid(null),
3124
- childExternalLabels
3733
+ childExternalRouteItems
3125
3734
  }, undefined, false, undefined, this),
3126
- /* @__PURE__ */ jsxDEV12("div", {
3735
+ /* @__PURE__ */ jsxDEV15(CallStackSection, {
3736
+ parent,
3737
+ childEntries,
3738
+ focusedChildCuid,
3739
+ onFocusChild: handleFocusChild,
3740
+ onSelectParent: onSelectEntry
3741
+ }, undefined, false, undefined, this),
3742
+ /* @__PURE__ */ jsxDEV15("div", {
3127
3743
  style: {
3128
3744
  flex: 1,
3129
3745
  overflowY: "auto",
@@ -3134,284 +3750,516 @@ function ActionDetailPanel({
3134
3750
  gap: "8px"
3135
3751
  },
3136
3752
  children: [
3137
- /* @__PURE__ */ jsxDEV12(CallStackSection, {
3138
- parent,
3139
- childEntries,
3140
- focusedChildCuid,
3141
- onFocusChild: handleFocusChild,
3142
- onSelectParent: onSelectEntry
3753
+ focusedEntry.input !== undefined ? /* @__PURE__ */ jsxDEV15(DetailSection, {
3754
+ label: "Input",
3755
+ value: focusedEntry.input
3756
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV15(DetailSection, {
3757
+ label: "Input",
3758
+ value: "No input required or given"
3143
3759
  }, undefined, false, undefined, this),
3144
- /* @__PURE__ */ jsxDEV12(MetaSection, {
3760
+ focusedEntry.status === "success" && /* @__PURE__ */ jsxDEV15(DetailSection, {
3761
+ label: "Output",
3762
+ value: focusedEntry.output,
3763
+ color: DEVTOOL_COLOR_SEMANTIC_SUCCESS
3764
+ }, undefined, false, undefined, this),
3765
+ (focusedEntry.status === "action-error" || focusedEntry.status === "failed" || focusedEntry.status === "aborted") && /* @__PURE__ */ jsxDEV15(ActionErrorDisplay, {
3145
3766
  entry: focusedEntry
3146
3767
  }, undefined, false, undefined, this),
3147
- /* @__PURE__ */ jsxDEV12(RoutingSection, {
3148
- entry: focusedEntry,
3149
- minHopCount: maxRoutingHops
3768
+ focusedEntry.progressUpdates.length > 0 && /* @__PURE__ */ jsxDEV15(DetailSection, {
3769
+ label: `Progress (${focusedEntry.progressUpdates.length})`,
3770
+ value: focusedEntry.progressUpdates
3150
3771
  }, undefined, false, undefined, this),
3151
- /* @__PURE__ */ jsxDEV12(StackTraceSection, {
3772
+ /* @__PURE__ */ jsxDEV15(StackTraceSection, {
3152
3773
  label: "Dispatch Site",
3153
3774
  stack: focusedEntry.callSite,
3154
- color: "#94a3b8"
3155
- }, undefined, false, undefined, this),
3156
- /* @__PURE__ */ jsxDEV12(DetailSection, {
3157
- label: "Input",
3158
- value: focusedEntry.input
3775
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
3776
+ minFrameCount: maxCallSiteFrames
3159
3777
  }, undefined, false, undefined, this),
3160
- focusedEntry.status === "success" && /* @__PURE__ */ jsxDEV12(DetailSection, {
3161
- label: "Output",
3162
- value: focusedEntry.output,
3163
- color: "#4ade80"
3778
+ /* @__PURE__ */ jsxDEV15(RoutingSection, {
3779
+ entry: focusedEntry,
3780
+ minHopCount: maxRoutingHops
3164
3781
  }, undefined, false, undefined, this),
3165
- focusedEntry.status === "failed" && /* @__PURE__ */ jsxDEV12(Fragment4, {
3166
- children: [
3167
- /* @__PURE__ */ jsxDEV12(DetailSection, {
3168
- label: "Error",
3169
- value: focusedEntry.error,
3170
- color: "#f87171"
3171
- }, undefined, false, undefined, this),
3172
- /* @__PURE__ */ jsxDEV12(StackTraceSection, {
3173
- label: "Error Stack",
3174
- stack: focusedEntry.errorStack,
3175
- color: "#f87171"
3176
- }, undefined, false, undefined, this)
3177
- ]
3178
- }, undefined, true, undefined, this),
3179
- focusedEntry.status === "aborted" && /* @__PURE__ */ jsxDEV12(Fragment4, {
3782
+ /* @__PURE__ */ jsxDEV15(MetaSection, {
3783
+ entry: focusedEntry
3784
+ }, undefined, false, undefined, this)
3785
+ ]
3786
+ }, undefined, true, undefined, this)
3787
+ ]
3788
+ }, undefined, true, undefined, this);
3789
+ }
3790
+
3791
+ // src/devtools/browser/components/action_list/ActionEntryRow.tsx
3792
+ import { Box, CircleX as CircleX2, Variable } from "lucide-react";
3793
+ import { Fragment as Fragment7, useState as useState8 } from "react";
3794
+
3795
+ // src/devtools/browser/components/Icon.tsx
3796
+ import { useState as useState7 } from "react";
3797
+ import { jsxDEV as jsxDEV16, Fragment as Fragment6 } from "react/jsx-dev-runtime";
3798
+ var ICON_SIZE_PX = {
3799
+ ["sm" /* sm */]: 13,
3800
+ ["md" /* md */]: 16,
3801
+ ["lg" /* lg */]: 18
3802
+ };
3803
+ function Icon({
3804
+ icon: IconComponent,
3805
+ color,
3806
+ size = "md" /* md */,
3807
+ subtle = false,
3808
+ tooltip,
3809
+ style
3810
+ }) {
3811
+ const [anchor, setAnchor] = useState7(null);
3812
+ const hasTooltip = tooltip != null;
3813
+ const colorEntry = SEMANTIC_COLORS[color];
3814
+ const resolvedColor = subtle ? colorEntry.subtle?.color ?? colorEntry.color : colorEntry.color;
3815
+ return /* @__PURE__ */ jsxDEV16(Fragment6, {
3816
+ children: [
3817
+ /* @__PURE__ */ jsxDEV16("div", {
3818
+ onMouseEnter: hasTooltip ? (e) => setAnchor(e.currentTarget.getBoundingClientRect()) : undefined,
3819
+ onMouseLeave: hasTooltip ? () => setAnchor(null) : undefined,
3820
+ style: {
3821
+ borderRadius: "0.4em",
3822
+ height: `${1.65 * getSizeValue(size)}em`,
3823
+ width: `${1.65 * getSizeValue(size)}em`,
3824
+ display: "flex",
3825
+ alignItems: "center",
3826
+ justifyContent: "center",
3827
+ background: "rgba(0,0,0,0.4)",
3828
+ color: resolvedColor,
3829
+ flexShrink: 0,
3830
+ cursor: hasTooltip ? "default" : undefined,
3831
+ ...style
3832
+ },
3833
+ children: /* @__PURE__ */ jsxDEV16(IconComponent, {
3834
+ size: ICON_SIZE_PX[size],
3835
+ strokeWidth: 1.5
3836
+ }, undefined, false, undefined, this)
3837
+ }, undefined, false, undefined, this),
3838
+ anchor != null && hasTooltip && /* @__PURE__ */ jsxDEV16(Tooltip, {
3839
+ anchor,
3840
+ config: tooltip
3841
+ }, undefined, false, undefined, this)
3842
+ ]
3843
+ }, undefined, true, undefined, this);
3844
+ }
3845
+
3846
+ // src/devtools/browser/components/action_list/ActionEntryRow.tsx
3847
+ import { jsxDEV as jsxDEV17, Fragment as Fragment8 } from "react/jsx-dev-runtime";
3848
+ function getLatestChipColor(status) {
3849
+ if (status === "failed")
3850
+ return "failed" /* failed */;
3851
+ if (status === "action-error")
3852
+ return "action_error" /* action_error */;
3853
+ if (status === "aborted")
3854
+ return "aborted" /* aborted */;
3855
+ return "success" /* success */;
3856
+ }
3857
+ var JSON_TOKEN_RE2 = /("(?:\\.|[^"\\])*")(\s*:)?|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b|\bnull\b|\bundefined\b)|([{}[\],])/g;
3858
+ function renderColoredJson2(text) {
3859
+ const nodes = [];
3860
+ let last = 0;
3861
+ let i = 0;
3862
+ JSON_TOKEN_RE2.lastIndex = 0;
3863
+ for (let m = JSON_TOKEN_RE2.exec(text);m !== null; m = JSON_TOKEN_RE2.exec(text)) {
3864
+ if (m.index > last)
3865
+ nodes.push(text.slice(last, m.index));
3866
+ const [, str, colon, num, kw, punct] = m;
3867
+ if (str != null) {
3868
+ if (colon != null) {
3869
+ nodes.push(/* @__PURE__ */ jsxDEV17("span", {
3870
+ style: { color: DEVTOOL_JSON_KEY },
3871
+ children: str
3872
+ }, i++, false, undefined, this));
3873
+ nodes.push(/* @__PURE__ */ jsxDEV17("span", {
3874
+ style: { color: DEVTOOL_JSON_PUNCTUATION },
3875
+ children: colon
3876
+ }, i++, false, undefined, this));
3877
+ } else {
3878
+ nodes.push(/* @__PURE__ */ jsxDEV17("span", {
3879
+ style: { color: DEVTOOL_JSON_STRING },
3880
+ children: str
3881
+ }, i++, false, undefined, this));
3882
+ }
3883
+ } else if (num != null) {
3884
+ nodes.push(/* @__PURE__ */ jsxDEV17("span", {
3885
+ style: { color: DEVTOOL_JSON_NUMBER },
3886
+ children: num
3887
+ }, i++, false, undefined, this));
3888
+ } else if (kw != null) {
3889
+ nodes.push(/* @__PURE__ */ jsxDEV17("span", {
3890
+ style: { color: DEVTOOL_JSON_KEYWORD },
3891
+ children: kw
3892
+ }, i++, false, undefined, this));
3893
+ } else if (punct != null) {
3894
+ nodes.push(/* @__PURE__ */ jsxDEV17("span", {
3895
+ style: { color: DEVTOOL_JSON_PUNCTUATION },
3896
+ children: punct
3897
+ }, i++, false, undefined, this));
3898
+ }
3899
+ last = JSON_TOKEN_RE2.lastIndex;
3900
+ }
3901
+ if (last < text.length)
3902
+ nodes.push(text.slice(last));
3903
+ return nodes;
3904
+ }
3905
+ function stripOuterBraces(json) {
3906
+ const lines = json.split(`
3907
+ `);
3908
+ if (lines.length > 2 && lines[0] === "{" && lines[lines.length - 1] === "}") {
3909
+ return lines.slice(1, -1).map((l) => l.slice(2)).join(`
3910
+ `);
3911
+ }
3912
+ return json;
3913
+ }
3914
+ function IoTooltipContent({ value }) {
3915
+ const text = stripOuterBraces(safeStringify(value, 2));
3916
+ return /* @__PURE__ */ jsxDEV17("div", {
3917
+ style: {
3918
+ fontFamily: "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace",
3919
+ fontSize: "10px",
3920
+ whiteSpace: "pre-wrap",
3921
+ wordBreak: "break-all",
3922
+ lineHeight: "1.5",
3923
+ textAlign: "left"
3924
+ },
3925
+ children: renderColoredJson2(text)
3926
+ }, undefined, false, undefined, this);
3927
+ }
3928
+ function GroupDotTooltip({
3929
+ entry,
3930
+ index,
3931
+ total,
3932
+ refTime,
3933
+ dotColor,
3934
+ anchor
3935
+ }) {
3936
+ const symbol = STATUS_SYMBOL[entry.status];
3937
+ const deltaMs = refTime - entry.startTime;
3938
+ const relStr = index === 0 ? "latest run" : `−${formatRelativeAge(deltaMs)} from latest`;
3939
+ const durationStr = entry.endTime != null ? `${entry.endTime - entry.startTime}ms` : "running…";
3940
+ return /* @__PURE__ */ jsxDEV17(Tooltip, {
3941
+ anchor,
3942
+ config: {
3943
+ align: "center",
3944
+ maxWidth: 240,
3945
+ content: /* @__PURE__ */ jsxDEV17(Fragment8, {
3946
+ children: [
3947
+ /* @__PURE__ */ jsxDEV17("div", {
3948
+ style: { color: dotColor, marginBottom: "1px" },
3180
3949
  children: [
3181
- focusedEntry.abortReason != null && /* @__PURE__ */ jsxDEV12(DetailSection, {
3182
- label: "Abort Reason",
3183
- value: focusedEntry.abortReason,
3184
- color: "#9ca3af"
3185
- }, undefined, false, undefined, this),
3186
- /* @__PURE__ */ jsxDEV12(StackTraceSection, {
3187
- label: "Abort Stack",
3188
- stack: focusedEntry.errorStack,
3189
- color: "#9ca3af"
3190
- }, undefined, false, undefined, this)
3950
+ symbol,
3951
+ " run ",
3952
+ index + 1,
3953
+ " of ",
3954
+ total
3191
3955
  ]
3192
3956
  }, undefined, true, undefined, this),
3193
- focusedEntry.progressUpdates.length > 0 && /* @__PURE__ */ jsxDEV12(DetailSection, {
3194
- label: `Progress (${focusedEntry.progressUpdates.length})`,
3195
- value: focusedEntry.progressUpdates
3957
+ /* @__PURE__ */ jsxDEV17("div", {
3958
+ style: { color: DEVTOOL_COLOR_TEXT_SECONDARY },
3959
+ children: formatTimestamp(entry.startTime)
3960
+ }, undefined, false, undefined, this),
3961
+ /* @__PURE__ */ jsxDEV17("div", {
3962
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED },
3963
+ children: durationStr
3964
+ }, undefined, false, undefined, this),
3965
+ index > 0 && /* @__PURE__ */ jsxDEV17("div", {
3966
+ style: {
3967
+ color: DEVTOOL_COLOR_TEXT_MUTED,
3968
+ marginTop: "3px",
3969
+ paddingTop: "3px",
3970
+ borderTop: `1px solid ${DEVTOOL_SECTION_BACKGROUND}`
3971
+ },
3972
+ children: relStr
3196
3973
  }, undefined, false, undefined, this)
3197
3974
  ]
3198
3975
  }, undefined, true, undefined, this)
3976
+ }
3977
+ }, undefined, false, undefined, this);
3978
+ }
3979
+ function GroupDot({
3980
+ entry,
3981
+ index,
3982
+ total,
3983
+ refTime,
3984
+ isActive,
3985
+ onSelect
3986
+ }) {
3987
+ const [anchor, setAnchor] = useState8(null);
3988
+ const dotColor = STATUS_COLOR[entry.status];
3989
+ const hovered = anchor != null;
3990
+ return /* @__PURE__ */ jsxDEV17(Fragment8, {
3991
+ children: [
3992
+ /* @__PURE__ */ jsxDEV17("button", {
3993
+ "data-cuid": entry.cuid,
3994
+ onClick: (e) => {
3995
+ e.stopPropagation();
3996
+ onSelect();
3997
+ },
3998
+ onMouseEnter: (e) => setAnchor(e.currentTarget.getBoundingClientRect()),
3999
+ onMouseLeave: () => setAnchor(null),
4000
+ style: {
4001
+ width: "9px",
4002
+ height: "9px",
4003
+ borderRadius: "50%",
4004
+ border: isActive ? `2px solid ${dotColor}` : hovered ? `1px solid ${dotColor}99` : "1px solid transparent",
4005
+ background: isActive ? "transparent" : dotColor,
4006
+ cursor: "pointer",
4007
+ padding: 0,
4008
+ flexShrink: 0,
4009
+ opacity: isActive ? 1 : hovered ? 0.8 : 0.35,
4010
+ transform: hovered ? "scale(1.55)" : "scale(1)",
4011
+ transition: "transform 0.1s ease, opacity 0.1s ease, border-color 0.1s ease"
4012
+ }
4013
+ }, undefined, false, undefined, this),
4014
+ hovered && anchor != null && /* @__PURE__ */ jsxDEV17(GroupDotTooltip, {
4015
+ entry,
4016
+ index,
4017
+ total,
4018
+ refTime,
4019
+ dotColor,
4020
+ anchor
4021
+ }, undefined, false, undefined, this)
3199
4022
  ]
3200
4023
  }, undefined, true, undefined, this);
3201
4024
  }
3202
-
3203
- // src/devtools/browser/components/ActionEntryRow.tsx
3204
- import { jsxDEV as jsxDEV13 } from "react/jsx-dev-runtime";
3205
4025
  function ActionEntryRow({
3206
4026
  entry,
3207
4027
  isSelected,
3208
4028
  onClick,
3209
- groupCount,
3210
- isSubEntry = false,
3211
4029
  isLatest = false,
3212
4030
  latestTime,
3213
- childExternalLabels
4031
+ childEntries,
4032
+ breakReasons,
4033
+ groupEntries,
4034
+ selectedGroupCuid,
4035
+ onSelectGroupEntry
3214
4036
  }) {
3215
- const color = STATUS_COLOR[entry.status];
3216
- const symbol = STATUS_SYMBOL[entry.status];
4037
+ const statusSemantic = STATUS_THING[entry.status];
4038
+ const statusIcon = STATUS_ICON[entry.status];
3217
4039
  const timestamp = formatTimestamp(entry.startTime);
3218
- if (isSubEntry) {
3219
- return /* @__PURE__ */ jsxDEV13("div", {
3220
- "data-cuid": entry.cuid,
3221
- onClick,
3222
- style: {
3223
- display: "flex",
3224
- alignItems: "center",
3225
- gap: "1em",
3226
- padding: "4px 10px 4px 26px",
3227
- cursor: "pointer",
3228
- background: isSelected ? "#131f35" : "#070d18",
3229
- borderBottom: "1px solid #0f172a",
3230
- borderLeft: isSelected ? "2px solid #3b82f6" : "2px solid transparent"
3231
- },
3232
- children: [
3233
- /* @__PURE__ */ jsxDEV13("span", {
3234
- style: { color: "#334155", fontSize: "10px", flexShrink: 0 },
3235
- children: symbol
3236
- }, undefined, false, undefined, this),
3237
- /* @__PURE__ */ jsxDEV13(DomainChip, {
3238
- subtle: true,
3239
- domain: entry.domain,
3240
- allDomains: entry.allDomains,
3241
- size: "sm"
3242
- }, undefined, false, undefined, this),
3243
- /* @__PURE__ */ jsxDEV13("span", {
3244
- children: [
3245
- /* @__PURE__ */ jsxDEV13("span", {
3246
- style: { color: isSelected ? "#818cf8" : "#3730a3", opacity: 0.5, fontSize: "10px" },
3247
- children: "⚡"
3248
- }, undefined, false, undefined, this),
3249
- /* @__PURE__ */ jsxDEV13("span", {
3250
- style: {
3251
- flex: 1,
3252
- color: "#475569",
3253
- fontSize: "11px",
3254
- overflow: "hidden",
3255
- textOverflow: "ellipsis",
3256
- whiteSpace: "nowrap",
3257
- minWidth: 0
3258
- },
3259
- children: entry.actionId
3260
- }, undefined, false, undefined, this)
3261
- ]
3262
- }, undefined, true, undefined, this),
3263
- /* @__PURE__ */ jsxDEV13("span", {
3264
- style: { color: "#334155", fontSize: "11px", flexShrink: 0 },
3265
- children: /* @__PURE__ */ jsxDEV13(DurationDisplay, {
3266
- entry
3267
- }, undefined, false, undefined, this)
3268
- }, undefined, false, undefined, this)
3269
- ]
3270
- }, undefined, true, undefined, this);
3271
- }
3272
- return /* @__PURE__ */ jsxDEV13("div", {
4040
+ const hasGroup = groupEntries != null && groupEntries.length > 1;
4041
+ const hasBottomContent = childEntries != null && childEntries.length > 0 || (breakReasons?.some((r) => r !== "new input" && r !== "new output") ?? false) || entry.error != null || entry.abortReason != null;
4042
+ return /* @__PURE__ */ jsxDEV17("div", {
3273
4043
  "data-cuid": entry.cuid,
3274
4044
  onClick,
3275
4045
  style: {
4046
+ position: "relative",
3276
4047
  display: "flex",
3277
- alignItems: "flex-start",
3278
- gap: "8px",
3279
- padding: isSelected ? "6px 12px 6px 10px" : "6px 12px",
4048
+ flexDirection: "column",
4049
+ gap: "5px",
4050
+ padding: "10px 12px",
3280
4051
  cursor: "pointer",
3281
- background: isSelected ? "#131f35" : "transparent",
3282
- borderBottom: "1px solid #0f172a",
3283
- borderLeft: isSelected ? "2px solid #60a5fa" : "2px solid transparent"
4052
+ background: isSelected ? DEVTOOL_LIST_HEADER_SELECTED_BACKGROUND : "transparent",
4053
+ border: `1px solid ${DEVTOOL_PANEL_BORDER}`,
4054
+ borderLeft: isSelected ? `2px solid ${STATUS_COLOR[entry.status]}` : entry.status === "failed" || entry.status === "action-error" ? `2px solid ${STATUS_COLOR[entry.status]}55` : `2px solid ${DEVTOOL_PANEL_BORDER}`,
4055
+ borderRadius: "3px",
4056
+ margin: "2px 4px"
3284
4057
  },
3285
4058
  children: [
3286
- /* @__PURE__ */ jsxDEV13("span", {
3287
- style: {
3288
- flexShrink: 0,
3289
- minWidth: "3.5em",
3290
- display: "flex",
3291
- alignItems: "center",
3292
- justifyContent: "start"
3293
- },
3294
- children: isLatest ? /* @__PURE__ */ jsxDEV13(Chip, {
3295
- color: "#60a5fa",
3296
- borderColor: "#1e3a5f",
3297
- children: "latest"
3298
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV13(Chip, {
3299
- color: "#475569",
3300
- borderColor: "#1e293b",
3301
- children: [
3302
- "+",
3303
- latestTime != null ? formatRelativeAge(latestTime - entry.startTime) : "?"
3304
- ]
3305
- }, undefined, true, undefined, this)
3306
- }, undefined, false, undefined, this),
3307
- /* @__PURE__ */ jsxDEV13("span", {
4059
+ /* @__PURE__ */ jsxDEV17("div", {
3308
4060
  style: {
3309
- color,
3310
- fontSize: "10px",
3311
- flexShrink: 0,
3312
- paddingTop: "2px",
3313
- animation: entry.status === "running" ? "__nice-action-pulse 1.2s ease-in-out infinite" : undefined
3314
- },
3315
- children: symbol
4061
+ position: "absolute",
4062
+ left: "2em",
4063
+ top: 0,
4064
+ bottom: 0,
4065
+ width: "1px",
4066
+ background: `${DEVTOOL_COLOR_SEMANTIC_METADATA}28`,
4067
+ pointerEvents: "none",
4068
+ zIndex: 0
4069
+ }
3316
4070
  }, undefined, false, undefined, this),
3317
- /* @__PURE__ */ jsxDEV13("div", {
3318
- style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: "3px" },
4071
+ /* @__PURE__ */ jsxDEV17("div", {
4072
+ style: { display: "flex", alignItems: "center", gap: "8px" },
3319
4073
  children: [
3320
- /* @__PURE__ */ jsxDEV13("div", {
4074
+ /* @__PURE__ */ jsxDEV17("div", {
3321
4075
  style: {
4076
+ position: "relative",
4077
+ zIndex: 1,
4078
+ flexShrink: 0,
4079
+ minWidth: "4em",
3322
4080
  display: "flex",
3323
4081
  alignItems: "center",
3324
- minWidth: 0,
3325
- overflow: "hidden",
3326
- gap: "0.3em"
4082
+ justifyContent: "flex-start"
3327
4083
  },
4084
+ children: isLatest ? /* @__PURE__ */ jsxDEV17(Chip, {
4085
+ color: getLatestChipColor(entry.status),
4086
+ children: "latest"
4087
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17(Chip, {
4088
+ size: "sm" /* sm */,
4089
+ color: getLatestChipColor(entry.status),
4090
+ children: [
4091
+ "+",
4092
+ latestTime != null ? formatRelativeAge(latestTime - entry.startTime) : "?"
4093
+ ]
4094
+ }, undefined, true, undefined, this)
4095
+ }, undefined, false, undefined, this),
4096
+ /* @__PURE__ */ jsxDEV17("div", {
4097
+ style: { flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: "0.5em" },
3328
4098
  children: [
3329
- /* @__PURE__ */ jsxDEV13(DomainChip, {
3330
- domain: entry.domain,
3331
- allDomains: entry.allDomains,
3332
- size: "md"
3333
- }, undefined, false, undefined, this),
3334
- /* @__PURE__ */ jsxDEV13("span", {
3335
- style: { color: isSelected ? "#818cf8" : "#3730a3", fontSize: "1em" },
3336
- children: "⚡"
3337
- }, undefined, false, undefined, this),
3338
- /* @__PURE__ */ jsxDEV13("span", {
4099
+ /* @__PURE__ */ jsxDEV17("span", {
3339
4100
  style: {
3340
- color: "#cbd5e1",
3341
- fontSize: "11px",
4101
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
4102
+ fontSize: "1.1em",
4103
+ fontFamily: "ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace",
3342
4104
  overflow: "hidden",
3343
4105
  textOverflow: "ellipsis",
3344
4106
  whiteSpace: "nowrap",
3345
4107
  flexShrink: 1,
3346
- minWidth: "24px"
4108
+ minWidth: "3em"
3347
4109
  },
3348
4110
  children: entry.actionId
4111
+ }, undefined, false, undefined, this),
4112
+ /* @__PURE__ */ jsxDEV17(DomainChip, {
4113
+ domain: entry.domain,
4114
+ allDomains: entry.allDomains
4115
+ }, undefined, false, undefined, this),
4116
+ /* @__PURE__ */ jsxDEV17(Icon, {
4117
+ icon: Variable,
4118
+ color: entry.input !== undefined ? "io_input" /* io_input */ : "default" /* default */,
4119
+ subtle: entry.input === undefined,
4120
+ tooltip: {
4121
+ content: entry.input !== undefined ? /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4122
+ value: entry.input
4123
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17("span", {
4124
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4125
+ children: "No input required or given"
4126
+ }, undefined, false, undefined, this),
4127
+ title: "Input"
4128
+ }
4129
+ }, undefined, false, undefined, this),
4130
+ /* @__PURE__ */ jsxDEV17(HandlerChips, {
4131
+ entry,
4132
+ size: "sm" /* sm */
4133
+ }, undefined, false, undefined, this),
4134
+ entry.status === "success" && entry.output !== undefined && /* @__PURE__ */ jsxDEV17(Icon, {
4135
+ icon: Box,
4136
+ color: "io_output" /* io_output */,
4137
+ tooltip: { content: /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4138
+ value: entry.output
4139
+ }, undefined, false, undefined, this), title: "Output" }
4140
+ }, undefined, false, undefined, this),
4141
+ (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV17(Icon, {
4142
+ icon: CircleX2,
4143
+ color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4144
+ tooltip: {
4145
+ content: /* @__PURE__ */ jsxDEV17(ActionErrorDisplay, {
4146
+ entry,
4147
+ compact: true
4148
+ }, undefined, false, undefined, this),
4149
+ title: entry.status === "aborted" ? "Aborted" : "Error",
4150
+ maxWidth: 340
4151
+ }
4152
+ }, undefined, false, undefined, this),
4153
+ /* @__PURE__ */ jsxDEV17("div", {
4154
+ style: { flex: 1 }
4155
+ }, undefined, false, undefined, this),
4156
+ /* @__PURE__ */ jsxDEV17("span", {
4157
+ style: {
4158
+ color: DEVTOOL_COLOR_SEMANTIC_METADATA,
4159
+ fontSize: "10px",
4160
+ letterSpacing: "0.02em",
4161
+ fontFamily: "ui-sans-serif, system-ui, sans-serif",
4162
+ flexShrink: 0
4163
+ },
4164
+ children: timestamp
4165
+ }, undefined, false, undefined, this),
4166
+ /* @__PURE__ */ jsxDEV17("span", {
4167
+ style: { color: DEVTOOL_COLOR_SEMANTIC_WARNING, fontSize: "11px", flexShrink: 0 },
4168
+ children: /* @__PURE__ */ jsxDEV17(DurationDisplay, {
4169
+ entry
4170
+ }, undefined, false, undefined, this)
3349
4171
  }, undefined, false, undefined, this)
3350
4172
  ]
3351
- }, undefined, true, undefined, this),
3352
- /* @__PURE__ */ jsxDEV13("div", {
3353
- style: {
3354
- display: "flex",
3355
- alignItems: "center",
3356
- justifyContent: "space-between",
3357
- gap: "6px"
3358
- },
4173
+ }, undefined, true, undefined, this)
4174
+ ]
4175
+ }, undefined, true, undefined, this),
4176
+ hasBottomContent && /* @__PURE__ */ jsxDEV17("div", {
4177
+ style: {
4178
+ display: "flex",
4179
+ flexWrap: "wrap",
4180
+ alignItems: "center",
4181
+ gap: "4px",
4182
+ paddingLeft: "4.5em"
4183
+ },
4184
+ children: [
4185
+ childEntries?.map((child) => /* @__PURE__ */ jsxDEV17(Fragment7, {
3359
4186
  children: [
3360
- /* @__PURE__ */ jsxDEV13("div", {
3361
- style: {
3362
- display: "flex",
3363
- flexDirection: "row",
3364
- alignItems: "center",
3365
- gap: "5px",
3366
- minWidth: 0,
3367
- overflow: "hidden"
3368
- },
3369
- children: [
3370
- /* @__PURE__ */ jsxDEV13(HandlerChips, {
3371
- entry,
3372
- size: "sm"
4187
+ /* @__PURE__ */ jsxDEV17(Icon, {
4188
+ icon: Variable,
4189
+ color: "io_input" /* io_input */,
4190
+ subtle: true,
4191
+ tooltip: {
4192
+ content: child.input !== undefined ? /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4193
+ value: child.input
4194
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17("span", {
4195
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4196
+ children: "No input required or given"
3373
4197
  }, undefined, false, undefined, this),
3374
- /* @__PURE__ */ jsxDEV13(ChildDispatchChips, {
3375
- labels: childExternalLabels,
3376
- size: "sm"
3377
- }, undefined, false, undefined, this)
3378
- ]
3379
- }, undefined, true, undefined, this),
3380
- /* @__PURE__ */ jsxDEV13("div", {
3381
- style: { display: "flex", alignItems: "center", gap: "6px", flexShrink: 0 },
3382
- children: [
3383
- groupCount != null && /* @__PURE__ */ jsxDEV13(Chip, {
3384
- color: "#3b82f6",
3385
- borderColor: "#1e3a5f",
3386
- fontSize: "9px",
3387
- padding: "1px 5px",
3388
- children: [
3389
- "x",
3390
- groupCount
3391
- ]
3392
- }, undefined, true, undefined, this),
3393
- /* @__PURE__ */ jsxDEV13("span", {
3394
- style: { color: "#1e3a5f", fontSize: "10px", letterSpacing: "0.02em" },
3395
- children: timestamp
4198
+ title: `Input · ${child.actionId}`
4199
+ }
4200
+ }, undefined, false, undefined, this),
4201
+ /* @__PURE__ */ jsxDEV17(HandlerChips, {
4202
+ entry: child,
4203
+ size: "sm" /* sm */,
4204
+ subtle: true
4205
+ }, undefined, false, undefined, this),
4206
+ child.status === "success" && child.output !== undefined && /* @__PURE__ */ jsxDEV17(Icon, {
4207
+ icon: Box,
4208
+ color: "io_output" /* io_output */,
4209
+ subtle: true,
4210
+ tooltip: {
4211
+ content: /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4212
+ value: child.output
3396
4213
  }, undefined, false, undefined, this),
3397
- /* @__PURE__ */ jsxDEV13("span", {
3398
- style: { color: "#475569", fontSize: "11px" },
3399
- children: /* @__PURE__ */ jsxDEV13(DurationDisplay, {
3400
- entry
3401
- }, undefined, false, undefined, this)
3402
- }, undefined, false, undefined, this)
3403
- ]
3404
- }, undefined, true, undefined, this)
4214
+ title: `Output · ${child.actionId}`
4215
+ }
4216
+ }, undefined, false, undefined, this)
3405
4217
  ]
3406
- }, undefined, true, undefined, this)
4218
+ }, child.actionId, true, undefined, this)),
4219
+ breakReasons?.filter((r) => r !== "new input" && r !== "new output").map((reason) => /* @__PURE__ */ jsxDEV17(Chip, {
4220
+ color: "default" /* default */,
4221
+ subtle: true,
4222
+ children: reason
4223
+ }, reason, false, undefined, this)),
4224
+ (childEntries?.length ?? 0) > 0 && (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV17(Icon, {
4225
+ icon: CircleX2,
4226
+ color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4227
+ subtle: true,
4228
+ tooltip: {
4229
+ content: /* @__PURE__ */ jsxDEV17(ActionErrorDisplay, {
4230
+ entry,
4231
+ compact: true
4232
+ }, undefined, false, undefined, this),
4233
+ title: entry.status === "aborted" ? "Aborted" : "Error",
4234
+ maxWidth: 340
4235
+ }
4236
+ }, undefined, false, undefined, this)
3407
4237
  ]
3408
- }, undefined, true, undefined, this)
4238
+ }, undefined, true, undefined, this),
4239
+ hasGroup && /* @__PURE__ */ jsxDEV17("div", {
4240
+ style: {
4241
+ display: "flex",
4242
+ flexWrap: "wrap",
4243
+ alignItems: "center",
4244
+ gap: "5px",
4245
+ paddingLeft: "4.6em",
4246
+ paddingBottom: "2px"
4247
+ },
4248
+ children: groupEntries.map((e, i) => /* @__PURE__ */ jsxDEV17(GroupDot, {
4249
+ entry: e,
4250
+ index: i,
4251
+ total: groupEntries.length,
4252
+ refTime: groupEntries[0].startTime,
4253
+ isActive: selectedGroupCuid === e.cuid,
4254
+ onSelect: () => onSelectGroupEntry?.(e.cuid)
4255
+ }, e.cuid, false, undefined, this))
4256
+ }, undefined, false, undefined, this)
3409
4257
  ]
3410
4258
  }, undefined, true, undefined, this);
3411
4259
  }
3412
4260
 
3413
4261
  // src/devtools/browser/components/PanelChrome.tsx
3414
- import { jsxDEV as jsxDEV14 } from "react/jsx-dev-runtime";
4262
+ import { jsxDEV as jsxDEV18 } from "react/jsx-dev-runtime";
3415
4263
  var DOCKED_SIZE_MIN = 140;
3416
4264
  var POSITION_GRID = [
3417
4265
  ["top-left", "dock-top", "top-right"],
@@ -3435,46 +4283,46 @@ function PanelHeader({
3435
4283
  onClose,
3436
4284
  onClear
3437
4285
  }) {
3438
- return /* @__PURE__ */ jsxDEV14("div", {
4286
+ return /* @__PURE__ */ jsxDEV18("div", {
3439
4287
  style: {
3440
4288
  display: "flex",
3441
4289
  alignItems: "center",
3442
4290
  justifyContent: "space-between",
3443
4291
  padding: "8px 12px",
3444
- background: "#1e293b",
3445
- borderBottom: "1px solid #0f172a",
4292
+ background: DEVTOOL_SECTION_BACKGROUND,
4293
+ borderBottom: `1px solid ${DEVTOOL_LIST_BASE_BACKGROUND}`,
3446
4294
  flexShrink: 0
3447
4295
  },
3448
4296
  children: [
3449
- /* @__PURE__ */ jsxDEV14("span", {
3450
- style: { color: "#60a5fa", fontWeight: "bold", fontSize: "11px" },
4297
+ /* @__PURE__ */ jsxDEV18("span", {
4298
+ style: { color: DEVTOOL_COLOR_SEMANTIC_SYSTEM, fontWeight: "bold", fontSize: "11px" },
3451
4299
  children: "⚡ nice-action devtools"
3452
4300
  }, undefined, false, undefined, this),
3453
- /* @__PURE__ */ jsxDEV14("div", {
4301
+ /* @__PURE__ */ jsxDEV18("div", {
3454
4302
  style: { display: "flex", gap: "10px", alignItems: "center" },
3455
4303
  children: [
3456
- /* @__PURE__ */ jsxDEV14(PositionPicker, {
4304
+ /* @__PURE__ */ jsxDEV18(PositionPicker, {
3457
4305
  position,
3458
4306
  onChange: onPositionChange
3459
4307
  }, undefined, false, undefined, this),
3460
- onClear != null && /* @__PURE__ */ jsxDEV14("button", {
4308
+ onClear != null && /* @__PURE__ */ jsxDEV18("button", {
3461
4309
  onClick: onClear,
3462
4310
  style: {
3463
4311
  background: "none",
3464
4312
  border: "none",
3465
- color: "#475569",
4313
+ color: DEVTOOL_COLOR_TEXT_MUTED,
3466
4314
  cursor: "pointer",
3467
4315
  fontSize: "11px",
3468
4316
  padding: "0"
3469
4317
  },
3470
4318
  children: "clear"
3471
4319
  }, undefined, false, undefined, this),
3472
- /* @__PURE__ */ jsxDEV14("button", {
4320
+ /* @__PURE__ */ jsxDEV18("button", {
3473
4321
  onClick: onClose,
3474
4322
  style: {
3475
4323
  background: "none",
3476
4324
  border: "none",
3477
- color: "#475569",
4325
+ color: DEVTOOL_COLOR_TEXT_MUTED,
3478
4326
  cursor: "pointer",
3479
4327
  fontSize: "16px",
3480
4328
  padding: "0",
@@ -3491,18 +4339,18 @@ function PositionPicker({
3491
4339
  position,
3492
4340
  onChange
3493
4341
  }) {
3494
- return /* @__PURE__ */ jsxDEV14("div", {
4342
+ return /* @__PURE__ */ jsxDEV18("div", {
3495
4343
  title: "Move / dock panel",
3496
4344
  style: { display: "grid", gridTemplateColumns: "repeat(3, 9px)", gap: "2px", padding: "2px" },
3497
4345
  children: POSITION_GRID.flat().map((pos) => {
3498
4346
  if (pos == null)
3499
- return /* @__PURE__ */ jsxDEV14("div", {
4347
+ return /* @__PURE__ */ jsxDEV18("div", {
3500
4348
  style: { width: "9px", height: "9px" }
3501
4349
  }, "center-empty", false, undefined, this);
3502
4350
  const isDock = pos.startsWith("dock-");
3503
4351
  const isTopBottom = pos === "dock-top" || pos === "dock-bottom";
3504
4352
  const isActive = pos === position;
3505
- return /* @__PURE__ */ jsxDEV14("div", {
4353
+ return /* @__PURE__ */ jsxDEV18("div", {
3506
4354
  title: pos,
3507
4355
  onClick: () => onChange(pos),
3508
4356
  style: {
@@ -3513,12 +4361,12 @@ function PositionPicker({
3513
4361
  justifyContent: "center",
3514
4362
  cursor: "pointer"
3515
4363
  },
3516
- children: /* @__PURE__ */ jsxDEV14("div", {
4364
+ children: /* @__PURE__ */ jsxDEV18("div", {
3517
4365
  style: {
3518
4366
  width: isDock ? isTopBottom ? "9px" : "3px" : "7px",
3519
4367
  height: isDock ? isTopBottom ? "3px" : "9px" : "7px",
3520
4368
  borderRadius: isDock ? "1px" : "50%",
3521
- background: isActive ? "#60a5fa" : "#334155"
4369
+ background: isActive ? DEVTOOL_COLOR_SEMANTIC_SYSTEM : DEVTOOL_COLOR_TEXT_FAINT
3522
4370
  }
3523
4371
  }, undefined, false, undefined, this)
3524
4372
  }, pos, false, undefined, this);
@@ -3549,7 +4397,7 @@ function ResizeHandle({
3549
4397
  window.addEventListener("mouseup", onUp);
3550
4398
  };
3551
4399
  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" };
3552
- return /* @__PURE__ */ jsxDEV14("div", {
4400
+ return /* @__PURE__ */ jsxDEV18("div", {
3553
4401
  onMouseDown,
3554
4402
  style: {
3555
4403
  position: "absolute",
@@ -3561,7 +4409,7 @@ function ResizeHandle({
3561
4409
  }
3562
4410
 
3563
4411
  // src/devtools/browser/NiceActionDevtools.tsx
3564
- import { jsxDEV as jsxDEV15, Fragment as Fragment5 } from "react/jsx-dev-runtime";
4412
+ import { jsxDEV as jsxDEV19, Fragment as Fragment9 } from "react/jsx-dev-runtime";
3565
4413
  if (typeof document !== "undefined" && !document.getElementById("__nice-action-devtools-styles")) {
3566
4414
  const style = document.createElement("style");
3567
4415
  style.id = "__nice-action-devtools-styles";
@@ -3576,6 +4424,23 @@ if (typeof document !== "undefined" && !document.getElementById("__nice-action-d
3576
4424
  85% { opacity: 1; }
3577
4425
  100% { transform: translateX(200%); opacity: 0; }
3578
4426
  }
4427
+ #__nice-action-devtools-panel ::-webkit-scrollbar {
4428
+ width: 4px;
4429
+ height: 4px;
4430
+ }
4431
+ #__nice-action-devtools-panel ::-webkit-scrollbar-track {
4432
+ background: transparent;
4433
+ }
4434
+ #__nice-action-devtools-panel ::-webkit-scrollbar-thumb {
4435
+ background: #334155;
4436
+ border-radius: 2px;
4437
+ }
4438
+ #__nice-action-devtools-panel ::-webkit-scrollbar-thumb:hover {
4439
+ background: #475569;
4440
+ }
4441
+ #__nice-action-devtools-panel ::-webkit-scrollbar-corner {
4442
+ background: transparent;
4443
+ }
3579
4444
  `;
3580
4445
  document.head?.appendChild(style);
3581
4446
  }
@@ -3619,7 +4484,9 @@ function canGroupWith(a, b) {
3619
4484
  const handlerA = getHandlerKey(a);
3620
4485
  const handlerB = getHandlerKey(b);
3621
4486
  const handlerConflict = handlerA !== "none" && handlerB !== "none" && handlerA !== handlerB;
3622
- return a.actionId === b.actionId && a.domain === b.domain && a.status === b.status && !handlerConflict && safeStringify(a.input, 0) === safeStringify(b.input, 0);
4487
+ const inputMatch = a.inputHash != null && b.inputHash != null ? a.inputHash === b.inputHash : safeStringify(a.input, 0) === safeStringify(b.input, 0);
4488
+ const outputMatch = a.outputHash != null && b.outputHash != null ? a.outputHash === b.outputHash : true;
4489
+ return a.actionId === b.actionId && a.domain === b.domain && a.status === b.status && !handlerConflict && inputMatch && outputMatch;
3623
4490
  }
3624
4491
  function groupEntries(entries) {
3625
4492
  const groups = [];
@@ -3635,7 +4502,7 @@ function groupEntries(entries) {
3635
4502
  }
3636
4503
  function NiceActionDevtools(props) {
3637
4504
  if (false) {}
3638
- return /* @__PURE__ */ jsxDEV15(NiceActionDevtools_Panel, {
4505
+ return /* @__PURE__ */ jsxDEV19(NiceActionDevtools_Panel, {
3639
4506
  ...props
3640
4507
  }, undefined, false, undefined, this);
3641
4508
  }
@@ -3644,34 +4511,25 @@ function NiceActionDevtools_Panel({
3644
4511
  position: defaultPosition = "bottom-right",
3645
4512
  initialOpen = false
3646
4513
  }) {
3647
- const [prefs, setPrefsRaw] = useState6(() => readPrefs(defaultPosition, initialOpen));
3648
- const [entries, setEntries] = useState6([]);
3649
- const [selectedCuid, setSelectedCuid] = useState6(null);
3650
- const [expandedGroupCuids, setExpandedGroupCuids] = useState6(new Set);
3651
- const [domainTooltip, setDomainTooltip] = useState6(null);
3652
- const showDomainTooltip = useCallback((rect, allDomains) => setDomainTooltip({ rect, allDomains }), []);
3653
- const hideDomainTooltip = useCallback(() => setDomainTooltip(null), []);
3654
- const domainTooltipCtx = useMemo2(() => ({ show: showDomainTooltip, hide: hideDomainTooltip }), [showDomainTooltip, hideDomainTooltip]);
4514
+ const [prefs, setPrefsRaw] = useState9(() => readPrefs(defaultPosition, initialOpen));
4515
+ const [entries, setEntries] = useState9([]);
4516
+ const [selectedCuid, setSelectedCuid] = useState9(null);
3655
4517
  useEffect3(() => core.subscribe(setEntries), [core]);
3656
4518
  const groups = useMemo2(() => {
3657
4519
  const byCuid = new Map(entries.map((e) => [e.cuid, e]));
3658
4520
  const roots = entries.filter((e) => e.status !== "running" && (e.parentCuid == null || !byCuid.has(e.parentCuid)));
3659
4521
  return groupEntries(roots);
3660
4522
  }, [entries]);
3661
- const childExternalLabelsMap = useMemo2(() => {
4523
+ const childEntriesMap = useMemo2(() => {
3662
4524
  const map = new Map;
3663
4525
  for (const entry of entries) {
3664
4526
  if (entry.parentCuid == null)
3665
4527
  continue;
3666
- const firstHop = entry.meta.routing[0];
3667
- if (firstHop == null)
3668
- continue;
3669
- const label = getExternalLabel(firstHop);
3670
- if (label == null)
3671
- continue;
3672
4528
  const existing = map.get(entry.parentCuid) ?? [];
3673
- if (!existing.includes(label))
3674
- map.set(entry.parentCuid, [...existing, label]);
4529
+ map.set(entry.parentCuid, [...existing, entry]);
4530
+ }
4531
+ for (const arr of map.values()) {
4532
+ arr.sort((a, b) => a.startTime - b.startTime);
3675
4533
  }
3676
4534
  return map;
3677
4535
  }, [entries]);
@@ -3679,18 +4537,12 @@ function NiceActionDevtools_Panel({
3679
4537
  const repCuid = group.representative.cuid;
3680
4538
  const allInGroup = [group.representative, ...group.rest];
3681
4539
  const selectedInGroup = allInGroup.find((e) => e.cuid === selectedCuid) ?? null;
3682
- setExpandedGroupCuids(new Set);
3683
4540
  if (selectedInGroup != null && selectedCuid !== repCuid) {
3684
4541
  setSelectedCuid(repCuid);
3685
4542
  } else {
3686
4543
  setSelectedCuid(selectedCuid === repCuid ? null : repCuid);
3687
4544
  }
3688
4545
  };
3689
- const handleExpandGroup = (group) => {
3690
- const oldestCuid = (group.rest[group.rest.length - 1] ?? group.representative).cuid;
3691
- setSelectedCuid(null);
3692
- setExpandedGroupCuids(new Set([oldestCuid]));
3693
- };
3694
4546
  const setPrefs = (update) => {
3695
4547
  setPrefsRaw((prev) => {
3696
4548
  const next = { ...prev, ...update };
@@ -3743,14 +4595,14 @@ function NiceActionDevtools_Panel({
3743
4595
  fontSize: "12px"
3744
4596
  };
3745
4597
  if (!isOpen) {
3746
- return /* @__PURE__ */ jsxDEV15("button", {
4598
+ return /* @__PURE__ */ jsxDEV19("button", {
3747
4599
  onClick: () => setPrefs({ isOpen: true }),
3748
4600
  style: {
3749
4601
  ...baseStyle,
3750
4602
  ...closedAnchor,
3751
- background: "#1e293b",
3752
- color: "#94a3b8",
3753
- border: "1px solid #334155",
4603
+ background: DEVTOOL_SECTION_BACKGROUND,
4604
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
4605
+ border: `1px solid ${DEVTOOL_COLOR_TEXT_FAINT}`,
3754
4606
  borderRadius: "6px",
3755
4607
  padding: "5px 10px",
3756
4608
  cursor: "pointer",
@@ -3758,10 +4610,10 @@ function NiceActionDevtools_Panel({
3758
4610
  },
3759
4611
  children: [
3760
4612
  "⚡ actions",
3761
- runningCount > 0 && /* @__PURE__ */ jsxDEV15("span", {
4613
+ runningCount > 0 && /* @__PURE__ */ jsxDEV19("span", {
3762
4614
  style: {
3763
4615
  marginLeft: "6px",
3764
- color: "#60a5fa",
4616
+ color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
3765
4617
  animation: "__nice-action-pulse 1.2s ease-in-out infinite"
3766
4618
  },
3767
4619
  children: [
@@ -3774,9 +4626,9 @@ function NiceActionDevtools_Panel({
3774
4626
  }
3775
4627
  const panelStyle = dockSide != null ? {
3776
4628
  ...baseStyle,
3777
- background: "#0f172a",
3778
- border: "1px solid #1e293b",
3779
- color: "#e2e8f0",
4629
+ background: DEVTOOL_LIST_BASE_BACKGROUND,
4630
+ border: `1px solid ${DEVTOOL_PANEL_BORDER}`,
4631
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
3780
4632
  display: "flex",
3781
4633
  flexDirection: "column",
3782
4634
  boxShadow: "0 -4px 24px rgba(0,0,0,0.4)",
@@ -3811,10 +4663,10 @@ function NiceActionDevtools_Panel({
3811
4663
  ...closedAnchor,
3812
4664
  width: "460px",
3813
4665
  maxHeight: "560px",
3814
- background: "#0f172a",
3815
- border: "1px solid #1e293b",
4666
+ background: DEVTOOL_LIST_BASE_BACKGROUND,
4667
+ border: `1px solid ${DEVTOOL_PANEL_BORDER}`,
3816
4668
  borderRadius: "10px",
3817
- color: "#e2e8f0",
4669
+ color: DEVTOOL_COLOR_TEXT_SECONDARY,
3818
4670
  display: "flex",
3819
4671
  flexDirection: "column",
3820
4672
  boxShadow: "0 25px 50px rgba(0,0,0,0.5)",
@@ -3825,179 +4677,210 @@ function NiceActionDevtools_Panel({
3825
4677
  const virtualListProps = {
3826
4678
  groups,
3827
4679
  selectedCuid,
3828
- expandedGroupCuids,
3829
4680
  onGroupClick: handleGroupRowClick,
3830
4681
  onSubClick: (cuid, isSelected) => {
3831
4682
  setSelectedCuid(isSelected ? null : cuid);
3832
- setExpandedGroupCuids(new Set);
3833
4683
  },
3834
- onExpandGroup: handleExpandGroup,
3835
- childExternalLabelsMap
4684
+ childEntriesMap
3836
4685
  };
3837
- return /* @__PURE__ */ jsxDEV15(DomainTooltipCtx.Provider, {
3838
- value: domainTooltipCtx,
3839
- children: /* @__PURE__ */ jsxDEV15("div", {
3840
- style: panelStyle,
3841
- children: [
3842
- domainTooltip != null && /* @__PURE__ */ jsxDEV15(DomainHierarchyTooltip, {
3843
- anchor: domainTooltip.rect,
3844
- allDomains: domainTooltip.allDomains
3845
- }, undefined, false, undefined, this),
3846
- dockSide != null && /* @__PURE__ */ jsxDEV15(ResizeHandle, {
3847
- dockSide,
3848
- dockedSize,
3849
- onChange: (size) => setPrefs(isHorizDock ? { dockedHeight: size } : { dockedWidth: size })
3850
- }, undefined, false, undefined, this),
3851
- /* @__PURE__ */ jsxDEV15(PanelHeader, {
3852
- position,
3853
- onPositionChange: (p) => setPrefs({ position: p }),
3854
- onClose: () => setPrefs({ isOpen: false }),
3855
- onClear: entries.length > 0 ? () => {
3856
- core.clear();
3857
- setSelectedCuid(null);
3858
- setExpandedGroupCuids(new Set);
3859
- } : undefined
3860
- }, undefined, false, undefined, this),
3861
- isHorizDock ? /* @__PURE__ */ jsxDEV15("div", {
3862
- style: { flex: 1, display: "flex", overflow: "hidden" },
3863
- children: [
3864
- /* @__PURE__ */ jsxDEV15(ActionList, {
3865
- ...virtualListProps,
3866
- style: {
3867
- width: "340px",
3868
- flexShrink: 0,
3869
- overflowY: "auto",
3870
- borderRight: "1px solid #1e293b"
3871
- }
3872
- }, undefined, false, undefined, this),
3873
- /* @__PURE__ */ jsxDEV15("div", {
3874
- style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" },
3875
- children: selectedEntry != null ? /* @__PURE__ */ jsxDEV15(ActionDetailPanel, {
3876
- entry: selectedEntry,
3877
- parent: selectedEntryParent,
3878
- childEntries: selectedEntryChildren,
3879
- onSelectEntry: (cuid) => setSelectedCuid(cuid)
3880
- }, selectedEntry.cuid, false, undefined, this) : /* @__PURE__ */ jsxDEV15("div", {
4686
+ return /* @__PURE__ */ jsxDEV19("div", {
4687
+ id: "__nice-action-devtools-panel",
4688
+ style: panelStyle,
4689
+ children: [
4690
+ dockSide != null && /* @__PURE__ */ jsxDEV19(ResizeHandle, {
4691
+ dockSide,
4692
+ dockedSize,
4693
+ onChange: (size) => setPrefs(isHorizDock ? { dockedHeight: size } : { dockedWidth: size })
4694
+ }, undefined, false, undefined, this),
4695
+ /* @__PURE__ */ jsxDEV19(PanelHeader, {
4696
+ position,
4697
+ onPositionChange: (p) => setPrefs({ position: p }),
4698
+ onClose: () => setPrefs({ isOpen: false }),
4699
+ onClear: entries.length > 0 ? () => {
4700
+ core.clear();
4701
+ setSelectedCuid(null);
4702
+ } : undefined
4703
+ }, undefined, false, undefined, this),
4704
+ isHorizDock ? /* @__PURE__ */ jsxDEV19("div", {
4705
+ style: { flex: 1, display: "flex", overflow: "hidden" },
4706
+ children: [
4707
+ /* @__PURE__ */ jsxDEV19("div", {
4708
+ style: { position: "relative", width: "340px", flexShrink: 0 },
4709
+ children: [
4710
+ /* @__PURE__ */ jsxDEV19(ActionList, {
4711
+ ...virtualListProps,
4712
+ style: { width: "100%", height: "100%", overflowY: "auto" }
4713
+ }, undefined, false, undefined, this),
4714
+ /* @__PURE__ */ jsxDEV19("div", {
3881
4715
  style: {
3882
- padding: "24px",
3883
- textAlign: "center",
3884
- color: "#475569",
3885
- fontSize: "11px"
3886
- },
3887
- children: "Select an action to inspect"
4716
+ position: "absolute",
4717
+ top: 0,
4718
+ right: 0,
4719
+ bottom: 0,
4720
+ width: "36px",
4721
+ pointerEvents: "none",
4722
+ background: `linear-gradient(to right, transparent, ${DEVTOOL_LIST_BASE_BACKGROUND} 88%)`
4723
+ }
3888
4724
  }, undefined, false, undefined, this)
3889
- }, undefined, false, undefined, this)
3890
- ]
3891
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV15(Fragment5, {
3892
- children: [
3893
- /* @__PURE__ */ jsxDEV15(ActionList, {
3894
- ...virtualListProps,
3895
- style: {
3896
- overflowY: "auto",
3897
- flex: 1,
3898
- minHeight: "80px",
3899
- borderBottom: selectedEntry != null ? "1px solid #1e293b" : "none"
3900
- }
3901
- }, undefined, false, undefined, this),
3902
- selectedEntry != null && /* @__PURE__ */ jsxDEV15("div", {
4725
+ ]
4726
+ }, undefined, true, undefined, this),
4727
+ /* @__PURE__ */ jsxDEV19("div", {
4728
+ style: {
4729
+ flex: 1,
4730
+ display: "flex",
4731
+ flexDirection: "column",
4732
+ overflow: "hidden",
4733
+ borderLeft: `1px solid ${DEVTOOL_PANEL_DIVIDER_BORDER}`,
4734
+ boxShadow: "inset 18px 0 36px -14px rgba(0,0,0,0.8)"
4735
+ },
4736
+ children: selectedEntry != null ? /* @__PURE__ */ jsxDEV19(ActionDetailPanel, {
4737
+ entry: selectedEntry,
4738
+ parent: selectedEntryParent,
4739
+ childEntries: selectedEntryChildren,
4740
+ onSelectEntry: (cuid) => setSelectedCuid(cuid)
4741
+ }, selectedEntry.cuid, false, undefined, this) : /* @__PURE__ */ jsxDEV19("div", {
3903
4742
  style: {
3904
- flexShrink: 0,
3905
- maxHeight: "45%",
3906
- display: "flex",
3907
- flexDirection: "column",
3908
- overflow: "hidden"
4743
+ padding: "24px",
4744
+ textAlign: "center",
4745
+ color: DEVTOOL_COLOR_TEXT_MUTED,
4746
+ fontSize: "11px"
3909
4747
  },
3910
- children: /* @__PURE__ */ jsxDEV15(ActionDetailPanel, {
3911
- entry: selectedEntry,
3912
- parent: selectedEntryParent,
3913
- childEntries: selectedEntryChildren,
3914
- onSelectEntry: (cuid) => setSelectedCuid(cuid)
3915
- }, selectedEntry.cuid, false, undefined, this)
4748
+ children: "Select an action to inspect"
3916
4749
  }, undefined, false, undefined, this)
3917
- ]
3918
- }, undefined, true, undefined, this)
3919
- ]
3920
- }, undefined, true, undefined, this)
3921
- }, undefined, false, undefined, this);
4750
+ }, undefined, false, undefined, this)
4751
+ ]
4752
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV19(Fragment9, {
4753
+ children: [
4754
+ /* @__PURE__ */ jsxDEV19("div", {
4755
+ style: { position: "relative", flex: 1, minHeight: "80px" },
4756
+ children: [
4757
+ /* @__PURE__ */ jsxDEV19(ActionList, {
4758
+ ...virtualListProps,
4759
+ style: { overflowY: "auto", height: "100%" }
4760
+ }, undefined, false, undefined, this),
4761
+ selectedEntry != null && /* @__PURE__ */ jsxDEV19("div", {
4762
+ style: {
4763
+ position: "absolute",
4764
+ bottom: 0,
4765
+ left: 0,
4766
+ right: 0,
4767
+ height: "36px",
4768
+ pointerEvents: "none",
4769
+ background: `linear-gradient(to bottom, transparent, ${DEVTOOL_LIST_BASE_BACKGROUND} 88%)`
4770
+ }
4771
+ }, undefined, false, undefined, this)
4772
+ ]
4773
+ }, undefined, true, undefined, this),
4774
+ selectedEntry != null && /* @__PURE__ */ jsxDEV19("div", {
4775
+ style: {
4776
+ flexShrink: 0,
4777
+ maxHeight: "55%",
4778
+ display: "flex",
4779
+ flexDirection: "column",
4780
+ overflow: "hidden",
4781
+ borderTop: `1px solid ${DEVTOOL_PANEL_DIVIDER_BORDER}`,
4782
+ boxShadow: "inset 0 18px 36px -14px rgba(0,0,0,0.8)"
4783
+ },
4784
+ children: /* @__PURE__ */ jsxDEV19(ActionDetailPanel, {
4785
+ entry: selectedEntry,
4786
+ parent: selectedEntryParent,
4787
+ childEntries: selectedEntryChildren,
4788
+ onSelectEntry: (cuid) => setSelectedCuid(cuid)
4789
+ }, selectedEntry.cuid, false, undefined, this)
4790
+ }, undefined, false, undefined, this)
4791
+ ]
4792
+ }, undefined, true, undefined, this)
4793
+ ]
4794
+ }, undefined, true, undefined, this);
4795
+ }
4796
+ function getBreakReasons(current, previous) {
4797
+ const reasons = [];
4798
+ const inputChanged = current.inputHash != null && previous.inputHash != null ? current.inputHash !== previous.inputHash : safeStringify(current.input, 0) !== safeStringify(previous.input, 0);
4799
+ if (inputChanged)
4800
+ reasons.push("new input");
4801
+ const outputChanged = current.outputHash != null && previous.outputHash != null && current.outputHash !== previous.outputHash;
4802
+ if (outputChanged)
4803
+ reasons.push("new output");
4804
+ return reasons;
4805
+ }
4806
+ function getGroupChildEntries(group, childEntriesMap) {
4807
+ const seen = new Set;
4808
+ const result = [];
4809
+ for (const e of [group.representative, ...group.rest]) {
4810
+ for (const child of childEntriesMap.get(e.cuid) ?? []) {
4811
+ if (!seen.has(child.actionId)) {
4812
+ seen.add(child.actionId);
4813
+ result.push(child);
4814
+ }
4815
+ }
4816
+ }
4817
+ return result.length > 0 ? result.sort((a, b) => a.startTime - b.startTime) : undefined;
3922
4818
  }
3923
4819
  function getFlatItemKey(item) {
3924
4820
  const oldestCuid = item.group.rest[item.group.rest.length - 1]?.cuid ?? item.group.representative.cuid;
3925
- if (item.type === "group")
3926
- return `g:${oldestCuid}`;
3927
- if (item.type === "sub")
3928
- return `s:${item.entry.cuid}`;
3929
- return `c:${item.position}:${oldestCuid}`;
4821
+ return `g:${oldestCuid}`;
3930
4822
  }
3931
4823
  function ActionList({
3932
4824
  groups,
3933
4825
  selectedCuid,
3934
- expandedGroupCuids,
3935
4826
  onGroupClick,
3936
4827
  onSubClick,
3937
- onExpandGroup,
3938
- childExternalLabelsMap,
4828
+ childEntriesMap,
3939
4829
  style
3940
4830
  }) {
3941
- const containerRef = useRef2(null);
4831
+ const containerRef = useRef(null);
3942
4832
  const latestTime = groups[0]?.representative.startTime;
3943
4833
  const flatItems = useMemo2(() => {
3944
- const result = [];
3945
- for (let gi = 0;gi < groups.length; gi++) {
3946
- const group = groups[gi];
3947
- const repCuid = group.representative.cuid;
3948
- const allInGroup = [group.representative, ...group.rest];
3949
- const selectedIdx = allInGroup.findIndex((e) => e.cuid === selectedCuid);
3950
- result.push({ type: "group", group, groupIndex: gi });
3951
- const oldestCuid = (group.rest[group.rest.length - 1] ?? group.representative).cuid;
3952
- if (selectedIdx > 0) {
3953
- const aboveCount = selectedIdx;
3954
- const belowCount = allInGroup.length - selectedIdx - 1;
3955
- if (aboveCount > 0)
3956
- result.push({ type: "group-count", count: aboveCount, position: "above", group });
3957
- result.push({ type: "sub", entry: allInGroup[selectedIdx], group });
3958
- if (belowCount > 0)
3959
- result.push({ type: "group-count", count: belowCount, position: "below", group });
3960
- } else if (selectedIdx === 0 && group.rest.length > 0) {
3961
- result.push({ type: "group-count", count: group.rest.length, position: "below", group });
3962
- } else {
3963
- const isExpanded = expandedGroupCuids.has(repCuid) || expandedGroupCuids.has(oldestCuid);
3964
- if (isExpanded) {
3965
- for (const entry of group.rest) {
3966
- result.push({ type: "sub", entry, group });
3967
- }
3968
- }
4834
+ return groups.map((group, gi) => {
4835
+ const prevGroup = groups[gi + 1];
4836
+ let breakReasons;
4837
+ if (prevGroup != null && prevGroup.representative.actionId === group.representative.actionId && prevGroup.representative.domain === group.representative.domain) {
4838
+ const reasons = getBreakReasons(group.representative, prevGroup.representative);
4839
+ if (reasons.length > 0)
4840
+ breakReasons = reasons;
3969
4841
  }
3970
- }
3971
- return result;
3972
- }, [groups, expandedGroupCuids, selectedCuid]);
3973
- const prevSelectedRef = useRef2(selectedCuid);
4842
+ return { group, groupIndex: gi, breakReasons };
4843
+ });
4844
+ }, [groups]);
4845
+ const prevSelectedRef = useRef(selectedCuid);
3974
4846
  useEffect3(() => {
3975
4847
  if (selectedCuid === prevSelectedRef.current)
3976
4848
  return;
3977
4849
  prevSelectedRef.current = selectedCuid;
3978
4850
  if (selectedCuid == null)
3979
4851
  return;
3980
- containerRef.current?.querySelector(`[data-cuid="${selectedCuid}"]`)?.scrollIntoView({ block: "nearest" });
3981
- }, [selectedCuid]);
4852
+ let repCuid = selectedCuid;
4853
+ for (const item of flatItems) {
4854
+ if (item.group.rest.some((e) => e.cuid === selectedCuid)) {
4855
+ repCuid = item.group.representative.cuid;
4856
+ break;
4857
+ }
4858
+ }
4859
+ containerRef.current?.querySelector(`[data-cuid="${repCuid}"]`)?.scrollIntoView({ block: "nearest" });
4860
+ }, [selectedCuid, flatItems]);
3982
4861
  if (groups.length === 0) {
3983
- return /* @__PURE__ */ jsxDEV15("div", {
4862
+ return /* @__PURE__ */ jsxDEV19("div", {
3984
4863
  style,
3985
- children: /* @__PURE__ */ jsxDEV15("div", {
3986
- style: { padding: "24px", textAlign: "center", color: "#475569" },
4864
+ children: /* @__PURE__ */ jsxDEV19("div", {
4865
+ style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
3987
4866
  children: "No actions recorded yet"
3988
4867
  }, undefined, false, undefined, this)
3989
4868
  }, undefined, false, undefined, this);
3990
4869
  }
3991
- return /* @__PURE__ */ jsxDEV15("div", {
4870
+ return /* @__PURE__ */ jsxDEV19("div", {
3992
4871
  ref: containerRef,
3993
4872
  style,
3994
4873
  children: flatItems.map((item) => {
3995
4874
  const key = getFlatItemKey(item);
3996
- return /* @__PURE__ */ jsxDEV15("div", {
3997
- "data-cuid": item.type === "group" ? item.group.representative.cuid : item.type === "sub" ? item.entry.cuid : undefined,
3998
- style: { borderBottom: "1px solid #101109", position: "relative", overflow: "hidden" },
4875
+ const { group } = item;
4876
+ return /* @__PURE__ */ jsxDEV19("div", {
4877
+ style: {
4878
+ borderBottom: `1px solid ${DEVTOOL_LIST_GROUP_DIVIDER}`,
4879
+ position: "relative",
4880
+ overflow: "hidden"
4881
+ },
3999
4882
  children: [
4000
- item.type === "group" && /* @__PURE__ */ jsxDEV15("div", {
4883
+ /* @__PURE__ */ jsxDEV19("div", {
4001
4884
  style: {
4002
4885
  position: "absolute",
4003
4886
  inset: 0,
@@ -4005,49 +4888,18 @@ function ActionList({
4005
4888
  background: "linear-gradient(90deg, transparent 0%, rgba(148, 210, 255, 0.13) 50%, transparent 100%)",
4006
4889
  animation: "__nice-action-shine 0.65s ease-out forwards"
4007
4890
  }
4008
- }, item.group.representative.cuid, false, undefined, this),
4009
- item.type === "group" ? /* @__PURE__ */ jsxDEV15(ActionEntryRow, {
4010
- entry: item.group.representative,
4011
- isSelected: selectedCuid === item.group.representative.cuid,
4012
- groupCount: item.group.rest.length > 0 ? item.group.rest.length + 1 : undefined,
4891
+ }, group.representative.cuid, false, undefined, this),
4892
+ /* @__PURE__ */ jsxDEV19(ActionEntryRow, {
4893
+ entry: group.representative,
4894
+ isSelected: selectedCuid === group.representative.cuid || group.rest.some((e) => e.cuid === selectedCuid),
4013
4895
  isLatest: item.groupIndex === 0,
4014
4896
  latestTime,
4015
- childExternalLabels: childExternalLabelsMap.get(item.group.representative.cuid),
4016
- onClick: () => onGroupClick(item.group)
4017
- }, undefined, false, undefined, this) : item.type === "group-count" ? /* @__PURE__ */ jsxDEV15("div", {
4018
- onClick: () => onExpandGroup(item.group),
4019
- style: {
4020
- padding: "2px 28px",
4021
- fontSize: "10px",
4022
- color: "#475569",
4023
- display: "flex",
4024
- alignItems: "center",
4025
- gap: "5px",
4026
- background: "#0a1120",
4027
- cursor: "pointer",
4028
- userSelect: "none"
4029
- },
4030
- children: [
4031
- /* @__PURE__ */ jsxDEV15("span", {
4032
- style: { opacity: 0.6 },
4033
- children: item.position === "above" ? "↑" : "↓"
4034
- }, undefined, false, undefined, this),
4035
- /* @__PURE__ */ jsxDEV15("span", {
4036
- children: [
4037
- item.count,
4038
- " ",
4039
- item.position === "above" ? "newer" : "older",
4040
- " — click to browse"
4041
- ]
4042
- }, undefined, true, undefined, this)
4043
- ]
4044
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV15(ActionEntryRow, {
4045
- entry: item.entry,
4046
- isSelected: selectedCuid === item.entry.cuid,
4047
- isSubEntry: true,
4048
- isLatest: false,
4049
- latestTime,
4050
- onClick: () => onSubClick(item.entry.cuid, selectedCuid === item.entry.cuid)
4897
+ childEntries: getGroupChildEntries(group, childEntriesMap),
4898
+ breakReasons: item.breakReasons,
4899
+ groupEntries: group.rest.length > 0 ? [group.representative, ...group.rest] : undefined,
4900
+ selectedGroupCuid: selectedCuid,
4901
+ onSelectGroupEntry: (cuid) => onSubClick(cuid, selectedCuid === cuid),
4902
+ onClick: () => onGroupClick(group)
4051
4903
  }, undefined, false, undefined, this)
4052
4904
  ]
4053
4905
  }, key, true, undefined, this);