actoviq-agent-sdk 0.4.21 → 0.4.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-zh.md +50 -113
- package/README.md +51 -164
- package/assets/hadamard-icon.ico +0 -0
- package/assets/hadamard-icon.png +0 -0
- package/bin/hadamard-gui.js +31 -12
- package/dist/src/codeIntel/codeIntelligenceService.d.ts +16 -0
- package/dist/src/codeIntel/codeIntelligenceService.d.ts.map +1 -1
- package/dist/src/codeIntel/codeIntelligenceService.js +87 -2
- package/dist/src/codeIntel/codeIntelligenceService.js.map +1 -1
- package/dist/src/codeIntel/codeIntelligenceTools.d.ts.map +1 -1
- package/dist/src/codeIntel/codeIntelligenceTools.js +6 -0
- package/dist/src/codeIntel/codeIntelligenceTools.js.map +1 -1
- package/dist/src/codeIntel/index.d.ts +1 -0
- package/dist/src/codeIntel/index.d.ts.map +1 -1
- package/dist/src/codeIntel/index.js +1 -0
- package/dist/src/codeIntel/index.js.map +1 -1
- package/dist/src/codeIntel/languageServerPresets.d.ts +13 -0
- package/dist/src/codeIntel/languageServerPresets.d.ts.map +1 -0
- package/dist/src/codeIntel/languageServerPresets.js +51 -0
- package/dist/src/codeIntel/languageServerPresets.js.map +1 -0
- package/dist/src/codeIntel/languageServerRegistry.d.ts +1 -0
- package/dist/src/codeIntel/languageServerRegistry.d.ts.map +1 -1
- package/dist/src/codeIntel/languageServerRegistry.js +2 -2
- package/dist/src/codeIntel/languageServerRegistry.js.map +1 -1
- package/dist/src/config/resolveRuntimeConfig.d.ts.map +1 -1
- package/dist/src/config/resolveRuntimeConfig.js +5 -0
- package/dist/src/config/resolveRuntimeConfig.js.map +1 -1
- package/dist/src/extensions/builtInExtensions.d.ts +61 -0
- package/dist/src/extensions/builtInExtensions.d.ts.map +1 -0
- package/dist/src/extensions/builtInExtensions.js +218 -0
- package/dist/src/extensions/builtInExtensions.js.map +1 -0
- package/dist/src/extensions/filterOutputPolicy.d.ts +21 -0
- package/dist/src/extensions/filterOutputPolicy.d.ts.map +1 -0
- package/dist/src/extensions/filterOutputPolicy.js +121 -0
- package/dist/src/extensions/filterOutputPolicy.js.map +1 -0
- package/dist/src/extensions/securityPolicy.d.ts +27 -0
- package/dist/src/extensions/securityPolicy.d.ts.map +1 -0
- package/dist/src/extensions/securityPolicy.js +238 -0
- package/dist/src/extensions/securityPolicy.js.map +1 -0
- package/dist/src/extensions/sessionCostTracker.d.ts +63 -0
- package/dist/src/extensions/sessionCostTracker.d.ts.map +1 -0
- package/dist/src/extensions/sessionCostTracker.js +213 -0
- package/dist/src/extensions/sessionCostTracker.js.map +1 -0
- package/dist/src/extensions/taskNotifications.d.ts +31 -0
- package/dist/src/extensions/taskNotifications.d.ts.map +1 -0
- package/dist/src/extensions/taskNotifications.js +50 -0
- package/dist/src/extensions/taskNotifications.js.map +1 -0
- package/dist/src/extensions/usageBar.d.ts +35 -0
- package/dist/src/extensions/usageBar.d.ts.map +1 -0
- package/dist/src/extensions/usageBar.js +67 -0
- package/dist/src/extensions/usageBar.js.map +1 -0
- package/dist/src/gui/contextRailStore.d.ts +13 -0
- package/dist/src/gui/contextRailStore.d.ts.map +1 -1
- package/dist/src/gui/contextRailStore.js +16 -0
- package/dist/src/gui/contextRailStore.js.map +1 -1
- package/dist/src/gui/electronMain.js +45 -5
- package/dist/src/gui/electronMain.js.map +1 -1
- package/dist/src/gui/guiDesignClientScript.d.ts.map +1 -1
- package/dist/src/gui/guiDesignClientScript.js +31 -0
- package/dist/src/gui/guiDesignClientScript.js.map +1 -1
- package/dist/src/gui/guiUsageRoutingAssets.d.ts +7 -0
- package/dist/src/gui/guiUsageRoutingAssets.d.ts.map +1 -0
- package/dist/src/gui/guiUsageRoutingAssets.js +509 -0
- package/dist/src/gui/guiUsageRoutingAssets.js.map +1 -0
- package/dist/src/gui/guiUsageRoutingHttpController.d.ts +11 -0
- package/dist/src/gui/guiUsageRoutingHttpController.d.ts.map +1 -0
- package/dist/src/gui/guiUsageRoutingHttpController.js +125 -0
- package/dist/src/gui/guiUsageRoutingHttpController.js.map +1 -0
- package/dist/src/gui/guiUsageRoutingRuntime.d.ts +36 -0
- package/dist/src/gui/guiUsageRoutingRuntime.d.ts.map +1 -0
- package/dist/src/gui/guiUsageRoutingRuntime.js +98 -0
- package/dist/src/gui/guiUsageRoutingRuntime.js.map +1 -0
- package/dist/src/gui/hadamardGui.d.ts +5 -0
- package/dist/src/gui/hadamardGui.d.ts.map +1 -1
- package/dist/src/gui/hadamardGui.js +159 -16
- package/dist/src/gui/hadamardGui.js.map +1 -1
- package/dist/src/gui/hadamardGuiAssets.d.ts.map +1 -1
- package/dist/src/gui/hadamardGuiAssets.js +297 -41
- package/dist/src/gui/hadamardGuiAssets.js.map +1 -1
- package/dist/src/index.d.ts +32 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +16 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/keyway/electronSecretStore.d.ts +37 -0
- package/dist/src/keyway/electronSecretStore.d.ts.map +1 -0
- package/dist/src/keyway/electronSecretStore.js +105 -0
- package/dist/src/keyway/electronSecretStore.js.map +1 -0
- package/dist/src/keyway/embeddedKeyway.d.ts +34 -0
- package/dist/src/keyway/embeddedKeyway.d.ts.map +1 -0
- package/dist/src/keyway/embeddedKeyway.js +81 -0
- package/dist/src/keyway/embeddedKeyway.js.map +1 -0
- package/dist/src/keyway/keywayLoopbackGateway.d.ts +30 -0
- package/dist/src/keyway/keywayLoopbackGateway.d.ts.map +1 -0
- package/dist/src/keyway/keywayLoopbackGateway.js +71 -0
- package/dist/src/keyway/keywayLoopbackGateway.js.map +1 -0
- package/dist/src/keyway/keywayMigrationService.d.ts +44 -0
- package/dist/src/keyway/keywayMigrationService.d.ts.map +1 -0
- package/dist/src/keyway/keywayMigrationService.js +219 -0
- package/dist/src/keyway/keywayMigrationService.js.map +1 -0
- package/dist/src/keyway/keywayModelApi.d.ts +24 -0
- package/dist/src/keyway/keywayModelApi.d.ts.map +1 -0
- package/dist/src/keyway/keywayModelApi.js +106 -0
- package/dist/src/keyway/keywayModelApi.js.map +1 -0
- package/dist/src/keyway/keywayPorts.d.ts +189 -0
- package/dist/src/keyway/keywayPorts.d.ts.map +1 -0
- package/dist/src/keyway/keywayPorts.js +2 -0
- package/dist/src/keyway/keywayPorts.js.map +1 -0
- package/dist/src/keyway/keywayProviderExecutor.d.ts +30 -0
- package/dist/src/keyway/keywayProviderExecutor.d.ts.map +1 -0
- package/dist/src/keyway/keywayProviderExecutor.js +257 -0
- package/dist/src/keyway/keywayProviderExecutor.js.map +1 -0
- package/dist/src/keyway/routingComposition.d.ts +18 -0
- package/dist/src/keyway/routingComposition.d.ts.map +1 -0
- package/dist/src/keyway/routingComposition.js +19 -0
- package/dist/src/keyway/routingComposition.js.map +1 -0
- package/dist/src/keyway/usageRoutingAdminService.d.ts +86 -0
- package/dist/src/keyway/usageRoutingAdminService.d.ts.map +1 -0
- package/dist/src/keyway/usageRoutingAdminService.js +384 -0
- package/dist/src/keyway/usageRoutingAdminService.js.map +1 -0
- package/dist/src/nativeCli/crushManagedClient.d.ts +84 -0
- package/dist/src/nativeCli/crushManagedClient.d.ts.map +1 -0
- package/dist/src/nativeCli/crushManagedClient.js +978 -0
- package/dist/src/nativeCli/crushManagedClient.js.map +1 -0
- package/dist/src/nativeCli/crushNativeCliClient.d.ts +19 -0
- package/dist/src/nativeCli/crushNativeCliClient.d.ts.map +1 -0
- package/dist/src/nativeCli/crushNativeCliClient.js +243 -0
- package/dist/src/nativeCli/crushNativeCliClient.js.map +1 -0
- package/dist/src/nativeCli/keywayNativeCliAdapter.d.ts +31 -0
- package/dist/src/nativeCli/keywayNativeCliAdapter.d.ts.map +1 -0
- package/dist/src/nativeCli/keywayNativeCliAdapter.js +35 -0
- package/dist/src/nativeCli/keywayNativeCliAdapter.js.map +1 -0
- package/dist/src/nativeCli/nativeCliAuth.d.ts +24 -0
- package/dist/src/nativeCli/nativeCliAuth.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliAuth.js +327 -0
- package/dist/src/nativeCli/nativeCliAuth.js.map +1 -0
- package/dist/src/nativeCli/nativeCliClient.d.ts +16 -0
- package/dist/src/nativeCli/nativeCliClient.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliClient.js +575 -0
- package/dist/src/nativeCli/nativeCliClient.js.map +1 -0
- package/dist/src/nativeCli/nativeCliCodewhaleProtocol.d.ts +18 -0
- package/dist/src/nativeCli/nativeCliCodewhaleProtocol.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliCodewhaleProtocol.js +376 -0
- package/dist/src/nativeCli/nativeCliCodewhaleProtocol.js.map +1 -0
- package/dist/src/nativeCli/nativeCliContracts.d.ts +22 -0
- package/dist/src/nativeCli/nativeCliContracts.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliContracts.js +2 -0
- package/dist/src/nativeCli/nativeCliContracts.js.map +1 -0
- package/dist/src/nativeCli/nativeCliCursorProtocol.d.ts +7 -0
- package/dist/src/nativeCli/nativeCliCursorProtocol.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliCursorProtocol.js +210 -0
- package/dist/src/nativeCli/nativeCliCursorProtocol.js.map +1 -0
- package/dist/src/nativeCli/nativeCliEnvironment.d.ts +3 -0
- package/dist/src/nativeCli/nativeCliEnvironment.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliEnvironment.js +17 -0
- package/dist/src/nativeCli/nativeCliEnvironment.js.map +1 -0
- package/dist/src/nativeCli/nativeCliExecResolver.d.ts +26 -0
- package/dist/src/nativeCli/nativeCliExecResolver.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliExecResolver.js +152 -0
- package/dist/src/nativeCli/nativeCliExecResolver.js.map +1 -0
- package/dist/src/nativeCli/nativeCliPiProtocol.d.ts +15 -0
- package/dist/src/nativeCli/nativeCliPiProtocol.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliPiProtocol.js +329 -0
- package/dist/src/nativeCli/nativeCliPiProtocol.js.map +1 -0
- package/dist/src/nativeCli/nativeCliProcessTree.d.ts +3 -0
- package/dist/src/nativeCli/nativeCliProcessTree.d.ts.map +1 -0
- package/dist/src/nativeCli/nativeCliProcessTree.js +104 -0
- package/dist/src/nativeCli/nativeCliProcessTree.js.map +1 -0
- package/dist/src/nativeCli/reasonixAcpSession.d.ts +35 -0
- package/dist/src/nativeCli/reasonixAcpSession.d.ts.map +1 -0
- package/dist/src/nativeCli/reasonixAcpSession.js +472 -0
- package/dist/src/nativeCli/reasonixAcpSession.js.map +1 -0
- package/dist/src/nativeCli/reasonixManagedClient.d.ts +56 -0
- package/dist/src/nativeCli/reasonixManagedClient.d.ts.map +1 -0
- package/dist/src/nativeCli/reasonixManagedClient.js +293 -0
- package/dist/src/nativeCli/reasonixManagedClient.js.map +1 -0
- package/dist/src/nativeCli/reasonixNativeCliClient.d.ts +20 -0
- package/dist/src/nativeCli/reasonixNativeCliClient.d.ts.map +1 -0
- package/dist/src/nativeCli/reasonixNativeCliClient.js +317 -0
- package/dist/src/nativeCli/reasonixNativeCliClient.js.map +1 -0
- package/dist/src/parity/bridgeExecResolver.d.ts +2 -25
- package/dist/src/parity/bridgeExecResolver.d.ts.map +1 -1
- package/dist/src/parity/bridgeExecResolver.js +2 -151
- package/dist/src/parity/bridgeExecResolver.js.map +1 -1
- package/dist/src/parity/bridgeProcessTree.d.ts +2 -2
- package/dist/src/parity/bridgeProcessTree.d.ts.map +1 -1
- package/dist/src/parity/bridgeProcessTree.js +2 -82
- package/dist/src/parity/bridgeProcessTree.js.map +1 -1
- package/dist/src/parity/crushManagedClient.d.ts +2 -83
- package/dist/src/parity/crushManagedClient.d.ts.map +1 -1
- package/dist/src/parity/crushManagedClient.js +2 -977
- package/dist/src/parity/crushManagedClient.js.map +1 -1
- package/dist/src/parity/externalCliAuth.d.ts +2 -22
- package/dist/src/parity/externalCliAuth.d.ts.map +1 -1
- package/dist/src/parity/externalCliAuth.js +2 -295
- package/dist/src/parity/externalCliAuth.js.map +1 -1
- package/dist/src/parity/hadamardBridgeSdk.d.ts.map +1 -1
- package/dist/src/parity/hadamardBridgeSdk.js +14 -1
- package/dist/src/parity/hadamardBridgeSdk.js.map +1 -1
- package/dist/src/parity/nativeCliBridgeAdapter.d.ts +6 -0
- package/dist/src/parity/nativeCliBridgeAdapter.d.ts.map +1 -0
- package/dist/src/parity/nativeCliBridgeAdapter.js +38 -0
- package/dist/src/parity/nativeCliBridgeAdapter.js.map +1 -0
- package/dist/src/parity/reasonixAcpSession.d.ts +2 -34
- package/dist/src/parity/reasonixAcpSession.d.ts.map +1 -1
- package/dist/src/parity/reasonixAcpSession.js +2 -471
- package/dist/src/parity/reasonixAcpSession.js.map +1 -1
- package/dist/src/parity/reasonixManagedClient.d.ts +2 -55
- package/dist/src/parity/reasonixManagedClient.d.ts.map +1 -1
- package/dist/src/parity/reasonixManagedClient.js +2 -292
- package/dist/src/parity/reasonixManagedClient.js.map +1 -1
- package/dist/src/provider/openai-client.js +2 -2
- package/dist/src/provider/openai-client.js.map +1 -1
- package/dist/src/provider/openai-model-api.d.ts.map +1 -1
- package/dist/src/provider/openai-model-api.js +5 -1
- package/dist/src/provider/openai-model-api.js.map +1 -1
- package/dist/src/runtime/agentClient.d.ts +14 -1
- package/dist/src/runtime/agentClient.d.ts.map +1 -1
- package/dist/src/runtime/agentClient.js +60 -6
- package/dist/src/runtime/agentClient.js.map +1 -1
- package/dist/src/runtime/toolPolicyPipeline.d.ts +32 -1
- package/dist/src/runtime/toolPolicyPipeline.d.ts.map +1 -1
- package/dist/src/runtime/toolPolicyPipeline.js +43 -3
- package/dist/src/runtime/toolPolicyPipeline.js.map +1 -1
- package/dist/src/tui/hadamardTuiController.d.ts.map +1 -1
- package/dist/src/tui/hadamardTuiController.js +62 -8
- package/dist/src/tui/hadamardTuiController.js.map +1 -1
- package/dist/src/tui/tuiBasicCommandHandler.d.ts +4 -0
- package/dist/src/tui/tuiBasicCommandHandler.d.ts.map +1 -1
- package/dist/src/tui/tuiBasicCommandHandler.js +23 -2
- package/dist/src/tui/tuiBasicCommandHandler.js.map +1 -1
- package/dist/src/tui/tuiCatalogCommandHandler.d.ts +2 -0
- package/dist/src/tui/tuiCatalogCommandHandler.d.ts.map +1 -1
- package/dist/src/tui/tuiCatalogCommandHandler.js +10 -1
- package/dist/src/tui/tuiCatalogCommandHandler.js.map +1 -1
- package/dist/src/tui/tuiUsageRoutingRuntime.d.ts +22 -0
- package/dist/src/tui/tuiUsageRoutingRuntime.d.ts.map +1 -0
- package/dist/src/tui/tuiUsageRoutingRuntime.js +81 -0
- package/dist/src/tui/tuiUsageRoutingRuntime.js.map +1 -0
- package/dist/src/types.d.ts +16 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/ui/commandSurface.d.ts.map +1 -1
- package/dist/src/ui/commandSurface.js +45 -1
- package/dist/src/ui/commandSurface.js.map +1 -1
- package/dist/src/ui/extensionsCommandView.d.ts +18 -0
- package/dist/src/ui/extensionsCommandView.d.ts.map +1 -0
- package/dist/src/ui/extensionsCommandView.js +82 -0
- package/dist/src/ui/extensionsCommandView.js.map +1 -0
- package/dist/src/ui/lspCommandView.d.ts +17 -0
- package/dist/src/ui/lspCommandView.d.ts.map +1 -0
- package/dist/src/ui/lspCommandView.js +25 -0
- package/dist/src/ui/lspCommandView.js.map +1 -0
- package/dist/src/ui/usageRoutingCommand.d.ts +13 -0
- package/dist/src/ui/usageRoutingCommand.d.ts.map +1 -0
- package/dist/src/ui/usageRoutingCommand.js +224 -0
- package/dist/src/ui/usageRoutingCommand.js.map +1 -0
- package/dist/src/usage/budgetService.d.ts +28 -0
- package/dist/src/usage/budgetService.d.ts.map +1 -0
- package/dist/src/usage/budgetService.js +50 -0
- package/dist/src/usage/budgetService.js.map +1 -0
- package/dist/src/usage/contracts.d.ts +149 -0
- package/dist/src/usage/contracts.d.ts.map +1 -0
- package/dist/src/usage/contracts.js +2 -0
- package/dist/src/usage/contracts.js.map +1 -0
- package/dist/src/usage/index.d.ts +7 -0
- package/dist/src/usage/index.d.ts.map +1 -0
- package/dist/src/usage/index.js +4 -0
- package/dist/src/usage/index.js.map +1 -0
- package/dist/src/usage/usageLedger.d.ts +19 -0
- package/dist/src/usage/usageLedger.d.ts.map +1 -0
- package/dist/src/usage/usageLedger.js +389 -0
- package/dist/src/usage/usageLedger.js.map +1 -0
- package/dist/src/usage/usageQueryService.d.ts +12 -0
- package/dist/src/usage/usageQueryService.d.ts.map +1 -0
- package/dist/src/usage/usageQueryService.js +29 -0
- package/dist/src/usage/usageQueryService.js.map +1 -0
- package/package.json +14 -2
- package/scripts/prepare-gui-launcher.mjs +62 -0
|
@@ -9,6 +9,7 @@ import { PROJECT_STATUSES, PROJECT_STATUS_LABELS } from './projectMeta.js';
|
|
|
9
9
|
import { renderMarkdown } from './guiMarkdown.js';
|
|
10
10
|
import { detectEditorLanguage, highlightCode } from './guiSyntaxHighlight.js';
|
|
11
11
|
import { getTranscriptClientScript, getTranscriptStyles } from './transcript/index.js';
|
|
12
|
+
import { usageRoutingBindings, usageRoutingClient, usageRoutingConfigurationHeaderHtml, usageRoutingConfigurationPageHtml, usageRoutingHtml, usageRoutingStyles } from './guiUsageRoutingAssets.js';
|
|
12
13
|
import { formatContextWindowTokens, STANDARD_CONTEXT_WINDOWS, } from '../config/modelContextWindow.js';
|
|
13
14
|
import { GUI_SESSION_CENTER_OPEN_CLIENT_SCRIPT, GUI_SESSION_CREATE_CLIENT_SCRIPT, } from './guiSessionClientScript.js';
|
|
14
15
|
import { GUI_DESIGN_CLIENT_SCRIPT } from './guiDesignClientScript.js';
|
|
@@ -93,10 +94,11 @@ export function createHadamardGuiHtml() {
|
|
|
93
94
|
</head>
|
|
94
95
|
<body>
|
|
95
96
|
<div class="app" id="appView">
|
|
96
|
-
<aside class="sidebar">
|
|
97
|
+
<aside class="sidebar" id="appSidebar">
|
|
97
98
|
<div class="brand">
|
|
98
99
|
<span class="brand-mark">${guiIcon('logo')}</span>
|
|
99
100
|
<span class="brand-name">Hadamard</span>
|
|
101
|
+
<button type="button" id="sidebarCollapseBtn" class="icon-btn sidebar-collapse-btn" aria-label="Collapse sidebar" title="Collapse sidebar" aria-expanded="true" aria-controls="appSidebar">${guiIcon('panelLeft')}</button>
|
|
100
102
|
</div>
|
|
101
103
|
<nav class="primary-nav" aria-label="Primary">
|
|
102
104
|
<button id="navProject" class="nav-btn region-nav active" data-region="project" aria-label="Project" title="Project"><span class="nav-icon">${guiIcon('folder')}</span><span>Project</span></button>
|
|
@@ -124,6 +126,7 @@ export function createHadamardGuiHtml() {
|
|
|
124
126
|
<button id="settingsBtn" class="nav-btn" aria-label="Settings" title="Settings"><span class="nav-icon">${guiIcon('gear')}</span><span>Settings</span></button>
|
|
125
127
|
</div>
|
|
126
128
|
</aside>
|
|
129
|
+
<button type="button" id="sidebarExpandBtn" class="sidebar-expand-fab hidden" aria-label="Expand sidebar" title="Expand sidebar" aria-expanded="false" aria-controls="appSidebar">${guiIcon('panelRight')}</button>
|
|
127
130
|
<main class="chat" data-region="project" id="regionProject">
|
|
128
131
|
<section class="project-overview" id="projectOverview">
|
|
129
132
|
<header class="region-header">
|
|
@@ -134,6 +137,7 @@ export function createHadamardGuiHtml() {
|
|
|
134
137
|
<div class="region-actions">
|
|
135
138
|
<button type="button" id="overviewChatsBtn" class="pill-btn">Chats</button>
|
|
136
139
|
<button type="button" id="overviewNewWorkspaceBtn" class="pill-btn">+ New workspace</button>
|
|
140
|
+
<button type="button" id="overviewRailToggleBtn" class="icon-btn" aria-label="Show panel" title="Show panel" aria-expanded="false" aria-controls="contextRail">${guiIcon('panelLeft')}</button>
|
|
137
141
|
</div>
|
|
138
142
|
</header>
|
|
139
143
|
<div class="overview-toolbar">
|
|
@@ -171,7 +175,7 @@ export function createHadamardGuiHtml() {
|
|
|
171
175
|
<button type="button" id="detailOpenLocationBtn" class="icon-btn" aria-label="Open workspace folder" title="Open workspace folder">${guiIcon('folder')}</button>
|
|
172
176
|
<button type="button" id="detailNewConversationBtn" class="pill-btn">+ New conversation</button>
|
|
173
177
|
<button type="button" id="detailConversationsBtn" class="icon-btn detail-conversations-toggle" aria-label="Hide conversations" title="Hide conversations" aria-expanded="true" aria-controls="projectDetailSidebar">${guiIcon('panelLeft')}</button>
|
|
174
|
-
<button type="button" id="detailAuxPanelToggleBtn" class="icon-btn" title="
|
|
178
|
+
<button type="button" id="detailAuxPanelToggleBtn" class="icon-btn" title="Show panel" aria-label="Show panel" aria-pressed="false">${guiIcon('panelLeft')}</button>
|
|
175
179
|
</div>
|
|
176
180
|
</header>
|
|
177
181
|
<div class="detail-body" id="detailBody"></div>
|
|
@@ -244,7 +248,7 @@ export function createHadamardGuiHtml() {
|
|
|
244
248
|
<div class="workbench-chat">
|
|
245
249
|
<section class="pane pane-chat active" id="pane-chat-default">
|
|
246
250
|
<div class="chat-chrome">
|
|
247
|
-
<section id="statusbar" class="statusbar"></section>
|
|
251
|
+
<section id="statusbar" class="statusbar"><span id="statusText"></span><span id="usagebar" class="usagebar hidden"></span></section>
|
|
248
252
|
<div id="squadRoster" class="squad-roster hidden"></div>
|
|
249
253
|
</div>
|
|
250
254
|
<section id="contextBar" class="context-bar hidden"></section>
|
|
@@ -512,16 +516,8 @@ export function createHadamardGuiHtml() {
|
|
|
512
516
|
<div class="region-body devices-region-body" id="regionDevicesBody"></div>
|
|
513
517
|
</section>
|
|
514
518
|
<section class="region hidden" data-region="bridge" id="regionBridge" aria-label="Configuration">
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
<h1>Configuration</h1>
|
|
518
|
-
<p>Configure models, providers, and local API or CLI runtimes</p>
|
|
519
|
-
</div>
|
|
520
|
-
<div class="region-actions">
|
|
521
|
-
<button type="button" id="bridgeNewConfig" class="pill-btn primary">+ New config</button>
|
|
522
|
-
</div>
|
|
523
|
-
</header>
|
|
524
|
-
<div class="region-body bridge-region-body">
|
|
519
|
+
${usageRoutingConfigurationHeaderHtml}
|
|
520
|
+
<div class="region-body bridge-region-body" id="configurationModelsPage">
|
|
525
521
|
<section class="settings-group">
|
|
526
522
|
<h2>Bridge mode</h2>
|
|
527
523
|
<label class="check-row"><input id="bridgeModeEnabled" type="checkbox">Enable bridge mode</label>
|
|
@@ -544,6 +540,7 @@ export function createHadamardGuiHtml() {
|
|
|
544
540
|
<div id="runtimeDiscoveryList" class="settings-card-list compact runtime-list"></div>
|
|
545
541
|
</section>
|
|
546
542
|
</div>
|
|
543
|
+
${usageRoutingConfigurationPageHtml}
|
|
547
544
|
</section>
|
|
548
545
|
<aside class="context-rail hidden" id="contextRail" aria-label="Context panel"></aside>
|
|
549
546
|
<div id="railToast" class="rail-toast hidden" role="status" aria-live="polite"></div>
|
|
@@ -863,6 +860,7 @@ export function createHadamardGuiHtml() {
|
|
|
863
860
|
<section>
|
|
864
861
|
<h2>Agent</h2>
|
|
865
862
|
<button type="button" class="settings-tab" data-settings-tab="capabilities"><span class="settings-icon">${guiIcon('tools')}</span>Capabilities</button>
|
|
863
|
+
<button type="button" class="settings-tab" data-settings-tab="extensions"><span class="settings-icon">${guiIcon('plug')}</span>Extensions & LSP</button>
|
|
866
864
|
<button type="button" class="settings-tab" data-settings-tab="sessions"><span class="settings-icon">${guiIcon('chat')}</span>Chats</button>
|
|
867
865
|
</section>
|
|
868
866
|
<section>
|
|
@@ -982,6 +980,7 @@ export function createHadamardGuiHtml() {
|
|
|
982
980
|
<div class="settings-action-row"><button type="button" id="externalCliHistoryMore" class="secondary-btn hidden">Load more</button></div>
|
|
983
981
|
</div>
|
|
984
982
|
</section>
|
|
983
|
+
${usageRoutingHtml}
|
|
985
984
|
<section class="settings-panel" data-settings-panel="appearance">
|
|
986
985
|
<h1>Appearance</h1>
|
|
987
986
|
<div class="settings-group two-col">
|
|
@@ -1033,6 +1032,19 @@ export function createHadamardGuiHtml() {
|
|
|
1033
1032
|
<div id="settingsTeamsList" class="settings-card-list"></div>
|
|
1034
1033
|
</div>
|
|
1035
1034
|
</section>
|
|
1035
|
+
<section class="settings-panel" data-settings-panel="extensions">
|
|
1036
|
+
<h1>Extensions & LSP</h1>
|
|
1037
|
+
<div class="settings-group">
|
|
1038
|
+
<h2>Built-in extensions</h2>
|
|
1039
|
+
<p class="muted">Enable Hadamard-owned runtime and interface features. Changes apply to subsequent runs.</p>
|
|
1040
|
+
<div id="settingsExtensionsList" class="settings-card-list"></div>
|
|
1041
|
+
</div>
|
|
1042
|
+
<div class="settings-group">
|
|
1043
|
+
<h2>Language servers</h2>
|
|
1044
|
+
<div class="settings-help-row"><span><strong>Detect installed language servers automatically</strong><small>Uses supported servers found on PATH when no explicit server with the same id is configured.</small></span><label class="switch-field"><input type="checkbox" id="settingsAutoDetectLanguageServers"></label></div>
|
|
1045
|
+
<div id="settingsLanguageServersList" class="settings-card-list compact"></div>
|
|
1046
|
+
</div>
|
|
1047
|
+
</section>
|
|
1036
1048
|
<section class="settings-panel" data-settings-panel="sessions">
|
|
1037
1049
|
<h1>Chats</h1>
|
|
1038
1050
|
<div class="settings-group">
|
|
@@ -1740,14 +1752,14 @@ body[data-theme="dark"] {
|
|
|
1740
1752
|
.project-doc-rich:focus { caret-color: var(--brand); }
|
|
1741
1753
|
.project-doc-formatbar { display: none; align-items: center; gap: 4px; margin: -30px -38px 24px; padding: 7px 10px; border-bottom: 1px solid var(--border); background: var(--bg-surface); overflow-x: auto; position: sticky; top: -30px; z-index: 2; }
|
|
1742
1754
|
.project-doc-scroll.editing .project-doc-formatbar { display: flex; }
|
|
1743
|
-
.project-doc-formatbar button { flex: 0 0 auto; min-width: 30px; height: 28px; border: 0; border-radius: 6px; background: transparent; color: var(--text-2); font: inherit; font-size: 12px; font-weight: 650; }
|
|
1744
|
-
.project-doc-formatbar button:hover { background: var(--surface-hover); color: var(--text-1); }
|
|
1755
|
+
.project-doc-formatbar button, .project-doc-formatbar select { flex: 0 0 auto; min-width: 30px; height: 28px; border: 0; border-radius: 6px; background: transparent; color: var(--text-2); font: inherit; font-size: 12px; font-weight: 650; } .project-doc-formatbar select { min-width: 50px; padding: 0 20px 0 8px; cursor: pointer; }
|
|
1756
|
+
.project-doc-formatbar button:hover, .project-doc-formatbar select:hover { background: var(--surface-hover); color: var(--text-1); } .project-doc-formatbar select:focus-visible { outline: 2px solid var(--border-active); outline-offset: -2px; }
|
|
1745
1757
|
.project-doc-view.md-prose { font-size: 13px; line-height: 1.9; color: var(--text-1); cursor: text; }
|
|
1746
1758
|
.project-doc-view.md-prose .design-header { font-size: 12px; letter-spacing: .01em; }
|
|
1747
1759
|
.project-doc-view.md-prose .md-h:first-child { margin-top: 0; }
|
|
1748
1760
|
.project-doc-view.md-prose h1.md-h { font-size: 1.2em; font-weight: 650; margin: 1em 0 .45em; line-height: 1.45; color: var(--text-1); }
|
|
1749
1761
|
.project-doc-view.md-prose h2.md-h { font-size: 1.08em; font-weight: 650; margin: .85em 0 .4em; line-height: 1.45; color: var(--text-1); }
|
|
1750
|
-
.project-doc-view.md-prose h3.md-h, .project-doc-view.md-prose h4.md-h { font-size: 1em; font-weight: 650; margin: .7em 0 .32em; line-height: 1.45; color: var(--text-1); }
|
|
1762
|
+
.project-doc-view.md-prose h3.md-h, .project-doc-view.md-prose h4.md-h, .project-doc-view.md-prose h5.md-h, .project-doc-view.md-prose h6.md-h { font-size: 1em; font-weight: 650; margin: .7em 0 .32em; line-height: 1.45; color: var(--text-1); }
|
|
1751
1763
|
.project-doc-view.md-prose p.md-p { margin: 0 0 .8em; }
|
|
1752
1764
|
.project-doc-view.md-prose p.md-p:last-child { margin-bottom: 0; }
|
|
1753
1765
|
.project-doc-view.md-prose ul.md-ul, .project-doc-view.md-prose ol.md-ol { margin: .3em 0 .8em; padding-left: 1.25em; }
|
|
@@ -2715,7 +2727,7 @@ body[data-theme="dark"] .git-diff-line.hunk { color: #d2a8ff; }
|
|
|
2715
2727
|
.graph-mode-pill { font-size: 11px; font-weight: 600; border-radius: 999px; padding: 3px 10px; background: var(--accent); color: var(--text-2); }
|
|
2716
2728
|
.graph-unreachable { opacity: .65; }
|
|
2717
2729
|
.context-rail { width: 320px; flex: 0 0 320px; border-left: 1px solid var(--border); background: var(--bg-app); overflow: auto; padding: 14px; }
|
|
2718
|
-
.app { height: 100vh; display: flex; overflow: hidden; border: 1px solid var(--border); background: var(--bg-app); }
|
|
2730
|
+
.app { height: 100vh; display: flex; position: relative; overflow: hidden; border: 1px solid var(--border); background: var(--bg-app); }
|
|
2719
2731
|
.sidebar {
|
|
2720
2732
|
width: 240px;
|
|
2721
2733
|
flex: 0 0 240px;
|
|
@@ -2727,6 +2739,16 @@ body[data-theme="dark"] .git-diff-line.hunk { color: #d2a8ff; }
|
|
|
2727
2739
|
background: var(--bg-app);
|
|
2728
2740
|
border-right: 1px solid var(--border);
|
|
2729
2741
|
}
|
|
2742
|
+
.sidebar.collapsed { display: none; }
|
|
2743
|
+
.sidebar .sidebar-collapse-btn { margin-left: auto; width: 24px; height: 24px; min-height: 24px; padding: 0; display: inline-grid; place-items: center; color: var(--text-2); }
|
|
2744
|
+
.sidebar .sidebar-collapse-btn:hover { color: var(--text-1); }
|
|
2745
|
+
.sidebar-expand-fab { position: absolute; top: 12px; left: 12px; z-index: 20; width: 32px; height: 32px; min-height: 32px; padding: 0; display: inline-grid; place-items: center; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-surface); color: var(--text-2); cursor: pointer; box-shadow: 0 2px 10px rgba(0,0,0,.1); }
|
|
2746
|
+
.sidebar-expand-fab:hover { color: var(--text-1); background: var(--surface-hover); }
|
|
2747
|
+
.sidebar-expand-fab .ui-icon, .sidebar .sidebar-collapse-btn .ui-icon { width: 15px; height: 15px; }
|
|
2748
|
+
@media (min-width: 861px) {
|
|
2749
|
+
.app:has(> .sidebar.collapsed) .region-header,
|
|
2750
|
+
.app:has(> .sidebar.collapsed) .topbar { padding-left: 54px; }
|
|
2751
|
+
}
|
|
2730
2752
|
/* Sidebar is nav + Pinned/Recent only. Chat lists live in the project detail
|
|
2731
2753
|
conversation sidebar; workspace open uses the overview "+ New workspace". */
|
|
2732
2754
|
body[data-sidebar-mode="nav"] .sidebar .sidebar-footer .nav-btn span:not(.nav-icon) { display: inline; }
|
|
@@ -2918,7 +2940,7 @@ body[data-sidebar-mode="nav"] .sidebar .sidebar-footer .nav-btn span:not(.nav-ic
|
|
|
2918
2940
|
.aux-splitter:hover, .aux-splitter.dragging { background: var(--brand); opacity: .55; }
|
|
2919
2941
|
.workbench-split.aux-collapsed .aux-splitter,
|
|
2920
2942
|
.workbench-split.aux-collapsed .aux-splitter { display: none; }
|
|
2921
|
-
.aux-panel { flex: 0 0 var(--aux-panel-width, 340px); width: var(--aux-panel-width, 340px); min-width: 240px; max-width: min(
|
|
2943
|
+
.aux-panel { flex: 0 0 var(--aux-panel-width, 340px); width: var(--aux-panel-width, 340px); min-width: 240px; max-width: min(82vw, 1600px); border-left: 1px solid var(--border); background: var(--bg-surface); display: flex; flex-direction: column; min-height: 0; transition: flex-basis .15s ease, width .15s ease, min-width .15s ease; }
|
|
2922
2944
|
.workbench-split.resizing-aux .aux-panel { transition: none; }
|
|
2923
2945
|
.aux-panel.collapsed { flex: 0 0 40px; width: 40px; min-width: 40px; max-width: 40px; }
|
|
2924
2946
|
.aux-panel.collapsed .aux-body,
|
|
@@ -2989,9 +3011,16 @@ body[data-sidebar-mode="nav"] .sidebar .sidebar-footer .nav-btn span:not(.nav-ic
|
|
|
2989
3011
|
.aux-browser-frame-host { flex: 1 1 auto; min-height: 240px; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: #fff; }
|
|
2990
3012
|
.aux-browser-frame { display: block; width: 100%; height: 100%; min-height: 240px; border: 0; }
|
|
2991
3013
|
.aux-file-preview { margin: 0; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface-muted); font-size: 12px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; max-height: calc(100% - 40px); overflow: auto; }
|
|
3014
|
+
.aux-file-editor-head .aux-view-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3015
|
+
.aux-file-editor-head .files-preview-modes { margin-left: auto; }
|
|
2992
3016
|
.aux-file-editor-body { display: flex; flex-direction: column; overflow: hidden; }
|
|
2993
3017
|
.aux-file-editor-path { flex: 0 0 auto; margin: 0 0 8px; font-size: 11.5px; word-break: break-all; }
|
|
2994
|
-
.aux-file-editor { flex: 1 1 auto; width:
|
|
3018
|
+
.aux-file-editor-content { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; overflow: hidden; border: 1px solid var(--border); border-radius: 8px; background: var(--code-bg, var(--bg-app)); }
|
|
3019
|
+
.aux-file-editor { flex: 1 1 auto; width: 100%; min-height: 0; resize: none; border: 0; border-radius: 0; padding: 10px 12px; background: var(--code-bg, var(--bg-app)); color: var(--text-1); font: 12px/1.5 ui-monospace, SFMono-Regular, Consolas, monospace; white-space: pre; overflow: auto; }
|
|
3020
|
+
.aux-file-rendered-preview { flex: 1 1 auto; width: 100%; min-width: 0; min-height: 0; overflow: auto; padding: 16px 18px; background: var(--bg-surface); color: var(--text-1); }
|
|
3021
|
+
.aux-file-rendered-preview.md-prose { font-size: 13px; line-height: 1.75; }
|
|
3022
|
+
.aux-file-rendered-preview.md-prose .md-h:first-child { margin-top: 0; }
|
|
3023
|
+
.aux-file-html-preview { display: block; flex: 1 1 auto; width: 100%; min-width: 0; min-height: 0; border: 0; background: #fff; }
|
|
2995
3024
|
.aux-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2996
3025
|
.aux-path-bar { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
|
|
2997
3026
|
.aux-path-bar input { flex: 1; min-width: 0; height: 30px; border: 1px solid var(--border); border-radius: 7px; padding: 0 10px; font-size: 12.5px; background: var(--bg-surface); color: var(--text-1); }
|
|
@@ -3052,6 +3081,9 @@ select { border: 1px solid var(--border); background: var(--bg-surface); color:
|
|
|
3052
3081
|
.statusbar { min-height: 34px; padding: 8px 18px; color: #6b6f75; font-size: 13px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 8px; }
|
|
3053
3082
|
.statusbar.running::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--brand); box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand) 45%, transparent); animation: pulse 1.2s infinite; }
|
|
3054
3083
|
.statusbar.error::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--err); }
|
|
3084
|
+
.usagebar { margin-left: auto; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 11.5px; font-weight: 400; white-space: nowrap; }
|
|
3085
|
+
.usagebar.warn { color: var(--warn); }
|
|
3086
|
+
.usagebar.critical { color: var(--err); }
|
|
3055
3087
|
.transcript { flex: 1; overflow: auto; }
|
|
3056
3088
|
.code-block { position: relative; margin: 10px 0; padding: 12px 14px; background: var(--code-bg); color: var(--code-fg); border-radius: 8px; overflow: auto; border: 1px solid var(--code-border); }
|
|
3057
3089
|
.code-block code { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 12.5px; line-height: 1.5; white-space: pre; }
|
|
@@ -4351,6 +4383,7 @@ body { margin: 0; color: var(--text-1); background: var(--bg-app); }
|
|
|
4351
4383
|
.dialog-actions button { border: 1px solid var(--border); border-radius: 8px; min-height: 34px; padding: 0 12px; background: var(--bg-surface); }
|
|
4352
4384
|
.dialog-actions .primary { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }
|
|
4353
4385
|
.settings-view { position: fixed; inset: 0; z-index: 20; display: flex; background: var(--bg-sidebar); color: var(--text-1); }
|
|
4386
|
+
body.settings-open .manager-shell { display: none; }
|
|
4354
4387
|
.settings-sidebar {
|
|
4355
4388
|
width: 240px;
|
|
4356
4389
|
flex: 0 0 240px;
|
|
@@ -4452,6 +4485,7 @@ body { margin: 0; color: var(--text-1); background: var(--bg-app); }
|
|
|
4452
4485
|
font-size: 12.5px;
|
|
4453
4486
|
line-height: 1.55;
|
|
4454
4487
|
}
|
|
4488
|
+
${usageRoutingStyles}
|
|
4455
4489
|
.mode-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
|
|
4456
4490
|
.mode-card {
|
|
4457
4491
|
min-height: 56px;
|
|
@@ -4777,6 +4811,8 @@ body[data-density="compact"] .composer-meta { padding: 5px 12px; }
|
|
|
4777
4811
|
/* Dark-theme reserves for the new workbench regions (plan/UI_PLAN §2 — U9). */
|
|
4778
4812
|
@media (max-width: 860px) {
|
|
4779
4813
|
.sidebar { width: 56px; flex-basis: 56px; padding: 12px 8px; }
|
|
4814
|
+
.sidebar.collapsed { display: flex; }
|
|
4815
|
+
.sidebar .sidebar-collapse-btn, .sidebar-expand-fab { display: none; }
|
|
4780
4816
|
.sidebar .search, .sidebar-recents, .command-section, .project-section h2, .project-session-list, .sidebar-link, .brand-name { display: none; }
|
|
4781
4817
|
.sidebar .brand, .sidebar .nav-btn { justify-content: center; padding-left: 0; padding-right: 0; }
|
|
4782
4818
|
.sidebar .nav-btn > span:not(.nav-icon) { display: none !important; }
|
|
@@ -5228,11 +5264,12 @@ const state = {
|
|
|
5228
5264
|
auxView: null,
|
|
5229
5265
|
auxCollapsed: false,
|
|
5230
5266
|
auxPanelWidth: 340,
|
|
5267
|
+
auxFileViewMode: 'source',
|
|
5231
5268
|
terminalDockHeight: 260,
|
|
5232
5269
|
activeWorkbenchSurface: 'conversation',
|
|
5233
5270
|
workbenchLayouts: {
|
|
5234
5271
|
conversation: { auxWidth: 340, terminalHeight: 260, auxView: null, auxCollapsed: false, terminalVisible: false },
|
|
5235
|
-
project: { auxWidth: 340, terminalHeight: 260, auxView: null, auxCollapsed:
|
|
5272
|
+
project: { auxWidth: 340, terminalHeight: 260, auxView: null, auxCollapsed: true, terminalVisible: false },
|
|
5236
5273
|
},
|
|
5237
5274
|
filesBrowsePath: null,
|
|
5238
5275
|
browserUrl: 'https://',
|
|
@@ -5248,6 +5285,10 @@ const state = {
|
|
|
5248
5285
|
gitSidebarWidth: 320,
|
|
5249
5286
|
detailSidebarWidth: 300,
|
|
5250
5287
|
detailConversationOpen: true,
|
|
5288
|
+
// App shell panels: the left sidebar defaults expanded, the overview's right
|
|
5289
|
+
// context rail defaults collapsed; both persist to localStorage on toggle.
|
|
5290
|
+
sidebarCollapsed: false,
|
|
5291
|
+
railCollapsed: true,
|
|
5251
5292
|
conversationListOpen: false,
|
|
5252
5293
|
conversationListQuery: '',
|
|
5253
5294
|
sessionUnread: new Set(),
|
|
@@ -5534,7 +5575,8 @@ function refreshOpenTerminalThemes() {
|
|
|
5534
5575
|
const AUX_PANEL_WIDTH_KEY = 'hadamard.gui.auxPanelWidth';
|
|
5535
5576
|
const WORKBENCH_LAYOUT_KEY = 'hadamard.gui.workbenchLayouts';
|
|
5536
5577
|
const AUX_PANEL_MIN_WIDTH = 240;
|
|
5537
|
-
const AUX_PANEL_MAX_WIDTH =
|
|
5578
|
+
const AUX_PANEL_MAX_WIDTH = 1600;
|
|
5579
|
+
const AUX_PRIMARY_MIN_WIDTH = 360;
|
|
5538
5580
|
const TERMINAL_DOCK_MIN_HEIGHT = 160;
|
|
5539
5581
|
const TERMINAL_DOCK_MAX_HEIGHT = 720;
|
|
5540
5582
|
|
|
@@ -5561,7 +5603,7 @@ function loadAuxPanelWidth() {
|
|
|
5561
5603
|
if (Number.isFinite(auxWidth)) state.workbenchLayouts[surface].auxWidth = Math.round(Math.max(AUX_PANEL_MIN_WIDTH, Math.min(AUX_PANEL_MAX_WIDTH, auxWidth)));
|
|
5562
5604
|
if (Number.isFinite(terminalHeight)) state.workbenchLayouts[surface].terminalHeight = Math.round(Math.max(TERMINAL_DOCK_MIN_HEIGHT, Math.min(TERMINAL_DOCK_MAX_HEIGHT, terminalHeight)));
|
|
5563
5605
|
if (saved.auxView === null || ['review', 'git', 'browser', 'files'].includes(saved.auxView)) state.workbenchLayouts[surface].auxView = saved.auxView;
|
|
5564
|
-
if (typeof saved.auxCollapsed === 'boolean') state.workbenchLayouts[surface].auxCollapsed = saved.auxCollapsed;
|
|
5606
|
+
if (typeof saved.auxCollapsed === 'boolean' && (surface !== 'project' || parsed.version === 2)) state.workbenchLayouts[surface].auxCollapsed = saved.auxCollapsed;
|
|
5565
5607
|
if (typeof saved.terminalVisible === 'boolean') state.workbenchLayouts[surface].terminalVisible = saved.terminalVisible;
|
|
5566
5608
|
}
|
|
5567
5609
|
const legacy = Number(localStorage.getItem(AUX_PANEL_WIDTH_KEY));
|
|
@@ -5572,7 +5614,7 @@ function loadAuxPanelWidth() {
|
|
|
5572
5614
|
}
|
|
5573
5615
|
|
|
5574
5616
|
function persistAuxPanelWidth() {
|
|
5575
|
-
try { localStorage.setItem(WORKBENCH_LAYOUT_KEY, JSON.stringify(state.workbenchLayouts)); } catch { /* optional */ }
|
|
5617
|
+
try { localStorage.setItem(WORKBENCH_LAYOUT_KEY, JSON.stringify({ version: 2, ...state.workbenchLayouts })); } catch { /* optional */ }
|
|
5576
5618
|
}
|
|
5577
5619
|
|
|
5578
5620
|
function applyAuxPanelWidth(width) {
|
|
@@ -5626,8 +5668,8 @@ function ensureAuxVisible() {
|
|
|
5626
5668
|
persistAuxPanelWidth();
|
|
5627
5669
|
syncAuxChrome();
|
|
5628
5670
|
}
|
|
5629
|
-
function openAuxView(kind) {
|
|
5630
|
-
ensureAuxVisible();
|
|
5671
|
+
function openAuxView(kind, reveal = true) {
|
|
5672
|
+
if (reveal) ensureAuxVisible();
|
|
5631
5673
|
state.auxView = kind;
|
|
5632
5674
|
activeWorkbenchLayout().auxView = kind;
|
|
5633
5675
|
persistAuxPanelWidth();
|
|
@@ -5661,7 +5703,10 @@ function bindAuxPanelResize() {
|
|
|
5661
5703
|
const split = activeWorkbenchSplit();
|
|
5662
5704
|
if (!split) return;
|
|
5663
5705
|
const bounds = split.getBoundingClientRect();
|
|
5664
|
-
const maxByViewport = Math.
|
|
5706
|
+
const maxByViewport = Math.max(
|
|
5707
|
+
AUX_PANEL_MIN_WIDTH,
|
|
5708
|
+
Math.min(AUX_PANEL_MAX_WIDTH, Math.floor(bounds.width - AUX_PRIMARY_MIN_WIDTH)),
|
|
5709
|
+
);
|
|
5665
5710
|
const delta = startX - event.clientX; // dragging left widens the right panel
|
|
5666
5711
|
const next = Math.max(AUX_PANEL_MIN_WIDTH, Math.min(maxByViewport, startWidth + delta));
|
|
5667
5712
|
applyAuxPanelWidth(next);
|
|
@@ -6687,7 +6732,8 @@ function flashStatus(message) {
|
|
|
6687
6732
|
setTimeout(() => { if (!state.running) setRunStatus(readyLabel()); }, 2600);
|
|
6688
6733
|
}
|
|
6689
6734
|
function setRunStatus(message, kind = '') {
|
|
6690
|
-
|
|
6735
|
+
const statusText = el('statusText');
|
|
6736
|
+
if (statusText) statusText.textContent = message || '';
|
|
6691
6737
|
statusbar.classList.toggle('running', kind === 'running');
|
|
6692
6738
|
statusbar.classList.toggle('error', kind === 'error');
|
|
6693
6739
|
updateSendButton();
|
|
@@ -7877,15 +7923,37 @@ function updateConversationSummary() {
|
|
|
7877
7923
|
|| 'default';
|
|
7878
7924
|
el('workspace').textContent = (snap.workDir || '') + ' - ' + model + ' - ' + permissionPresetForValue(permissionSelectValue(snap.permissionMode)).title + ' - mode:' + (snap.agentMode || 'react') + ' - effort:' + snap.effort + ' - team:' + (snap.activeTeamName || 'none');
|
|
7879
7925
|
}
|
|
7926
|
+
function workspaceHtmlPreviewDocument(source) {
|
|
7927
|
+
const parsed = new DOMParser().parseFromString(String(source || ''), 'text/html');
|
|
7928
|
+
parsed.querySelectorAll('script, iframe, object, embed, base, link, meta[http-equiv]').forEach(node => node.remove());
|
|
7929
|
+
parsed.querySelectorAll('*').forEach(node => {
|
|
7930
|
+
for (const attribute of [...node.attributes]) {
|
|
7931
|
+
const name = attribute.name.toLowerCase();
|
|
7932
|
+
const value = String(attribute.value || '').trim();
|
|
7933
|
+
if (/^on/i.test(name) || ['srcset', 'action', 'formaction', 'poster', 'data', 'xlink:href'].includes(name)) {
|
|
7934
|
+
node.removeAttribute(attribute.name);
|
|
7935
|
+
} else if (name === 'src' && !/^data:image\\/(?:png|gif|jpe?g|webp|svg\\+xml);/i.test(value)) {
|
|
7936
|
+
node.removeAttribute(attribute.name);
|
|
7937
|
+
} else if (name === 'href' && !value.startsWith('#')) {
|
|
7938
|
+
node.removeAttribute(attribute.name);
|
|
7939
|
+
}
|
|
7940
|
+
}
|
|
7941
|
+
});
|
|
7942
|
+
const meta = parsed.createElement('meta');
|
|
7943
|
+
meta.httpEquiv = 'Content-Security-Policy';
|
|
7944
|
+
meta.content = "default-src 'none'; style-src 'unsafe-inline'; img-src data:; font-src data:; script-src 'none'; connect-src 'none'; frame-src 'none'; media-src 'none'; object-src 'none'; form-action 'none'; base-uri 'none'";
|
|
7945
|
+
parsed.head.prepend(meta);
|
|
7946
|
+
return '<!doctype html>' + parsed.documentElement.outerHTML;
|
|
7947
|
+
}
|
|
7880
7948
|
async function renderAuxFileEditor(filePath) {
|
|
7881
7949
|
const view = el('auxView');
|
|
7882
7950
|
if (!view) return;
|
|
7883
7951
|
view.textContent = '';
|
|
7884
7952
|
const head = document.createElement('div');
|
|
7885
|
-
head.className = 'aux-view-header';
|
|
7953
|
+
head.className = 'aux-view-header aux-file-editor-head';
|
|
7886
7954
|
const title = document.createElement('span');
|
|
7887
7955
|
title.className = 'aux-view-title';
|
|
7888
|
-
title.textContent = filePath.split(/
|
|
7956
|
+
title.textContent = String(filePath || '').replaceAll(String.fromCharCode(92), '/').split('/').pop() || 'File';
|
|
7889
7957
|
const backBtn = document.createElement('button');
|
|
7890
7958
|
backBtn.type = 'button';
|
|
7891
7959
|
backBtn.className = 'pill-btn';
|
|
@@ -7920,6 +7988,31 @@ async function renderAuxFileEditor(filePath) {
|
|
|
7920
7988
|
body.appendChild(note);
|
|
7921
7989
|
return;
|
|
7922
7990
|
}
|
|
7991
|
+
const language = detectEditorLanguage(data.path || filePath);
|
|
7992
|
+
const previewKind = language === 'markdown'
|
|
7993
|
+
? 'markdown'
|
|
7994
|
+
: /\\.html?$/i.test(String(data.path || filePath)) ? 'html' : null;
|
|
7995
|
+
let viewMode = state.auxFileViewMode === 'preview' ? 'preview' : 'source';
|
|
7996
|
+
const modeButtons = [];
|
|
7997
|
+
if (previewKind) {
|
|
7998
|
+
const modes = document.createElement('div');
|
|
7999
|
+
modes.className = 'files-preview-modes aux-file-preview-modes';
|
|
8000
|
+
modes.setAttribute('role', 'tablist');
|
|
8001
|
+
modes.setAttribute('aria-label', previewKind === 'markdown' ? 'Markdown display mode' : 'HTML display mode');
|
|
8002
|
+
for (const mode of ['source', 'preview']) {
|
|
8003
|
+
const button = document.createElement('button');
|
|
8004
|
+
button.type = 'button';
|
|
8005
|
+
button.className = 'files-preview-mode';
|
|
8006
|
+
button.textContent = mode === 'source' ? 'Source' : 'Preview';
|
|
8007
|
+
button.setAttribute('role', 'tab');
|
|
8008
|
+
button.addEventListener('click', () => applyViewMode(mode));
|
|
8009
|
+
modeButtons.push({ button, mode });
|
|
8010
|
+
modes.appendChild(button);
|
|
8011
|
+
}
|
|
8012
|
+
head.insertBefore(modes, backBtn);
|
|
8013
|
+
}
|
|
8014
|
+
const content = document.createElement('div');
|
|
8015
|
+
content.className = 'aux-file-editor-content';
|
|
7923
8016
|
const editor = document.createElement('textarea');
|
|
7924
8017
|
editor.className = 'aux-file-editor';
|
|
7925
8018
|
editor.value = typeof data.text === 'string' ? data.text : '';
|
|
@@ -7927,7 +8020,42 @@ async function renderAuxFileEditor(filePath) {
|
|
|
7927
8020
|
editor.spellcheck = false;
|
|
7928
8021
|
editor.wrap = 'off';
|
|
7929
8022
|
editor.setAttribute('aria-label', 'File editor');
|
|
7930
|
-
|
|
8023
|
+
content.appendChild(editor);
|
|
8024
|
+
let renderedPreview = null;
|
|
8025
|
+
if (previewKind === 'markdown') {
|
|
8026
|
+
renderedPreview = document.createElement('div');
|
|
8027
|
+
renderedPreview.className = 'aux-file-rendered-preview md-prose hidden';
|
|
8028
|
+
renderedPreview.setAttribute('aria-label', 'Markdown preview');
|
|
8029
|
+
content.appendChild(renderedPreview);
|
|
8030
|
+
} else if (previewKind === 'html') {
|
|
8031
|
+
renderedPreview = document.createElement('iframe');
|
|
8032
|
+
renderedPreview.className = 'aux-file-html-preview hidden';
|
|
8033
|
+
renderedPreview.title = 'HTML preview';
|
|
8034
|
+
renderedPreview.setAttribute('sandbox', '');
|
|
8035
|
+
renderedPreview.setAttribute('referrerpolicy', 'no-referrer');
|
|
8036
|
+
content.appendChild(renderedPreview);
|
|
8037
|
+
}
|
|
8038
|
+
body.appendChild(content);
|
|
8039
|
+
function renderCurrentPreview() {
|
|
8040
|
+
if (previewKind === 'markdown' && renderedPreview) {
|
|
8041
|
+
renderMarkdownInto(renderedPreview, editor.value);
|
|
8042
|
+
} else if (previewKind === 'html' && renderedPreview) {
|
|
8043
|
+
renderedPreview.srcdoc = workspaceHtmlPreviewDocument(editor.value);
|
|
8044
|
+
}
|
|
8045
|
+
}
|
|
8046
|
+
function applyViewMode(mode) {
|
|
8047
|
+
viewMode = mode === 'preview' && renderedPreview ? 'preview' : 'source';
|
|
8048
|
+
state.auxFileViewMode = viewMode;
|
|
8049
|
+
editor.classList.toggle('hidden', viewMode !== 'source');
|
|
8050
|
+
if (renderedPreview) renderedPreview.classList.toggle('hidden', viewMode !== 'preview');
|
|
8051
|
+
for (const item of modeButtons) {
|
|
8052
|
+
const active = item.mode === viewMode;
|
|
8053
|
+
item.button.classList.toggle('active', active);
|
|
8054
|
+
item.button.setAttribute('aria-selected', active ? 'true' : 'false');
|
|
8055
|
+
item.button.tabIndex = active ? 0 : -1;
|
|
8056
|
+
}
|
|
8057
|
+
if (viewMode === 'preview') renderCurrentPreview();
|
|
8058
|
+
}
|
|
7931
8059
|
let savedText = editor.value;
|
|
7932
8060
|
editor.addEventListener('input', () => { saveBtn.disabled = editor.value === savedText; });
|
|
7933
8061
|
const save = async () => {
|
|
@@ -7956,6 +8084,7 @@ async function renderAuxFileEditor(filePath) {
|
|
|
7956
8084
|
void save();
|
|
7957
8085
|
}
|
|
7958
8086
|
});
|
|
8087
|
+
applyViewMode(viewMode);
|
|
7959
8088
|
if (data.truncated) {
|
|
7960
8089
|
const note = document.createElement('p');
|
|
7961
8090
|
note.className = 'muted';
|
|
@@ -8028,8 +8157,24 @@ function renderComposerMeta() {
|
|
|
8028
8157
|
branchChip.disabled = !isRepo;
|
|
8029
8158
|
}
|
|
8030
8159
|
}
|
|
8160
|
+
function renderUsageBar() {
|
|
8161
|
+
const bar = el('usagebar');
|
|
8162
|
+
if (!bar) return;
|
|
8163
|
+
const snap = state.snapshot || {};
|
|
8164
|
+
if (!snap.usageBarText) {
|
|
8165
|
+
bar.classList.add('hidden');
|
|
8166
|
+
bar.textContent = '';
|
|
8167
|
+
return;
|
|
8168
|
+
}
|
|
8169
|
+
bar.textContent = snap.usageBarText;
|
|
8170
|
+
bar.title = 'Context / session usage';
|
|
8171
|
+
bar.classList.remove('hidden');
|
|
8172
|
+
bar.classList.toggle('warn', snap.usageBarLevel === 'warn');
|
|
8173
|
+
bar.classList.toggle('critical', snap.usageBarLevel === 'critical');
|
|
8174
|
+
}
|
|
8031
8175
|
function renderStatusExtras() {
|
|
8032
8176
|
const snap = state.snapshot || {};
|
|
8177
|
+
renderUsageBar();
|
|
8033
8178
|
const bar = el('contextBar');
|
|
8034
8179
|
bar.textContent = '';
|
|
8035
8180
|
const addBadge = (cls, text, title) => {
|
|
@@ -9116,6 +9261,42 @@ function toggleDetailConversationDrawer() {
|
|
|
9116
9261
|
: !sidebar?.classList.contains('desktop-collapsed');
|
|
9117
9262
|
setDetailConversationDrawer(!open);
|
|
9118
9263
|
}
|
|
9264
|
+
// --- App shell panels: collapsible left sidebar + right context rail. ---
|
|
9265
|
+
function setSidebarCollapsed(collapsed, persist) {
|
|
9266
|
+
state.sidebarCollapsed = Boolean(collapsed);
|
|
9267
|
+
const sidebar = el('appSidebar');
|
|
9268
|
+
const expander = el('sidebarExpandBtn');
|
|
9269
|
+
const toggle = el('sidebarCollapseBtn');
|
|
9270
|
+
sidebar?.classList.toggle('collapsed', state.sidebarCollapsed);
|
|
9271
|
+
expander?.classList.toggle('hidden', !state.sidebarCollapsed);
|
|
9272
|
+
toggle?.setAttribute('aria-expanded', state.sidebarCollapsed ? 'false' : 'true');
|
|
9273
|
+
expander?.setAttribute('aria-expanded', state.sidebarCollapsed ? 'false' : 'true');
|
|
9274
|
+
if (persist !== false) try { localStorage.setItem('hadamard.gui.sidebarCollapsed', state.sidebarCollapsed ? '1' : '0'); } catch { /* optional */ }
|
|
9275
|
+
}
|
|
9276
|
+
function loadSidebarCollapsed() {
|
|
9277
|
+
let saved = false;
|
|
9278
|
+
try { saved = localStorage.getItem('hadamard.gui.sidebarCollapsed') === '1'; } catch { /* optional */ }
|
|
9279
|
+
setSidebarCollapsed(saved, false);
|
|
9280
|
+
}
|
|
9281
|
+
function setContextRailCollapsed(collapsed, persist) {
|
|
9282
|
+
state.railCollapsed = Boolean(collapsed);
|
|
9283
|
+
if (persist !== false) try { localStorage.setItem('hadamard.gui.railCollapsed', state.railCollapsed ? '1' : '0'); } catch { /* optional */ }
|
|
9284
|
+
const toggle = el('overviewRailToggleBtn');
|
|
9285
|
+
if (toggle) {
|
|
9286
|
+
const expanded = !state.railCollapsed;
|
|
9287
|
+
toggle.setAttribute('aria-expanded', expanded ? 'true' : 'false');
|
|
9288
|
+
toggle.setAttribute('aria-label', expanded ? 'Hide panel' : 'Show panel');
|
|
9289
|
+
toggle.setAttribute('title', expanded ? 'Hide panel' : 'Show panel');
|
|
9290
|
+
toggle.innerHTML = guiIcon(expanded ? 'panelRight' : 'panelLeft');
|
|
9291
|
+
}
|
|
9292
|
+
renderContextRail();
|
|
9293
|
+
}
|
|
9294
|
+
function loadContextRailCollapsed() {
|
|
9295
|
+
// Default is collapsed: only an explicit '0' reopens the rail on startup.
|
|
9296
|
+
let saved = true;
|
|
9297
|
+
try { saved = localStorage.getItem('hadamard.gui.railCollapsed') !== '0'; } catch { /* optional */ }
|
|
9298
|
+
setContextRailCollapsed(saved, false);
|
|
9299
|
+
}
|
|
9119
9300
|
function runningSessionIds() {
|
|
9120
9301
|
return new Set((state.snapshot?.runs || []).filter(run => run.status === 'running' && run.sessionId).map(run => run.sessionId));
|
|
9121
9302
|
}
|
|
@@ -10179,9 +10360,9 @@ function richTextToMarkdown(root) {
|
|
|
10179
10360
|
if (node.nodeType === Node.TEXT_NODE) return (node.textContent || '').trim();
|
|
10180
10361
|
if (node.nodeType !== Node.ELEMENT_NODE) return '';
|
|
10181
10362
|
const tag = node.tagName.toLowerCase();
|
|
10182
|
-
if (/^h[1-6]$/.test(tag)) return '#'.repeat(Number(tag[1])) + ' ' + inline(node).trim();
|
|
10363
|
+
if ((tag === 'p' || tag === 'div') && node.children.length === 1 && /^(ul|ol)$/i.test(node.firstElementChild?.tagName || '')) return block(node.firstElementChild); if (/^h[1-6]$/.test(tag)) return '#'.repeat(Number(tag[1])) + ' ' + inline(node).trim();
|
|
10183
10364
|
if (tag === 'blockquote') return inline(node).trim().split('\\n').map(line => '> ' + line).join('\\n');
|
|
10184
|
-
if (tag === 'pre') return String.fromCharCode(96).repeat(3) + '\\n' +
|
|
10365
|
+
if (tag === 'pre') { const language = node.querySelector(':scope > .code-lang')?.textContent?.trim() || ''; const code = node.querySelector(':scope > code')?.textContent ?? node.textContent ?? ''; return String.fromCharCode(96).repeat(3) + language + '\\n' + code.replace(/\\n$/, '') + '\\n' + String.fromCharCode(96).repeat(3); }
|
|
10185
10366
|
if (tag === 'hr') return '---';
|
|
10186
10367
|
if (tag === 'ul' || tag === 'ol') return Array.from(node.children).map((item, index) => {
|
|
10187
10368
|
const checkbox = item.querySelector(':scope > input[type="checkbox"]');
|
|
@@ -10225,7 +10406,7 @@ function runProjectDocFormat(command, value) {
|
|
|
10225
10406
|
rich.focus();
|
|
10226
10407
|
if (command === 'codeBlock') document.execCommand('formatBlock', false, 'pre');
|
|
10227
10408
|
else if (command === 'blockquote') document.execCommand('formatBlock', false, 'blockquote');
|
|
10228
|
-
else if (command === 'heading') document.execCommand('formatBlock', false, value || '
|
|
10409
|
+
else if (command === 'heading') document.execCommand('formatBlock', false, value || 'p');
|
|
10229
10410
|
else if (command === 'link') {
|
|
10230
10411
|
const href = window.prompt('Link URL', 'https://');
|
|
10231
10412
|
if (href && /^https?:\\/\\//i.test(href)) document.execCommand('createLink', false, href);
|
|
@@ -10240,9 +10421,9 @@ function runProjectDocFormat(command, value) {
|
|
|
10240
10421
|
scheduleProjectDocSave();
|
|
10241
10422
|
}
|
|
10242
10423
|
function createProjectDocFormatBar() {
|
|
10243
|
-
const bar = document.createElement('div'); bar.className = 'project-doc-formatbar'; bar.setAttribute('role', 'toolbar'); bar.setAttribute('aria-label', 'Markdown formatting');
|
|
10424
|
+
const bar = document.createElement('div'); bar.className = 'project-doc-formatbar'; bar.setAttribute('role', 'toolbar'); bar.setAttribute('aria-label', 'Markdown formatting'); bar.appendChild(createProjectDocHeadingSelect());
|
|
10244
10425
|
const actions = [
|
|
10245
|
-
['
|
|
10426
|
+
['B', 'bold', '', 'Bold'], ['I', 'italic', '', 'Italic'], ['S', 'strikeThrough', '', 'Strikethrough'],
|
|
10246
10427
|
['•', 'insertUnorderedList', '', 'Bulleted list'], ['1.', 'insertOrderedList', '', 'Numbered list'], ['☑', 'task', '', 'Task list'],
|
|
10247
10428
|
['❝', 'blockquote', '', 'Quote'], ['</>', 'codeBlock', '', 'Code block'], ['↗', 'link', '', 'Link'], ['▧', 'image', '', 'Image'], ['▦', 'table', '', 'Table'],
|
|
10248
10429
|
['↶', 'undo', '', 'Undo'], ['↷', 'redo', '', 'Redo'], ['MD', 'source', '', 'Markdown source'],
|
|
@@ -11228,7 +11409,7 @@ function mountWorkbenchTools(surface) {
|
|
|
11228
11409
|
state.auxCollapsed = layout.auxCollapsed === true;
|
|
11229
11410
|
applyAuxPanelWidth(layout.auxWidth);
|
|
11230
11411
|
applyTerminalDockHeight(layout.terminalHeight);
|
|
11231
|
-
if (state.auxView) openAuxView(state.auxView);
|
|
11412
|
+
if (state.auxView) openAuxView(state.auxView, !state.auxCollapsed);
|
|
11232
11413
|
else showAuxLauncher();
|
|
11233
11414
|
dock.classList.toggle('hidden', layout.terminalVisible !== true);
|
|
11234
11415
|
syncAuxChrome();
|
|
@@ -13178,7 +13359,7 @@ function renderProjectDetail() {
|
|
|
13178
13359
|
docRich.setAttribute('role', 'textbox');
|
|
13179
13360
|
docRich.setAttribute('aria-multiline', 'true');
|
|
13180
13361
|
docRich.setAttribute('aria-label', 'Rich text document editor');
|
|
13181
|
-
|
|
13362
|
+
for (const eventName of ['focus', 'input', 'keyup', 'mouseup']) docRich.addEventListener(eventName, () => { if (eventName === 'input') scheduleProjectDocSave(); syncProjectDocHeadingSelect(); });
|
|
13182
13363
|
docRich.addEventListener('keydown', event => {
|
|
13183
13364
|
if (event.key === 'Escape') {
|
|
13184
13365
|
event.preventDefault();
|
|
@@ -13588,7 +13769,7 @@ function renderContextRail() {
|
|
|
13588
13769
|
const rail = el('contextRail');
|
|
13589
13770
|
if (!rail) return;
|
|
13590
13771
|
rail.textContent = '';
|
|
13591
|
-
if (state.activeRegion !== 'project' || state.projectView !== 'overview') {
|
|
13772
|
+
if (state.activeRegion !== 'project' || state.projectView !== 'overview' || state.railCollapsed) {
|
|
13592
13773
|
rail.classList.add('hidden');
|
|
13593
13774
|
return;
|
|
13594
13775
|
}
|
|
@@ -13837,12 +14018,13 @@ async function requestRailNotificationPermission() {
|
|
|
13837
14018
|
}
|
|
13838
14019
|
function showRailNotification(note) {
|
|
13839
14020
|
const text = note?.text || 'Reminder';
|
|
14021
|
+
const title = note?.title || 'Reminder';
|
|
13840
14022
|
if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {
|
|
13841
|
-
try { new Notification('Hadamard reminder', { body: text }); } catch { /* ignore */ }
|
|
14023
|
+
try { new Notification(note?.title || 'Hadamard reminder', { body: text }); } catch { /* ignore */ }
|
|
13842
14024
|
}
|
|
13843
14025
|
const toast = el('railToast');
|
|
13844
14026
|
if (!toast) return;
|
|
13845
|
-
toast.innerHTML = '<strong>
|
|
14027
|
+
toast.innerHTML = '<strong>' + escapeHtml(title) + '</strong> ' + escapeHtml(text);
|
|
13846
14028
|
toast.classList.remove('hidden');
|
|
13847
14029
|
clearTimeout(showRailNotification._timer);
|
|
13848
14030
|
showRailNotification._timer = setTimeout(() => toast.classList.add('hidden'), 8000);
|
|
@@ -25478,6 +25660,7 @@ function openProjectGitFromSettings() {
|
|
|
25478
25660
|
switchProjectView('detail');
|
|
25479
25661
|
setProjectDetailTab('git');
|
|
25480
25662
|
}
|
|
25663
|
+
${usageRoutingClient}
|
|
25481
25664
|
function showSettingsTab(tab) {
|
|
25482
25665
|
const requested = String(tab || 'general');
|
|
25483
25666
|
const hasTab = !!document.querySelector('.settings-tab[data-settings-tab="' + requested + '"]');
|
|
@@ -25490,6 +25673,7 @@ function showSettingsTab(tab) {
|
|
|
25490
25673
|
if (active === 'models') renderBridgeConfigs();
|
|
25491
25674
|
if (active === 'mcp') renderMcpServers();
|
|
25492
25675
|
if (active === 'sessions') renderArchived();
|
|
25676
|
+
if (active === 'usage-routing') void refreshUsageRouting();
|
|
25493
25677
|
}
|
|
25494
25678
|
// ── Assistant widget (global FAB + Global/Project scope) ───
|
|
25495
25679
|
// Talks to /api/manager/* with scope=global|project. Global uses assistant
|
|
@@ -26765,6 +26949,7 @@ async function openSettings(tab = 'general') {
|
|
|
26765
26949
|
setChecked('settingsShowRouterProfilesInComposer', preferences.showRouterProfilesInComposer !== false);
|
|
26766
26950
|
setChecked('settingsUseDefaultModelAsFallback', preferences.useDefaultModelAsFallback !== false);
|
|
26767
26951
|
setChecked('settingsShowBuiltInSubagents', preferences.showBuiltInSubagents === true);
|
|
26952
|
+
renderExtensionSettings(settings);
|
|
26768
26953
|
updateFallbackHint();
|
|
26769
26954
|
const terminalGroup = el('settingsTerminalGroup');
|
|
26770
26955
|
if (terminalGroup) {
|
|
@@ -26779,10 +26964,14 @@ async function openSettings(tab = 'general') {
|
|
|
26779
26964
|
renderShortcutsPanel();
|
|
26780
26965
|
el('settingsStatus').textContent = '';
|
|
26781
26966
|
renderSettingsCommandPanels();
|
|
26967
|
+
document.body.classList.add('settings-open');
|
|
26782
26968
|
el('settingsModal').classList.remove('hidden');
|
|
26783
26969
|
showSettingsTab(tab);
|
|
26784
26970
|
}
|
|
26785
|
-
function closeSettings() {
|
|
26971
|
+
function closeSettings() {
|
|
26972
|
+
el('settingsModal').classList.add('hidden');
|
|
26973
|
+
document.body.classList.remove('settings-open');
|
|
26974
|
+
}
|
|
26786
26975
|
function derivePermissionPreset() {
|
|
26787
26976
|
if (el('settingsPermissionPreset').value) return el('settingsPermissionPreset').value;
|
|
26788
26977
|
if (el('settingsFullAccess').checked) return 'full';
|
|
@@ -26792,9 +26981,68 @@ function derivePermissionPreset() {
|
|
|
26792
26981
|
}
|
|
26793
26982
|
let settingsAutosaveTimer = null;
|
|
26794
26983
|
let settingsAutosaveSeq = 0;
|
|
26984
|
+
function renderExtensionSettings(settings) {
|
|
26985
|
+
const extensionRoot = el('settingsExtensionsList');
|
|
26986
|
+
if (extensionRoot) {
|
|
26987
|
+
extensionRoot.textContent = '';
|
|
26988
|
+
const extensions = Array.isArray(settings.extensions) ? settings.extensions : [];
|
|
26989
|
+
if (extensions.length === 0) {
|
|
26990
|
+
extensionRoot.innerHTML = '<p class="muted">Built-in extensions are unavailable until the runtime is configured.</p>';
|
|
26991
|
+
} else {
|
|
26992
|
+
extensions.forEach(extension => {
|
|
26993
|
+
const row = document.createElement('div');
|
|
26994
|
+
row.className = 'settings-help-row';
|
|
26995
|
+
const copy = document.createElement('span');
|
|
26996
|
+
const title = document.createElement('strong');
|
|
26997
|
+
title.textContent = extension.title || extension.id;
|
|
26998
|
+
const description = document.createElement('small');
|
|
26999
|
+
const defaultState = extension.defaultEnabled ? 'on' : 'off';
|
|
27000
|
+
description.textContent = (extension.description || '') + ' Default: ' + defaultState + ' · ' + (extension.kind || 'runtime') + '.';
|
|
27001
|
+
copy.append(title, description);
|
|
27002
|
+
const label = document.createElement('label');
|
|
27003
|
+
label.className = 'switch-field';
|
|
27004
|
+
const toggle = document.createElement('input');
|
|
27005
|
+
toggle.type = 'checkbox';
|
|
27006
|
+
toggle.id = 'settingsExtension-' + extension.id;
|
|
27007
|
+
toggle.dataset.extensionId = extension.id;
|
|
27008
|
+
toggle.checked = extension.enabled === true;
|
|
27009
|
+
label.append(toggle);
|
|
27010
|
+
row.append(copy, label);
|
|
27011
|
+
extensionRoot.append(row);
|
|
27012
|
+
});
|
|
27013
|
+
}
|
|
27014
|
+
}
|
|
27015
|
+
setChecked('settingsAutoDetectLanguageServers', settings.autoDetectLanguageServers !== false);
|
|
27016
|
+
const lspRoot = el('settingsLanguageServersList');
|
|
27017
|
+
if (!lspRoot) return;
|
|
27018
|
+
lspRoot.textContent = '';
|
|
27019
|
+
const servers = Array.isArray(settings.languageServers) ? settings.languageServers : [];
|
|
27020
|
+
if (servers.length === 0) {
|
|
27021
|
+
lspRoot.innerHTML = '<p class="muted">No language servers are configured or currently detected.</p>';
|
|
27022
|
+
return;
|
|
27023
|
+
}
|
|
27024
|
+
servers.forEach(server => {
|
|
27025
|
+
const row = document.createElement('div');
|
|
27026
|
+
row.className = 'settings-help-row';
|
|
27027
|
+
const copy = document.createElement('span');
|
|
27028
|
+
const title = document.createElement('strong');
|
|
27029
|
+
title.textContent = server.id || 'Language server';
|
|
27030
|
+
const description = document.createElement('small');
|
|
27031
|
+
description.textContent = [Array.isArray(server.languages) ? server.languages.join(', ') : '', server.command || ''].filter(Boolean).join(' · ');
|
|
27032
|
+
copy.append(title, description);
|
|
27033
|
+
row.append(copy);
|
|
27034
|
+
lspRoot.append(row);
|
|
27035
|
+
});
|
|
27036
|
+
}
|
|
26795
27037
|
function collectSettingsBody() {
|
|
27038
|
+
const extensions = {};
|
|
27039
|
+
document.querySelectorAll('#settingsExtensionsList input[data-extension-id]').forEach(toggle => {
|
|
27040
|
+
extensions[toggle.dataset.extensionId] = { enabled: toggle.checked };
|
|
27041
|
+
});
|
|
26796
27042
|
return {
|
|
26797
27043
|
permissionPreset: derivePermissionPreset(),
|
|
27044
|
+
extensions,
|
|
27045
|
+
autoDetectLanguageServers: el('settingsAutoDetectLanguageServers')?.checked !== false,
|
|
26798
27046
|
preferences: {
|
|
26799
27047
|
theme: el('settingsTheme').value,
|
|
26800
27048
|
density: el('settingsDensity').value,
|
|
@@ -26827,6 +27075,7 @@ async function persistSettingsNow() {
|
|
|
26827
27075
|
if (seq !== settingsAutosaveSeq) return;
|
|
26828
27076
|
if (!res.ok) {
|
|
26829
27077
|
if (status) status.textContent = 'Save failed';
|
|
27078
|
+
renderExtensionSettings(state.snapshot?.settings || {});
|
|
26830
27079
|
addMessage('error', await res.text());
|
|
26831
27080
|
return;
|
|
26832
27081
|
}
|
|
@@ -26849,6 +27098,7 @@ async function persistSettingsNow() {
|
|
|
26849
27098
|
} catch (error) {
|
|
26850
27099
|
if (seq !== settingsAutosaveSeq) return;
|
|
26851
27100
|
if (status) status.textContent = 'Save failed';
|
|
27101
|
+
renderExtensionSettings(state.snapshot?.settings || {});
|
|
26852
27102
|
addMessage('error', error?.message || String(error));
|
|
26853
27103
|
}
|
|
26854
27104
|
}
|
|
@@ -26899,6 +27149,7 @@ document.querySelectorAll('[data-decision]').forEach(button => {
|
|
|
26899
27149
|
});
|
|
26900
27150
|
});
|
|
26901
27151
|
document.querySelectorAll('.settings-tab').forEach(button => button.addEventListener('click', () => showSettingsTab(button.dataset.settingsTab)));
|
|
27152
|
+
${usageRoutingBindings}
|
|
26902
27153
|
el('composer').addEventListener('submit', async (event) => {
|
|
26903
27154
|
event.preventDefault();
|
|
26904
27155
|
if (state.running) {
|
|
@@ -27142,6 +27393,9 @@ el('detailRemoveWorkPathBtn')?.addEventListener('click', () => {
|
|
|
27142
27393
|
});
|
|
27143
27394
|
el('detailOpenLocationBtn').addEventListener('click', openLocation);
|
|
27144
27395
|
el('detailConversationsBtn').addEventListener('click', toggleDetailConversationDrawer);
|
|
27396
|
+
el('sidebarCollapseBtn').addEventListener('click', () => setSidebarCollapsed(true));
|
|
27397
|
+
el('sidebarExpandBtn').addEventListener('click', () => setSidebarCollapsed(false));
|
|
27398
|
+
el('overviewRailToggleBtn').addEventListener('click', () => setContextRailCollapsed(!state.railCollapsed));
|
|
27145
27399
|
el('sessionCenterBack').addEventListener('click', () => switchProjectView('overview'));
|
|
27146
27400
|
el('sessionCenterNew').addEventListener('click', async () => {
|
|
27147
27401
|
const projectPath = el('sessionCenterProject')?.value || state.snapshot?.workDir;
|
|
@@ -27512,6 +27766,8 @@ el('terminalDockClose').addEventListener('click', () => {
|
|
|
27512
27766
|
});
|
|
27513
27767
|
loadAuxPanelWidth();
|
|
27514
27768
|
loadSessionIndicatorState();
|
|
27769
|
+
loadSidebarCollapsed();
|
|
27770
|
+
loadContextRailCollapsed();
|
|
27515
27771
|
applyAuxPanelWidth(activeWorkbenchLayout().auxWidth);
|
|
27516
27772
|
applyTerminalDockHeight(activeWorkbenchLayout().terminalHeight);
|
|
27517
27773
|
bindAuxPanelResize();
|