@vibe-forge/client 2.0.0 → 2.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/AGENTS.md +4 -1
- package/dist/assets/{arc-CbOXL0l9.js → arc-CqviK3HX.js} +1 -1
- package/dist/assets/{blockDiagram-c4efeb88-CqxINvsS.js → blockDiagram-c4efeb88-BEp50UHp.js} +1 -1
- package/dist/assets/{c4Diagram-c83219d4-BKazU0hb.js → c4Diagram-c83219d4-C5w55JzM.js} +1 -1
- package/dist/assets/channel-C6LTxxLg.js +1 -0
- package/dist/assets/{classDiagram-beda092f-fAFX5BpB.js → classDiagram-beda092f-CQJVtHEy.js} +1 -1
- package/dist/assets/{classDiagram-v2-2358418a-w1VkNGJj.js → classDiagram-v2-2358418a-B37Xl9jB.js} +1 -1
- package/dist/assets/clone-CG6ZcokX.js +1 -0
- package/dist/assets/{createText-1719965b-CEinakVP.js → createText-1719965b-9YwvWMdV.js} +1 -1
- package/dist/assets/{cssMode-DPqRki4y.js → cssMode-BX88r5f4.js} +1 -1
- package/dist/assets/{edges-96097737-Cb0F1_3K.js → edges-96097737-CNHoXVrD.js} +1 -1
- package/dist/assets/{erDiagram-0228fc6a-C-N2fx-J.js → erDiagram-0228fc6a-BoYldy0g.js} +1 -1
- package/dist/assets/{flowDb-c6c81e3f-D1Xz_8Gf.js → flowDb-c6c81e3f-CoPw_R-Q.js} +1 -1
- package/dist/assets/{flowDiagram-50d868cf-DyPSZyAj.js → flowDiagram-50d868cf-nCqbSXd-.js} +1 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-CSZTI7GQ.js +1 -0
- package/dist/assets/{flowchart-elk-definition-6af322e1-Dr1DDXwE.js → flowchart-elk-definition-6af322e1-BwMuPTrV.js} +1 -1
- package/dist/assets/{freemarker2-C3DvPFaK.js → freemarker2-DUFDSvgj.js} +1 -1
- package/dist/assets/{ganttDiagram-a2739b55-DmvY1GRj.js → ganttDiagram-a2739b55-CLNH3S_C.js} +1 -1
- package/dist/assets/{gitGraphDiagram-82fe8481-CoXfPYYi.js → gitGraphDiagram-82fe8481-uDu1ectX.js} +1 -1
- package/dist/assets/{graph-BkDQy7Qt.js → graph-DuC4kt4I.js} +1 -1
- package/dist/assets/{handlebars-BcTFdqjl.js → handlebars-BSd4a6l9.js} +1 -1
- package/dist/assets/{html-Dg-O6XFr.js → html-H48gEjQd.js} +1 -1
- package/dist/assets/{htmlMode-B_wqYWvn.js → htmlMode-Nqw7-Nqh.js} +1 -1
- package/dist/assets/{index-5325376f-kxPTR3_e.js → index-5325376f-rnz0GXAT.js} +1 -1
- package/dist/assets/{index-wkhI4dr6.js → index-DeQLT67a.js} +398 -377
- package/dist/assets/index-DiOCtPLP.css +32 -0
- package/dist/assets/{infoDiagram-8eee0895-BEvqkwPI.js → infoDiagram-8eee0895-BsGB550b.js} +1 -1
- package/dist/assets/{javascript-DhlOH8_z.js → javascript-0g2herYV.js} +1 -1
- package/dist/assets/{journeyDiagram-c64418c1-gKtLYmmp.js → journeyDiagram-c64418c1-DLldlz0H.js} +1 -1
- package/dist/assets/{jsonMode-DxTbF9OD.js → jsonMode-CN5ZURMh.js} +1 -1
- package/dist/assets/{layout-CDaZEk6E.js → layout-QKUiDNJK.js} +1 -1
- package/dist/assets/{line-DNRQu8iq.js → line-CeP3XWjD.js} +1 -1
- package/dist/assets/{linear-Cph9Z6_j.js → linear-74cQVgWT.js} +1 -1
- package/dist/assets/{liquid-ByZ6JgRG.js → liquid-B6cRrfrb.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-DzvhkgnM.js → lspLanguageFeatures-C5ogOh5E.js} +1 -1
- package/dist/assets/{mdx-D8RGHTl6.js → mdx-BBIy-KRj.js} +1 -1
- package/dist/assets/{mermaid.core-BgcryF__.js → mermaid.core-BhdbV0mr.js} +4 -4
- package/dist/assets/{mindmap-definition-8da855dc-WrxK0FcB.js → mindmap-definition-8da855dc-B67VKJuD.js} +1 -1
- package/dist/assets/{pieDiagram-a8764435-VsZBsiQy.js → pieDiagram-a8764435-Cxv9WY_E.js} +1 -1
- package/dist/assets/{python-CXVtk_cg.js → python-CBdGo8__.js} +1 -1
- package/dist/assets/{quadrantDiagram-1e28029f-BVlgwOvU.js → quadrantDiagram-1e28029f-BTkj65P_.js} +1 -1
- package/dist/assets/{razor-0tind7h2.js → razor-azKH0Dwj.js} +1 -1
- package/dist/assets/{requirementDiagram-08caed73-CpPMPoYp.js → requirementDiagram-08caed73-D4jVXpOT.js} +1 -1
- package/dist/assets/{sankeyDiagram-a04cb91d-Cm5nnRmc.js → sankeyDiagram-a04cb91d-CXhutIA1.js} +1 -1
- package/dist/assets/{sequenceDiagram-c5b8d532-DpMlJvJB.js → sequenceDiagram-c5b8d532-B56TTZlx.js} +1 -1
- package/dist/assets/{stateDiagram-1ecb1508-DU1zc7vq.js → stateDiagram-1ecb1508-Cs0plMcS.js} +1 -1
- package/dist/assets/{stateDiagram-v2-c2b004d7-D-0RgmAp.js → stateDiagram-v2-c2b004d7-LSJaXPJN.js} +1 -1
- package/dist/assets/{styles-b4e223ce-BSO-yNWV.js → styles-b4e223ce-UdXfHMuu.js} +1 -1
- package/dist/assets/{styles-ca3715f6-CHnsn2Ro.js → styles-ca3715f6-EuRy_hTu.js} +1 -1
- package/dist/assets/{styles-d45a18b0-B-rVGjEq.js → styles-d45a18b0-B24zVoK3.js} +1 -1
- package/dist/assets/{svgDrawCommon-b86b1483-CA3Pl89f.js → svgDrawCommon-b86b1483-B2S0NW3K.js} +1 -1
- package/dist/assets/{timeline-definition-faaaa080-BcihLR6s.js → timeline-definition-faaaa080-DFWKh9mU.js} +1 -1
- package/dist/assets/{tsMode-D9GGa5Ur.js → tsMode-FZsHWiOn.js} +1 -1
- package/dist/assets/{typescript-BT9CK_EL.js → typescript-CYdJ3s3D.js} +1 -1
- package/dist/assets/{xml-DNO75J-T.js → xml-C16X_hpZ.js} +1 -1
- package/dist/assets/{xychartDiagram-f5964ef8-DJTwe32X.js → xychartDiagram-f5964ef8-DyBiBYci.js} +1 -1
- package/dist/assets/{yaml-7CVzhiP2.js → yaml-CRjA4-Rj.js} +1 -1
- package/dist/index.html +8 -3
- package/dist/manifest.webmanifest +30 -0
- package/dist/pwa-icon-192.png +0 -0
- package/dist/pwa-icon-512.png +0 -0
- package/dist/sw.js +105 -0
- package/index.html +6 -1
- package/package.json +13 -13
- package/public/manifest.webmanifest +30 -0
- package/public/pwa-icon-192.png +0 -0
- package/public/pwa-icon-512.png +0 -0
- package/public/sw.js +105 -0
- package/src/App.tsx +13 -1
- package/src/api/README.md +1 -0
- package/src/api/adapters.ts +63 -0
- package/src/api/auth-token.ts +51 -0
- package/src/api/auth.ts +46 -0
- package/src/api/automation.ts +10 -0
- package/src/api/base.ts +20 -17
- package/src/api/config.ts +5 -1
- package/src/api/knowledge.ts +59 -0
- package/src/api/sessions.ts +35 -3
- package/src/api/skill-hub.ts +126 -0
- package/src/api/workspace.ts +33 -1
- package/src/api/worktree-environments.ts +53 -0
- package/src/api.ts +62 -7
- package/src/client-build-info.ts +19 -0
- package/src/components/ConfigView.scss +595 -28
- package/src/components/ConfigView.tsx +568 -138
- package/src/components/NavRail.scss +1 -2
- package/src/components/NavRail.tsx +33 -3
- package/src/components/Sidebar.scss +0 -44
- package/src/components/Sidebar.tsx +109 -37
- package/src/components/auth/AuthGate.scss +79 -0
- package/src/components/auth/AuthGate.tsx +174 -0
- package/src/components/automation-view/@components/AutomationTaskComposer.tsx +218 -0
- package/src/components/automation-view/@components/AutomationTriggerRow.tsx +192 -0
- package/src/components/automation-view/@hooks/use-automation-startup-options-data.tsx +289 -0
- package/src/components/automation-view/@hooks/use-automation-startup-static-options.ts +51 -0
- package/src/components/automation-view/@utils/sender-model-options.tsx +52 -0
- package/src/components/automation-view/@utils/startup-options.ts +26 -0
- package/src/components/automation-view/AutomationEmptyGuide.tsx +61 -0
- package/src/components/automation-view/AutomationEmptyLanding.scss +165 -0
- package/src/components/automation-view/AutomationEmptyLanding.tsx +199 -0
- package/src/components/automation-view/AutomationRuleDetailPreview.tsx +179 -0
- package/src/components/automation-view/PanelTitleActions.tsx +66 -0
- package/src/components/automation-view/RuleFormPanel.scss +172 -49
- package/src/components/automation-view/RuleFormPanel.tsx +196 -91
- package/src/components/automation-view/RuleSidebar.scss +128 -41
- package/src/components/automation-view/RuleSidebar.tsx +173 -89
- package/src/components/automation-view/RunHistoryPanel.scss +307 -72
- package/src/components/automation-view/RunHistoryPanel.tsx +185 -165
- package/src/components/automation-view/TaskList.scss +126 -64
- package/src/components/automation-view/TaskList.tsx +15 -31
- package/src/components/automation-view/TriggerList.scss +87 -8
- package/src/components/automation-view/TriggerList.tsx +14 -173
- package/src/components/automation-view/index.scss +165 -37
- package/src/components/automation-view/index.tsx +174 -87
- package/src/components/automation-view/types.ts +13 -0
- package/src/components/chat/AGENTS.md +3 -1
- package/src/components/chat/ChatHeader.tsx +56 -33
- package/src/components/chat/ChatHistoryView.tsx +250 -121
- package/src/components/chat/NewSessionGuide.scss +274 -204
- package/src/components/chat/NewSessionGuide.tsx +40 -111
- package/src/components/chat/NewSessionGuideStarterList.tsx +187 -0
- package/src/components/chat/NewSessionGuideStarterSection.tsx +120 -0
- package/src/components/chat/bottom-dock-constants.ts +4 -0
- package/src/components/chat/conversation-starter-apply.ts +181 -0
- package/src/components/chat/git-controls/ChatGitControls.scss +65 -0
- package/src/components/chat/git-controls/DraftGitControls.tsx +14 -0
- package/src/components/chat/git-controls/DraftWorktreeEnvironmentDropdown.tsx +115 -0
- package/src/components/chat/messages/MessageItem.tsx +3 -2
- package/src/components/chat/messages/MessageStatusNotice.tsx +12 -4
- package/src/components/chat/messages/build-chat-history-status-notices.ts +18 -13
- package/src/components/chat/messages/message-action-utils.ts +18 -0
- package/src/components/chat/new-session-guide-config.ts +19 -0
- package/src/components/chat/new-session-guide-items.ts +172 -0
- package/src/components/chat/new-session-guide-list-order.ts +58 -0
- package/src/components/chat/sender/@components/account-select/AccountSelectControl.scss +112 -0
- package/src/components/chat/sender/@components/account-select/AccountSelectControl.tsx +280 -0
- package/src/components/chat/sender/@components/account-select/AccountSelectDropdown.scss +155 -0
- package/src/components/chat/sender/@components/adapter-select/AdapterSelectControl.scss +51 -12
- package/src/components/chat/sender/@components/adapter-select/AdapterSelectDropdown.scss +14 -0
- package/src/components/chat/sender/@components/effort-select/EffortSelectControl.scss +36 -0
- package/src/components/chat/sender/@components/effort-select/EffortSelectControl.tsx +17 -12
- package/src/components/chat/sender/@components/model-select/ModelSelectControl.scss +62 -0
- package/src/components/chat/sender/@components/model-select/ModelSelectControl.tsx +17 -12
- package/src/components/chat/sender/@components/model-select/ModelSelectMenu.scss +2 -0
- package/src/components/chat/sender/@components/model-select/ModelSelectMenuLabels.scss +24 -0
- package/src/components/chat/sender/@components/permission-mode-control/PermissionModeControl.scss +199 -0
- package/src/components/chat/sender/@components/permission-mode-control/PermissionModeControl.tsx +172 -0
- package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.scss +1 -10
- package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.tsx +16 -65
- package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +13 -1
- package/src/components/chat/sender/@components/sender-header-controls/SenderHeaderControls.tsx +157 -0
- package/src/components/chat/sender/@components/sender-monaco-editor/monaco-runtime.ts +1 -17
- package/src/components/chat/sender/@components/sender-toolbar/SenderSelectBase.scss +18 -2
- package/src/components/chat/sender/@components/sender-toolbar/SenderSelectShared.scss +18 -1
- package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.scss +2 -0
- package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.tsx +40 -40
- package/src/components/chat/sender/@components/session-target/SenderSessionTargetBar.scss +215 -0
- package/src/components/chat/sender/@components/session-target/SenderSessionTargetBar.tsx +185 -0
- package/src/components/chat/sender/@core/build-sender-toolbar.ts +6 -0
- package/src/components/chat/sender/@core/create-sender-toolbar-handlers.ts +21 -1
- package/src/components/chat/sender/@core/get-sender-runtime-state.ts +3 -2
- package/src/components/chat/sender/@core/sender-toolbar-bindings.ts +12 -0
- package/src/components/chat/sender/@hooks/use-sender-controller.ts +56 -1
- package/src/components/chat/sender/@hooks/use-sender-reference-actions.ts +9 -66
- package/src/components/chat/sender/@types/sender-props.ts +18 -0
- package/src/components/chat/sender/@types/sender-toolbar-types.ts +8 -1
- package/src/components/chat/sender/@types/sender-types.ts +1 -3
- package/src/components/chat/sender/@utils/sender-constants.ts +1 -1
- package/src/components/chat/sender/Sender.scss +245 -2
- package/src/components/chat/sender/Sender.tsx +1 -0
- package/src/components/chat/status-bar/ChatStatusBar.scss +85 -0
- package/src/components/chat/status-bar/ChatStatusBar.tsx +48 -0
- package/src/components/chat/terminal/@components/TerminalManagerList.tsx +191 -0
- package/src/components/chat/terminal/@components/TerminalPane.scss +71 -0
- package/src/components/chat/terminal/@components/TerminalPane.tsx +137 -0
- package/src/components/chat/terminal/@components/TerminalPanelActions.tsx +75 -0
- package/src/components/chat/terminal/@hooks/use-terminal-instance.ts +36 -0
- package/src/components/chat/terminal/@hooks/use-terminal-session.ts +18 -21
- package/src/components/chat/terminal/@hooks/use-terminal-title-editor.ts +72 -0
- package/src/components/chat/terminal/@utils/terminal-keyboard.ts +141 -0
- package/src/components/chat/terminal/@utils/terminal-panes.ts +123 -0
- package/src/components/chat/terminal/ChatTerminalView.scss +310 -38
- package/src/components/chat/terminal/ChatTerminalView.tsx +151 -79
- package/src/components/chat/tools/core/ToolDiffViewer.tsx +3 -17
- package/src/components/chat/workspace-drawer/ChatWorkspaceDrawer.scss +778 -0
- package/src/components/chat/workspace-drawer/ChatWorkspaceDrawer.tsx +112 -0
- package/src/components/chat/workspace-drawer/ChatWorkspaceDrawerToolbar.tsx +183 -0
- package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFileRow.tsx +75 -0
- package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFiles.tsx +161 -0
- package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFolderTree.tsx +191 -0
- package/src/components/chat/workspace-drawer/WorkspaceDrawerTree.tsx +35 -0
- package/src/components/chat/workspace-drawer/WorkspaceDrawerTreeState.tsx +17 -0
- package/src/components/chat/workspace-drawer/changed-files-model.ts +152 -0
- package/src/components/chat/workspace-drawer/workspace-drawer-icons.ts +110 -0
- package/src/components/chat/workspace-file-editor/WorkspaceFileBreadcrumb.tsx +17 -0
- package/src/components/chat/workspace-file-editor/WorkspaceFileEditorView.scss +283 -0
- package/src/components/chat/workspace-file-editor/WorkspaceFileEditorView.tsx +165 -0
- package/src/components/chat/workspace-file-editor/WorkspaceFileTabs.tsx +135 -0
- package/src/components/chat/workspace-file-editor/use-workspace-file-editor-state.ts +113 -0
- package/src/components/chat/workspace-file-editor/workspace-file-editor-language.ts +55 -0
- package/src/components/composer-landing/ComposerLanding.scss +75 -0
- package/src/components/composer-landing/ComposerLanding.tsx +47 -0
- package/src/components/config/AGENTS.md +45 -0
- package/src/components/config/AdapterAccountsManager.scss +540 -0
- package/src/components/config/AdapterAccountsManager.tsx +846 -0
- package/src/components/config/AppSettingsPanel.tsx +24 -2
- package/src/components/config/ConfigAboutSection.scss +7 -1
- package/src/components/config/ConfigAboutSection.tsx +21 -3
- package/src/components/config/ConfigEditors.scss +12 -0
- package/src/components/config/ConfigFieldRow.scss +88 -4
- package/src/components/config/ConfigSectionForm.scss +88 -3
- package/src/components/config/ConfigSectionForm.tsx +948 -138
- package/src/components/config/ConfigSectionPanel.tsx +188 -12
- package/src/components/config/ConfigSourceSwitch.tsx +32 -18
- package/src/components/config/DetailCollectionFieldActions.tsx +63 -0
- package/src/components/config/DetailListField.tsx +413 -0
- package/src/components/config/McpServerItemEditor.tsx +154 -0
- package/src/components/config/RecommendedModelsItemEditor.tsx +146 -0
- package/src/components/config/WorktreeEnvironmentDetailView.tsx +126 -0
- package/src/components/config/WorktreeEnvironmentListView.tsx +126 -0
- package/src/components/config/WorktreeEnvironmentPanel.scss +430 -0
- package/src/components/config/WorktreeEnvironmentPanel.tsx +147 -0
- package/src/components/config/WorktreeEnvironmentScriptEditorCard.tsx +125 -0
- package/src/components/config/WorktreeEnvironmentScriptEditors.tsx +189 -0
- package/src/components/config/configConflict.ts +41 -0
- package/src/components/config/configDetail.ts +381 -0
- package/src/components/config/configSchema.ts +850 -179
- package/src/components/config/configUtils.ts +1 -1
- package/src/components/config/record-editors/RecordEditors.scss +187 -2
- package/src/components/config/record-editors/RecordJsonEditor.tsx +27 -2
- package/src/components/config/record-editors/SchemaObjectEditor.tsx +183 -0
- package/src/components/config/record-editors/SchemaRecordEditor.tsx +184 -0
- package/src/components/config/record-editors/index.tsx +2 -1
- package/src/components/config/record-editors/schemaRecordUtils.ts +55 -0
- package/src/components/config/use-worktree-environment-auto-save.ts +386 -0
- package/src/components/config/worktree-environment-panel-model.ts +108 -0
- package/src/components/dock-panel/DockPanel.scss +84 -17
- package/src/components/dock-panel/DockPanel.tsx +37 -34
- package/src/components/dock-panel/DockPanelHeader.tsx +65 -0
- package/src/components/dock-panel/use-dock-panel-fullscreen.ts +51 -0
- package/src/components/knowledge-base/KnowledgeBaseView.scss +276 -38
- package/src/components/knowledge-base/KnowledgeBaseView.tsx +252 -46
- package/src/components/knowledge-base/components/ActionButton.scss +30 -4
- package/src/components/knowledge-base/components/ActionButton.tsx +13 -3
- package/src/components/knowledge-base/components/CreateSkillModal.tsx +59 -0
- package/src/components/knowledge-base/components/EmptyState.scss +4 -2
- package/src/components/knowledge-base/components/EntitiesTab.tsx +20 -20
- package/src/components/knowledge-base/components/EntityList.scss +3 -0
- package/src/components/knowledge-base/components/FilterBar.scss +1 -0
- package/src/components/knowledge-base/components/FilterBar.tsx +12 -8
- package/src/components/knowledge-base/components/FlowsTab.tsx +20 -20
- package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +7 -6
- package/src/components/knowledge-base/components/KnowledgeContentControls.tsx +35 -0
- package/src/components/knowledge-base/components/KnowledgeList.scss +14 -3
- package/src/components/knowledge-base/components/KnowledgeMobilePanel.tsx +122 -0
- package/src/components/knowledge-base/components/KnowledgeSidebar.tsx +97 -0
- package/src/components/knowledge-base/components/LoadingState.scss +2 -1
- package/src/components/knowledge-base/components/ProjectSkillsList.tsx +79 -0
- package/src/components/knowledge-base/components/RuleList.scss +3 -0
- package/src/components/knowledge-base/components/RulesTab.tsx +31 -30
- package/src/components/knowledge-base/components/SectionHeader.scss +13 -1
- package/src/components/knowledge-base/components/SectionHeader.tsx +5 -3
- package/src/components/knowledge-base/components/SkillArchiveInput.tsx +43 -0
- package/src/components/knowledge-base/components/SkillHubResultItem.tsx +112 -0
- package/src/components/knowledge-base/components/SkillMarketResults.tsx +98 -0
- package/src/components/knowledge-base/components/SkillMarketView.tsx +198 -0
- package/src/components/knowledge-base/components/SkillMarketView.types.ts +28 -0
- package/src/components/knowledge-base/components/SkillRegistryErrors.tsx +21 -0
- package/src/components/knowledge-base/components/SkillRegistryModal.tsx +74 -0
- package/src/components/knowledge-base/components/SkillsCliModal.tsx +154 -0
- package/src/components/knowledge-base/components/SkillsTab.scss +424 -0
- package/src/components/knowledge-base/components/SkillsTab.tsx +319 -35
- package/src/components/knowledge-base/components/SkillsTabActions.tsx +88 -0
- package/src/components/knowledge-base/components/SpecList.scss +3 -0
- package/src/components/knowledge-base/components/TabContent.scss +4 -3
- package/src/components/knowledge-base/components/skill-hub-utils.ts +108 -0
- package/src/components/knowledge-base/components/use-skill-market-filters.ts +37 -0
- package/src/components/knowledge-base/components/use-skill-market-query-input.ts +44 -0
- package/src/components/knowledge-base/components/use-skill-market-search.ts +49 -0
- package/src/components/knowledge-base/components/use-skill-registry-modal.ts +68 -0
- package/src/components/monaco/monaco-runtime.ts +44 -0
- package/src/components/monaco/use-monaco-theme.ts +63 -0
- package/src/components/nav-rail-account-actions.tsx +104 -0
- package/src/components/server-connection/ServerConnectionGate.scss +356 -0
- package/src/components/server-connection/ServerConnectionGate.tsx +238 -0
- package/src/components/server-connection/ServerConnectionProfileModal.tsx +145 -0
- package/src/components/server-connection/ServerConnectionProfiles.tsx +113 -0
- package/src/components/server-connection/ServerConnectionUrlInput.tsx +85 -0
- package/src/components/sidebar/SidebarHeader.scss +5 -41
- package/src/components/sidebar/SidebarHeader.tsx +74 -66
- package/src/components/sidebar/SidebarHeaderSearchActions.tsx +24 -28
- package/src/components/sidebar-list/SidebarListHeader.scss +246 -0
- package/src/components/sidebar-list/SidebarListHeader.tsx +146 -0
- package/src/components/workspace/ContextFilePicker.scss +9 -26
- package/src/components/workspace/ContextFilePicker.tsx +31 -113
- package/src/components/workspace/context-file-types.ts +36 -0
- package/src/components/workspace/project-file-tree/ProjectFileTree.scss +298 -0
- package/src/components/workspace/project-file-tree/ProjectFileTree.tsx +138 -0
- package/src/components/workspace/project-file-tree/ProjectFileTreeRow.tsx +167 -0
- package/src/components/workspace/project-file-tree/ProjectFileTreeRowContextMenu.tsx +106 -0
- package/src/components/workspace/project-file-tree/ProjectFileTreeRows.tsx +139 -0
- package/src/components/workspace/project-file-tree/project-file-tree-helpers.ts +101 -0
- package/src/components/workspace/project-file-tree/project-file-tree-icons.ts +93 -0
- package/src/components/workspace/project-file-tree/project-file-tree-types.ts +27 -0
- package/src/components/workspace/project-file-tree/use-project-file-tree-data.ts +197 -0
- package/src/components/workspace/project-file-tree/use-project-file-tree-selection.ts +144 -0
- package/src/hooks/chat/chat-session-target.ts +69 -0
- package/src/hooks/chat/chat-session-workspace-draft.ts +11 -4
- package/src/hooks/chat/interaction-state.ts +1 -0
- package/src/hooks/chat/optimistic-session-creation.ts +189 -0
- package/src/hooks/chat/use-chat-adapter-account-selection.tsx +156 -0
- package/src/hooks/chat/use-chat-route-bottom-panel.ts +181 -0
- package/src/hooks/chat/use-chat-route-deep-link-view.ts +33 -0
- package/src/hooks/chat/use-chat-session-actions.ts +259 -65
- package/src/hooks/chat/use-chat-session-messages.ts +71 -4
- package/src/hooks/chat/use-chat-session.ts +36 -1
- package/src/hooks/chat/workspace-file-panel-state.ts +43 -0
- package/src/hooks/session-subscription-cache.ts +25 -0
- package/src/hooks/use-chat-layout-query-state.ts +29 -0
- package/src/hooks/use-sender-header-query-state.ts +35 -0
- package/src/hooks/use-session-subscription.ts +17 -8
- package/src/i18n-resources.ts +44 -0
- package/src/i18n.ts +21 -6
- package/src/main.tsx +8 -0
- package/src/pwa.ts +46 -0
- package/src/resources/locales/en.json +729 -24
- package/src/resources/locales/zh.json +731 -26
- package/src/routes/ChatRoute.scss +105 -7
- package/src/routes/ChatRoute.tsx +11 -165
- package/src/routes/ChatRouteBottomPanel.tsx +47 -0
- package/src/routes/ChatRouteView.tsx +199 -0
- package/src/runtime-config.ts +155 -2
- package/src/server-connection-history.ts +179 -0
- package/src/store/index.ts +40 -0
- package/src/styles/global.scss +3 -0
- package/src/utils/mobile-viewport.ts +67 -0
- package/src/version-compatibility.ts +37 -0
- package/src/vite-env.d.ts +9 -0
- package/src/ws.ts +20 -9
- package/vite.config.ts +23 -1
- package/dist/assets/channel-Dnopc5A6.js +0 -1
- package/dist/assets/clone-sQthahUA.js +0 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-OazrdWQO.js +0 -1
- package/dist/assets/index-o93dlo92.css +0 -32
- package/src/components/chat/NewSessionGuideCompactPanel.tsx +0 -130
- package/src/components/chat/NewSessionGuideGrid.tsx +0 -141
- package/src/components/chat/sender/@components/reference-actions/ReferencePermissionActionsPopover.tsx +0 -114
package/src/runtime-config.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
export type RuntimeEnv = Partial<{
|
|
2
|
+
__VF_PROJECT_AI_SERVER_BASE_URL__: string
|
|
2
3
|
__VF_PROJECT_AI_SERVER_HOST__: string
|
|
3
4
|
__VF_PROJECT_AI_SERVER_PORT__: string
|
|
4
5
|
__VF_PROJECT_AI_SERVER_WS_PATH__: string
|
|
6
|
+
__VF_PROJECT_AI_CLIENT_MODE__: string
|
|
5
7
|
__VF_PROJECT_AI_CLIENT_BASE__: string
|
|
8
|
+
__VF_PROJECT_AI_CLIENT_VERSION__: string
|
|
9
|
+
__VF_PROJECT_AI_CLIENT_COMMIT_HASH__: string
|
|
6
10
|
}>
|
|
7
11
|
|
|
12
|
+
export const SERVER_BASE_URL_STORAGE_KEY = 'vf_server_base_url'
|
|
13
|
+
export const SERVER_CONNECTION_PICKER_STORAGE_KEY = 'vf_server_connection_picker_requested'
|
|
14
|
+
|
|
8
15
|
export const resolveDevDocumentTitle = (
|
|
9
16
|
baseTitle: string,
|
|
10
17
|
input: {
|
|
@@ -57,6 +64,95 @@ const normalizePath = (value?: string) => {
|
|
|
57
64
|
return next
|
|
58
65
|
}
|
|
59
66
|
|
|
67
|
+
const normalizeServerHost = (value?: string) => {
|
|
68
|
+
const next = value?.trim()
|
|
69
|
+
if (next == null || next === '' || next === '0.0.0.0' || next === '::' || next === '[::]') {
|
|
70
|
+
return undefined
|
|
71
|
+
}
|
|
72
|
+
return next
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const hasUrlProtocol = (value: string) => /^[a-z][a-z\d+.-]*:\/\//i.test(value)
|
|
76
|
+
|
|
77
|
+
const getStorage = () => {
|
|
78
|
+
try {
|
|
79
|
+
return globalThis.localStorage
|
|
80
|
+
} catch {
|
|
81
|
+
return undefined
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const getBrowserProtocol = () => (
|
|
86
|
+
globalThis.location?.protocol === 'https:' ? 'https' : 'http'
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
const getClientMode = () => (
|
|
90
|
+
pickNonEmptyValue(
|
|
91
|
+
getRuntimeEnv().__VF_PROJECT_AI_CLIENT_MODE__,
|
|
92
|
+
import.meta.env.__VF_PROJECT_AI_CLIENT_MODE__,
|
|
93
|
+
import.meta.env.__VF_PROJECT_AI_CLIENT_DEPLOY_MODE__
|
|
94
|
+
)?.trim().toLowerCase()
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
export const normalizeServerBaseUrl = (value?: string) => {
|
|
98
|
+
const trimmed = value?.trim() ?? ''
|
|
99
|
+
if (trimmed === '') {
|
|
100
|
+
return undefined
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const rawUrl = hasUrlProtocol(trimmed) ? trimmed : `${getBrowserProtocol()}://${trimmed}`
|
|
104
|
+
try {
|
|
105
|
+
const url = new URL(rawUrl)
|
|
106
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
107
|
+
return undefined
|
|
108
|
+
}
|
|
109
|
+
url.hash = ''
|
|
110
|
+
url.search = ''
|
|
111
|
+
return url.toString().replace(/\/$/, '')
|
|
112
|
+
} catch {
|
|
113
|
+
return undefined
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const createServerUrlFromBase = (baseUrl: string, path: string) => {
|
|
118
|
+
const normalizedBaseUrl = normalizeServerBaseUrl(baseUrl)
|
|
119
|
+
if (normalizedBaseUrl == null) {
|
|
120
|
+
throw new Error('Invalid server base URL')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const relativePath = path.replace(/^\/+/, '')
|
|
124
|
+
return new URL(relativePath, `${normalizedBaseUrl}/`).toString()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const getStoredServerBaseUrl = () => (
|
|
128
|
+
normalizeServerBaseUrl(getStorage()?.getItem(SERVER_BASE_URL_STORAGE_KEY) ?? undefined)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
export const setStoredServerBaseUrl = (value: string) => {
|
|
132
|
+
const normalized = normalizeServerBaseUrl(value)
|
|
133
|
+
if (normalized == null) {
|
|
134
|
+
return undefined
|
|
135
|
+
}
|
|
136
|
+
getStorage()?.setItem(SERVER_BASE_URL_STORAGE_KEY, normalized)
|
|
137
|
+
return normalized
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const clearStoredServerBaseUrl = () => {
|
|
141
|
+
getStorage()?.removeItem(SERVER_BASE_URL_STORAGE_KEY)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const isStandaloneClientMode = () => {
|
|
145
|
+
const mode = getClientMode()
|
|
146
|
+
return mode === 'standalone' || mode === 'independent'
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const isDesktopClientMode = () => getClientMode() === 'desktop'
|
|
150
|
+
|
|
151
|
+
export const isServerConnectionManagedClientMode = () => {
|
|
152
|
+
const mode = getClientMode()
|
|
153
|
+
return mode === 'standalone' || mode === 'independent' || mode === 'desktop'
|
|
154
|
+
}
|
|
155
|
+
|
|
60
156
|
export const getRuntimeEnv = (): RuntimeEnv => getGlobalRuntimeEnv() ?? {}
|
|
61
157
|
|
|
62
158
|
export const resolveClientBase = (...values: Array<string | undefined>) => (
|
|
@@ -73,14 +169,71 @@ export const getClientBase = () => (
|
|
|
73
169
|
)
|
|
74
170
|
|
|
75
171
|
export const getServerHostEnv = () =>
|
|
76
|
-
|
|
77
|
-
|
|
172
|
+
normalizeServerHost(
|
|
173
|
+
getRuntimeEnv().__VF_PROJECT_AI_SERVER_HOST__ ??
|
|
174
|
+
import.meta.env.__VF_PROJECT_AI_SERVER_HOST__
|
|
175
|
+
)
|
|
78
176
|
|
|
79
177
|
export const getServerPortEnv = () =>
|
|
80
178
|
getRuntimeEnv().__VF_PROJECT_AI_SERVER_PORT__ ??
|
|
81
179
|
import.meta.env.__VF_PROJECT_AI_SERVER_PORT__
|
|
82
180
|
|
|
181
|
+
export const getConfiguredServerBaseUrl = () => {
|
|
182
|
+
const configuredServerBaseUrl = normalizeServerBaseUrl(
|
|
183
|
+
getRuntimeEnv().__VF_PROJECT_AI_SERVER_BASE_URL__ ??
|
|
184
|
+
import.meta.env.__VF_PROJECT_AI_SERVER_BASE_URL__
|
|
185
|
+
)
|
|
186
|
+
if (configuredServerBaseUrl != null) {
|
|
187
|
+
return configuredServerBaseUrl
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const serverHost = getServerHostEnv()
|
|
191
|
+
const serverPort = getServerPortEnv()?.trim()
|
|
192
|
+
if (serverHost == null || serverPort == null || serverPort === '') {
|
|
193
|
+
return undefined
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return normalizeServerBaseUrl(`${serverHost}:${serverPort}`)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export const isServerConnectionPickerRequested = () => (
|
|
200
|
+
getStorage()?.getItem(SERVER_CONNECTION_PICKER_STORAGE_KEY) === 'true'
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
export const requestServerConnectionPicker = (
|
|
204
|
+
{ clearCurrentServer = false }: { clearCurrentServer?: boolean } = {}
|
|
205
|
+
) => {
|
|
206
|
+
if (clearCurrentServer) {
|
|
207
|
+
clearStoredServerBaseUrl()
|
|
208
|
+
}
|
|
209
|
+
getStorage()?.setItem(SERVER_CONNECTION_PICKER_STORAGE_KEY, 'true')
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export const clearServerConnectionPickerRequest = () => {
|
|
213
|
+
getStorage()?.removeItem(SERVER_CONNECTION_PICKER_STORAGE_KEY)
|
|
214
|
+
}
|
|
215
|
+
|
|
83
216
|
export const getServerWsPath = () =>
|
|
84
217
|
normalizePath(
|
|
85
218
|
getRuntimeEnv().__VF_PROJECT_AI_SERVER_WS_PATH__ ?? import.meta.env.__VF_PROJECT_AI_SERVER_WS_PATH__
|
|
86
219
|
)
|
|
220
|
+
|
|
221
|
+
export const getServerBaseUrl = () => {
|
|
222
|
+
if (isServerConnectionManagedClientMode()) {
|
|
223
|
+
const storedServerBaseUrl = getStoredServerBaseUrl()
|
|
224
|
+
if (storedServerBaseUrl != null) {
|
|
225
|
+
return storedServerBaseUrl
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const configuredServerBaseUrl = getConfiguredServerBaseUrl()
|
|
230
|
+
if (configuredServerBaseUrl != null) {
|
|
231
|
+
return configuredServerBaseUrl
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const serverHost = getServerHostEnv() ?? globalThis.location?.hostname ?? 'localhost'
|
|
235
|
+
const serverPort = getServerPortEnv() ?? '8787'
|
|
236
|
+
return normalizeServerBaseUrl(`${serverHost}:${serverPort}`) ?? `${getBrowserProtocol()}://localhost:8787`
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const createServerUrl = (path: string) => createServerUrlFromBase(getServerBaseUrl(), path)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { normalizeServerBaseUrl } from '#~/runtime-config'
|
|
2
|
+
|
|
3
|
+
export const SERVER_BASE_URL_HISTORY_STORAGE_KEY = 'vf_server_base_url_history'
|
|
4
|
+
|
|
5
|
+
export interface ServerConnectionProfile {
|
|
6
|
+
serverUrl: string
|
|
7
|
+
alias?: string
|
|
8
|
+
description?: string
|
|
9
|
+
authToken?: string
|
|
10
|
+
serverVersion?: string
|
|
11
|
+
createdAt: number
|
|
12
|
+
lastConnectedAt: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ServerConnectionProfileDetails {
|
|
16
|
+
alias?: string
|
|
17
|
+
description?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getStorage = () => {
|
|
21
|
+
try {
|
|
22
|
+
return globalThis.localStorage
|
|
23
|
+
} catch {
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const normalizeOptionalText = (value: unknown) => {
|
|
29
|
+
const normalized = typeof value === 'string' ? value.trim() : ''
|
|
30
|
+
return normalized === '' ? undefined : normalized
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const normalizeProfile = (value: unknown, fallbackTime: number): ServerConnectionProfile | undefined => {
|
|
34
|
+
if (typeof value === 'string') {
|
|
35
|
+
const serverUrl = normalizeServerBaseUrl(value)
|
|
36
|
+
return serverUrl == null ? undefined : {
|
|
37
|
+
serverUrl,
|
|
38
|
+
createdAt: fallbackTime,
|
|
39
|
+
lastConnectedAt: fallbackTime
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) return undefined
|
|
43
|
+
|
|
44
|
+
const record = value as Record<string, unknown>
|
|
45
|
+
const serverUrl = normalizeServerBaseUrl(record.serverUrl as string | undefined)
|
|
46
|
+
if (serverUrl == null) return undefined
|
|
47
|
+
|
|
48
|
+
const createdAt = typeof record.createdAt === 'number' ? record.createdAt : fallbackTime
|
|
49
|
+
const lastConnectedAt = typeof record.lastConnectedAt === 'number' ? record.lastConnectedAt : createdAt
|
|
50
|
+
const alias = normalizeOptionalText(record.alias)
|
|
51
|
+
const description = normalizeOptionalText(record.description)
|
|
52
|
+
const authToken = normalizeOptionalText(record.authToken)
|
|
53
|
+
const serverVersion = normalizeOptionalText(record.serverVersion)
|
|
54
|
+
return {
|
|
55
|
+
serverUrl,
|
|
56
|
+
createdAt,
|
|
57
|
+
lastConnectedAt,
|
|
58
|
+
...(alias != null ? { alias } : {}),
|
|
59
|
+
...(description != null ? { description } : {}),
|
|
60
|
+
...(authToken != null ? { authToken } : {}),
|
|
61
|
+
...(serverVersion != null ? { serverVersion } : {})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const sortProfiles = (profiles: ServerConnectionProfile[]) => (
|
|
66
|
+
[...profiles].sort((left, right) => right.lastConnectedAt - left.lastConnectedAt)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
const saveProfiles = (profiles: ServerConnectionProfile[]) => {
|
|
70
|
+
const normalizedProfiles = sortProfiles(profiles)
|
|
71
|
+
getStorage()?.setItem(SERVER_BASE_URL_HISTORY_STORAGE_KEY, JSON.stringify(normalizedProfiles))
|
|
72
|
+
return normalizedProfiles
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const getServerConnectionProfiles = () => {
|
|
76
|
+
const raw = getStorage()?.getItem(SERVER_BASE_URL_HISTORY_STORAGE_KEY)
|
|
77
|
+
if (raw == null || raw.trim() === '') return []
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const parsed = JSON.parse(raw) as unknown
|
|
81
|
+
if (!Array.isArray(parsed)) return []
|
|
82
|
+
|
|
83
|
+
const profileByUrl = new Map<string, ServerConnectionProfile>()
|
|
84
|
+
const fallbackTime = Date.now()
|
|
85
|
+
for (const item of parsed) {
|
|
86
|
+
const profile = normalizeProfile(item, fallbackTime)
|
|
87
|
+
if (profile == null || profileByUrl.has(profile.serverUrl)) continue
|
|
88
|
+
profileByUrl.set(profile.serverUrl, profile)
|
|
89
|
+
}
|
|
90
|
+
return sortProfiles(Array.from(profileByUrl.values()))
|
|
91
|
+
} catch {
|
|
92
|
+
return []
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const getRecentServerBaseUrls = () => (
|
|
97
|
+
getServerConnectionProfiles().map(profile => profile.serverUrl)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
export const rememberServerBaseUrl = (value: string, details: { serverVersion?: string } = {}) => {
|
|
101
|
+
const serverUrl = normalizeServerBaseUrl(value)
|
|
102
|
+
if (serverUrl == null) return getServerConnectionProfiles()
|
|
103
|
+
|
|
104
|
+
const now = Date.now()
|
|
105
|
+
const profiles = getServerConnectionProfiles()
|
|
106
|
+
const existing = profiles.find(profile => profile.serverUrl === serverUrl)
|
|
107
|
+
const nextProfile: ServerConnectionProfile = {
|
|
108
|
+
...existing,
|
|
109
|
+
serverUrl,
|
|
110
|
+
createdAt: existing?.createdAt ?? now,
|
|
111
|
+
lastConnectedAt: now,
|
|
112
|
+
...(normalizeOptionalText(details.serverVersion) != null
|
|
113
|
+
? { serverVersion: normalizeOptionalText(details.serverVersion) }
|
|
114
|
+
: {})
|
|
115
|
+
}
|
|
116
|
+
return saveProfiles([
|
|
117
|
+
nextProfile,
|
|
118
|
+
...profiles.filter(profile => profile.serverUrl !== serverUrl)
|
|
119
|
+
])
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const updateServerConnectionProfile = (serverUrl: string, details: ServerConnectionProfileDetails) => {
|
|
123
|
+
const normalizedServerUrl = normalizeServerBaseUrl(serverUrl)
|
|
124
|
+
if (normalizedServerUrl == null) return getServerConnectionProfiles()
|
|
125
|
+
|
|
126
|
+
const now = Date.now()
|
|
127
|
+
const profiles = getServerConnectionProfiles()
|
|
128
|
+
const existing = profiles.find(profile => profile.serverUrl === normalizedServerUrl)
|
|
129
|
+
const alias = normalizeOptionalText(details.alias)
|
|
130
|
+
const description = normalizeOptionalText(details.description)
|
|
131
|
+
const { alias: _alias, description: _description, ...existingProfile } = existing ?? {}
|
|
132
|
+
return saveProfiles([
|
|
133
|
+
{
|
|
134
|
+
...existingProfile,
|
|
135
|
+
serverUrl: normalizedServerUrl,
|
|
136
|
+
createdAt: existing?.createdAt ?? now,
|
|
137
|
+
lastConnectedAt: existing?.lastConnectedAt ?? now,
|
|
138
|
+
...(alias != null ? { alias } : {}),
|
|
139
|
+
...(description != null ? { description } : {})
|
|
140
|
+
},
|
|
141
|
+
...profiles.filter(profile => profile.serverUrl !== normalizedServerUrl)
|
|
142
|
+
])
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const removeServerConnectionProfile = (serverUrl: string) => {
|
|
146
|
+
const normalizedServerUrl = normalizeServerBaseUrl(serverUrl)
|
|
147
|
+
if (normalizedServerUrl == null) return getServerConnectionProfiles()
|
|
148
|
+
return saveProfiles(getServerConnectionProfiles().filter(profile => profile.serverUrl !== normalizedServerUrl))
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export const getAuthTokenForServerUrl = (serverUrl: string) => (
|
|
152
|
+
getServerConnectionProfiles().find(profile => profile.serverUrl === normalizeServerBaseUrl(serverUrl))
|
|
153
|
+
?.authToken
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
export const setAuthTokenForServerUrl = (serverUrl: string, token: string) => {
|
|
157
|
+
const normalizedToken = token.trim()
|
|
158
|
+
if (normalizedToken === '') return
|
|
159
|
+
|
|
160
|
+
const profiles = rememberServerBaseUrl(serverUrl)
|
|
161
|
+
const normalizedServerUrl = normalizeServerBaseUrl(serverUrl)
|
|
162
|
+
saveProfiles(
|
|
163
|
+
profiles.map(profile =>
|
|
164
|
+
profile.serverUrl === normalizedServerUrl ? { ...profile, authToken: normalizedToken } : profile
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export const clearAuthTokenForServerUrl = (serverUrl: string) => {
|
|
170
|
+
const normalizedServerUrl = normalizeServerBaseUrl(serverUrl)
|
|
171
|
+
if (normalizedServerUrl == null) return getServerConnectionProfiles()
|
|
172
|
+
return saveProfiles(
|
|
173
|
+
getServerConnectionProfiles().map(profile => {
|
|
174
|
+
if (profile.serverUrl !== normalizedServerUrl) return profile
|
|
175
|
+
const { authToken: _authToken, ...nextProfile } = profile
|
|
176
|
+
return nextProfile
|
|
177
|
+
})
|
|
178
|
+
)
|
|
179
|
+
}
|
package/src/store/index.ts
CHANGED
|
@@ -22,4 +22,44 @@ export const themeAtom = atom<ThemeMode>(
|
|
|
22
22
|
(localStorage.getItem('theme') as ThemeMode) || 'system'
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
+
export type SenderHeaderDisplayMode = 'expanded' | 'collapsed'
|
|
26
|
+
|
|
27
|
+
const SENDER_HEADER_DISPLAY_STORAGE_KEY = 'vf_sender_header_default_display'
|
|
28
|
+
|
|
29
|
+
const isSenderHeaderDisplayMode = (
|
|
30
|
+
value: string
|
|
31
|
+
): value is SenderHeaderDisplayMode => {
|
|
32
|
+
return value === 'expanded' || value === 'collapsed'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const getStoredSenderHeaderDisplayMode = (): SenderHeaderDisplayMode => {
|
|
36
|
+
try {
|
|
37
|
+
const raw = localStorage.getItem(SENDER_HEADER_DISPLAY_STORAGE_KEY)
|
|
38
|
+
if (raw != null && isSenderHeaderDisplayMode(raw)) {
|
|
39
|
+
return raw
|
|
40
|
+
}
|
|
41
|
+
} catch {}
|
|
42
|
+
|
|
43
|
+
return 'expanded'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const senderHeaderDisplayBaseAtom = atom<SenderHeaderDisplayMode>(
|
|
47
|
+
getStoredSenderHeaderDisplayMode()
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
export const senderHeaderDisplayAtom = atom(
|
|
51
|
+
get => get(senderHeaderDisplayBaseAtom),
|
|
52
|
+
(_get, set, value: SenderHeaderDisplayMode) => {
|
|
53
|
+
const nextValue = isSenderHeaderDisplayMode(value)
|
|
54
|
+
? value
|
|
55
|
+
: 'expanded'
|
|
56
|
+
|
|
57
|
+
set(senderHeaderDisplayBaseAtom, nextValue)
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
localStorage.setItem(SENDER_HEADER_DISPLAY_STORAGE_KEY, nextValue)
|
|
61
|
+
} catch {}
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
25
65
|
export const showAnnouncementsAtom = atom(true)
|
package/src/styles/global.scss
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const KEYBOARD_VISIBLE_THRESHOLD = 80
|
|
2
|
+
|
|
3
|
+
const focusableSelector = [
|
|
4
|
+
'input',
|
|
5
|
+
'textarea',
|
|
6
|
+
'select',
|
|
7
|
+
'[contenteditable="true"]',
|
|
8
|
+
'[role="textbox"]'
|
|
9
|
+
].join(',')
|
|
10
|
+
|
|
11
|
+
const getViewport = () => globalThis.visualViewport
|
|
12
|
+
|
|
13
|
+
const getFocusedInput = () => {
|
|
14
|
+
const activeElement = document.activeElement
|
|
15
|
+
if (!(activeElement instanceof HTMLElement)) return undefined
|
|
16
|
+
return activeElement.matches(focusableSelector) ? activeElement : undefined
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const scrollFocusedInputIntoView = () => {
|
|
20
|
+
const focusedInput = getFocusedInput()
|
|
21
|
+
if (focusedInput == null) return
|
|
22
|
+
|
|
23
|
+
focusedInput.scrollIntoView({
|
|
24
|
+
block: 'center',
|
|
25
|
+
inline: 'nearest',
|
|
26
|
+
behavior: 'auto'
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const setupMobileViewport = () => {
|
|
31
|
+
if (typeof window === 'undefined') return
|
|
32
|
+
|
|
33
|
+
let scrollFrame = 0
|
|
34
|
+
|
|
35
|
+
const updateViewportVars = () => {
|
|
36
|
+
const viewport = getViewport()
|
|
37
|
+
const viewportHeight = viewport?.height ?? window.innerHeight
|
|
38
|
+
const viewportOffsetTop = viewport?.offsetTop ?? 0
|
|
39
|
+
const focusedInput = getFocusedInput()
|
|
40
|
+
const keyboardInset = viewport == null || focusedInput == null
|
|
41
|
+
? 0
|
|
42
|
+
: Math.max(0, window.innerHeight - viewportHeight - viewportOffsetTop)
|
|
43
|
+
|
|
44
|
+
document.documentElement.style.setProperty('--vf-visual-viewport-height', `${Math.round(viewportHeight)}px`)
|
|
45
|
+
document.documentElement.style.setProperty('--vf-keyboard-inset-bottom', `${Math.round(keyboardInset)}px`)
|
|
46
|
+
document.documentElement.classList.toggle('has-mobile-keyboard', keyboardInset > KEYBOARD_VISIBLE_THRESHOLD)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const scheduleFocusedInputScroll = () => {
|
|
50
|
+
window.cancelAnimationFrame(scrollFrame)
|
|
51
|
+
scrollFrame = window.requestAnimationFrame(() => {
|
|
52
|
+
updateViewportVars()
|
|
53
|
+
scrollFocusedInputIntoView()
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
updateViewportVars()
|
|
58
|
+
|
|
59
|
+
getViewport()?.addEventListener('resize', scheduleFocusedInputScroll)
|
|
60
|
+
getViewport()?.addEventListener('scroll', scheduleFocusedInputScroll)
|
|
61
|
+
window.addEventListener('resize', scheduleFocusedInputScroll)
|
|
62
|
+
window.addEventListener('orientationchange', scheduleFocusedInputScroll)
|
|
63
|
+
document.addEventListener('focusin', scheduleFocusedInputScroll)
|
|
64
|
+
document.addEventListener('focusout', () => {
|
|
65
|
+
window.setTimeout(updateViewportVars, 120)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface ParsedSemver {
|
|
2
|
+
major: number
|
|
3
|
+
minor: number
|
|
4
|
+
patch: number
|
|
5
|
+
prerelease?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const SEMVER_PATTERN = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/
|
|
9
|
+
|
|
10
|
+
export const parseSemverVersion = (value: string | undefined): ParsedSemver | undefined => {
|
|
11
|
+
const match = value?.trim().match(SEMVER_PATTERN)
|
|
12
|
+
if (match == null) return undefined
|
|
13
|
+
return {
|
|
14
|
+
major: Number(match[1]),
|
|
15
|
+
minor: Number(match[2]),
|
|
16
|
+
patch: Number(match[3]),
|
|
17
|
+
...(match[4] != null ? { prerelease: match[4] } : {})
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const areSemverVersionsCompatible = (
|
|
22
|
+
clientVersion: string | undefined,
|
|
23
|
+
serverVersion: string | undefined
|
|
24
|
+
) => {
|
|
25
|
+
const client = parseSemverVersion(clientVersion)
|
|
26
|
+
const server = parseSemverVersion(serverVersion)
|
|
27
|
+
if (client == null || server == null) return false
|
|
28
|
+
if (client.prerelease != null || server.prerelease != null) {
|
|
29
|
+
return client.major === server.major &&
|
|
30
|
+
client.minor === server.minor &&
|
|
31
|
+
client.patch === server.patch &&
|
|
32
|
+
client.prerelease === server.prerelease
|
|
33
|
+
}
|
|
34
|
+
if (client.major !== server.major) return false
|
|
35
|
+
if (client.major === 0) return client.minor === server.minor
|
|
36
|
+
return true
|
|
37
|
+
}
|
package/src/vite-env.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
/// <reference types="vite/client" />
|
|
2
2
|
|
|
3
3
|
interface ImportMetaEnv {
|
|
4
|
+
readonly __VF_PROJECT_AI_SERVER_BASE_URL__: string
|
|
4
5
|
readonly __VF_PROJECT_AI_SERVER_HOST__: string
|
|
5
6
|
readonly __VF_PROJECT_AI_SERVER_PORT__: string
|
|
6
7
|
readonly __VF_PROJECT_AI_SERVER_WS_PATH__: string
|
|
7
8
|
readonly __VF_PROJECT_AI_CLIENT_HOST__: string
|
|
9
|
+
readonly __VF_PROJECT_AI_CLIENT_MODE__: string
|
|
10
|
+
readonly __VF_PROJECT_AI_CLIENT_DEPLOY_MODE__: string
|
|
8
11
|
readonly __VF_PROJECT_AI_CLIENT_PORT__: string
|
|
9
12
|
readonly __VF_PROJECT_AI_CLIENT_BASE__: string
|
|
13
|
+
readonly __VF_PROJECT_AI_CLIENT_VERSION__: string
|
|
14
|
+
readonly __VF_PROJECT_AI_CLIENT_COMMIT_HASH__: string
|
|
10
15
|
readonly __VF_PROJECT_AI_DEV_GIT_REF__: string
|
|
11
16
|
}
|
|
12
17
|
|
|
@@ -16,9 +21,13 @@ interface ImportMeta {
|
|
|
16
21
|
|
|
17
22
|
interface Window {
|
|
18
23
|
__VF_PROJECT_AI_RUNTIME_ENV__?: Partial<{
|
|
24
|
+
__VF_PROJECT_AI_SERVER_BASE_URL__: string
|
|
19
25
|
__VF_PROJECT_AI_SERVER_HOST__: string
|
|
20
26
|
__VF_PROJECT_AI_SERVER_PORT__: string
|
|
21
27
|
__VF_PROJECT_AI_SERVER_WS_PATH__: string
|
|
28
|
+
__VF_PROJECT_AI_CLIENT_MODE__: string
|
|
22
29
|
__VF_PROJECT_AI_CLIENT_BASE__: string
|
|
30
|
+
__VF_PROJECT_AI_CLIENT_VERSION__: string
|
|
31
|
+
__VF_PROJECT_AI_CLIENT_COMMIT_HASH__: string
|
|
23
32
|
}>
|
|
24
33
|
}
|
package/src/ws.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { WSEvent } from '@vibe-forge/core'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { createServerUrl, getServerWsPath } from '#~/runtime-config.js'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
const SERVER_PORT = getServerPortEnv() || '8787'
|
|
7
|
-
const WS_PROTOCOL = window.location.protocol === 'https:' ? 'wss' : 'ws'
|
|
8
|
-
const WS_URL = `${WS_PROTOCOL}://${SERVER_HOST}:${SERVER_PORT}${getServerWsPath()}`
|
|
5
|
+
import { getAuthToken } from './api/auth-token'
|
|
9
6
|
|
|
10
7
|
export interface WSHandlers<TMessage = WSEvent> {
|
|
11
8
|
onOpen?: () => void
|
|
@@ -14,12 +11,26 @@ export interface WSHandlers<TMessage = WSEvent> {
|
|
|
14
11
|
onClose?: () => void
|
|
15
12
|
}
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const createWebSocketUrl = (params?: Record<string, string>) => {
|
|
15
|
+
const url = new URL(createServerUrl(getServerWsPath()))
|
|
16
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
17
|
+
|
|
18
|
+
const authToken = getAuthToken()
|
|
19
|
+
if (authToken != null) {
|
|
20
|
+
url.searchParams.set('authToken', authToken)
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
if (params) {
|
|
20
|
-
const
|
|
21
|
-
|
|
24
|
+
for (const [key, value] of Object.entries(params)) {
|
|
25
|
+
url.searchParams.set(key, value)
|
|
26
|
+
}
|
|
22
27
|
}
|
|
28
|
+
|
|
29
|
+
return url.toString()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function createSocket<TMessage = WSEvent>(handlers: WSHandlers<TMessage>, params?: Record<string, string>) {
|
|
33
|
+
const url = createWebSocketUrl(params)
|
|
23
34
|
const ws = new WebSocket(url)
|
|
24
35
|
ws.addEventListener('open', () => handlers.onOpen?.())
|
|
25
36
|
ws.addEventListener('message', (ev) => {
|
package/vite.config.ts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { readFileSync } from 'node:fs'
|
|
2
3
|
import process from 'node:process'
|
|
3
4
|
import { fileURLToPath } from 'node:url'
|
|
4
5
|
|
|
5
6
|
import react from '@vitejs/plugin-react'
|
|
6
7
|
import { defineConfig } from 'vite'
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const clientMode = process.env.__VF_PROJECT_AI_CLIENT_MODE__
|
|
10
|
+
const clientDeployMode = process.env.__VF_PROJECT_AI_CLIENT_DEPLOY_MODE__
|
|
11
|
+
const isDev = clientMode === 'dev'
|
|
12
|
+
const isStandalone = clientMode === 'standalone' ||
|
|
13
|
+
clientMode === 'independent' ||
|
|
14
|
+
clientDeployMode === 'standalone' ||
|
|
15
|
+
clientDeployMode === 'independent'
|
|
9
16
|
const clientBase = isDev
|
|
17
|
+
? (process.env.__VF_PROJECT_AI_CLIENT_BASE__ ?? '/')
|
|
18
|
+
: isStandalone
|
|
10
19
|
? (process.env.__VF_PROJECT_AI_CLIENT_BASE__ ?? '/')
|
|
11
20
|
: '/__VF_PROJECT_AI_CLIENT_BASE__/'
|
|
12
21
|
const repoRoot = fileURLToPath(new URL('../..', import.meta.url))
|
|
22
|
+
const clientPackageJson = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')) as {
|
|
23
|
+
version?: string
|
|
24
|
+
}
|
|
13
25
|
|
|
14
26
|
const readGit = (args: string[]) =>
|
|
15
27
|
execFileSync('git', args, {
|
|
@@ -30,8 +42,18 @@ const resolveDevGitRef = () => {
|
|
|
30
42
|
}
|
|
31
43
|
}
|
|
32
44
|
|
|
45
|
+
const resolveGitCommitHash = () => {
|
|
46
|
+
try {
|
|
47
|
+
return readGit(['rev-parse', 'HEAD'])
|
|
48
|
+
} catch {
|
|
49
|
+
return ''
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
33
53
|
const devGitRef = isDev ? resolveDevGitRef() : ''
|
|
34
54
|
process.env.__VF_PROJECT_AI_DEV_GIT_REF__ = devGitRef
|
|
55
|
+
process.env.__VF_PROJECT_AI_CLIENT_VERSION__ ??= clientPackageJson.version ?? ''
|
|
56
|
+
process.env.__VF_PROJECT_AI_CLIENT_COMMIT_HASH__ ??= resolveGitCommitHash()
|
|
35
57
|
const normalizeTitle = (title: string) => title.trim().replace(/\s+\[[^\]]+\]$/, '')
|
|
36
58
|
|
|
37
59
|
export default defineConfig({
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{al as o,am as n}from"./mermaid.core-BgcryF__.js";const l=(a,r)=>o.lang.round(n.parse(a)[r]);export{l as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as r}from"./graph-BkDQy7Qt.js";var a=4;function n(o){return r(o,a)}export{n as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{f as o,p as e}from"./flowDb-c6c81e3f-D1Xz_8Gf.js";import{f as a,g as t}from"./styles-d45a18b0-B-rVGjEq.js";import{ar as i}from"./mermaid.core-BgcryF__.js";import"./graph-BkDQy7Qt.js";import"./layout-CDaZEk6E.js";import"./index-wkhI4dr6.js";import"./index-5325376f-kxPTR3_e.js";import"./clone-sQthahUA.js";import"./edges-96097737-Cb0F1_3K.js";import"./createText-1719965b-CEinakVP.js";import"./line-DNRQu8iq.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";import"./channel-Dnopc5A6.js";const n={parser:e,db:o,renderer:t,styles:a,init:r=>{r.flowchart||(r.flowchart={}),r.flowchart.arrowMarkerAbsolute=r.arrowMarkerAbsolute,i({flowchart:{arrowMarkerAbsolute:r.arrowMarkerAbsolute}}),t.setConf(r.flowchart),o.clear(),o.setGen("gen-2")}};export{n as diagram};
|