@data-club/ai-hub 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/passwordPolicy.d.ts +55 -0
- package/dist/auth/passwordPolicy.d.ts.map +1 -0
- package/dist/auth/passwordPolicy.js +63 -0
- package/dist/auth/passwordPolicy.js.map +1 -0
- package/dist/auth/texts.d.ts +815 -0
- package/dist/auth/texts.d.ts.map +1 -0
- package/dist/auth/texts.js +429 -0
- package/dist/auth/texts.js.map +1 -0
- package/dist/client/AIHubClient.d.ts +1058 -0
- package/dist/client/AIHubClient.d.ts.map +1 -0
- package/dist/client/AIHubClient.js +950 -0
- package/dist/client/AIHubClient.js.map +1 -0
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +9 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/sseParser.d.ts +41 -0
- package/dist/client/sseParser.d.ts.map +1 -0
- package/dist/client/sseParser.js +153 -0
- package/dist/client/sseParser.js.map +1 -0
- package/dist/client/tokenStorage.d.ts +56 -0
- package/dist/client/tokenStorage.d.ts.map +1 -0
- package/dist/client/tokenStorage.js +116 -0
- package/dist/client/tokenStorage.js.map +1 -0
- package/dist/components/AgentsPicker/index.d.ts +70 -0
- package/dist/components/AgentsPicker/index.d.ts.map +1 -0
- package/dist/components/AgentsPicker/index.js +63 -0
- package/dist/components/AgentsPicker/index.js.map +1 -0
- package/dist/components/AuthGate/index.d.ts +79 -0
- package/dist/components/AuthGate/index.d.ts.map +1 -0
- package/dist/components/AuthGate/index.js +61 -0
- package/dist/components/AuthGate/index.js.map +1 -0
- package/dist/components/CacheBadge/index.d.ts +88 -0
- package/dist/components/CacheBadge/index.d.ts.map +1 -0
- package/dist/components/CacheBadge/index.js +127 -0
- package/dist/components/CacheBadge/index.js.map +1 -0
- package/dist/components/ChangePassword/index.d.ts +109 -0
- package/dist/components/ChangePassword/index.d.ts.map +1 -0
- package/dist/components/ChangePassword/index.js +142 -0
- package/dist/components/ChangePassword/index.js.map +1 -0
- package/dist/components/ChatShell/ShellHeader.d.ts +44 -0
- package/dist/components/ChatShell/ShellHeader.d.ts.map +1 -0
- package/dist/components/ChatShell/ShellHeader.js +14 -0
- package/dist/components/ChatShell/ShellHeader.js.map +1 -0
- package/dist/components/ChatShell/UserMenu.d.ts +48 -0
- package/dist/components/ChatShell/UserMenu.d.ts.map +1 -0
- package/dist/components/ChatShell/UserMenu.js +86 -0
- package/dist/components/ChatShell/UserMenu.js.map +1 -0
- package/dist/components/ChatShell/index.d.ts +98 -0
- package/dist/components/ChatShell/index.d.ts.map +1 -0
- package/dist/components/ChatShell/index.js +124 -0
- package/dist/components/ChatShell/index.js.map +1 -0
- package/dist/components/DataClubAIHub/index.d.ts +132 -0
- package/dist/components/DataClubAIHub/index.d.ts.map +1 -0
- package/dist/components/DataClubAIHub/index.js +124 -0
- package/dist/components/DataClubAIHub/index.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.d.ts +89 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.js +199 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.d.ts +33 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.js +137 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.d.ts +50 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.js +93 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.d.ts +49 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.js +94 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.d.ts +37 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.js +44 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.d.ts +56 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.js +158 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.d.ts +29 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.js +183 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.d.ts +38 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.js +294 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts +36 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.js +373 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.d.ts +47 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.js +233 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/index.d.ts +87 -0
- package/dist/components/DataClubAIHubAdmin/index.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/index.js +137 -0
- package/dist/components/DataClubAIHubAdmin/index.js.map +1 -0
- package/dist/components/DataClubAIHubLogin/index.d.ts +113 -0
- package/dist/components/DataClubAIHubLogin/index.d.ts.map +1 -0
- package/dist/components/DataClubAIHubLogin/index.js +123 -0
- package/dist/components/DataClubAIHubLogin/index.js.map +1 -0
- package/dist/components/EffortControl/index.d.ts +57 -0
- package/dist/components/EffortControl/index.d.ts.map +1 -0
- package/dist/components/EffortControl/index.js +84 -0
- package/dist/components/EffortControl/index.js.map +1 -0
- package/dist/components/Layout/index.d.ts +63 -0
- package/dist/components/Layout/index.d.ts.map +1 -0
- package/dist/components/Layout/index.js +45 -0
- package/dist/components/Layout/index.js.map +1 -0
- package/dist/components/MainColumn/index.d.ts +69 -0
- package/dist/components/MainColumn/index.d.ts.map +1 -0
- package/dist/components/MainColumn/index.js +47 -0
- package/dist/components/MainColumn/index.js.map +1 -0
- package/dist/components/MarkdownRenderer/index.d.ts +66 -0
- package/dist/components/MarkdownRenderer/index.d.ts.map +1 -0
- package/dist/components/MarkdownRenderer/index.js +153 -0
- package/dist/components/MarkdownRenderer/index.js.map +1 -0
- package/dist/components/MessageInput/index.d.ts +85 -0
- package/dist/components/MessageInput/index.d.ts.map +1 -0
- package/dist/components/MessageInput/index.js +139 -0
- package/dist/components/MessageInput/index.js.map +1 -0
- package/dist/components/MessageList/index.d.ts +156 -0
- package/dist/components/MessageList/index.d.ts.map +1 -0
- package/dist/components/MessageList/index.js +352 -0
- package/dist/components/MessageList/index.js.map +1 -0
- package/dist/components/ReasoningSelector/index.d.ts +77 -0
- package/dist/components/ReasoningSelector/index.d.ts.map +1 -0
- package/dist/components/ReasoningSelector/index.js +156 -0
- package/dist/components/ReasoningSelector/index.js.map +1 -0
- package/dist/components/ReasoningView/index.d.ts +94 -0
- package/dist/components/ReasoningView/index.d.ts.map +1 -0
- package/dist/components/ReasoningView/index.js +83 -0
- package/dist/components/ReasoningView/index.js.map +1 -0
- package/dist/components/ScrollToPresentButton/index.d.ts +54 -0
- package/dist/components/ScrollToPresentButton/index.d.ts.map +1 -0
- package/dist/components/ScrollToPresentButton/index.js +44 -0
- package/dist/components/ScrollToPresentButton/index.js.map +1 -0
- package/dist/components/SessionsPanel/SessionTitleModal.d.ts +79 -0
- package/dist/components/SessionsPanel/SessionTitleModal.d.ts.map +1 -0
- package/dist/components/SessionsPanel/SessionTitleModal.js +102 -0
- package/dist/components/SessionsPanel/SessionTitleModal.js.map +1 -0
- package/dist/components/SessionsPanel/index.d.ts +100 -0
- package/dist/components/SessionsPanel/index.d.ts.map +1 -0
- package/dist/components/SessionsPanel/index.js +176 -0
- package/dist/components/SessionsPanel/index.js.map +1 -0
- package/dist/components/SystemNotice/index.d.ts +66 -0
- package/dist/components/SystemNotice/index.d.ts.map +1 -0
- package/dist/components/SystemNotice/index.js +81 -0
- package/dist/components/SystemNotice/index.js.map +1 -0
- package/dist/components/ThemeSwitcher/index.d.ts +66 -0
- package/dist/components/ThemeSwitcher/index.d.ts.map +1 -0
- package/dist/components/ThemeSwitcher/index.js +73 -0
- package/dist/components/ThemeSwitcher/index.js.map +1 -0
- package/dist/components/ToolCallView/formatContent.d.ts +36 -0
- package/dist/components/ToolCallView/formatContent.d.ts.map +1 -0
- package/dist/components/ToolCallView/formatContent.js +53 -0
- package/dist/components/ToolCallView/formatContent.js.map +1 -0
- package/dist/components/ToolCallView/index.d.ts +120 -0
- package/dist/components/ToolCallView/index.d.ts.map +1 -0
- package/dist/components/ToolCallView/index.js +104 -0
- package/dist/components/ToolCallView/index.js.map +1 -0
- package/dist/components/TpmBanner/index.d.ts +53 -0
- package/dist/components/TpmBanner/index.d.ts.map +1 -0
- package/dist/components/TpmBanner/index.js +116 -0
- package/dist/components/TpmBanner/index.js.map +1 -0
- package/dist/components/TurnStatusIndicator/index.d.ts +77 -0
- package/dist/components/TurnStatusIndicator/index.d.ts.map +1 -0
- package/dist/components/TurnStatusIndicator/index.js +122 -0
- package/dist/components/TurnStatusIndicator/index.js.map +1 -0
- package/dist/components/internal/PasswordInput.d.ts +62 -0
- package/dist/components/internal/PasswordInput.d.ts.map +1 -0
- package/dist/components/internal/PasswordInput.js +42 -0
- package/dist/components/internal/PasswordInput.js.map +1 -0
- package/dist/context/AIHubContext.d.ts +220 -0
- package/dist/context/AIHubContext.d.ts.map +1 -0
- package/dist/context/AIHubContext.js +19 -0
- package/dist/context/AIHubContext.js.map +1 -0
- package/dist/context/AIHubProvider.d.ts +75 -0
- package/dist/context/AIHubProvider.d.ts.map +1 -0
- package/dist/context/AIHubProvider.js +954 -0
- package/dist/context/AIHubProvider.js.map +1 -0
- package/dist/context/index.d.ts +9 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +9 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/theme.d.ts +43 -0
- package/dist/context/theme.d.ts.map +1 -0
- package/dist/context/theme.js +70 -0
- package/dist/context/theme.js.map +1 -0
- package/dist/context/useAIHub.d.ts +104 -0
- package/dist/context/useAIHub.d.ts.map +1 -0
- package/dist/context/useAIHub.js +63 -0
- package/dist/context/useAIHub.js.map +1 -0
- package/dist/context/useAIHubAuth.d.ts +44 -0
- package/dist/context/useAIHubAuth.d.ts.map +1 -0
- package/dist/context/useAIHubAuth.js +35 -0
- package/dist/context/useAIHubAuth.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/primitives/index.d.ts +99 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +97 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/state/affordances.d.ts +182 -0
- package/dist/state/affordances.d.ts.map +1 -0
- package/dist/state/affordances.js +189 -0
- package/dist/state/affordances.js.map +1 -0
- package/dist/state/stateReducer.d.ts +72 -0
- package/dist/state/stateReducer.d.ts.map +1 -0
- package/dist/state/stateReducer.js +122 -0
- package/dist/state/stateReducer.js.map +1 -0
- package/dist/stories/EffortControl.stories.d.ts +14 -0
- package/dist/stories/EffortControl.stories.d.ts.map +1 -0
- package/dist/stories/EffortControl.stories.js +43 -0
- package/dist/stories/EffortControl.stories.js.map +1 -0
- package/dist/stories/MarkdownRenderer.stories.d.ts +25 -0
- package/dist/stories/MarkdownRenderer.stories.d.ts.map +1 -0
- package/dist/stories/MarkdownRenderer.stories.js +178 -0
- package/dist/stories/MarkdownRenderer.stories.js.map +1 -0
- package/dist/stories/MessageBubble.stories.d.ts +21 -0
- package/dist/stories/MessageBubble.stories.d.ts.map +1 -0
- package/dist/stories/MessageBubble.stories.js +59 -0
- package/dist/stories/MessageBubble.stories.js.map +1 -0
- package/dist/stories/ReasoningView.stories.d.ts +18 -0
- package/dist/stories/ReasoningView.stories.d.ts.map +1 -0
- package/dist/stories/ReasoningView.stories.js +62 -0
- package/dist/stories/ReasoningView.stories.js.map +1 -0
- package/dist/stories/ScrollToPresentButton.stories.d.ts +18 -0
- package/dist/stories/ScrollToPresentButton.stories.d.ts.map +1 -0
- package/dist/stories/ScrollToPresentButton.stories.js +34 -0
- package/dist/stories/ScrollToPresentButton.stories.js.map +1 -0
- package/dist/stories/SystemNotice.stories.d.ts +17 -0
- package/dist/stories/SystemNotice.stories.d.ts.map +1 -0
- package/dist/stories/SystemNotice.stories.js +42 -0
- package/dist/stories/SystemNotice.stories.js.map +1 -0
- package/dist/stories/ThemeSwitcher.stories.d.ts +15 -0
- package/dist/stories/ThemeSwitcher.stories.d.ts.map +1 -0
- package/dist/stories/ThemeSwitcher.stories.js +35 -0
- package/dist/stories/ThemeSwitcher.stories.js.map +1 -0
- package/dist/stories/ToolCallView.stories.d.ts +20 -0
- package/dist/stories/ToolCallView.stories.d.ts.map +1 -0
- package/dist/stories/ToolCallView.stories.js +65 -0
- package/dist/stories/ToolCallView.stories.js.map +1 -0
- package/dist/stories/TpmBanner.stories.d.ts +24 -0
- package/dist/stories/TpmBanner.stories.d.ts.map +1 -0
- package/dist/stories/TpmBanner.stories.js +63 -0
- package/dist/stories/TpmBanner.stories.js.map +1 -0
- package/dist/stories/TurnStatusIndicator.stories.d.ts +25 -0
- package/dist/stories/TurnStatusIndicator.stories.d.ts.map +1 -0
- package/dist/stories/TurnStatusIndicator.stories.js +56 -0
- package/dist/stories/TurnStatusIndicator.stories.js.map +1 -0
- package/dist/stories/_mockProvider.d.ts +44 -0
- package/dist/stories/_mockProvider.d.ts.map +1 -0
- package/dist/stories/_mockProvider.js +84 -0
- package/dist/stories/_mockProvider.js.map +1 -0
- package/dist/types.d.ts +787 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/webcomponent/defineWebComponent.d.ts +106 -0
- package/dist/webcomponent/defineWebComponent.d.ts.map +1 -0
- package/dist/webcomponent/defineWebComponent.js +126 -0
- package/dist/webcomponent/defineWebComponent.js.map +1 -0
- package/dist/webcomponent/index.d.ts +7 -0
- package/dist/webcomponent/index.d.ts.map +1 -0
- package/dist/webcomponent/index.js +7 -0
- package/dist/webcomponent/index.js.map +1 -0
- package/package.json +63 -0
- package/src/__lint-canary__/step1-lint-canary.ts.disabled +28 -0
- package/src/auth/passwordPolicy.ts +75 -0
- package/src/auth/texts.ts +1294 -0
- package/src/client/AIHubClient.ts +1718 -0
- package/src/client/index.ts +30 -0
- package/src/client/sseParser.ts +168 -0
- package/src/client/tokenStorage.ts +131 -0
- package/src/components/AgentsPicker/index.tsx +147 -0
- package/src/components/AuthGate/index.tsx +132 -0
- package/src/components/CacheBadge/index.tsx +245 -0
- package/src/components/ChangePassword/index.tsx +375 -0
- package/src/components/ChatShell/ShellHeader.tsx +80 -0
- package/src/components/ChatShell/UserMenu.tsx +196 -0
- package/src/components/ChatShell/index.tsx +307 -0
- package/src/components/DataClubAIHub/index.tsx +300 -0
- package/src/components/DataClubAIHubAdmin/AgentEditorModal.tsx +505 -0
- package/src/components/DataClubAIHubAdmin/AgentsPage.tsx +342 -0
- package/src/components/DataClubAIHubAdmin/CreateUserModal.tsx +214 -0
- package/src/components/DataClubAIHubAdmin/PasswordRevealModal.tsx +204 -0
- package/src/components/DataClubAIHubAdmin/ResetPasswordModal.tsx +122 -0
- package/src/components/DataClubAIHubAdmin/RotatingMessageEditorModal.tsx +408 -0
- package/src/components/DataClubAIHubAdmin/RotatingMessagesPage.tsx +373 -0
- package/src/components/DataClubAIHubAdmin/SessionsOverviewPage.tsx +639 -0
- package/src/components/DataClubAIHubAdmin/SettingsPage.tsx +979 -0
- package/src/components/DataClubAIHubAdmin/UsersPage.tsx +495 -0
- package/src/components/DataClubAIHubAdmin/index.tsx +277 -0
- package/src/components/DataClubAIHubLogin/index.tsx +282 -0
- package/src/components/EffortControl/index.tsx +138 -0
- package/src/components/Layout/index.tsx +92 -0
- package/src/components/MainColumn/index.tsx +131 -0
- package/src/components/MarkdownRenderer/index.tsx +256 -0
- package/src/components/MessageInput/index.tsx +283 -0
- package/src/components/MessageList/index.tsx +753 -0
- package/src/components/ReasoningSelector/index.tsx +268 -0
- package/src/components/ReasoningView/index.tsx +183 -0
- package/src/components/ScrollToPresentButton/index.tsx +85 -0
- package/src/components/SessionsPanel/SessionTitleModal.tsx +256 -0
- package/src/components/SessionsPanel/index.tsx +406 -0
- package/src/components/SystemNotice/index.tsx +151 -0
- package/src/components/ThemeSwitcher/index.tsx +136 -0
- package/src/components/ToolCallView/formatContent.ts +50 -0
- package/src/components/ToolCallView/index.tsx +274 -0
- package/src/components/TpmBanner/index.tsx +172 -0
- package/src/components/TurnStatusIndicator/index.tsx +203 -0
- package/src/components/internal/PasswordInput.tsx +145 -0
- package/src/context/AIHubContext.ts +249 -0
- package/src/context/AIHubProvider.tsx +1084 -0
- package/src/context/index.ts +9 -0
- package/src/context/theme.ts +76 -0
- package/src/context/useAIHub.ts +151 -0
- package/src/context/useAIHubAuth.ts +65 -0
- package/src/index.ts +275 -0
- package/src/primitives/index.ts +101 -0
- package/src/state/affordances.ts +321 -0
- package/src/state/stateReducer.ts +131 -0
- package/src/stories/EffortControl.stories.tsx +63 -0
- package/src/stories/MarkdownRenderer.stories.tsx +201 -0
- package/src/stories/MessageBubble.stories.tsx +101 -0
- package/src/stories/ReasoningView.stories.tsx +81 -0
- package/src/stories/ScrollToPresentButton.stories.tsx +52 -0
- package/src/stories/SystemNotice.stories.tsx +59 -0
- package/src/stories/ThemeSwitcher.stories.tsx +55 -0
- package/src/stories/ToolCallView.stories.tsx +95 -0
- package/src/stories/TpmBanner.stories.tsx +93 -0
- package/src/stories/TurnStatusIndicator.stories.tsx +86 -0
- package/src/stories/_mockProvider.tsx +116 -0
- package/src/styles/CLASSES.md +356 -0
- package/src/styles/default.css +2937 -0
- package/src/types.ts +867 -0
- package/src/webcomponent/defineWebComponent.tsx +193 -0
- package/src/webcomponent/index.ts +11 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `<SessionsPanel />` — the left-side list of the caller's sessions for
|
|
4
|
+
* the currently-opened agent.
|
|
5
|
+
*
|
|
6
|
+
* Includes:
|
|
7
|
+
*
|
|
8
|
+
* - `new_session_button` → opens `SessionTitleModal` in create mode.
|
|
9
|
+
* - One `session_item` per row with hover-revealed `edit_title_button` +
|
|
10
|
+
* `archive_session_button` actions. Edit opens the same modal in
|
|
11
|
+
* `edit` mode pre-filled with the row's title. Archive uses a native
|
|
12
|
+
* `confirm()` (v1; future polish is a styled modal).
|
|
13
|
+
* - `archived_filter_toggle` at the bottom of the panel — flipping it
|
|
14
|
+
* re-fetches with `include_archived=true`. Archived rows render with
|
|
15
|
+
* the `--archived` modifier and their hover-actions swap to an
|
|
16
|
+
* Unarchive button.
|
|
17
|
+
* - Collapsible / resizable variants — Step 9 ships the collapsible
|
|
18
|
+
* reveal strip; resizable drag is layout-only and uses a CSS gutter
|
|
19
|
+
* the parent layout owns.
|
|
20
|
+
*
|
|
21
|
+
* **No delete action exists anywhere on this panel by design** — v1
|
|
22
|
+
* sessions are archive-only (§6.3.1).
|
|
23
|
+
*
|
|
24
|
+
* Exported under `AIHub.SessionsPanel`.
|
|
25
|
+
*
|
|
26
|
+
* @see SPECIFICATIONS.md §7.1 — exports
|
|
27
|
+
* @see SPECIFICATIONS.md §6.3.1 — sessions
|
|
28
|
+
* @see ui-sketches/03-chat.md — sessions_panel
|
|
29
|
+
*/
|
|
30
|
+
import { useEffect, useMemo, useState } from "react";
|
|
31
|
+
import { resolveAIHubTexts, } from "../../auth/texts.js";
|
|
32
|
+
import { useAIHub } from "../../context/useAIHub.js";
|
|
33
|
+
import { SessionTitleModal } from "./SessionTitleModal.js";
|
|
34
|
+
const DEFAULT_CLASS_NAMES = Object.freeze({
|
|
35
|
+
root: "data-club-ai-hub__sessions-panel",
|
|
36
|
+
rootCollapsed: "data-club-ai-hub__sessions-panel--collapsed",
|
|
37
|
+
customHeader: "data-club-ai-hub__sessions-panel__custom-header",
|
|
38
|
+
newSessionButton: "data-club-ai-hub__sessions-panel__new-button",
|
|
39
|
+
reveal: "data-club-ai-hub__sessions-panel__reveal",
|
|
40
|
+
collapseToggle: "data-club-ai-hub__sessions-panel__collapse-toggle",
|
|
41
|
+
list: "data-club-ai-hub__sessions-panel__list",
|
|
42
|
+
empty: "data-club-ai-hub__sessions-panel__empty",
|
|
43
|
+
loading: "data-club-ai-hub__sessions-panel__loading",
|
|
44
|
+
item: "data-club-ai-hub__sessions-panel__item",
|
|
45
|
+
itemActive: "data-club-ai-hub__sessions-panel__item--active",
|
|
46
|
+
itemArchived: "data-club-ai-hub__sessions-panel__item--archived",
|
|
47
|
+
itemTitle: "data-club-ai-hub__sessions-panel__item-title",
|
|
48
|
+
itemMeta: "data-club-ai-hub__sessions-panel__item-meta",
|
|
49
|
+
itemActions: "data-club-ai-hub__sessions-panel__item-actions",
|
|
50
|
+
actionButton: "data-club-ai-hub__sessions-panel__action-button",
|
|
51
|
+
footer: "data-club-ai-hub__sessions-panel__footer",
|
|
52
|
+
archivedToggle: "data-club-ai-hub__sessions-panel__archived-toggle",
|
|
53
|
+
customFooter: "data-club-ai-hub__sessions-panel__custom-footer",
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Formats an ISO-8601 timestamp into a short "N min ago" / "yesterday" /
|
|
57
|
+
* "N days ago" line. Intentionally minimal — i18n libraries can take this
|
|
58
|
+
* over later via the `texts.*` map if needed.
|
|
59
|
+
*
|
|
60
|
+
* @param iso - ISO timestamp.
|
|
61
|
+
* @returns the short relative-time string.
|
|
62
|
+
*/
|
|
63
|
+
function formatRelative(iso) {
|
|
64
|
+
const then = Date.parse(iso);
|
|
65
|
+
if (Number.isNaN(then))
|
|
66
|
+
return "";
|
|
67
|
+
const diffMs = Date.now() - then;
|
|
68
|
+
const minutes = Math.round(diffMs / 60_000);
|
|
69
|
+
if (minutes < 1)
|
|
70
|
+
return "just now";
|
|
71
|
+
if (minutes === 1)
|
|
72
|
+
return "1 min ago";
|
|
73
|
+
if (minutes < 60)
|
|
74
|
+
return `${minutes} min ago`;
|
|
75
|
+
const hours = Math.round(minutes / 60);
|
|
76
|
+
if (hours === 1)
|
|
77
|
+
return "1 hr ago";
|
|
78
|
+
if (hours < 24)
|
|
79
|
+
return `${hours} hr ago`;
|
|
80
|
+
const days = Math.round(hours / 24);
|
|
81
|
+
if (days === 1)
|
|
82
|
+
return "yesterday";
|
|
83
|
+
return `${days} days ago`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Renders the sessions panel.
|
|
87
|
+
*
|
|
88
|
+
* @param props - see `SessionsPanelProps`.
|
|
89
|
+
* @returns the rendered panel.
|
|
90
|
+
*/
|
|
91
|
+
export function SessionsPanel(props) {
|
|
92
|
+
const { sessions, sessionsLoading, activeSessionId, setActiveSession, createSession, patchSession, includeArchivedSessions, setIncludeArchivedSessions, } = useAIHub();
|
|
93
|
+
const texts = resolveAIHubTexts(props.texts);
|
|
94
|
+
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
95
|
+
const showCreate = props.showCreateButton ?? true;
|
|
96
|
+
const collapsible = props.collapsible ?? true;
|
|
97
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
98
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
99
|
+
const [editingSessionId, setEditingSessionId] = useState(null);
|
|
100
|
+
const editingSession = useMemo(() => {
|
|
101
|
+
if (!editingSessionId)
|
|
102
|
+
return null;
|
|
103
|
+
return sessions.find((s) => s.id === editingSessionId) ?? null;
|
|
104
|
+
}, [editingSessionId, sessions]);
|
|
105
|
+
// Stale-modal guard: if the row being edited gets archived/removed under
|
|
106
|
+
// us, close the modal so we don't submit edits against a stale id.
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (editingSessionId && !editingSession) {
|
|
109
|
+
setEditingSessionId(null);
|
|
110
|
+
}
|
|
111
|
+
}, [editingSessionId, editingSession]);
|
|
112
|
+
if (collapsed) {
|
|
113
|
+
return (_jsx("div", { className: `${cls.root} ${cls.rootCollapsed}`, "data-testid": "sessions-panel", "data-collapsed": "true", children: _jsx("button", { type: "button", className: cls.reveal, onClick: () => setCollapsed(false), "aria-label": texts.chat.expandSessionsPanel, "data-testid": "sessions-panel-reveal", children: "\u226B" }) }));
|
|
114
|
+
}
|
|
115
|
+
const rootClass = [cls.root, props.className].filter(Boolean).join(" ");
|
|
116
|
+
async function handleArchive(session) {
|
|
117
|
+
const prompt = texts.chat.archiveConfirmPrompt.replace("{title}", session.title);
|
|
118
|
+
// eslint-disable-next-line no-alert
|
|
119
|
+
if (typeof window !== "undefined" && !window.confirm(prompt)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
await patchSession(session.id, { isArchived: true });
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
/* surfaced via provider's onError; row stays */
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function handleUnarchive(session) {
|
|
130
|
+
try {
|
|
131
|
+
await patchSession(session.id, { isArchived: false });
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
/* surfaced via provider's onError */
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return (_jsxs("aside", { className: rootClass, "data-testid": "sessions-panel", "aria-label": "Sessions", children: [props.customHeader ? (_jsx("div", { className: cls.customHeader, "data-testid": "sessions-panel-custom-header", children: props.customHeader })) : null, showCreate ? (_jsx("button", { type: "button", className: cls.newSessionButton, onClick: () => {
|
|
138
|
+
setEditingSessionId(null);
|
|
139
|
+
setModalOpen(true);
|
|
140
|
+
}, "data-testid": "sessions-panel-new-button", children: texts.chat.newSessionButton })) : null, collapsible ? (_jsx("button", { type: "button", className: cls.collapseToggle, onClick: () => setCollapsed(true), "aria-label": texts.chat.collapseSessionsPanel, "data-testid": "sessions-panel-collapse", children: "\u226A" })) : null, sessionsLoading && sessions.length === 0 ? (_jsx("p", { className: cls.loading, "data-testid": "sessions-panel-loading", children: texts.chat.sessionsLoading })) : null, !sessionsLoading && sessions.length === 0 ? (_jsx("p", { className: cls.empty, "data-testid": "sessions-panel-empty", children: texts.chat.sessionsEmpty })) : null, _jsx("ul", { className: cls.list, "data-testid": "sessions-panel-list", children: sessions.map((session) => {
|
|
141
|
+
const isActive = session.id === activeSessionId;
|
|
142
|
+
const itemClasses = [
|
|
143
|
+
cls.item,
|
|
144
|
+
isActive ? cls.itemActive : "",
|
|
145
|
+
session.is_archived ? cls.itemArchived : "",
|
|
146
|
+
]
|
|
147
|
+
.filter(Boolean)
|
|
148
|
+
.join(" ");
|
|
149
|
+
const displayTitle = session.title.trim().length > 0
|
|
150
|
+
? session.title
|
|
151
|
+
: texts.chat.untitledSessionFallback;
|
|
152
|
+
return (_jsxs("li", { className: itemClasses, "data-testid": "session-item", "data-active": isActive ? "true" : "false", "data-archived": session.is_archived ? "true" : "false", "data-session-id": session.id, children: [_jsxs("button", { type: "button", className: cls.itemTitle, onClick: () => setActiveSession(session.id), "data-testid": "session-item-open", children: [_jsx("span", { children: displayTitle }), _jsx("span", { className: cls.itemMeta, children: formatRelative(session.updated_at) })] }), _jsx("div", { className: cls.itemActions, "data-testid": "session-item-actions", children: !session.is_archived ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: cls.actionButton, "aria-label": texts.chat.editSessionTitleAriaLabel, onClick: () => {
|
|
153
|
+
setEditingSessionId(session.id);
|
|
154
|
+
setModalOpen(true);
|
|
155
|
+
}, "data-testid": "session-item-edit", children: "\u270E" }), _jsx("button", { type: "button", className: cls.actionButton, "aria-label": texts.chat.archiveSessionAriaLabel, onClick: () => {
|
|
156
|
+
void handleArchive(session);
|
|
157
|
+
}, "data-testid": "session-item-archive", children: "\uD83D\uDDC4" })] })) : (_jsx("button", { type: "button", className: cls.actionButton, "aria-label": texts.chat.unarchiveSessionAriaLabel, onClick: () => {
|
|
158
|
+
void handleUnarchive(session);
|
|
159
|
+
}, "data-testid": "session-item-unarchive", children: "\u2934" })) })] }, session.id));
|
|
160
|
+
}) }), _jsxs("div", { className: cls.footer, children: [props.customFooter ? (_jsx("div", { className: cls.customFooter, "data-testid": "sessions-panel-custom-footer", children: props.customFooter })) : null, _jsx("button", { type: "button", className: cls.archivedToggle, onClick: () => setIncludeArchivedSessions(!includeArchivedSessions), "aria-pressed": includeArchivedSessions, "data-testid": "sessions-panel-archived-toggle", children: includeArchivedSessions
|
|
161
|
+
? texts.chat.hideArchivedToggle
|
|
162
|
+
: texts.chat.showArchivedToggle })] }), _jsx(SessionTitleModal, { mode: editingSession ? "edit" : "create", open: modalOpen, initialTitle: editingSession?.title ?? "", onCancel: () => {
|
|
163
|
+
setModalOpen(false);
|
|
164
|
+
setEditingSessionId(null);
|
|
165
|
+
}, onSubmit: async (title) => {
|
|
166
|
+
if (editingSession) {
|
|
167
|
+
await patchSession(editingSession.id, { title });
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
await createSession(title);
|
|
171
|
+
}
|
|
172
|
+
setModalOpen(false);
|
|
173
|
+
setEditingSessionId(null);
|
|
174
|
+
}, texts: texts.chat })] }));
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/SessionsPanel/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<SystemNotice />` — banner rendered above `messages_area` for non-fatal
|
|
3
|
+
* system events (TPM wait, recovery resumed, exhausted error). Variants:
|
|
4
|
+
*
|
|
5
|
+
* - `--tpm-wait` — provider rate-limited; recovery in progress
|
|
6
|
+
* - `--resumed` — recovery succeeded; usually auto-dismissed after a brief flash
|
|
7
|
+
* - `--error` — non-recoverable (e.g. `tpm_exhausted`)
|
|
8
|
+
*
|
|
9
|
+
* Pure presentational — the parent (`MessageList` in the monolith) decides
|
|
10
|
+
* which variant to render, what body text to show, and any auto-dismiss
|
|
11
|
+
* timer. Tier-3 wrappers can use the primitive directly with their own
|
|
12
|
+
* content too.
|
|
13
|
+
*
|
|
14
|
+
* Exported under `AIHub.SystemNotice`.
|
|
15
|
+
*
|
|
16
|
+
* @see SPECIFICATIONS.md §9.4 — system_notice events
|
|
17
|
+
* @see ui-sketches/03-chat.md — system_notice
|
|
18
|
+
*/
|
|
19
|
+
import { type ReactNode } from "react";
|
|
20
|
+
/**
|
|
21
|
+
* BEM class names emitted by `<SystemNotice />`.
|
|
22
|
+
*/
|
|
23
|
+
export interface SystemNoticeClassNames {
|
|
24
|
+
/** Outer banner element. */
|
|
25
|
+
root: string;
|
|
26
|
+
/** Modifier — `--tpm-wait`. */
|
|
27
|
+
rootTpmWait: string;
|
|
28
|
+
/** Modifier — `--resumed`. */
|
|
29
|
+
rootResumed: string;
|
|
30
|
+
/** Modifier — `--error`. */
|
|
31
|
+
rootError: string;
|
|
32
|
+
/** Icon span. */
|
|
33
|
+
icon: string;
|
|
34
|
+
/** Body text span. */
|
|
35
|
+
body: string;
|
|
36
|
+
/** Action button (e.g. retry on error variant). */
|
|
37
|
+
action: string;
|
|
38
|
+
}
|
|
39
|
+
/** Props for `<SystemNotice />`. */
|
|
40
|
+
export interface SystemNoticeProps {
|
|
41
|
+
/** Variant — controls the modifier class + the default icon. */
|
|
42
|
+
variant: "tpm-wait" | "resumed" | "error";
|
|
43
|
+
/** Body text (i18n-supplied). */
|
|
44
|
+
message: string;
|
|
45
|
+
/** Override the default icon character for the variant. */
|
|
46
|
+
icon?: string;
|
|
47
|
+
/** Optional inline action button. */
|
|
48
|
+
action?: {
|
|
49
|
+
/** Button label. */
|
|
50
|
+
label: string;
|
|
51
|
+
/** Click handler. */
|
|
52
|
+
onClick: () => void;
|
|
53
|
+
};
|
|
54
|
+
/** Extra class merged onto the root. */
|
|
55
|
+
className?: string;
|
|
56
|
+
/** Per-element class overrides. */
|
|
57
|
+
classNames?: Partial<SystemNoticeClassNames>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Renders the notice.
|
|
61
|
+
*
|
|
62
|
+
* @param props - see `SystemNoticeProps`.
|
|
63
|
+
* @returns the rendered notice.
|
|
64
|
+
*/
|
|
65
|
+
export declare function SystemNotice(props: SystemNoticeProps): ReactNode;
|
|
66
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/SystemNotice/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;CAChB;AAYD,oCAAoC;AACpC,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,OAAO,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;IAC1C,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,CAAC,EAAE;QACP,oBAAoB;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,qBAAqB;QACrB,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,CAAC;IACF,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC9C;AAyCD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAiChE"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `<SystemNotice />` — banner rendered above `messages_area` for non-fatal
|
|
4
|
+
* system events (TPM wait, recovery resumed, exhausted error). Variants:
|
|
5
|
+
*
|
|
6
|
+
* - `--tpm-wait` — provider rate-limited; recovery in progress
|
|
7
|
+
* - `--resumed` — recovery succeeded; usually auto-dismissed after a brief flash
|
|
8
|
+
* - `--error` — non-recoverable (e.g. `tpm_exhausted`)
|
|
9
|
+
*
|
|
10
|
+
* Pure presentational — the parent (`MessageList` in the monolith) decides
|
|
11
|
+
* which variant to render, what body text to show, and any auto-dismiss
|
|
12
|
+
* timer. Tier-3 wrappers can use the primitive directly with their own
|
|
13
|
+
* content too.
|
|
14
|
+
*
|
|
15
|
+
* Exported under `AIHub.SystemNotice`.
|
|
16
|
+
*
|
|
17
|
+
* @see SPECIFICATIONS.md §9.4 — system_notice events
|
|
18
|
+
* @see ui-sketches/03-chat.md — system_notice
|
|
19
|
+
*/
|
|
20
|
+
import {} from "react";
|
|
21
|
+
const DEFAULT_CLASS_NAMES = Object.freeze({
|
|
22
|
+
root: "data-club-ai-hub__system-notice",
|
|
23
|
+
rootTpmWait: "data-club-ai-hub__system-notice--tpm-wait",
|
|
24
|
+
rootResumed: "data-club-ai-hub__system-notice--resumed",
|
|
25
|
+
rootError: "data-club-ai-hub__system-notice--error",
|
|
26
|
+
icon: "data-club-ai-hub__system-notice__icon",
|
|
27
|
+
body: "data-club-ai-hub__system-notice__body",
|
|
28
|
+
action: "data-club-ai-hub__system-notice__action",
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Default icon glyph per variant.
|
|
32
|
+
*/
|
|
33
|
+
function defaultIcon(variant) {
|
|
34
|
+
switch (variant) {
|
|
35
|
+
case "tpm-wait":
|
|
36
|
+
return "⏱";
|
|
37
|
+
case "resumed":
|
|
38
|
+
return "✓";
|
|
39
|
+
case "error":
|
|
40
|
+
return "⚠";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns the BEM modifier for the variant.
|
|
45
|
+
*/
|
|
46
|
+
function modifierForVariant(variant, cls) {
|
|
47
|
+
switch (variant) {
|
|
48
|
+
case "tpm-wait":
|
|
49
|
+
return cls.rootTpmWait;
|
|
50
|
+
case "resumed":
|
|
51
|
+
return cls.rootResumed;
|
|
52
|
+
case "error":
|
|
53
|
+
return cls.rootError;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* `role` ARIA value per variant. Error gets `alert` so screen readers
|
|
58
|
+
* announce; wait/resumed get `status` (polite live region).
|
|
59
|
+
*/
|
|
60
|
+
function roleForVariant(variant) {
|
|
61
|
+
return variant === "error" ? "alert" : "status";
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Renders the notice.
|
|
65
|
+
*
|
|
66
|
+
* @param props - see `SystemNoticeProps`.
|
|
67
|
+
* @returns the rendered notice.
|
|
68
|
+
*/
|
|
69
|
+
export function SystemNotice(props) {
|
|
70
|
+
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
71
|
+
const icon = props.icon ?? defaultIcon(props.variant);
|
|
72
|
+
const rootClass = [
|
|
73
|
+
cls.root,
|
|
74
|
+
modifierForVariant(props.variant, cls),
|
|
75
|
+
props.className,
|
|
76
|
+
]
|
|
77
|
+
.filter(Boolean)
|
|
78
|
+
.join(" ");
|
|
79
|
+
return (_jsxs("div", { className: rootClass, role: roleForVariant(props.variant), "data-testid": "system-notice", "data-variant": props.variant, children: [_jsx("span", { className: cls.icon, "aria-hidden": "true", children: icon }), _jsx("span", { className: cls.body, children: props.message }), props.action ? (_jsx("button", { type: "button", className: cls.action, onClick: props.action.onClick, "data-testid": "system-notice-action", children: props.action.label })) : null] }));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/SystemNotice/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAkB,MAAM,OAAO,CAAC;AAsBvC,MAAM,mBAAmB,GAA2B,MAAM,CAAC,MAAM,CAAC;IAChE,IAAI,EAAE,iCAAiC;IACvC,WAAW,EAAE,2CAA2C;IACxD,WAAW,EAAE,0CAA0C;IACvD,SAAS,EAAE,wCAAwC;IACnD,IAAI,EAAE,uCAAuC;IAC7C,IAAI,EAAE,uCAAuC;IAC7C,MAAM,EAAE,yCAAyC;CAClD,CAA2B,CAAC;AAuB7B;;GAEG;AACH,SAAS,WAAW,CAAC,OAAqC;IACxD,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,GAAG,CAAC;QACb,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC;QACb,KAAK,OAAO;YACV,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,OAAqC,EACrC,GAA2B;IAE3B,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,GAAG,CAAC,WAAW,CAAC;QACzB,KAAK,SAAS;YACZ,OAAO,GAAG,CAAC,WAAW,CAAC;QACzB,KAAK,OAAO;YACV,OAAO,GAAG,CAAC,SAAS,CAAC;IACzB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,OAAqC;IAC3D,OAAO,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,GAAG,GAAG,EAAE,GAAG,mBAAmB,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;IACpE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG;QAChB,GAAG,CAAC,IAAI;QACR,kBAAkB,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC;QACtC,KAAK,CAAC,SAAS;KAChB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,CACL,eACE,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,iBACvB,eAAe,kBACb,KAAK,CAAC,OAAO,aAE3B,eAAM,SAAS,EAAE,GAAG,CAAC,IAAI,iBAAc,MAAM,YAC1C,IAAI,GACA,EACP,eAAM,SAAS,EAAE,GAAG,CAAC,IAAI,YAAG,KAAK,CAAC,OAAO,GAAQ,EAChD,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CACd,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,GAAG,CAAC,MAAM,EACrB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,iBACjB,sBAAsB,YAEjC,KAAK,CAAC,MAAM,CAAC,KAAK,GACZ,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<ThemeSwitcher />` — sun/moon toggle that flips the active theme via
|
|
3
|
+
* `setTheme` from `useAIHub()`.
|
|
4
|
+
*
|
|
5
|
+
* Renders **nothing** when `themeSwitcherEnabled === false` (i.e. the
|
|
6
|
+
* super_admin has disabled the switcher for this deployment per §7.6) —
|
|
7
|
+
* not a disabled control, not a hidden control, but absent from the DOM
|
|
8
|
+
* entirely. That's the contract callers — including `UserMenu` —
|
|
9
|
+
* depend on: a `ThemeSwitcher` inside a conditional is safe to leave in
|
|
10
|
+
* place; the primitive self-suppresses.
|
|
11
|
+
*
|
|
12
|
+
* Optimistic update: clicking the switcher flips the local `theme`
|
|
13
|
+
* value immediately and posts `PATCH /auth/me/preferences { theme }`.
|
|
14
|
+
* On a 409 `theme_switcher_disabled` (server-side switcher disabled
|
|
15
|
+
* mid-call), the provider's `setTheme` reverts the optimistic state and
|
|
16
|
+
* surfaces the error via `onError`.
|
|
17
|
+
*
|
|
18
|
+
* Exported under `AIHub.ThemeSwitcher`.
|
|
19
|
+
*
|
|
20
|
+
* @see SPECIFICATIONS.md §7.6 — theme resolution
|
|
21
|
+
* @see ui-sketches/00-shell.md — `Theme: Light ↔ Dark` item in user menu
|
|
22
|
+
*/
|
|
23
|
+
import { type ReactNode } from "react";
|
|
24
|
+
import { type AIHubTexts, type DeepPartial } from "../../auth/texts.js";
|
|
25
|
+
/**
|
|
26
|
+
* BEM class names emitted by `<ThemeSwitcher />`.
|
|
27
|
+
*/
|
|
28
|
+
export interface ThemeSwitcherClassNames {
|
|
29
|
+
/** The button element. */
|
|
30
|
+
root: string;
|
|
31
|
+
/** Modifier added when the active theme is light. */
|
|
32
|
+
rootLight: string;
|
|
33
|
+
/** Modifier added when the active theme is dark. */
|
|
34
|
+
rootDark: string;
|
|
35
|
+
/** The icon span. */
|
|
36
|
+
icon: string;
|
|
37
|
+
/** The label text span. */
|
|
38
|
+
label: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Props for `<ThemeSwitcher />`.
|
|
42
|
+
*/
|
|
43
|
+
export interface ThemeSwitcherProps {
|
|
44
|
+
/** Whether to render a label next to the icon. Default true. */
|
|
45
|
+
showLabel?: boolean;
|
|
46
|
+
/** Wrapper-supplied i18n. */
|
|
47
|
+
texts?: DeepPartial<AIHubTexts>;
|
|
48
|
+
/** Extra class merged onto the root. */
|
|
49
|
+
className?: string;
|
|
50
|
+
/** Per-element class overrides. */
|
|
51
|
+
classNames?: Partial<ThemeSwitcherClassNames>;
|
|
52
|
+
/**
|
|
53
|
+
* Forwarded to the underlying button — only used by the test harness
|
|
54
|
+
* + Storybook stories that want to click the switcher without going
|
|
55
|
+
* through the provider's optimistic-update path.
|
|
56
|
+
*/
|
|
57
|
+
onClick?: () => void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Renders the switcher.
|
|
61
|
+
*
|
|
62
|
+
* @param props - see `ThemeSwitcherProps`.
|
|
63
|
+
* @returns the rendered switcher, or `null` when disabled by config.
|
|
64
|
+
*/
|
|
65
|
+
export declare function ThemeSwitcher(props: ThemeSwitcherProps): ReactNode;
|
|
66
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ThemeSwitcher/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAqB,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG3F;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAUD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAChC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC9C;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,CAwDlE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `<ThemeSwitcher />` — sun/moon toggle that flips the active theme via
|
|
4
|
+
* `setTheme` from `useAIHub()`.
|
|
5
|
+
*
|
|
6
|
+
* Renders **nothing** when `themeSwitcherEnabled === false` (i.e. the
|
|
7
|
+
* super_admin has disabled the switcher for this deployment per §7.6) —
|
|
8
|
+
* not a disabled control, not a hidden control, but absent from the DOM
|
|
9
|
+
* entirely. That's the contract callers — including `UserMenu` —
|
|
10
|
+
* depend on: a `ThemeSwitcher` inside a conditional is safe to leave in
|
|
11
|
+
* place; the primitive self-suppresses.
|
|
12
|
+
*
|
|
13
|
+
* Optimistic update: clicking the switcher flips the local `theme`
|
|
14
|
+
* value immediately and posts `PATCH /auth/me/preferences { theme }`.
|
|
15
|
+
* On a 409 `theme_switcher_disabled` (server-side switcher disabled
|
|
16
|
+
* mid-call), the provider's `setTheme` reverts the optimistic state and
|
|
17
|
+
* surfaces the error via `onError`.
|
|
18
|
+
*
|
|
19
|
+
* Exported under `AIHub.ThemeSwitcher`.
|
|
20
|
+
*
|
|
21
|
+
* @see SPECIFICATIONS.md §7.6 — theme resolution
|
|
22
|
+
* @see ui-sketches/00-shell.md — `Theme: Light ↔ Dark` item in user menu
|
|
23
|
+
*/
|
|
24
|
+
import {} from "react";
|
|
25
|
+
import { resolveAIHubTexts } from "../../auth/texts.js";
|
|
26
|
+
import { useAIHub } from "../../context/useAIHub.js";
|
|
27
|
+
const DEFAULT_CLASS_NAMES = Object.freeze({
|
|
28
|
+
root: "data-club-ai-hub__theme-switcher",
|
|
29
|
+
rootLight: "data-club-ai-hub__theme-switcher--light",
|
|
30
|
+
rootDark: "data-club-ai-hub__theme-switcher--dark",
|
|
31
|
+
icon: "data-club-ai-hub__theme-switcher__icon",
|
|
32
|
+
label: "data-club-ai-hub__theme-switcher__label",
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Renders the switcher.
|
|
36
|
+
*
|
|
37
|
+
* @param props - see `ThemeSwitcherProps`.
|
|
38
|
+
* @returns the rendered switcher, or `null` when disabled by config.
|
|
39
|
+
*/
|
|
40
|
+
export function ThemeSwitcher(props) {
|
|
41
|
+
const { theme, setTheme, themeSwitcherEnabled } = useAIHub();
|
|
42
|
+
const texts = resolveAIHubTexts(props.texts);
|
|
43
|
+
const chatTexts = texts.chat;
|
|
44
|
+
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
45
|
+
const showLabel = props.showLabel ?? true;
|
|
46
|
+
if (!themeSwitcherEnabled)
|
|
47
|
+
return null;
|
|
48
|
+
const isDark = theme === "dark";
|
|
49
|
+
// `aria-checked` reflects "is dark on?" so the switcher is a
|
|
50
|
+
// 2-state switch (light ↔ dark), which matches sketches/00-shell.md.
|
|
51
|
+
const ariaLabel = isDark
|
|
52
|
+
? chatTexts.themeSwitchToLightAriaLabel
|
|
53
|
+
: chatTexts.themeSwitchToDarkAriaLabel;
|
|
54
|
+
const visualLabel = isDark ? chatTexts.themeLightLabel : chatTexts.themeDarkLabel;
|
|
55
|
+
const icon = isDark ? "☀" : "☾";
|
|
56
|
+
const next = isDark ? "light" : "dark";
|
|
57
|
+
const rootClass = [
|
|
58
|
+
cls.root,
|
|
59
|
+
isDark ? cls.rootDark : cls.rootLight,
|
|
60
|
+
props.className,
|
|
61
|
+
]
|
|
62
|
+
.filter(Boolean)
|
|
63
|
+
.join(" ");
|
|
64
|
+
function handleClick() {
|
|
65
|
+
if (props.onClick) {
|
|
66
|
+
props.onClick();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
void setTheme(next);
|
|
70
|
+
}
|
|
71
|
+
return (_jsxs("button", { type: "button", role: "switch", "aria-checked": isDark, "aria-label": ariaLabel, className: rootClass, onClick: handleClick, "data-testid": "theme-switcher", "data-theme-state": theme, children: [_jsx("span", { className: cls.icon, "aria-hidden": "true", children: icon }), showLabel ? (_jsx("span", { className: cls.label, "data-testid": "theme-switcher-label", children: visualLabel })) : null] }));
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ThemeSwitcher/index.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAkB,MAAM,OAAO,CAAC;AAGvC,OAAO,EAAE,iBAAiB,EAAqC,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAkBrD,MAAM,mBAAmB,GAA4B,MAAM,CAAC,MAAM,CAAC;IACjE,IAAI,EAAE,kCAAkC;IACxC,SAAS,EAAE,yCAAyC;IACpD,QAAQ,EAAE,wCAAwC;IAClD,IAAI,EAAE,wCAAwC;IAC9C,KAAK,EAAE,yCAAyC;CACjD,CAA4B,CAAC;AAsB9B;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7D,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAmB,KAAK,CAAC,IAAI,CAAC;IAC7C,MAAM,GAAG,GAAG,EAAE,GAAG,mBAAmB,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;IACpE,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC;IAE1C,IAAI,CAAC,oBAAoB;QAAE,OAAO,IAAI,CAAC;IAEvC,MAAM,MAAM,GAAG,KAAK,KAAK,MAAM,CAAC;IAChC,6DAA6D;IAC7D,qEAAqE;IACrE,MAAM,SAAS,GAAG,MAAM;QACtB,CAAC,CAAC,SAAS,CAAC,2BAA2B;QACvC,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC;IACzC,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC;IAClF,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAChC,MAAM,IAAI,GAAqB,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAEzD,MAAM,SAAS,GAAG;QAChB,GAAG,CAAC,IAAI;QACR,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS;QACrC,KAAK,CAAC,SAAS;KAChB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,SAAS,WAAW;QAClB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,KAAK,CAAC,OAAO,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,CACL,kBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,kBACC,MAAM,gBACR,SAAS,EACrB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,WAAW,iBACR,gBAAgB,sBACV,KAAK,aAEvB,eAAM,SAAS,EAAE,GAAG,CAAC,IAAI,iBAAc,MAAM,YAC1C,IAAI,GACA,EACN,SAAS,CAAC,CAAC,CAAC,CACX,eAAM,SAAS,EAAE,GAAG,CAAC,KAAK,iBAAc,sBAAsB,YAC3D,WAAW,GACP,CACR,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default display-side formatter for tool-call input/output text rendered
|
|
3
|
+
* inside `<ToolCallView />`.
|
|
4
|
+
*
|
|
5
|
+
* Tool inputs reach the UI as raw JSON text (assembled from
|
|
6
|
+
* `tool_call_input_delta` chunks); tool outputs are either a string from
|
|
7
|
+
* Letta or a `JSON.stringify` of the structured return. In both shapes,
|
|
8
|
+
* any newline inside a string value is encoded as the two-character
|
|
9
|
+
* sequence `\n`, which a `<pre>` element renders as the literal text
|
|
10
|
+
* `\n` instead of an actual line break. Same for `\t` / `\r`. That makes
|
|
11
|
+
* any multi-line tool payload (file diffs, command output, prompts)
|
|
12
|
+
* unreadable.
|
|
13
|
+
*
|
|
14
|
+
* Strategy:
|
|
15
|
+
*
|
|
16
|
+
* 1. Try `JSON.parse(raw)`. If it parses, re-stringify with 2-space
|
|
17
|
+
* indent — that pretty-prints the structure.
|
|
18
|
+
* 2. Whether or not parsing succeeded, replace the whitespace escape
|
|
19
|
+
* sequences (`\n`, `\t`, `\r`, including the `\r\n` pair) with
|
|
20
|
+
* their literal characters so they render as real layout.
|
|
21
|
+
*
|
|
22
|
+
* The output is NOT valid JSON anymore — it's a display form. Other
|
|
23
|
+
* escapes (`\"`, `\\`, `\uXXXX`) are left alone because they're either
|
|
24
|
+
* still meaningful for the reader or rare enough that unescaping them
|
|
25
|
+
* would risk corrupting binary-ish content.
|
|
26
|
+
*
|
|
27
|
+
* Implementation projects that need different behavior (e.g. raw view
|
|
28
|
+
* for debugging) can pass their own `formatContent` to `<ToolCallView />`
|
|
29
|
+
* or pass identity (`(s) => s`).
|
|
30
|
+
*
|
|
31
|
+
* @param raw - the input or output string as carried on
|
|
32
|
+
* `AIHubToolCallRecord` / the streaming tool-call accumulator.
|
|
33
|
+
* @returns the formatted string for display.
|
|
34
|
+
*/
|
|
35
|
+
export declare function formatToolContentForDisplay(raw: string): string;
|
|
36
|
+
//# sourceMappingURL=formatContent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatContent.d.ts","sourceRoot":"","sources":["../../../src/components/ToolCallView/formatContent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAe/D"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default display-side formatter for tool-call input/output text rendered
|
|
3
|
+
* inside `<ToolCallView />`.
|
|
4
|
+
*
|
|
5
|
+
* Tool inputs reach the UI as raw JSON text (assembled from
|
|
6
|
+
* `tool_call_input_delta` chunks); tool outputs are either a string from
|
|
7
|
+
* Letta or a `JSON.stringify` of the structured return. In both shapes,
|
|
8
|
+
* any newline inside a string value is encoded as the two-character
|
|
9
|
+
* sequence `\n`, which a `<pre>` element renders as the literal text
|
|
10
|
+
* `\n` instead of an actual line break. Same for `\t` / `\r`. That makes
|
|
11
|
+
* any multi-line tool payload (file diffs, command output, prompts)
|
|
12
|
+
* unreadable.
|
|
13
|
+
*
|
|
14
|
+
* Strategy:
|
|
15
|
+
*
|
|
16
|
+
* 1. Try `JSON.parse(raw)`. If it parses, re-stringify with 2-space
|
|
17
|
+
* indent — that pretty-prints the structure.
|
|
18
|
+
* 2. Whether or not parsing succeeded, replace the whitespace escape
|
|
19
|
+
* sequences (`\n`, `\t`, `\r`, including the `\r\n` pair) with
|
|
20
|
+
* their literal characters so they render as real layout.
|
|
21
|
+
*
|
|
22
|
+
* The output is NOT valid JSON anymore — it's a display form. Other
|
|
23
|
+
* escapes (`\"`, `\\`, `\uXXXX`) are left alone because they're either
|
|
24
|
+
* still meaningful for the reader or rare enough that unescaping them
|
|
25
|
+
* would risk corrupting binary-ish content.
|
|
26
|
+
*
|
|
27
|
+
* Implementation projects that need different behavior (e.g. raw view
|
|
28
|
+
* for debugging) can pass their own `formatContent` to `<ToolCallView />`
|
|
29
|
+
* or pass identity (`(s) => s`).
|
|
30
|
+
*
|
|
31
|
+
* @param raw - the input or output string as carried on
|
|
32
|
+
* `AIHubToolCallRecord` / the streaming tool-call accumulator.
|
|
33
|
+
* @returns the formatted string for display.
|
|
34
|
+
*/
|
|
35
|
+
export function formatToolContentForDisplay(raw) {
|
|
36
|
+
if (raw === "")
|
|
37
|
+
return raw;
|
|
38
|
+
let formatted = raw;
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(raw);
|
|
41
|
+
formatted = JSON.stringify(parsed, null, 2);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Not valid JSON (mid-stream chunk, plain text output, etc.) —
|
|
45
|
+
// fall through to the escape-sequence unwrap on the raw input.
|
|
46
|
+
}
|
|
47
|
+
return formatted
|
|
48
|
+
.replace(/\\r\\n/g, "\n")
|
|
49
|
+
.replace(/\\n/g, "\n")
|
|
50
|
+
.replace(/\\t/g, "\t")
|
|
51
|
+
.replace(/\\r/g, "\r");
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=formatContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatContent.js","sourceRoot":"","sources":["../../../src/components/ToolCallView/formatContent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,UAAU,2BAA2B,CAAC,GAAW;IACrD,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC;IAC3B,IAAI,SAAS,GAAG,GAAG,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;QAC/D,+DAA+D;IACjE,CAAC;IACD,OAAO,SAAS;SACb,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;SACxB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;SACrB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;SACrB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|