@assistant-ui/react-devtools 1.2.6 → 1.2.7
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/README.md +26 -8
- package/dist/DevToolsModal.d.ts +18 -2
- package/dist/DevToolsModal.d.ts.map +1 -1
- package/dist/DevToolsModal.js +25 -232
- package/dist/DevToolsModal.js.map +1 -1
- package/dist/DevToolsModalImpl.d.ts +11 -0
- package/dist/DevToolsModalImpl.d.ts.map +1 -0
- package/dist/DevToolsModalImpl.js +62 -0
- package/dist/DevToolsModalImpl.js.map +1 -0
- package/dist/data/createInProcessClient.d.ts +17 -0
- package/dist/data/createInProcessClient.d.ts.map +1 -0
- package/dist/data/createInProcessClient.js +54 -0
- package/dist/data/createInProcessClient.js.map +1 -0
- package/dist/data/projectApi.d.ts +22 -0
- package/dist/data/projectApi.d.ts.map +1 -0
- package/dist/data/projectApi.js +103 -0
- package/dist/data/projectApi.js.map +1 -0
- package/dist/data/types.d.ts +52 -0
- package/dist/data/types.d.ts.map +1 -0
- package/dist/data/types.js +10 -0
- package/dist/data/types.js.map +1 -0
- package/dist/data/useDevToolsClient.d.ts +19 -0
- package/dist/data/useDevToolsClient.d.ts.map +1 -0
- package/dist/data/useDevToolsClient.js +70 -0
- package/dist/data/useDevToolsClient.js.map +1 -0
- package/dist/index.d.ts +9 -10
- package/dist/index.js +7 -9
- package/dist/shell/DevToolsOverlay.d.ts +23 -0
- package/dist/shell/DevToolsOverlay.d.ts.map +1 -0
- package/dist/shell/DevToolsOverlay.js +106 -0
- package/dist/shell/DevToolsOverlay.js.map +1 -0
- package/dist/shell/DevToolsPanel.d.ts +23 -0
- package/dist/shell/DevToolsPanel.d.ts.map +1 -0
- package/dist/shell/DevToolsPanel.js +256 -0
- package/dist/shell/DevToolsPanel.js.map +1 -0
- package/dist/shell/ShadowRoot.d.ts +24 -0
- package/dist/shell/ShadowRoot.d.ts.map +1 -0
- package/dist/shell/ShadowRoot.js +107 -0
- package/dist/shell/ShadowRoot.js.map +1 -0
- package/dist/shell/SplitLayout.d.ts +28 -0
- package/dist/shell/SplitLayout.d.ts.map +1 -0
- package/dist/shell/SplitLayout.js +67 -0
- package/dist/shell/SplitLayout.js.map +1 -0
- package/dist/shell/registry.d.ts +41 -0
- package/dist/shell/registry.d.ts.map +1 -0
- package/dist/shell/registry.js +36 -0
- package/dist/shell/registry.js.map +1 -0
- package/dist/shell/tabs/ActivityTab.d.ts +13 -0
- package/dist/shell/tabs/ActivityTab.d.ts.map +1 -0
- package/dist/shell/tabs/ActivityTab.js +259 -0
- package/dist/shell/tabs/ActivityTab.js.map +1 -0
- package/dist/shell/tabs/ContextTab.d.ts +11 -0
- package/dist/shell/tabs/ContextTab.d.ts.map +1 -0
- package/dist/shell/tabs/ContextTab.js +210 -0
- package/dist/shell/tabs/ContextTab.js.map +1 -0
- package/dist/shell/tabs/RawTab.d.ts +11 -0
- package/dist/shell/tabs/RawTab.d.ts.map +1 -0
- package/dist/shell/tabs/RawTab.js +238 -0
- package/dist/shell/tabs/RawTab.js.map +1 -0
- package/dist/shell/tabs/ThreadTab.d.ts +12 -0
- package/dist/shell/tabs/ThreadTab.d.ts.map +1 -0
- package/dist/shell/tabs/ThreadTab.js +426 -0
- package/dist/shell/tabs/ThreadTab.js.map +1 -0
- package/dist/shell/tabs/navSelection.d.ts +10 -0
- package/dist/shell/tabs/navSelection.d.ts.map +1 -0
- package/dist/shell/tabs/navSelection.js +37 -0
- package/dist/shell/tabs/navSelection.js.map +1 -0
- package/dist/styles/panel.generated.d.ts +5 -0
- package/dist/styles/panel.generated.d.ts.map +1 -0
- package/dist/styles/panel.generated.js +6 -0
- package/dist/styles/panel.generated.js.map +1 -0
- package/dist/types.d.ts +1 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/common.d.ts +24 -0
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/common.js +64 -0
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/diff.d.ts +16 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +41 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/serialization.d.ts.map +1 -1
- package/dist/utils/serialization.js +4 -1
- package/dist/utils/serialization.js.map +1 -1
- package/dist/views/activity/EventLogRow.d.ts +28 -0
- package/dist/views/activity/EventLogRow.d.ts.map +1 -0
- package/dist/views/activity/EventLogRow.js +185 -0
- package/dist/views/activity/EventLogRow.js.map +1 -0
- package/dist/views/activity/EventStreamPane.d.ts +11 -0
- package/dist/views/activity/EventStreamPane.d.ts.map +1 -0
- package/dist/views/activity/EventStreamPane.js +98 -0
- package/dist/views/activity/EventStreamPane.js.map +1 -0
- package/dist/views/activity/OrphansPane.d.ts +11 -0
- package/dist/views/activity/OrphansPane.d.ts.map +1 -0
- package/dist/views/activity/OrphansPane.js +39 -0
- package/dist/views/activity/OrphansPane.js.map +1 -0
- package/dist/views/activity/RunDetailPane.d.ts +11 -0
- package/dist/views/activity/RunDetailPane.d.ts.map +1 -0
- package/dist/views/activity/RunDetailPane.js +344 -0
- package/dist/views/activity/RunDetailPane.js.map +1 -0
- package/dist/views/activity/activityNodes.d.ts +39 -0
- package/dist/views/activity/activityNodes.d.ts.map +1 -0
- package/dist/views/activity/activityNodes.js +199 -0
- package/dist/views/activity/activityNodes.js.map +1 -0
- package/dist/views/activity/index.d.ts +6 -0
- package/dist/views/activity/index.js +6 -0
- package/dist/views/attachments/AttachmentList.d.ts +15 -0
- package/dist/views/attachments/AttachmentList.d.ts.map +1 -0
- package/dist/views/attachments/AttachmentList.js +279 -0
- package/dist/views/attachments/AttachmentList.js.map +1 -0
- package/dist/views/attachments/MediaPartView.d.ts +27 -0
- package/dist/views/attachments/MediaPartView.d.ts.map +1 -0
- package/dist/views/attachments/MediaPartView.js +180 -0
- package/dist/views/attachments/MediaPartView.js.map +1 -0
- package/dist/views/attachments/formatBytes.d.ts +8 -0
- package/dist/views/attachments/formatBytes.d.ts.map +1 -0
- package/dist/views/attachments/formatBytes.js +14 -0
- package/dist/views/attachments/formatBytes.js.map +1 -0
- package/dist/views/attachments/index.d.ts +5 -0
- package/dist/views/attachments/index.js +4 -0
- package/dist/views/attachments/parseAttachment.d.ts +8 -0
- package/dist/views/attachments/parseAttachment.d.ts.map +1 -0
- package/dist/views/attachments/parseAttachment.js +58 -0
- package/dist/views/attachments/parseAttachment.js.map +1 -0
- package/dist/views/attachments/types.d.ts +18 -0
- package/dist/views/attachments/types.d.ts.map +1 -0
- package/dist/views/attachments/types.js +0 -0
- package/dist/views/context/ContextDetail.d.ts +14 -0
- package/dist/views/context/ContextDetail.d.ts.map +1 -0
- package/dist/views/context/ContextDetail.js +87 -0
- package/dist/views/context/ContextDetail.js.map +1 -0
- package/dist/views/context/ToolUIsView.d.ts +9 -0
- package/dist/views/context/ToolUIsView.d.ts.map +1 -0
- package/dist/views/context/ToolUIsView.js +80 -0
- package/dist/views/context/ToolUIsView.js.map +1 -0
- package/dist/views/context/contextNodes.d.ts +32 -0
- package/dist/views/context/contextNodes.d.ts.map +1 -0
- package/dist/views/context/contextNodes.js +49 -0
- package/dist/views/context/contextNodes.js.map +1 -0
- package/dist/views/context/index.d.ts +4 -0
- package/dist/views/context/index.js +4 -0
- package/dist/views/mcp/McpView.d.ts +11 -0
- package/dist/views/mcp/McpView.d.ts.map +1 -0
- package/dist/views/mcp/McpView.js +239 -0
- package/dist/views/mcp/McpView.js.map +1 -0
- package/dist/views/mcp/index.d.ts +2 -0
- package/dist/views/mcp/index.js +2 -0
- package/dist/views/mcp/parse.d.ts +7 -0
- package/dist/views/mcp/parse.d.ts.map +1 -0
- package/dist/views/mcp/parse.js +43 -0
- package/dist/views/mcp/parse.js.map +1 -0
- package/dist/views/mcp/types.d.ts +22 -0
- package/dist/views/mcp/types.d.ts.map +1 -0
- package/dist/views/mcp/types.js +0 -0
- package/dist/views/message/ChainOfThought.d.ts +11 -0
- package/dist/views/message/ChainOfThought.d.ts.map +1 -0
- package/dist/views/message/ChainOfThought.js +132 -0
- package/dist/views/message/ChainOfThought.js.map +1 -0
- package/dist/views/message/MessageDetailPane.d.ts +12 -0
- package/dist/views/message/MessageDetailPane.d.ts.map +1 -0
- package/dist/views/message/MessageDetailPane.js +38 -0
- package/dist/views/message/MessageDetailPane.js.map +1 -0
- package/dist/views/message/MessageItem.d.ts +13 -0
- package/dist/views/message/MessageItem.d.ts.map +1 -0
- package/dist/views/message/MessageItem.js +136 -0
- package/dist/views/message/MessageItem.js.map +1 -0
- package/dist/views/message/MessageList.d.ts +13 -0
- package/dist/views/message/MessageList.d.ts.map +1 -0
- package/dist/views/message/MessageList.js +95 -0
- package/dist/views/message/MessageList.js.map +1 -0
- package/dist/views/message/MessageMetrics.d.ts +11 -0
- package/dist/views/message/MessageMetrics.d.ts.map +1 -0
- package/dist/views/message/MessageMetrics.js +93 -0
- package/dist/views/message/MessageMetrics.js.map +1 -0
- package/dist/views/message/MessageTimeline.d.ts +16 -0
- package/dist/views/message/MessageTimeline.d.ts.map +1 -0
- package/dist/views/message/MessageTimeline.js +100 -0
- package/dist/views/message/MessageTimeline.js.map +1 -0
- package/dist/views/message/PartDisclosure.d.ts +18 -0
- package/dist/views/message/PartDisclosure.d.ts.map +1 -0
- package/dist/views/message/PartDisclosure.js +79 -0
- package/dist/views/message/PartDisclosure.js.map +1 -0
- package/dist/views/message/PartView.d.ts +13 -0
- package/dist/views/message/PartView.d.ts.map +1 -0
- package/dist/views/message/PartView.js +416 -0
- package/dist/views/message/PartView.js.map +1 -0
- package/dist/views/message/RoleLabel.d.ts +11 -0
- package/dist/views/message/RoleLabel.d.ts.map +1 -0
- package/dist/views/message/RoleLabel.js +30 -0
- package/dist/views/message/RoleLabel.js.map +1 -0
- package/dist/views/message/StatusBadge.d.ts +17 -0
- package/dist/views/message/StatusBadge.d.ts.map +1 -0
- package/dist/views/message/StatusBadge.js +58 -0
- package/dist/views/message/StatusBadge.js.map +1 -0
- package/dist/views/message/ToolCallView.d.ts +13 -0
- package/dist/views/message/ToolCallView.d.ts.map +1 -0
- package/dist/views/message/ToolCallView.js +289 -0
- package/dist/views/message/ToolCallView.js.map +1 -0
- package/dist/views/message/TtftBar.d.ts +16 -0
- package/dist/views/message/TtftBar.d.ts.map +1 -0
- package/dist/views/message/TtftBar.js +128 -0
- package/dist/views/message/TtftBar.js.map +1 -0
- package/dist/views/message/index.d.ts +6 -0
- package/dist/views/message/index.js +5 -0
- package/dist/views/message/messagePlainText.d.ts +8 -0
- package/dist/views/message/messagePlainText.d.ts.map +1 -0
- package/dist/views/message/messagePlainText.js +39 -0
- package/dist/views/message/messagePlainText.js.map +1 -0
- package/dist/views/message/parse.d.ts +10 -0
- package/dist/views/message/parse.d.ts.map +1 -0
- package/dist/views/message/parse.js +235 -0
- package/dist/views/message/parse.js.map +1 -0
- package/dist/views/message/types.d.ts +114 -0
- package/dist/views/message/types.d.ts.map +1 -0
- package/dist/views/message/types.js +0 -0
- package/dist/views/model-context/ModelContextView.d.ts +26 -0
- package/dist/views/model-context/ModelContextView.d.ts.map +1 -0
- package/dist/views/model-context/ModelContextView.js +214 -0
- package/dist/views/model-context/ModelContextView.js.map +1 -0
- package/dist/views/nav.d.ts +19 -0
- package/dist/views/nav.d.ts.map +1 -0
- package/dist/views/nav.js +8 -0
- package/dist/views/nav.js.map +1 -0
- package/dist/views/raw/RawDetail.d.ts +15 -0
- package/dist/views/raw/RawDetail.d.ts.map +1 -0
- package/dist/views/raw/RawDetail.js +79 -0
- package/dist/views/raw/RawDetail.js.map +1 -0
- package/dist/views/raw/index.d.ts +3 -0
- package/dist/views/raw/index.js +3 -0
- package/dist/views/raw/rawNodes.d.ts +20 -0
- package/dist/views/raw/rawNodes.d.ts.map +1 -0
- package/dist/views/raw/rawNodes.js +78 -0
- package/dist/views/raw/rawNodes.js.map +1 -0
- package/dist/views/raw/statePreview.d.ts +5 -0
- package/dist/views/raw/statePreview.d.ts.map +1 -0
- package/dist/views/raw/statePreview.js +213 -0
- package/dist/views/raw/statePreview.js.map +1 -0
- package/dist/views/runs/PayloadDiff.d.ts +11 -0
- package/dist/views/runs/PayloadDiff.d.ts.map +1 -0
- package/dist/views/runs/PayloadDiff.js +92 -0
- package/dist/views/runs/PayloadDiff.js.map +1 -0
- package/dist/views/runs/parse.d.ts +8 -0
- package/dist/views/runs/parse.d.ts.map +1 -0
- package/dist/views/runs/parse.js +78 -0
- package/dist/views/runs/parse.js.map +1 -0
- package/dist/views/runs/types.d.ts +25 -0
- package/dist/views/runs/types.d.ts.map +1 -0
- package/dist/views/runs/types.js +0 -0
- package/dist/views/scopes/ScopesView.d.ts +9 -0
- package/dist/views/scopes/ScopesView.d.ts.map +1 -0
- package/dist/views/scopes/ScopesView.js +235 -0
- package/dist/views/scopes/ScopesView.js.map +1 -0
- package/dist/views/scopes/index.d.ts +2 -0
- package/dist/views/scopes/index.js +2 -0
- package/dist/views/scopes/parse.d.ts +7 -0
- package/dist/views/scopes/parse.d.ts.map +1 -0
- package/dist/views/scopes/parse.js +23 -0
- package/dist/views/scopes/parse.js.map +1 -0
- package/dist/views/scopes/types.d.ts +10 -0
- package/dist/views/scopes/types.d.ts.map +1 -0
- package/dist/views/scopes/types.js +0 -0
- package/dist/views/thread/ComposerAttachments.d.ts +11 -0
- package/dist/views/thread/ComposerAttachments.d.ts.map +1 -0
- package/dist/views/thread/ComposerAttachments.js +22 -0
- package/dist/views/thread/ComposerAttachments.js.map +1 -0
- package/dist/views/thread/ComposerFlags.d.ts +11 -0
- package/dist/views/thread/ComposerFlags.d.ts.map +1 -0
- package/dist/views/thread/ComposerFlags.js +54 -0
- package/dist/views/thread/ComposerFlags.js.map +1 -0
- package/dist/views/thread/ComposerQueue.d.ts +11 -0
- package/dist/views/thread/ComposerQueue.d.ts.map +1 -0
- package/dist/views/thread/ComposerQueue.js +55 -0
- package/dist/views/thread/ComposerQueue.js.map +1 -0
- package/dist/views/thread/ConversationList.d.ts +18 -0
- package/dist/views/thread/ConversationList.d.ts.map +1 -0
- package/dist/views/thread/ConversationList.js +228 -0
- package/dist/views/thread/ConversationList.js.map +1 -0
- package/dist/views/thread/ConversationStatusDot.d.ts +29 -0
- package/dist/views/thread/ConversationStatusDot.d.ts.map +1 -0
- package/dist/views/thread/ConversationStatusDot.js +91 -0
- package/dist/views/thread/ConversationStatusDot.js.map +1 -0
- package/dist/views/thread/ThreadDetails.d.ts +13 -0
- package/dist/views/thread/ThreadDetails.d.ts.map +1 -0
- package/dist/views/thread/ThreadDetails.js +170 -0
- package/dist/views/thread/ThreadDetails.js.map +1 -0
- package/dist/views/thread/Transcript.d.ts +21 -0
- package/dist/views/thread/Transcript.d.ts.map +1 -0
- package/dist/views/thread/Transcript.js +520 -0
- package/dist/views/thread/Transcript.js.map +1 -0
- package/dist/views/thread/index.d.ts +10 -0
- package/dist/views/thread/index.js +9 -0
- package/dist/views/thread/resolve.d.ts +13 -0
- package/dist/views/thread/resolve.d.ts.map +1 -0
- package/dist/views/thread/resolve.js +29 -0
- package/dist/views/thread/resolve.js.map +1 -0
- package/dist/views/thread/types.d.ts +50 -0
- package/dist/views/thread/types.d.ts.map +1 -0
- package/dist/views/thread/types.js +0 -0
- package/dist/views/thread/utils.d.ts +10 -0
- package/dist/views/thread/utils.d.ts.map +1 -0
- package/dist/views/thread/utils.js +77 -0
- package/dist/views/thread/utils.js.map +1 -0
- package/dist/views/ui/CenteredMessage.d.ts +11 -0
- package/dist/views/ui/CenteredMessage.d.ts.map +1 -0
- package/dist/views/ui/CenteredMessage.js +21 -0
- package/dist/views/ui/CenteredMessage.js.map +1 -0
- package/dist/views/ui/Chip.d.ts +13 -0
- package/dist/views/ui/Chip.d.ts.map +1 -0
- package/dist/views/ui/Chip.js +30 -0
- package/dist/views/ui/Chip.js.map +1 -0
- package/dist/views/ui/ControlButton.d.ts +10 -0
- package/dist/views/ui/ControlButton.d.ts.map +1 -0
- package/dist/views/ui/ControlButton.js +39 -0
- package/dist/views/ui/ControlButton.js.map +1 -0
- package/dist/views/ui/CopyButton.d.ts +19 -0
- package/dist/views/ui/CopyButton.d.ts.map +1 -0
- package/dist/views/ui/CopyButton.js +125 -0
- package/dist/views/ui/CopyButton.js.map +1 -0
- package/dist/views/ui/EmptyState.d.ts +11 -0
- package/dist/views/ui/EmptyState.d.ts.map +1 -0
- package/dist/views/ui/EmptyState.js +21 -0
- package/dist/views/ui/EmptyState.js.map +1 -0
- package/dist/views/ui/InfoCard.d.ts +22 -0
- package/dist/views/ui/InfoCard.d.ts.map +1 -0
- package/dist/views/ui/InfoCard.js +44 -0
- package/dist/views/ui/InfoCard.js.map +1 -0
- package/dist/views/ui/JSONTree.d.ts +16 -0
- package/dist/views/ui/JSONTree.d.ts.map +1 -0
- package/dist/views/ui/JSONTree.js +394 -0
- package/dist/views/ui/JSONTree.js.map +1 -0
- package/dist/views/ui/PaneHeader.d.ts +27 -0
- package/dist/views/ui/PaneHeader.d.ts.map +1 -0
- package/dist/views/ui/PaneHeader.js +71 -0
- package/dist/views/ui/PaneHeader.js.map +1 -0
- package/dist/views/ui/RailTime.d.ts +12 -0
- package/dist/views/ui/RailTime.d.ts.map +1 -0
- package/dist/views/ui/RailTime.js +49 -0
- package/dist/views/ui/RailTime.js.map +1 -0
- package/dist/views/ui/SectionLabel.d.ts +11 -0
- package/dist/views/ui/SectionLabel.d.ts.map +1 -0
- package/dist/views/ui/SectionLabel.js +21 -0
- package/dist/views/ui/SectionLabel.js.map +1 -0
- package/dist/views/ui/SelectableRow.d.ts +18 -0
- package/dist/views/ui/SelectableRow.d.ts.map +1 -0
- package/dist/views/ui/SelectableRow.js +49 -0
- package/dist/views/ui/SelectableRow.js.map +1 -0
- package/dist/views/ui/Sparkline.d.ts +17 -0
- package/dist/views/ui/Sparkline.d.ts.map +1 -0
- package/dist/views/ui/Sparkline.js +96 -0
- package/dist/views/ui/Sparkline.js.map +1 -0
- package/dist/views/ui/SummaryItem.d.ts +23 -0
- package/dist/views/ui/SummaryItem.d.ts.map +1 -0
- package/dist/views/ui/SummaryItem.js +59 -0
- package/dist/views/ui/SummaryItem.js.map +1 -0
- package/dist/views/ui/ToneBadge.d.ts +18 -0
- package/dist/views/ui/ToneBadge.d.ts.map +1 -0
- package/dist/views/ui/ToneBadge.js +34 -0
- package/dist/views/ui/ToneBadge.js.map +1 -0
- package/dist/views/ui/badgeTone.d.ts +21 -0
- package/dist/views/ui/badgeTone.d.ts.map +1 -0
- package/dist/views/ui/badgeTone.js +33 -0
- package/dist/views/ui/badgeTone.js.map +1 -0
- package/dist/views/ui/index.d.ts +16 -0
- package/dist/views/ui/index.js +16 -0
- package/dist/views/ui/useCopyToClipboard.d.ts +12 -0
- package/dist/views/ui/useCopyToClipboard.d.ts.map +1 -0
- package/dist/views/ui/useCopyToClipboard.js +44 -0
- package/dist/views/ui/useCopyToClipboard.js.map +1 -0
- package/package.json +9 -5
- package/src/DevToolsModal.tsx +26 -179
- package/src/DevToolsModalImpl.tsx +60 -0
- package/src/data/createInProcessClient.ts +66 -0
- package/src/data/projectApi.test.ts +100 -0
- package/src/data/projectApi.ts +169 -0
- package/src/data/types.ts +54 -0
- package/src/data/useDevToolsClient.ts +59 -0
- package/src/index.ts +16 -13
- package/src/shell/DevToolsOverlay.tsx +84 -0
- package/src/shell/DevToolsPanel.tsx +192 -0
- package/src/shell/ShadowRoot.tsx +85 -0
- package/src/shell/SplitLayout.tsx +46 -0
- package/src/shell/registry.ts +51 -0
- package/src/shell/tabs/ActivityTab.test.tsx +34 -0
- package/src/shell/tabs/ActivityTab.tsx +161 -0
- package/src/shell/tabs/ContextTab.test.tsx +37 -0
- package/src/shell/tabs/ContextTab.tsx +157 -0
- package/src/shell/tabs/RawTab.test.tsx +43 -0
- package/src/shell/tabs/RawTab.tsx +123 -0
- package/src/shell/tabs/ThreadTab.tsx +220 -0
- package/src/shell/tabs/navSelection.ts +17 -0
- package/src/styles/panel.css +153 -0
- package/src/styles/panel.generated.ts +2 -0
- package/src/types.ts +0 -5
- package/src/utils/common.test.ts +30 -0
- package/src/utils/common.ts +101 -0
- package/src/utils/diff.test.ts +37 -0
- package/src/utils/diff.ts +41 -0
- package/src/utils/serialization.test.ts +31 -0
- package/src/utils/serialization.ts +4 -1
- package/src/views/activity/EventLogRow.tsx +108 -0
- package/src/views/activity/EventStreamPane.tsx +86 -0
- package/src/views/activity/OrphansPane.tsx +23 -0
- package/src/views/activity/RunDetailPane.tsx +128 -0
- package/src/views/activity/activityNodes.test.ts +24 -0
- package/src/views/activity/activityNodes.ts +179 -0
- package/src/views/activity/index.ts +10 -0
- package/src/views/attachments/AttachmentList.tsx +122 -0
- package/src/views/attachments/MediaPartView.tsx +77 -0
- package/src/views/attachments/formatBytes.ts +15 -0
- package/src/views/attachments/index.ts +4 -0
- package/src/views/attachments/parseAttachment.test.ts +37 -0
- package/src/views/attachments/parseAttachment.ts +85 -0
- package/src/views/attachments/types.ts +15 -0
- package/src/views/context/ContextDetail.tsx +37 -0
- package/src/views/context/ToolUIsView.tsx +44 -0
- package/src/views/context/contextNodes.test.ts +31 -0
- package/src/views/context/contextNodes.ts +66 -0
- package/src/views/context/index.ts +4 -0
- package/src/views/mcp/McpView.tsx +125 -0
- package/src/views/mcp/index.ts +1 -0
- package/src/views/mcp/parse.test.ts +63 -0
- package/src/views/mcp/parse.ts +65 -0
- package/src/views/mcp/render.test.tsx +34 -0
- package/src/views/mcp/types.ts +20 -0
- package/src/views/message/ChainOfThought.tsx +74 -0
- package/src/views/message/MessageDetailPane.tsx +26 -0
- package/src/views/message/MessageItem.tsx +94 -0
- package/src/views/message/MessageList.tsx +48 -0
- package/src/views/message/MessageMetrics.tsx +68 -0
- package/src/views/message/MessageTimeline.test.tsx +78 -0
- package/src/views/message/MessageTimeline.tsx +51 -0
- package/src/views/message/PartDisclosure.tsx +32 -0
- package/src/views/message/PartView.tsx +197 -0
- package/src/views/message/RoleLabel.tsx +22 -0
- package/src/views/message/StatusBadge.tsx +28 -0
- package/src/views/message/ToolCallView.tsx +151 -0
- package/src/views/message/TtftBar.tsx +44 -0
- package/src/views/message/index.ts +5 -0
- package/src/views/message/messagePlainText.test.ts +48 -0
- package/src/views/message/messagePlainText.ts +65 -0
- package/src/views/message/parse.test.ts +269 -0
- package/src/views/message/parse.ts +282 -0
- package/src/views/message/render.test.tsx +128 -0
- package/src/views/message/types.ts +137 -0
- package/src/views/model-context/ModelContextView.tsx +71 -0
- package/src/views/model-context/render.test.tsx +24 -0
- package/src/views/nav.ts +18 -0
- package/src/views/raw/RawDetail.tsx +39 -0
- package/src/views/raw/index.ts +3 -0
- package/src/views/raw/rawNodes.test.ts +38 -0
- package/src/views/raw/rawNodes.ts +107 -0
- package/src/views/raw/statePreview.tsx +188 -0
- package/src/views/runs/PayloadDiff.tsx +49 -0
- package/src/views/runs/parse.test.ts +152 -0
- package/src/views/runs/parse.ts +110 -0
- package/src/views/runs/types.ts +23 -0
- package/src/views/scopes/ScopesView.tsx +105 -0
- package/src/views/scopes/index.ts +1 -0
- package/src/views/scopes/parse.test.ts +35 -0
- package/src/views/scopes/parse.ts +30 -0
- package/src/views/scopes/render.test.tsx +35 -0
- package/src/views/scopes/types.ts +6 -0
- package/src/views/thread/ComposerAttachments.test.tsx +36 -0
- package/src/views/thread/ComposerAttachments.tsx +8 -0
- package/src/views/thread/ComposerFlags.test.tsx +23 -0
- package/src/views/thread/ComposerFlags.tsx +19 -0
- package/src/views/thread/ComposerQueue.test.tsx +20 -0
- package/src/views/thread/ComposerQueue.tsx +26 -0
- package/src/views/thread/ConversationList.tsx +127 -0
- package/src/views/thread/ConversationStatusDot.test.ts +86 -0
- package/src/views/thread/ConversationStatusDot.tsx +126 -0
- package/src/views/thread/ThreadDetails.tsx +85 -0
- package/src/views/thread/Transcript.test.tsx +56 -0
- package/src/views/thread/Transcript.tsx +332 -0
- package/src/views/thread/index.ts +19 -0
- package/src/views/thread/render.test.tsx +41 -0
- package/src/views/thread/resolve.ts +36 -0
- package/src/views/thread/types.ts +53 -0
- package/src/views/thread/utils.test.ts +72 -0
- package/src/views/thread/utils.ts +149 -0
- package/src/views/ui/CenteredMessage.tsx +7 -0
- package/src/views/ui/Chip.tsx +17 -0
- package/src/views/ui/ControlButton.tsx +15 -0
- package/src/views/ui/CopyButton.tsx +73 -0
- package/src/views/ui/EmptyState.tsx +7 -0
- package/src/views/ui/InfoCard.tsx +35 -0
- package/src/views/ui/JSONTree.test.tsx +29 -0
- package/src/views/ui/JSONTree.tsx +240 -0
- package/src/views/ui/PaneHeader.tsx +46 -0
- package/src/views/ui/RailTime.tsx +27 -0
- package/src/views/ui/SectionLabel.tsx +7 -0
- package/src/views/ui/SelectableRow.tsx +41 -0
- package/src/views/ui/Sparkline.tsx +49 -0
- package/src/views/ui/SummaryItem.tsx +25 -0
- package/src/views/ui/ToneBadge.tsx +26 -0
- package/src/views/ui/badgeTone.ts +40 -0
- package/src/views/ui/index.ts +20 -0
- package/src/views/ui/useCopyToClipboard.ts +27 -0
- package/dist/DevToolsFrame.d.ts +0 -11
- package/dist/DevToolsFrame.d.ts.map +0 -1
- package/dist/DevToolsFrame.js +0 -66
- package/dist/DevToolsFrame.js.map +0 -1
- package/dist/DevToolsHost.d.ts +0 -38
- package/dist/DevToolsHost.d.ts.map +0 -1
- package/dist/DevToolsHost.js +0 -93
- package/dist/DevToolsHost.js.map +0 -1
- package/dist/ExtensionHost.d.ts +0 -10
- package/dist/ExtensionHost.d.ts.map +0 -1
- package/dist/ExtensionHost.js +0 -42
- package/dist/ExtensionHost.js.map +0 -1
- package/dist/FrameClient.d.ts +0 -38
- package/dist/FrameClient.d.ts.map +0 -1
- package/dist/FrameClient.js +0 -53
- package/dist/FrameClient.js.map +0 -1
- package/dist/FrameHost.d.ts +0 -11
- package/dist/FrameHost.d.ts.map +0 -1
- package/dist/FrameHost.js +0 -26
- package/dist/FrameHost.js.map +0 -1
- package/dist/constants.d.ts +0 -6
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -7
- package/dist/constants.js.map +0 -1
- package/dist/styles/DevToolsModal.styles.d.ts +0 -18
- package/dist/styles/DevToolsModal.styles.d.ts.map +0 -1
- package/dist/styles/DevToolsModal.styles.js +0 -120
- package/dist/styles/DevToolsModal.styles.js.map +0 -1
- package/src/DevToolsFrame.tsx +0 -55
- package/src/DevToolsHost.ts +0 -178
- package/src/ExtensionHost.ts +0 -57
- package/src/FrameClient.ts +0 -99
- package/src/FrameHost.ts +0 -31
- package/src/constants.ts +0 -2
- package/src/styles/DevToolsModal.styles.ts +0 -137
package/src/DevToolsModal.tsx
CHANGED
|
@@ -1,183 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
attributeFilter: ["class"],
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
if (document.body !== document.documentElement) {
|
|
28
|
-
observer.observe(document.body, {
|
|
29
|
-
attributes: true,
|
|
30
|
-
attributeFilter: ["class"],
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return () => observer.disconnect();
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const DevToolsModalImpl = () => {
|
|
38
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
39
|
-
const [buttonHover, setButtonHover] = useState(false);
|
|
40
|
-
const [closeHover, setCloseHover] = useState(false);
|
|
41
|
-
|
|
42
|
-
const darkMode = useSyncExternalStore(
|
|
43
|
-
subscribeToThemeChanges,
|
|
44
|
-
isDarkMode,
|
|
45
|
-
() => false, // Server-side always returns false
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const styles = useMemo(() => getStyles(darkMode), [darkMode]);
|
|
49
|
-
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (typeof document === "undefined") return;
|
|
52
|
-
|
|
53
|
-
const styleId = "devtools-modal-animations";
|
|
54
|
-
if (!document.getElementById(styleId)) {
|
|
55
|
-
const style = document.createElement("style");
|
|
56
|
-
style.id = styleId;
|
|
57
|
-
style.textContent = ANIMATION_STYLES;
|
|
58
|
-
document.head.appendChild(style);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return () => {
|
|
62
|
-
const style = document.getElementById(styleId);
|
|
63
|
-
if (style && !document.querySelector("[data-devtools-modal]")) {
|
|
64
|
-
style.remove();
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}, []);
|
|
68
|
-
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
if (!isOpen) return;
|
|
71
|
-
|
|
72
|
-
const handleEscape = (event: KeyboardEvent) => {
|
|
73
|
-
if (event.key === "Escape") {
|
|
74
|
-
setIsOpen(false);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
document.addEventListener("keydown", handleEscape);
|
|
79
|
-
return () => document.removeEventListener("keydown", handleEscape);
|
|
80
|
-
}, [isOpen]);
|
|
81
|
-
|
|
82
|
-
return (
|
|
83
|
-
<>
|
|
84
|
-
<div style={styles.floatingContainer}>
|
|
85
|
-
<button
|
|
86
|
-
type="button"
|
|
87
|
-
onClick={() => setIsOpen(true)}
|
|
88
|
-
onMouseEnter={() => setButtonHover(true)}
|
|
89
|
-
onMouseLeave={() => setButtonHover(false)}
|
|
90
|
-
style={{
|
|
91
|
-
...styles.floatingButton,
|
|
92
|
-
...(buttonHover ? styles.floatingButtonHover : {}),
|
|
93
|
-
}}
|
|
94
|
-
aria-label="Open assistant-ui DevTools"
|
|
95
|
-
title="Open assistant-ui DevTools"
|
|
96
|
-
>
|
|
97
|
-
<svg
|
|
98
|
-
aria-hidden="true"
|
|
99
|
-
width="20"
|
|
100
|
-
height="20"
|
|
101
|
-
viewBox="0 0 24 24"
|
|
102
|
-
fill="none"
|
|
103
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
104
|
-
style={{ width: "20px", height: "20px" }}
|
|
105
|
-
>
|
|
106
|
-
<path
|
|
107
|
-
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
|
108
|
-
stroke="currentColor"
|
|
109
|
-
strokeWidth="1.8"
|
|
110
|
-
strokeLinecap="round"
|
|
111
|
-
strokeLinejoin="round"
|
|
112
|
-
fill="none"
|
|
113
|
-
/>
|
|
114
|
-
</svg>
|
|
115
|
-
</button>
|
|
116
|
-
</div>
|
|
117
|
-
|
|
118
|
-
{isOpen && (
|
|
119
|
-
<>
|
|
120
|
-
<div style={styles.backdrop} onClick={() => setIsOpen(false)} />
|
|
121
|
-
|
|
122
|
-
<div style={styles.modal} data-devtools-modal>
|
|
123
|
-
<button
|
|
124
|
-
type="button"
|
|
125
|
-
onClick={() => setIsOpen(false)}
|
|
126
|
-
onMouseEnter={() => setCloseHover(true)}
|
|
127
|
-
onMouseLeave={() => setCloseHover(false)}
|
|
128
|
-
style={{
|
|
129
|
-
...styles.dismissButton,
|
|
130
|
-
...(closeHover ? styles.dismissButtonHover : {}),
|
|
131
|
-
}}
|
|
132
|
-
aria-label="Close DevTools"
|
|
133
|
-
>
|
|
134
|
-
<svg
|
|
135
|
-
aria-hidden="true"
|
|
136
|
-
width="14"
|
|
137
|
-
height="14"
|
|
138
|
-
viewBox="0 0 24 24"
|
|
139
|
-
fill="none"
|
|
140
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
141
|
-
>
|
|
142
|
-
<path
|
|
143
|
-
d="M18 6L6 18"
|
|
144
|
-
stroke="currentColor"
|
|
145
|
-
strokeWidth="1.6"
|
|
146
|
-
strokeLinecap="round"
|
|
147
|
-
strokeLinejoin="round"
|
|
148
|
-
/>
|
|
149
|
-
<path
|
|
150
|
-
d="M6 6L18 18"
|
|
151
|
-
stroke="currentColor"
|
|
152
|
-
strokeWidth="1.6"
|
|
153
|
-
strokeLinecap="round"
|
|
154
|
-
strokeLinejoin="round"
|
|
155
|
-
/>
|
|
156
|
-
</svg>
|
|
157
|
-
</button>
|
|
158
|
-
|
|
159
|
-
<div style={styles.modalContent}>
|
|
160
|
-
<DevToolsFrame
|
|
161
|
-
style={{
|
|
162
|
-
width: "100%",
|
|
163
|
-
height: "100%",
|
|
164
|
-
border: "none",
|
|
165
|
-
borderRadius: "12px",
|
|
166
|
-
backgroundColor: "transparent",
|
|
167
|
-
}}
|
|
168
|
-
/>
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
</>
|
|
172
|
-
)}
|
|
173
|
-
</>
|
|
174
|
-
);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// Export a component that only renders in development
|
|
178
|
-
export const DevToolsModal = () => {
|
|
179
|
-
// Check if we're in production - most bundlers will replace process.env.NODE_ENV
|
|
180
|
-
// This allows the entire component to be eliminated via dead code elimination
|
|
3
|
+
import { lazy, Suspense } from "react";
|
|
4
|
+
import type { DevToolsPanelPlugin } from "./shell/registry";
|
|
5
|
+
import type { DevToolsClient } from "./data/types";
|
|
6
|
+
|
|
7
|
+
export interface DevToolsModalProps {
|
|
8
|
+
/** Extra inspector tabs appended after the builtins. */
|
|
9
|
+
plugins?: DevToolsPanelPlugin[];
|
|
10
|
+
/** Force a theme. Defaults to "system", which follows the host `.dark` class. */
|
|
11
|
+
theme?: "light" | "dark" | "system";
|
|
12
|
+
/** Data source. Defaults to the in-process DevToolsHooks client. */
|
|
13
|
+
client?: DevToolsClient;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const DevToolsModalImpl = lazy(() => import("./DevToolsModalImpl"));
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Dev-only. In production the body returns null before the lazy panel chunk is
|
|
20
|
+
* ever requested, so the panel and its compiled styles stay out of the
|
|
21
|
+
* production bundle (the dynamic import is also code-split).
|
|
22
|
+
*/
|
|
23
|
+
export const DevToolsModal = (props: DevToolsModalProps = {}) => {
|
|
181
24
|
if (
|
|
182
25
|
typeof process !== "undefined" &&
|
|
183
26
|
process.env?.NODE_ENV === "production"
|
|
@@ -185,5 +28,9 @@ export const DevToolsModal = () => {
|
|
|
185
28
|
return null;
|
|
186
29
|
}
|
|
187
30
|
|
|
188
|
-
return
|
|
31
|
+
return (
|
|
32
|
+
<Suspense fallback={null}>
|
|
33
|
+
<DevToolsModalImpl {...props} />
|
|
34
|
+
</Suspense>
|
|
35
|
+
);
|
|
189
36
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo, useSyncExternalStore } from "react";
|
|
4
|
+
import { DevToolsOverlay } from "./shell/DevToolsOverlay";
|
|
5
|
+
import { ShadowRoot } from "./shell/ShadowRoot";
|
|
6
|
+
import type { DevToolsModalProps } from "./DevToolsModal";
|
|
7
|
+
|
|
8
|
+
const isDarkMode = (): boolean => {
|
|
9
|
+
if (typeof document === "undefined") return false;
|
|
10
|
+
return (
|
|
11
|
+
document.documentElement.classList.contains("dark") ||
|
|
12
|
+
document.body.classList.contains("dark")
|
|
13
|
+
);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const subscribeToThemeChanges = (callback: () => void) => {
|
|
17
|
+
if (typeof MutationObserver === "undefined") {
|
|
18
|
+
return () => {};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const observer = new MutationObserver(callback);
|
|
22
|
+
observer.observe(document.documentElement, {
|
|
23
|
+
attributes: true,
|
|
24
|
+
attributeFilter: ["class"],
|
|
25
|
+
});
|
|
26
|
+
if (document.body !== document.documentElement) {
|
|
27
|
+
observer.observe(document.body, {
|
|
28
|
+
attributes: true,
|
|
29
|
+
attributeFilter: ["class"],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return () => observer.disconnect();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const DevToolsModalImpl = ({
|
|
37
|
+
plugins,
|
|
38
|
+
theme = "system",
|
|
39
|
+
client,
|
|
40
|
+
}: DevToolsModalProps) => {
|
|
41
|
+
const darkMode = useSyncExternalStore(
|
|
42
|
+
subscribeToThemeChanges,
|
|
43
|
+
isDarkMode,
|
|
44
|
+
() => false,
|
|
45
|
+
);
|
|
46
|
+
const resolved = theme === "system" ? (darkMode ? "dark" : "light") : theme;
|
|
47
|
+
|
|
48
|
+
// Stable element identity so the shadow root only re-renders on real changes,
|
|
49
|
+
// not on every render of the host tree.
|
|
50
|
+
const overlay = useMemo(
|
|
51
|
+
() => (
|
|
52
|
+
<DevToolsOverlay theme={resolved} plugins={plugins} client={client} />
|
|
53
|
+
),
|
|
54
|
+
[resolved, plugins, client],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return <ShadowRoot theme={resolved}>{overlay}</ShadowRoot>;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default DevToolsModalImpl;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DevToolsHooks } from "@assistant-ui/react";
|
|
2
|
+
import { projectApi } from "./projectApi";
|
|
3
|
+
import {
|
|
4
|
+
EMPTY_SNAPSHOT,
|
|
5
|
+
type ApiInfo,
|
|
6
|
+
type DevToolsClient,
|
|
7
|
+
type DevToolsSnapshot,
|
|
8
|
+
} from "./types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The default transport: reads the in-process DevToolsHooks registry and
|
|
12
|
+
* re-projects it on every change.
|
|
13
|
+
*
|
|
14
|
+
* Projection runs inside the subscribe/change callbacks (outside React render)
|
|
15
|
+
* because the scope accessors throw when invoked during a render, and
|
|
16
|
+
* getSnapshot returns the cached result.
|
|
17
|
+
*/
|
|
18
|
+
export const createInProcessClient = (): DevToolsClient => {
|
|
19
|
+
let snapshot: DevToolsSnapshot = EMPTY_SNAPSHOT;
|
|
20
|
+
|
|
21
|
+
const rebuild = () => {
|
|
22
|
+
const apis = DevToolsHooks.getApis();
|
|
23
|
+
const byId = new Map<number, ApiInfo>();
|
|
24
|
+
for (const [id, entry] of apis) {
|
|
25
|
+
try {
|
|
26
|
+
byId.set(id, projectApi(id, entry));
|
|
27
|
+
} catch {
|
|
28
|
+
// Skip an api that fails to project rather than breaking the panel.
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// apiIds tracks byId so the selector never lists an id without data.
|
|
32
|
+
snapshot = { apiIds: [...byId.keys()], byId };
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
subscribe(listener) {
|
|
37
|
+
rebuild();
|
|
38
|
+
return DevToolsHooks.subscribe(() => {
|
|
39
|
+
rebuild();
|
|
40
|
+
listener();
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
getSnapshot: () => snapshot,
|
|
44
|
+
getServerSnapshot: () => EMPTY_SNAPSHOT,
|
|
45
|
+
clearEvents: (apiId) => DevToolsHooks.clearEventLogs(apiId),
|
|
46
|
+
switchToThread: (apiId, threadId) => {
|
|
47
|
+
const entry = DevToolsHooks.getApis().get(apiId);
|
|
48
|
+
const threads = entry?.api.threads;
|
|
49
|
+
if (!threads || typeof threads !== "function") return;
|
|
50
|
+
try {
|
|
51
|
+
const methods = threads() as {
|
|
52
|
+
switchToThread?: (id: string) => void | Promise<void>;
|
|
53
|
+
};
|
|
54
|
+
return Promise.resolve(methods.switchToThread?.(threadId)).catch(
|
|
55
|
+
() => {},
|
|
56
|
+
);
|
|
57
|
+
} catch {
|
|
58
|
+
// The thread scope can throw when the runtime is not ready; ignore.
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/** Shared default client used by DevToolsModal and DevToolsPanel. */
|
|
66
|
+
export const inProcessClient = createInProcessClient();
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { projectApi } from "./projectApi";
|
|
3
|
+
|
|
4
|
+
type Scope = (() => unknown) & {
|
|
5
|
+
source: string | null;
|
|
6
|
+
query: Record<string, unknown> | null;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const scope = (
|
|
10
|
+
source: string | null,
|
|
11
|
+
query: Record<string, unknown> | null,
|
|
12
|
+
value: unknown,
|
|
13
|
+
): Scope => {
|
|
14
|
+
const fn = (() => value) as Scope;
|
|
15
|
+
fn.source = source;
|
|
16
|
+
fn.query = query;
|
|
17
|
+
return fn;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe("projectApi", () => {
|
|
21
|
+
const entry = {
|
|
22
|
+
api: {
|
|
23
|
+
thread: scope(
|
|
24
|
+
"root",
|
|
25
|
+
{},
|
|
26
|
+
{
|
|
27
|
+
getState: () => ({ messages: [], isRunning: false }),
|
|
28
|
+
append: () => {},
|
|
29
|
+
getModelContext: () => ({ system: "be nice", tools: [] }),
|
|
30
|
+
},
|
|
31
|
+
),
|
|
32
|
+
composer: scope(
|
|
33
|
+
"root",
|
|
34
|
+
{},
|
|
35
|
+
{
|
|
36
|
+
getState: () => ({ text: "hello" }),
|
|
37
|
+
},
|
|
38
|
+
),
|
|
39
|
+
message: scope(
|
|
40
|
+
"messages",
|
|
41
|
+
{ index: 0 },
|
|
42
|
+
{
|
|
43
|
+
getState: () => ({}),
|
|
44
|
+
},
|
|
45
|
+
),
|
|
46
|
+
},
|
|
47
|
+
logs: [{ time: new Date(0), event: "thread.run-start", data: { foo: 1 } }],
|
|
48
|
+
} as unknown as Parameters<typeof projectApi>[1];
|
|
49
|
+
|
|
50
|
+
const result = projectApi(7, entry);
|
|
51
|
+
|
|
52
|
+
it("carries the api id", () => {
|
|
53
|
+
expect(result.id).toBe(7);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("collects root-scope state by scope name", () => {
|
|
57
|
+
expect(result.state.thread).toEqual({ messages: [], isRunning: false });
|
|
58
|
+
expect(result.state.composer).toEqual({ text: "hello" });
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("omits non-root scopes from state but keeps them in the scope graph", () => {
|
|
62
|
+
expect(result.state.message).toBeUndefined();
|
|
63
|
+
const scopes = result.scopes as Array<{
|
|
64
|
+
name: string;
|
|
65
|
+
source: string | null;
|
|
66
|
+
methods: string[];
|
|
67
|
+
}>;
|
|
68
|
+
const thread = scopes.find((s) => s.name === "thread");
|
|
69
|
+
expect(thread?.source).toBe("root");
|
|
70
|
+
expect(thread?.methods).toEqual(
|
|
71
|
+
expect.arrayContaining(["getState", "append", "getModelContext"]),
|
|
72
|
+
);
|
|
73
|
+
expect(scopes.find((s) => s.name === "message")?.source).toBe("messages");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("normalizes the model context from the thread scope", () => {
|
|
77
|
+
expect(result.modelContext).toEqual({ system: "be nice" });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("keeps event-log timestamps as Date instances", () => {
|
|
81
|
+
expect(result.logs[0]?.time).toBeInstanceOf(Date);
|
|
82
|
+
expect(result.logs[0]?.event).toBe("thread.run-start");
|
|
83
|
+
expect(result.logs[0]?.data).toEqual({ foo: 1 });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("does not throw on scopes whose accessor throws", () => {
|
|
87
|
+
const broken = scope("root", {}, undefined);
|
|
88
|
+
const throwing = (() => {
|
|
89
|
+
throw new Error("not mounted");
|
|
90
|
+
}) as unknown as Scope;
|
|
91
|
+
throwing.source = "derived";
|
|
92
|
+
throwing.query = null;
|
|
93
|
+
const result = projectApi(1, {
|
|
94
|
+
api: { broken, throwing },
|
|
95
|
+
logs: [],
|
|
96
|
+
} as unknown as Parameters<typeof projectApi>[1]);
|
|
97
|
+
const scopes = result.scopes as Array<{ name: string }>;
|
|
98
|
+
expect(scopes.map((s) => s.name)).toEqual(["broken", "throwing"]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type { AssistantClient } from "@assistant-ui/react";
|
|
2
|
+
import { isRecord, isStringArray } from "../utils/common";
|
|
3
|
+
import {
|
|
4
|
+
sanitizeAndRedact,
|
|
5
|
+
sanitizeForMessage,
|
|
6
|
+
serializeModelContext,
|
|
7
|
+
} from "../utils/serialization";
|
|
8
|
+
import type { ApiInfo, EventLogEntry } from "./types";
|
|
9
|
+
|
|
10
|
+
interface DevToolsApiEntry {
|
|
11
|
+
api: Partial<AssistantClient>;
|
|
12
|
+
logs: ReadonlyArray<EventLogEntry>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Lists the method names of a client proxy. The client proxy throws from its
|
|
17
|
+
* `getOwnPropertyDescriptor` trap, so `Object.keys` is best-effort and isolated
|
|
18
|
+
* from state extraction.
|
|
19
|
+
*/
|
|
20
|
+
const readMethods = (scopeValue: unknown): string[] => {
|
|
21
|
+
if (!scopeValue || typeof scopeValue !== "object") return [];
|
|
22
|
+
try {
|
|
23
|
+
return Object.keys(scopeValue).filter(
|
|
24
|
+
(key) =>
|
|
25
|
+
typeof (scopeValue as Record<string, unknown>)[key] === "function",
|
|
26
|
+
);
|
|
27
|
+
} catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type ThreadsClientMethods = {
|
|
33
|
+
__internal_getAssistantRuntime?: () => {
|
|
34
|
+
threads: {
|
|
35
|
+
getById: (threadId: string) => {
|
|
36
|
+
getState: () => {
|
|
37
|
+
messages: unknown;
|
|
38
|
+
isRunning?: boolean;
|
|
39
|
+
isLoading?: boolean;
|
|
40
|
+
isDisabled?: boolean;
|
|
41
|
+
suggestions: unknown;
|
|
42
|
+
capabilities: unknown;
|
|
43
|
+
};
|
|
44
|
+
composer: { getState: () => unknown };
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Reads cached thread states for every id in the thread list. Only threads whose
|
|
52
|
+
* runtime has been mounted (visited in the app) return data; unvisited threads
|
|
53
|
+
* are omitted so DevTools can still list them from `state.threads.threadItems`.
|
|
54
|
+
*/
|
|
55
|
+
const collectThreadSnapshots = (
|
|
56
|
+
entry: DevToolsApiEntry,
|
|
57
|
+
state: Record<string, unknown>,
|
|
58
|
+
): Record<string, unknown> | undefined => {
|
|
59
|
+
const threadsState = state.threads;
|
|
60
|
+
if (!isRecord(threadsState)) return undefined;
|
|
61
|
+
|
|
62
|
+
const threadsScope = entry.api.threads;
|
|
63
|
+
if (typeof threadsScope !== "function") return undefined;
|
|
64
|
+
|
|
65
|
+
let threadsClient: ThreadsClientMethods;
|
|
66
|
+
try {
|
|
67
|
+
threadsClient = threadsScope() as ThreadsClientMethods;
|
|
68
|
+
} catch {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const assistantRuntime = threadsClient.__internal_getAssistantRuntime?.();
|
|
73
|
+
if (!assistantRuntime) return undefined;
|
|
74
|
+
|
|
75
|
+
const threadIds = [
|
|
76
|
+
...isStringArray(threadsState.threadIds),
|
|
77
|
+
...isStringArray(threadsState.archivedThreadIds),
|
|
78
|
+
];
|
|
79
|
+
if (threadIds.length === 0) return undefined;
|
|
80
|
+
|
|
81
|
+
const snapshots: Record<string, unknown> = {};
|
|
82
|
+
for (const threadId of threadIds) {
|
|
83
|
+
try {
|
|
84
|
+
const threadRuntime = assistantRuntime.threads.getById(threadId);
|
|
85
|
+
const threadState = threadRuntime.getState();
|
|
86
|
+
snapshots[threadId] = sanitizeForMessage({
|
|
87
|
+
messages: threadState.messages,
|
|
88
|
+
isRunning: threadState.isRunning,
|
|
89
|
+
isLoading: threadState.isLoading,
|
|
90
|
+
isDisabled: threadState.isDisabled,
|
|
91
|
+
suggestions: threadState.suggestions,
|
|
92
|
+
capabilities: threadState.capabilities,
|
|
93
|
+
composer: threadRuntime.composer.getState(),
|
|
94
|
+
});
|
|
95
|
+
} catch {
|
|
96
|
+
// Thread runtime not mounted yet (never opened in the app).
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return Object.keys(snapshots).length > 0 ? snapshots : undefined;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Projects a live DevToolsHooks api entry into the plain, render-ready shape the
|
|
105
|
+
* views consume. This is the in-process equivalent of the old
|
|
106
|
+
* DevToolsHost.sendUpdate(): it walks the scope accessors for root-scope state
|
|
107
|
+
* and the scope graph, normalizes the model context, and redacts credentials.
|
|
108
|
+
*
|
|
109
|
+
* `state` and each `log.data` are passed through sanitizeForMessage so the JSON
|
|
110
|
+
* renderers cannot crash on circular references or non-serializable values;
|
|
111
|
+
* `log.time` is kept as a Date for the clock formatter.
|
|
112
|
+
*/
|
|
113
|
+
export const projectApi = (apiId: number, entry: DevToolsApiEntry): ApiInfo => {
|
|
114
|
+
const state: Record<string, unknown> = {};
|
|
115
|
+
const scopes: Array<{
|
|
116
|
+
name: string;
|
|
117
|
+
source: string | null;
|
|
118
|
+
query: Record<string, unknown> | null;
|
|
119
|
+
methods: string[];
|
|
120
|
+
}> = [];
|
|
121
|
+
|
|
122
|
+
for (const [name, scope] of Object.entries(entry.api)) {
|
|
123
|
+
if (typeof scope !== "function" || !("source" in scope)) continue;
|
|
124
|
+
|
|
125
|
+
let methods: string[] = [];
|
|
126
|
+
try {
|
|
127
|
+
const scopeValue = scope();
|
|
128
|
+
if (scope.source === "root") {
|
|
129
|
+
state[name] = scopeValue?.getState?.() ?? scopeValue;
|
|
130
|
+
}
|
|
131
|
+
methods = readMethods(scopeValue);
|
|
132
|
+
} catch {
|
|
133
|
+
// scope() may throw for derived scopes before the client is mounted.
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
scopes.push({
|
|
137
|
+
name,
|
|
138
|
+
source: scope.source,
|
|
139
|
+
query: scope.query,
|
|
140
|
+
methods,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let modelContext: ApiInfo["modelContext"];
|
|
145
|
+
try {
|
|
146
|
+
modelContext = serializeModelContext(
|
|
147
|
+
entry.api.thread?.().getModelContext(),
|
|
148
|
+
);
|
|
149
|
+
} catch {
|
|
150
|
+
// A throwing thread()/getModelContext() should not drop the whole api;
|
|
151
|
+
// show partial data (state, scopes, logs) without the model context.
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const sanitizedState = sanitizeForMessage(state) as Record<string, unknown>;
|
|
155
|
+
const threadSnapshots = collectThreadSnapshots(entry, sanitizedState);
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
id: apiId,
|
|
159
|
+
state: sanitizedState,
|
|
160
|
+
logs: entry.logs.map((log) => ({
|
|
161
|
+
time: log.time,
|
|
162
|
+
event: log.event,
|
|
163
|
+
data: sanitizeForMessage(log.data),
|
|
164
|
+
})),
|
|
165
|
+
modelContext,
|
|
166
|
+
scopes: sanitizeAndRedact(scopes),
|
|
167
|
+
...(threadSnapshots ? { threadSnapshots } : {}),
|
|
168
|
+
};
|
|
169
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { SerializedModelContext } from "../types";
|
|
2
|
+
|
|
3
|
+
export type { SerializedModelContext } from "../types";
|
|
4
|
+
|
|
5
|
+
export interface EventLogEntry {
|
|
6
|
+
readonly time: Date;
|
|
7
|
+
readonly event: string;
|
|
8
|
+
readonly data: unknown;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ApiInfo {
|
|
12
|
+
id: number;
|
|
13
|
+
state: Record<string, unknown>;
|
|
14
|
+
logs: EventLogEntry[];
|
|
15
|
+
modelContext?: SerializedModelContext | undefined;
|
|
16
|
+
scopes?: unknown;
|
|
17
|
+
/**
|
|
18
|
+
* Cached thread states keyed by thread id. Populated for threads whose runtime
|
|
19
|
+
* has been mounted (visited in the app). Unvisited threads only appear in
|
|
20
|
+
* `state.threads.threadItems`.
|
|
21
|
+
*/
|
|
22
|
+
threadSnapshots?: Readonly<Record<string, unknown>>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A JSON-safe view of every inspected instance. The map values are stable until
|
|
27
|
+
* the next change so it can be returned directly from useSyncExternalStore.
|
|
28
|
+
*/
|
|
29
|
+
export interface DevToolsSnapshot {
|
|
30
|
+
apiIds: number[];
|
|
31
|
+
byId: ReadonlyMap<number, ApiInfo>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The transport between the data source and the panel UI. The default
|
|
36
|
+
* implementation reads the in-process DevToolsHooks registry, but the panel only
|
|
37
|
+
* depends on this interface, so the same UI can be driven by a postMessage
|
|
38
|
+
* bridge, a browser-extension relay, a remote socket, or a fixture for tests.
|
|
39
|
+
*/
|
|
40
|
+
export interface DevToolsClient {
|
|
41
|
+
/** Subscribe to snapshot changes; returns an unsubscribe. */
|
|
42
|
+
subscribe(listener: () => void): () => void;
|
|
43
|
+
/** The current snapshot. Must return a stable reference until it changes. */
|
|
44
|
+
getSnapshot(): DevToolsSnapshot;
|
|
45
|
+
/** Snapshot used during SSR/hydration. Defaults to an empty snapshot. */
|
|
46
|
+
getServerSnapshot?(): DevToolsSnapshot;
|
|
47
|
+
/** Clears the buffered event log for an instance. */
|
|
48
|
+
clearEvents(apiId: number): void;
|
|
49
|
+
/** Switches the inspected instance to a thread by id, when supported. */
|
|
50
|
+
switchToThread?(apiId: number, threadId: string): void | Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Shared stable empty snapshot identity for the empty/server state. */
|
|
54
|
+
export const EMPTY_SNAPSHOT: DevToolsSnapshot = { apiIds: [], byId: new Map() };
|