@assistant-ui/react-devtools 1.2.19 → 1.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DevToolsModal.d.ts +10 -13
- package/dist/DevToolsModal.d.ts.map +1 -1
- package/dist/DevToolsModalImpl.d.ts +3 -5
- package/dist/DevToolsModalImpl.d.ts.map +1 -1
- package/dist/data/createInProcessClient.d.ts +3 -6
- package/dist/data/createInProcessClient.d.ts.map +1 -1
- package/dist/data/projectApi.d.ts +6 -8
- package/dist/data/projectApi.d.ts.map +1 -1
- package/dist/data/projectApi.js +2 -2
- package/dist/data/projectApi.js.map +1 -1
- package/dist/data/types.d.ts +33 -35
- package/dist/data/types.d.ts.map +1 -1
- package/dist/data/useDevToolsClient.d.ts +7 -10
- package/dist/data/useDevToolsClient.d.ts.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.d.ts.map +1 -0
- package/dist/shell/DevToolsOverlay.d.ts +7 -10
- package/dist/shell/DevToolsOverlay.d.ts.map +1 -1
- package/dist/shell/DevToolsPanel.d.ts +12 -15
- package/dist/shell/DevToolsPanel.d.ts.map +1 -1
- package/dist/shell/ShadowRoot.d.ts +7 -10
- package/dist/shell/ShadowRoot.d.ts.map +1 -1
- package/dist/shell/SplitLayout.d.ts +13 -16
- package/dist/shell/SplitLayout.d.ts.map +1 -1
- package/dist/shell/registry.d.ts +34 -37
- package/dist/shell/registry.d.ts.map +1 -1
- package/dist/shell/tabs/ActivityTab.d.ts +2 -5
- package/dist/shell/tabs/ActivityTab.d.ts.map +1 -1
- package/dist/shell/tabs/ContextTab.d.ts +2 -5
- package/dist/shell/tabs/ContextTab.d.ts.map +1 -1
- package/dist/shell/tabs/RawTab.d.ts +2 -5
- package/dist/shell/tabs/RawTab.d.ts.map +1 -1
- package/dist/shell/tabs/ThreadTab.d.ts +2 -5
- package/dist/shell/tabs/ThreadTab.d.ts.map +1 -1
- package/dist/shell/tabs/navSelection.d.ts +1 -4
- package/dist/shell/tabs/navSelection.d.ts.map +1 -1
- package/dist/styles/panel.generated.d.ts +1 -4
- package/dist/styles/panel.generated.d.ts.map +1 -1
- package/dist/types.d.ts +6 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/common.d.ts +13 -16
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/diff.d.ts +6 -9
- package/dist/utils/diff.d.ts.map +1 -1
- package/dist/utils/serialization.d.ts +7 -10
- package/dist/utils/serialization.d.ts.map +1 -1
- package/dist/utils/serialization.js +17 -0
- package/dist/utils/serialization.js.map +1 -1
- package/dist/utils/toolNormalization.d.ts +14 -17
- package/dist/utils/toolNormalization.d.ts.map +1 -1
- package/dist/utils/unserializable.d.ts +2 -5
- package/dist/utils/unserializable.d.ts.map +1 -1
- package/dist/views/activity/EventLogRow.d.ts +12 -15
- package/dist/views/activity/EventLogRow.d.ts.map +1 -1
- package/dist/views/activity/EventStreamPane.d.ts +3 -6
- package/dist/views/activity/EventStreamPane.d.ts.map +1 -1
- package/dist/views/activity/OrphansPane.d.ts +3 -6
- package/dist/views/activity/OrphansPane.d.ts.map +1 -1
- package/dist/views/activity/RunDetailPane.d.ts +3 -6
- package/dist/views/activity/RunDetailPane.d.ts.map +1 -1
- package/dist/views/activity/activityNodes.d.ts +29 -32
- package/dist/views/activity/activityNodes.d.ts.map +1 -1
- package/dist/views/activity/index.d.ts +7 -6
- package/dist/views/activity/index.d.ts.map +1 -0
- package/dist/views/attachments/AttachmentList.d.ts +5 -8
- package/dist/views/attachments/AttachmentList.d.ts.map +1 -1
- package/dist/views/attachments/MediaPartView.d.ts +10 -13
- package/dist/views/attachments/MediaPartView.d.ts.map +1 -1
- package/dist/views/attachments/formatBytes.d.ts +3 -6
- package/dist/views/attachments/formatBytes.d.ts.map +1 -1
- package/dist/views/attachments/index.d.ts +5 -5
- package/dist/views/attachments/index.d.ts.map +1 -0
- package/dist/views/attachments/parseAttachment.d.ts +3 -6
- package/dist/views/attachments/parseAttachment.d.ts.map +1 -1
- package/dist/views/attachments/types.d.ts +12 -15
- package/dist/views/attachments/types.d.ts.map +1 -1
- package/dist/views/context/ContextDetail.d.ts +5 -8
- package/dist/views/context/ContextDetail.d.ts.map +1 -1
- package/dist/views/context/ToolUIsView.d.ts +2 -5
- package/dist/views/context/ToolUIsView.d.ts.map +1 -1
- package/dist/views/context/contextNodes.d.ts +21 -24
- package/dist/views/context/contextNodes.d.ts.map +1 -1
- package/dist/views/context/index.d.ts +5 -4
- package/dist/views/context/index.d.ts.map +1 -0
- package/dist/views/mcp/McpView.d.ts +3 -6
- package/dist/views/mcp/McpView.d.ts.map +1 -1
- package/dist/views/mcp/index.d.ts +2 -2
- package/dist/views/mcp/index.d.ts.map +1 -0
- package/dist/views/mcp/parse.d.ts +2 -5
- package/dist/views/mcp/parse.d.ts.map +1 -1
- package/dist/views/mcp/types.d.ts +15 -18
- package/dist/views/mcp/types.d.ts.map +1 -1
- package/dist/views/message/ChainOfThought.d.ts +3 -6
- package/dist/views/message/ChainOfThought.d.ts.map +1 -1
- package/dist/views/message/MessageDetailPane.d.ts +4 -7
- package/dist/views/message/MessageDetailPane.d.ts.map +1 -1
- package/dist/views/message/MessageItem.d.ts +5 -8
- package/dist/views/message/MessageItem.d.ts.map +1 -1
- package/dist/views/message/MessageList.d.ts +4 -7
- package/dist/views/message/MessageList.d.ts.map +1 -1
- package/dist/views/message/MessageMetrics.d.ts +3 -6
- package/dist/views/message/MessageMetrics.d.ts.map +1 -1
- package/dist/views/message/MessageTimeline.d.ts +7 -10
- package/dist/views/message/MessageTimeline.d.ts.map +1 -1
- package/dist/views/message/PartDisclosure.d.ts +6 -9
- package/dist/views/message/PartDisclosure.d.ts.map +1 -1
- package/dist/views/message/PartView.d.ts +4 -7
- package/dist/views/message/PartView.d.ts.map +1 -1
- package/dist/views/message/RoleLabel.d.ts +3 -6
- package/dist/views/message/RoleLabel.d.ts.map +1 -1
- package/dist/views/message/StatusBadge.d.ts +7 -10
- package/dist/views/message/StatusBadge.d.ts.map +1 -1
- package/dist/views/message/ToolCallView.d.ts +4 -7
- package/dist/views/message/ToolCallView.d.ts.map +1 -1
- package/dist/views/message/TtftBar.d.ts +3 -6
- package/dist/views/message/TtftBar.d.ts.map +1 -1
- package/dist/views/message/index.d.ts +6 -6
- package/dist/views/message/index.d.ts.map +1 -0
- package/dist/views/message/messagePlainText.d.ts +2 -5
- package/dist/views/message/messagePlainText.d.ts.map +1 -1
- package/dist/views/message/parse.d.ts +5 -8
- package/dist/views/message/parse.d.ts.map +1 -1
- package/dist/views/message/types.d.ts +108 -110
- package/dist/views/message/types.d.ts.map +1 -1
- package/dist/views/model-context/ModelContextView.d.ts +9 -12
- package/dist/views/model-context/ModelContextView.d.ts.map +1 -1
- package/dist/views/nav.d.ts +10 -13
- package/dist/views/nav.d.ts.map +1 -1
- package/dist/views/raw/RawDetail.d.ts +5 -8
- package/dist/views/raw/RawDetail.d.ts.map +1 -1
- package/dist/views/raw/index.d.ts +4 -3
- package/dist/views/raw/index.d.ts.map +1 -0
- package/dist/views/raw/rawNodes.d.ts +13 -16
- package/dist/views/raw/rawNodes.d.ts.map +1 -1
- package/dist/views/raw/statePreview.d.ts +1 -4
- package/dist/views/raw/statePreview.d.ts.map +1 -1
- package/dist/views/runs/PayloadDiff.d.ts +3 -6
- package/dist/views/runs/PayloadDiff.d.ts.map +1 -1
- package/dist/views/runs/parse.d.ts +3 -6
- package/dist/views/runs/parse.d.ts.map +1 -1
- package/dist/views/runs/types.d.ts +18 -21
- package/dist/views/runs/types.d.ts.map +1 -1
- package/dist/views/scopes/ScopesView.d.ts +2 -5
- package/dist/views/scopes/ScopesView.d.ts.map +1 -1
- package/dist/views/scopes/index.d.ts +2 -2
- package/dist/views/scopes/index.d.ts.map +1 -0
- package/dist/views/scopes/parse.d.ts +2 -5
- package/dist/views/scopes/parse.d.ts.map +1 -1
- package/dist/views/scopes/types.d.ts +5 -8
- package/dist/views/scopes/types.d.ts.map +1 -1
- package/dist/views/thread/ComposerAttachments.d.ts +3 -6
- package/dist/views/thread/ComposerAttachments.d.ts.map +1 -1
- package/dist/views/thread/ComposerFlags.d.ts +3 -6
- package/dist/views/thread/ComposerFlags.d.ts.map +1 -1
- package/dist/views/thread/ComposerQueue.d.ts +3 -6
- package/dist/views/thread/ComposerQueue.d.ts.map +1 -1
- package/dist/views/thread/ConversationList.d.ts +7 -10
- package/dist/views/thread/ConversationList.d.ts.map +1 -1
- package/dist/views/thread/ConversationStatusDot.d.ts +12 -15
- package/dist/views/thread/ConversationStatusDot.d.ts.map +1 -1
- package/dist/views/thread/ThreadDetails.d.ts +4 -7
- package/dist/views/thread/ThreadDetails.d.ts.map +1 -1
- package/dist/views/thread/Transcript.d.ts +8 -11
- package/dist/views/thread/Transcript.d.ts.map +1 -1
- package/dist/views/thread/index.d.ts +10 -10
- package/dist/views/thread/index.d.ts.map +1 -0
- package/dist/views/thread/resolve.d.ts +3 -6
- package/dist/views/thread/resolve.d.ts.map +1 -1
- package/dist/views/thread/types.d.ts +40 -42
- package/dist/views/thread/types.d.ts.map +1 -1
- package/dist/views/thread/utils.d.ts +5 -8
- package/dist/views/thread/utils.d.ts.map +1 -1
- package/dist/views/ui/CenteredMessage.d.ts +3 -6
- package/dist/views/ui/CenteredMessage.d.ts.map +1 -1
- package/dist/views/ui/Chip.d.ts +4 -7
- package/dist/views/ui/Chip.d.ts.map +1 -1
- package/dist/views/ui/ControlButton.d.ts +2 -5
- package/dist/views/ui/ControlButton.d.ts.map +1 -1
- package/dist/views/ui/CopyButton.d.ts +7 -10
- package/dist/views/ui/CopyButton.d.ts.map +1 -1
- package/dist/views/ui/EmptyState.d.ts +3 -6
- package/dist/views/ui/EmptyState.d.ts.map +1 -1
- package/dist/views/ui/InfoCard.d.ts +6 -9
- package/dist/views/ui/InfoCard.d.ts.map +1 -1
- package/dist/views/ui/JSONTree.d.ts +4 -7
- package/dist/views/ui/JSONTree.d.ts.map +1 -1
- package/dist/views/ui/PaneHeader.d.ts +8 -11
- package/dist/views/ui/PaneHeader.d.ts.map +1 -1
- package/dist/views/ui/RailTime.d.ts +3 -6
- package/dist/views/ui/RailTime.d.ts.map +1 -1
- package/dist/views/ui/SectionLabel.d.ts +3 -6
- package/dist/views/ui/SectionLabel.d.ts.map +1 -1
- package/dist/views/ui/SelectableRow.d.ts +8 -11
- package/dist/views/ui/SelectableRow.d.ts.map +1 -1
- package/dist/views/ui/Sparkline.d.ts +3 -6
- package/dist/views/ui/Sparkline.d.ts.map +1 -1
- package/dist/views/ui/SummaryItem.d.ts +6 -9
- package/dist/views/ui/SummaryItem.d.ts.map +1 -1
- package/dist/views/ui/ToneBadge.d.ts +7 -10
- package/dist/views/ui/ToneBadge.d.ts.map +1 -1
- package/dist/views/ui/badgeTone.d.ts +13 -16
- package/dist/views/ui/badgeTone.d.ts.map +1 -1
- package/dist/views/ui/getInlineJson.d.ts +1 -4
- package/dist/views/ui/getInlineJson.d.ts.map +1 -1
- package/dist/views/ui/index.d.ts +17 -16
- package/dist/views/ui/index.d.ts.map +1 -0
- package/dist/views/ui/useCopyToClipboard.d.ts +4 -7
- package/dist/views/ui/useCopyToClipboard.d.ts.map +1 -1
- package/package.json +14 -13
- package/src/data/projectApi.test.ts +41 -0
- package/src/data/projectApi.ts +2 -2
- package/src/utils/serialization.test.ts +81 -0
- package/src/utils/serialization.ts +36 -0
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
//#region src/views/ui/InfoCard.d.ts
|
|
1
|
+
import type { ReactNode } from "react";
|
|
3
2
|
/**
|
|
4
3
|
* A flat content section: a header row (title + optional count/action) over its
|
|
5
4
|
* content. No box, no nesting; sections are separated by whitespace on the
|
|
6
5
|
* panel surface.
|
|
7
6
|
*/
|
|
8
|
-
declare const InfoCard: ({ title, count, action, children }: {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
export declare const InfoCard: ({ title, count, action, children, }: {
|
|
8
|
+
title?: ReactNode;
|
|
9
|
+
count?: ReactNode;
|
|
10
|
+
action?: ReactNode;
|
|
11
|
+
children: ReactNode;
|
|
13
12
|
}) => import("react").JSX.Element;
|
|
14
|
-
//#endregion
|
|
15
|
-
export { InfoCard };
|
|
16
13
|
//# sourceMappingURL=InfoCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfoCard.d.ts","
|
|
1
|
+
{"version":3,"file":"InfoCard.d.ts","sourceRoot":"","sources":["../../../src/views/ui/InfoCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,qCAKtB;IACD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB,gCAiBA,CAAC"}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
//#region src/views/ui/JSONTree.d.ts
|
|
2
1
|
/**
|
|
3
2
|
* Recursive JSON view. `compact` fits tool rows; copy always provides formatted JSON.
|
|
4
3
|
*/
|
|
5
|
-
declare const JSONTree: ({ value, openDepth, compact }: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export declare const JSONTree: ({ value, openDepth, compact, }: {
|
|
5
|
+
value: unknown;
|
|
6
|
+
openDepth?: number;
|
|
7
|
+
compact?: boolean;
|
|
9
8
|
}) => import("react").JSX.Element;
|
|
10
|
-
//#endregion
|
|
11
|
-
export { JSONTree };
|
|
12
9
|
//# sourceMappingURL=JSONTree.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSONTree.d.ts","
|
|
1
|
+
{"version":3,"file":"JSONTree.d.ts","sourceRoot":"","sources":["../../../src/views/ui/JSONTree.tsx"],"names":[],"mappings":"AAuMA;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,gCAItB;IACD,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,gCA8BA,CAAC"}
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
//#region src/views/ui/PaneHeader.d.ts
|
|
1
|
+
import type { ReactNode } from "react";
|
|
3
2
|
/**
|
|
4
3
|
* Fixed-height rail header. Every column in a split layout should use this so
|
|
5
4
|
* titles line up across columns.
|
|
6
5
|
*/
|
|
7
|
-
declare const PaneHeader: ({ children, trailing, borderless }: {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
export declare const PaneHeader: ({ children, trailing, borderless, }: {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
trailing?: ReactNode | undefined;
|
|
9
|
+
borderless?: boolean;
|
|
11
10
|
}) => import("react").JSX.Element;
|
|
12
11
|
/** Header that grows below a {@link PaneHeader}-height title row. */
|
|
13
|
-
declare const PaneHeaderStack: ({ header, children }: {
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
export declare const PaneHeaderStack: ({ header, children, }: {
|
|
13
|
+
header: ReactNode;
|
|
14
|
+
children?: ReactNode | undefined;
|
|
16
15
|
}) => import("react").JSX.Element;
|
|
17
|
-
//#endregion
|
|
18
|
-
export { PaneHeader, PaneHeaderStack };
|
|
19
16
|
//# sourceMappingURL=PaneHeader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaneHeader.d.ts","
|
|
1
|
+
{"version":3,"file":"PaneHeader.d.ts","sourceRoot":"","sources":["../../../src/views/ui/PaneHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,qCAIxB;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,gCAiBA,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,eAAe,GAAI,uBAG7B;IACD,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAClC,gCAKA,CAAC"}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
//#region src/views/ui/RailTime.d.ts
|
|
2
1
|
/** Compact timestamp for narrow rails; full value goes in the tooltip. */
|
|
3
|
-
declare const RailTime: ({ value, className }: {
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
export declare const RailTime: ({ value, className, }: {
|
|
3
|
+
value: string | undefined;
|
|
4
|
+
className?: string | undefined;
|
|
6
5
|
}) => import("react").JSX.Element | null;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { RailTime };
|
|
9
6
|
//# sourceMappingURL=RailTime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RailTime.d.ts","
|
|
1
|
+
{"version":3,"file":"RailTime.d.ts","sourceRoot":"","sources":["../../../src/views/ui/RailTime.tsx"],"names":[],"mappings":"AAGA,0EAA0E;AAC1E,eAAO,MAAM,QAAQ,GAAI,uBAGtB;IACD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,uCAgBA,CAAC"}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
children: ReactNode;
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export declare const SectionLabel: ({ children }: {
|
|
3
|
+
children: ReactNode;
|
|
5
4
|
}) => import("react").JSX.Element;
|
|
6
|
-
//#endregion
|
|
7
|
-
export { SectionLabel };
|
|
8
5
|
//# sourceMappingURL=SectionLabel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionLabel.d.ts","
|
|
1
|
+
{"version":3,"file":"SectionLabel.d.ts","sourceRoot":"","sources":["../../../src/views/ui/SectionLabel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,eAAO,MAAM,YAAY,GAAI,cAAc;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,gCAIjE,CAAC"}
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
//#region src/views/ui/SelectableRow.d.ts
|
|
1
|
+
import { type ReactNode } from "react";
|
|
3
2
|
/**
|
|
4
3
|
* A row in a master rail. The leading border + accent fill mark the current
|
|
5
4
|
* selection; the whole row is the hit target. Content is free-form so a row can
|
|
6
5
|
* be a single line or a small block (a transcript turn).
|
|
7
6
|
*/
|
|
8
|
-
declare const SelectableRow: import("react").ForwardRefExoticComponent<{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
export declare const SelectableRow: import("react").ForwardRefExoticComponent<{
|
|
8
|
+
selected?: boolean;
|
|
9
|
+
onSelect?: (() => void) | undefined;
|
|
10
|
+
className?: string | undefined;
|
|
11
|
+
/** Fixed-height row for uniform rails. */
|
|
12
|
+
dense?: boolean;
|
|
13
|
+
children: ReactNode;
|
|
15
14
|
} & import("react").RefAttributes<HTMLButtonElement>>;
|
|
16
|
-
//#endregion
|
|
17
|
-
export { SelectableRow };
|
|
18
15
|
//# sourceMappingURL=SelectableRow.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectableRow.d.ts","
|
|
1
|
+
{"version":3,"file":"SelectableRow.d.ts","sourceRoot":"","sources":["../../../src/views/ui/SelectableRow.tsx"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,aAAa;eAGX,OAAO;eACP,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS;gBACvB,MAAM,GAAG,SAAS;IAC9B,0CAA0C;YAClC,OAAO;cACL,SAAS;qDAwBrB,CAAC"}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
//#region src/views/ui/Sparkline.d.ts
|
|
2
1
|
/**
|
|
3
2
|
* A monochrome trend line drawn as an SVG polyline. No axes, legend, or
|
|
4
3
|
* gridlines: it answers "is this metric rising, falling, or spiking" at a
|
|
5
4
|
* glance and nothing more. Renders nothing below 2 points; color comes from the
|
|
6
5
|
* surrounding text color (`currentColor`).
|
|
7
6
|
*/
|
|
8
|
-
declare const Sparkline: ({ values, className }: {
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
export declare const Sparkline: ({ values, className, }: {
|
|
8
|
+
values: readonly number[];
|
|
9
|
+
className?: string;
|
|
11
10
|
}) => import("react").JSX.Element | null;
|
|
12
|
-
//#endregion
|
|
13
|
-
export { Sparkline };
|
|
14
11
|
//# sourceMappingURL=Sparkline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sparkline.d.ts","
|
|
1
|
+
{"version":3,"file":"Sparkline.d.ts","sourceRoot":"","sources":["../../../src/views/ui/Sparkline.tsx"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,wBAGvB;IACD,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,uCAkCA,CAAC"}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
//#region src/views/ui/SummaryItem.d.ts
|
|
1
|
+
import type { ReactNode } from "react";
|
|
3
2
|
/**
|
|
4
3
|
* A key/value row: label left, value right on one baseline. Flat (no box). Group
|
|
5
4
|
* a sequence in `SummaryList` for hairline dividers.
|
|
6
5
|
*/
|
|
7
|
-
declare const SummaryItem: ({ label, value }: {
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export declare const SummaryItem: ({ label, value, }: {
|
|
7
|
+
label: string;
|
|
8
|
+
value: ReactNode;
|
|
10
9
|
}) => import("react").JSX.Element;
|
|
11
10
|
/** Divided list of `SummaryItem` rows. Unboxed: dividers do the grouping. */
|
|
12
|
-
declare const SummaryList: ({ children }: {
|
|
13
|
-
|
|
11
|
+
export declare const SummaryList: ({ children }: {
|
|
12
|
+
children: ReactNode;
|
|
14
13
|
}) => import("react").JSX.Element;
|
|
15
|
-
//#endregion
|
|
16
|
-
export { SummaryItem, SummaryList };
|
|
17
14
|
//# sourceMappingURL=SummaryItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SummaryItem.d.ts","
|
|
1
|
+
{"version":3,"file":"SummaryItem.d.ts","sourceRoot":"","sources":["../../../src/views/ui/SummaryItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,mBAGzB;IACD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,gCAOA,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,WAAW,GAAI,cAAc;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,gCAEhE,CAAC"}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
children: ReactNode;
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { BadgeTone } from "./badgeTone.js";
|
|
3
|
+
export declare const ToneBadge: ({ tone, size, className, children, }: {
|
|
4
|
+
tone?: BadgeTone | undefined;
|
|
5
|
+
size?: "default" | "sm";
|
|
6
|
+
className?: string | undefined;
|
|
7
|
+
children: ReactNode;
|
|
9
8
|
}) => import("react").JSX.Element;
|
|
10
|
-
//#endregion
|
|
11
|
-
export { ToneBadge };
|
|
12
9
|
//# sourceMappingURL=ToneBadge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToneBadge.d.ts","
|
|
1
|
+
{"version":3,"file":"ToneBadge.d.ts","sourceRoot":"","sources":["../../../src/views/ui/ToneBadge.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,uBAAoB;AAE7C,eAAO,MAAM,SAAS,GAAI,sCAKvB;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB,gCAUA,CAAC"}
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
readonly zinc: "border-zinc-300 bg-zinc-500/10 text-zinc-600 dark:border-zinc-600 dark:bg-zinc-500/15 dark:text-zinc-300";
|
|
1
|
+
export declare const BADGE_TONE: {
|
|
2
|
+
readonly blue: "border-blue-300 bg-blue-500/10 text-blue-700 dark:border-blue-500/40 dark:bg-blue-500/15 dark:text-blue-300";
|
|
3
|
+
readonly emerald: "border-emerald-300 bg-emerald-500/10 text-emerald-700 dark:border-emerald-500/40 dark:bg-emerald-500/15 dark:text-emerald-300";
|
|
4
|
+
readonly amber: "border-amber-300 bg-amber-500/10 text-amber-700 dark:border-amber-500/40 dark:bg-amber-500/15 dark:text-amber-300";
|
|
5
|
+
readonly red: "border-red-300 bg-red-500/10 text-red-700 dark:border-red-500/40 dark:bg-red-500/15 dark:text-red-300";
|
|
6
|
+
readonly violet: "border-violet-300 bg-violet-500/10 text-violet-700 dark:border-violet-500/40 dark:bg-violet-500/15 dark:text-violet-300";
|
|
7
|
+
readonly zinc: "border-zinc-300 bg-zinc-500/10 text-zinc-600 dark:border-zinc-600 dark:bg-zinc-500/15 dark:text-zinc-300";
|
|
9
8
|
};
|
|
10
|
-
type BadgeTone = keyof typeof BADGE_TONE;
|
|
9
|
+
export type BadgeTone = keyof typeof BADGE_TONE;
|
|
11
10
|
/** Message and attachment lifecycle status to badge tone. */
|
|
12
|
-
declare const STATUS_TONE: Record<string, BadgeTone>;
|
|
11
|
+
export declare const STATUS_TONE: Record<string, BadgeTone>;
|
|
13
12
|
/** MCP connection state to badge tone. */
|
|
14
|
-
declare const CONNECTION_TONE: Record<string, BadgeTone>;
|
|
15
|
-
declare const BADGE_BASE = "inline-flex items-center rounded-md border px-1.5 py-0.5 text-[11px] font-medium leading-none";
|
|
16
|
-
declare const BADGE_SM = "inline-flex items-center rounded border px-1 py-px text-[9px] font-medium leading-none";
|
|
13
|
+
export declare const CONNECTION_TONE: Record<string, BadgeTone>;
|
|
14
|
+
export declare const BADGE_BASE = "inline-flex items-center rounded-md border px-1.5 py-0.5 text-[11px] font-medium leading-none";
|
|
15
|
+
export declare const BADGE_SM = "inline-flex items-center rounded border px-1 py-px text-[9px] font-medium leading-none";
|
|
17
16
|
/** Uniform width for short status labels in transcript rails (e.g. opt vs running). */
|
|
18
|
-
declare const RAIL_STATUS_BADGE_CLASS = "min-w-[2.875rem] justify-center";
|
|
19
|
-
//#endregion
|
|
20
|
-
export { BADGE_BASE, BADGE_SM, BADGE_TONE, BadgeTone, CONNECTION_TONE, RAIL_STATUS_BADGE_CLASS, STATUS_TONE };
|
|
17
|
+
export declare const RAIL_STATUS_BADGE_CLASS = "min-w-[2.875rem] justify-center";
|
|
21
18
|
//# sourceMappingURL=badgeTone.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badgeTone.d.ts","
|
|
1
|
+
{"version":3,"file":"badgeTone.d.ts","sourceRoot":"","sources":["../../../src/views/ui/badgeTone.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;;;CAUb,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,UAAU,CAAC;AAEhD,6DAA6D;AAC7D,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAKjD,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAOrD,CAAC;AAEF,eAAO,MAAM,UAAU,kGAC0E,CAAC;AAElG,eAAO,MAAM,QAAQ,2FACqE,CAAC;AAE3F,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,oCAAoC,CAAC"}
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
declare function getInlineJson(value: unknown, limit: number): string | undefined;
|
|
3
|
-
//#endregion
|
|
4
|
-
export { getInlineJson };
|
|
1
|
+
export declare function getInlineJson(value: unknown, limit: number): string | undefined;
|
|
5
2
|
//# sourceMappingURL=getInlineJson.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getInlineJson.d.ts","
|
|
1
|
+
{"version":3,"file":"getInlineJson.d.ts","sourceRoot":"","sources":["../../../src/views/ui/getInlineJson.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,sBAmC1D"}
|
package/dist/views/ui/index.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export {
|
|
1
|
+
export { CONNECTION_TONE, RAIL_STATUS_BADGE_CLASS, STATUS_TONE, } from "./badgeTone.js";
|
|
2
|
+
export type { BadgeTone } from "./badgeTone.js";
|
|
3
|
+
export { CenteredMessage } from "./CenteredMessage.js";
|
|
4
|
+
export { Chip } from "./Chip.js";
|
|
5
|
+
export { ControlButton } from "./ControlButton.js";
|
|
6
|
+
export { CopyButton } from "./CopyButton.js";
|
|
7
|
+
export { EmptyState } from "./EmptyState.js";
|
|
8
|
+
export { InfoCard } from "./InfoCard.js";
|
|
9
|
+
export { JSONTree } from "./JSONTree.js";
|
|
10
|
+
export { PaneHeader, PaneHeaderStack } from "./PaneHeader.js";
|
|
11
|
+
export { RailTime } from "./RailTime.js";
|
|
12
|
+
export { SectionLabel } from "./SectionLabel.js";
|
|
13
|
+
export { SelectableRow } from "./SelectableRow.js";
|
|
14
|
+
export { Sparkline } from "./Sparkline.js";
|
|
15
|
+
export { SummaryItem, SummaryList } from "./SummaryItem.js";
|
|
16
|
+
export { ToneBadge } from "./ToneBadge.js";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/views/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,WAAW,GACZ,uBAAoB;AACrB,YAAY,EAAE,SAAS,EAAE,uBAAoB;AAC7C,OAAO,EAAE,eAAe,EAAE,6BAA0B;AACpD,OAAO,EAAE,IAAI,EAAE,kBAAe;AAC9B,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAChD,OAAO,EAAE,UAAU,EAAE,wBAAqB;AAC1C,OAAO,EAAE,UAAU,EAAE,wBAAqB;AAC1C,OAAO,EAAE,QAAQ,EAAE,sBAAmB;AACtC,OAAO,EAAE,QAAQ,EAAE,sBAAmB;AACtC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,wBAAqB;AAC3D,OAAO,EAAE,QAAQ,EAAE,sBAAmB;AACtC,OAAO,EAAE,YAAY,EAAE,0BAAuB;AAC9C,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAChD,OAAO,EAAE,SAAS,EAAE,uBAAoB;AACxC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,yBAAsB;AACzD,OAAO,EAAE,SAAS,EAAE,uBAAoB"}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
copiedDuration?: number;
|
|
1
|
+
export declare const useCopyToClipboard: ({ copiedDuration, }?: {
|
|
2
|
+
copiedDuration?: number;
|
|
4
3
|
}) => {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
isCopied: boolean;
|
|
5
|
+
copy: (value: string) => void;
|
|
7
6
|
};
|
|
8
|
-
//#endregion
|
|
9
|
-
export { useCopyToClipboard };
|
|
10
7
|
//# sourceMappingURL=useCopyToClipboard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCopyToClipboard.d.ts","
|
|
1
|
+
{"version":3,"file":"useCopyToClipboard.d.ts","sourceRoot":"","sources":["../../../src/views/ui/useCopyToClipboard.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,GAAI,sBAEhC;IACD,cAAc,CAAC,EAAE,MAAM,CAAC;CACpB;;kBAIM,MAAM;CAgBjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-devtools",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.21",
|
|
4
4
|
"description": "React development tools for assistant-ui components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"assistant-ui",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"clsx": "^2.1.1",
|
|
31
|
-
"zod": "^4.5
|
|
31
|
+
"zod": "^4.6.5"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@assistant-ui/react": "^0.15.0",
|
|
35
|
-
"@assistant-ui/tap": "^0.9.
|
|
35
|
+
"@assistant-ui/tap": "^0.9.19",
|
|
36
36
|
"@types/react": "*",
|
|
37
37
|
"@types/react-dom": "*",
|
|
38
38
|
"react": "^18 || ^19",
|
|
@@ -47,19 +47,19 @@
|
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@assistant-ui/react": "0.15.
|
|
51
|
-
"@assistant-ui/tap": "0.9.
|
|
52
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
50
|
+
"@assistant-ui/react": "0.15.22",
|
|
51
|
+
"@assistant-ui/tap": "0.9.19",
|
|
52
|
+
"@assistant-ui/x-buildutils": "0.0.29",
|
|
53
53
|
"@assistant-ui/x-performance": "0.0.0",
|
|
54
54
|
"@tailwindcss/cli": "^4.3.3",
|
|
55
|
-
"@types/node": "^26.
|
|
56
|
-
"@types/react": "^19.
|
|
57
|
-
"@types/react-dom": "^19.
|
|
55
|
+
"@types/node": "^26.5.1",
|
|
56
|
+
"@types/react": "^19.3.0",
|
|
57
|
+
"@types/react-dom": "^19.3.0",
|
|
58
58
|
"jsdom": "^30.0.1",
|
|
59
|
-
"react": "^19.
|
|
60
|
-
"react-dom": "^19.
|
|
59
|
+
"react": "^19.3.0",
|
|
60
|
+
"react-dom": "^19.3.0",
|
|
61
61
|
"tailwindcss": "^4.3.3",
|
|
62
|
-
"vitest": "^5.0.
|
|
62
|
+
"vitest": "^5.0.1"
|
|
63
63
|
},
|
|
64
64
|
"publishConfig": {
|
|
65
65
|
"access": "public",
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"scripts": {
|
|
78
78
|
"build:css": "node scripts/build-styles.mjs",
|
|
79
79
|
"build": "pnpm build:css && aui-build",
|
|
80
|
-
"test": "vitest run"
|
|
80
|
+
"test": "vitest run",
|
|
81
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json"
|
|
81
82
|
}
|
|
82
83
|
}
|
|
@@ -136,4 +136,45 @@ describe("projectApi", () => {
|
|
|
136
136
|
const scopes = result.scopes as Array<{ name: string }>;
|
|
137
137
|
expect(scopes.map((s) => s.name)).toEqual(["broken", "throwing"]);
|
|
138
138
|
});
|
|
139
|
+
|
|
140
|
+
it("collects snapshots for prototype-named thread ids", () => {
|
|
141
|
+
const threads = scope(
|
|
142
|
+
"root",
|
|
143
|
+
{},
|
|
144
|
+
{
|
|
145
|
+
getState: () => ({
|
|
146
|
+
threadIds: ["__proto__"],
|
|
147
|
+
archivedThreadIds: [],
|
|
148
|
+
}),
|
|
149
|
+
__internal_getAssistantRuntime: () => ({
|
|
150
|
+
threads: {
|
|
151
|
+
getById: () => ({
|
|
152
|
+
getState: () => ({
|
|
153
|
+
messages: [],
|
|
154
|
+
suggestions: [],
|
|
155
|
+
capabilities: {},
|
|
156
|
+
}),
|
|
157
|
+
composer: { getState: () => ({ text: "" }) },
|
|
158
|
+
}),
|
|
159
|
+
},
|
|
160
|
+
}),
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const projected = projectApi(1, {
|
|
165
|
+
api: { threads },
|
|
166
|
+
logs: [],
|
|
167
|
+
} as unknown as Parameters<typeof projectApi>[1]);
|
|
168
|
+
|
|
169
|
+
expect(Object.hasOwn(projected.threadSnapshots ?? {}, "__proto__")).toBe(
|
|
170
|
+
true,
|
|
171
|
+
);
|
|
172
|
+
expect(Object.getPrototypeOf(projected.threadSnapshots)).toBe(
|
|
173
|
+
Object.prototype,
|
|
174
|
+
);
|
|
175
|
+
expect(projected.threadSnapshots?.["__proto__"]).toMatchObject({
|
|
176
|
+
messages: [],
|
|
177
|
+
composer: { text: "" },
|
|
178
|
+
});
|
|
179
|
+
});
|
|
139
180
|
});
|
package/src/data/projectApi.ts
CHANGED
|
@@ -82,7 +82,7 @@ const collectThreadSnapshots = (
|
|
|
82
82
|
];
|
|
83
83
|
if (threadIds.length === 0) return undefined;
|
|
84
84
|
|
|
85
|
-
const snapshots: Record<string, unknown> =
|
|
85
|
+
const snapshots: Record<string, unknown> = Object.create(null);
|
|
86
86
|
for (const threadId of threadIds) {
|
|
87
87
|
try {
|
|
88
88
|
const threadRuntime = assistantRuntime.threads.getById(threadId);
|
|
@@ -101,7 +101,7 @@ const collectThreadSnapshots = (
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
return Object.keys(snapshots).length > 0 ? snapshots : undefined;
|
|
104
|
+
return Object.keys(snapshots).length > 0 ? { ...snapshots } : undefined;
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
/**
|
|
@@ -307,3 +307,84 @@ describe("serializeModelContext", () => {
|
|
|
307
307
|
});
|
|
308
308
|
});
|
|
309
309
|
});
|
|
310
|
+
|
|
311
|
+
describe("sanitizeForMessage errors", () => {
|
|
312
|
+
it("keeps the name, message and stack an Error hides behind non-enumerable properties", () => {
|
|
313
|
+
const result = sanitizeForMessage(new Error("boom")) as Record<
|
|
314
|
+
string,
|
|
315
|
+
unknown
|
|
316
|
+
>;
|
|
317
|
+
|
|
318
|
+
expect(result["name"]).toBe("Error");
|
|
319
|
+
expect(result["message"]).toBe("boom");
|
|
320
|
+
expect(typeof result["stack"]).toBe("string");
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("keeps custom fields and the error subclass name", () => {
|
|
324
|
+
class HttpError extends Error {
|
|
325
|
+
override name = "HttpError";
|
|
326
|
+
status = 503;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const result = sanitizeForMessage(new HttpError("unavailable")) as Record<
|
|
330
|
+
string,
|
|
331
|
+
unknown
|
|
332
|
+
>;
|
|
333
|
+
|
|
334
|
+
expect(result["name"]).toBe("HttpError");
|
|
335
|
+
expect(result["message"]).toBe("unavailable");
|
|
336
|
+
expect(result["status"]).toBe(503);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it("serializes a cause chain", () => {
|
|
340
|
+
const result = sanitizeForMessage(
|
|
341
|
+
new Error("outer", { cause: new Error("inner") }),
|
|
342
|
+
) as Record<string, unknown>;
|
|
343
|
+
|
|
344
|
+
expect(result["cause"]).toMatchObject({ name: "Error", message: "inner" });
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it("serializes an error nested in a value", () => {
|
|
348
|
+
const result = sanitizeForMessage({
|
|
349
|
+
status: { reason: "error", error: new Error("nested") },
|
|
350
|
+
}) as { status: { error: Record<string, unknown> } };
|
|
351
|
+
|
|
352
|
+
expect(result.status.error["message"]).toBe("nested");
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it("sanitizes non-JSON values assigned to name, message or stack", () => {
|
|
356
|
+
const error = new Error("boom");
|
|
357
|
+
Object.defineProperty(error, "name", { value: Symbol("weird") });
|
|
358
|
+
Object.defineProperty(error, "message", { value: 10n });
|
|
359
|
+
Object.defineProperty(error, "stack", { value: { nested: 1n } });
|
|
360
|
+
|
|
361
|
+
const result = sanitizeForMessage(error) as Record<string, unknown>;
|
|
362
|
+
|
|
363
|
+
expect(result["name"]).toBe("Symbol(weird)");
|
|
364
|
+
expect(result["message"]).toBe("10");
|
|
365
|
+
expect(result["stack"]).toEqual({ nested: "1" });
|
|
366
|
+
expect(() => JSON.stringify(result)).not.toThrow();
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it("serializes an error from another realm", () => {
|
|
370
|
+
// a cross-realm Error fails instanceof; both it and this stand-in answer
|
|
371
|
+
// the Object.prototype.toString brand check the same way
|
|
372
|
+
// a real cross-realm Error keeps name/message non-enumerable, so only the
|
|
373
|
+
// brand check can surface them; both answer Object.prototype.toString alike
|
|
374
|
+
const foreign = { [Symbol.toStringTag]: "Error" };
|
|
375
|
+
Object.defineProperty(foreign, "name", { value: "ForeignError" });
|
|
376
|
+
Object.defineProperty(foreign, "message", { value: "from an iframe" });
|
|
377
|
+
|
|
378
|
+
const result = sanitizeForMessage(foreign) as Record<string, unknown>;
|
|
379
|
+
|
|
380
|
+
expect(result["name"]).toBe("ForeignError");
|
|
381
|
+
expect(result["message"]).toBe("from an iframe");
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("does not recurse forever on a self-referencing cause", () => {
|
|
385
|
+
const error = new Error("loop") as Error & { cause?: unknown };
|
|
386
|
+
error.cause = error;
|
|
387
|
+
|
|
388
|
+
expect(() => sanitizeForMessage(error)).not.toThrow();
|
|
389
|
+
});
|
|
390
|
+
});
|
|
@@ -20,6 +20,12 @@ const setOwnProperty = (
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
// An Error from an iframe or worker fails `instanceof`, so the brand check is
|
|
24
|
+
// what keeps a cross-realm error from serializing as an empty object.
|
|
25
|
+
const isErrorLike = (value: object): boolean =>
|
|
26
|
+
value instanceof Error ||
|
|
27
|
+
Object.prototype.toString.call(value) === "[object Error]";
|
|
28
|
+
|
|
23
29
|
export const sanitizeForMessage = (
|
|
24
30
|
value: unknown,
|
|
25
31
|
seen = new WeakSet<object>(),
|
|
@@ -99,6 +105,36 @@ export const sanitizeForMessage = (
|
|
|
99
105
|
return result;
|
|
100
106
|
}
|
|
101
107
|
|
|
108
|
+
// `name`, `message` and `stack` are not enumerable, so the branch below
|
|
109
|
+
// would render every Error as an empty object. Each is sanitized like any
|
|
110
|
+
// other value, since an Error carries whatever its author assigned.
|
|
111
|
+
if (isErrorLike(value)) {
|
|
112
|
+
const error: Record<string, unknown> = {
|
|
113
|
+
name: sanitizeForMessage(readProperty(value, "name"), seen),
|
|
114
|
+
message: sanitizeForMessage(readProperty(value, "message"), seen),
|
|
115
|
+
};
|
|
116
|
+
const stack = readProperty(value, "stack");
|
|
117
|
+
if (stack !== undefined) {
|
|
118
|
+
error["stack"] = sanitizeForMessage(stack, seen);
|
|
119
|
+
}
|
|
120
|
+
const cause = readProperty(value, "cause");
|
|
121
|
+
if (cause !== undefined) {
|
|
122
|
+
error["cause"] = sanitizeForMessage(cause, seen);
|
|
123
|
+
}
|
|
124
|
+
for (const key of Object.keys(value)) {
|
|
125
|
+
try {
|
|
126
|
+
setOwnProperty(
|
|
127
|
+
error,
|
|
128
|
+
key,
|
|
129
|
+
sanitizeForMessage(readProperty(value, key), seen),
|
|
130
|
+
);
|
|
131
|
+
} catch {
|
|
132
|
+
setOwnProperty(error, key, UNSERIALIZABLE);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return error;
|
|
136
|
+
}
|
|
137
|
+
|
|
102
138
|
const result: Record<string, unknown> = {};
|
|
103
139
|
for (const key of Object.keys(value)) {
|
|
104
140
|
try {
|