claudedesk 4.3.1 → 4.4.0
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/.github/workflows/ci.yml +44 -2
- package/CLAUDE.md +36 -3
- package/PHASE_1_IMPLEMENTATION.md +313 -0
- package/PHASE_2_PARTIAL_IMPLEMENTATION.md +286 -0
- package/dist/main/cli-manager.js +67 -2
- package/dist/main/command-registry.js +196 -0
- package/dist/main/git-manager.js +841 -0
- package/dist/main/index.js +25 -1
- package/dist/main/ipc-handlers.js +347 -3
- package/dist/main/layout-presets-manager.js +233 -0
- package/dist/main/model-history-manager.js +187 -0
- package/dist/main/session-manager.js +83 -26
- package/dist/main/session-persistence.js +1 -0
- package/dist/main/session-pool.js +40 -9
- package/dist/main/settings-persistence.js +67 -12
- package/dist/renderer/assets/index-BNeYLqV4.css +32 -0
- package/dist/renderer/assets/index-D5O5Ljoo.js +17189 -0
- package/dist/renderer/index.html +2 -2
- package/dist/shared/ipc-contract.js +79 -0
- package/dist/shared/model-detector.js +83 -0
- package/dist/shared/types/command-types.js +5 -0
- package/dist/shared/types/git-types.js +2 -0
- package/dist/types/layout-presets.js +11 -0
- package/docs/git-integration-implementation-tasks.md +974 -0
- package/docs/git-integration-product-spec.md +916 -0
- package/docs/git-integration-ui-spec.md +1464 -0
- package/docs/repo-index.md +83 -8
- package/e2e/app-launch.spec.ts +31 -0
- package/e2e/fixtures/electron.ts +34 -0
- package/e2e/keyboard-shortcuts.spec.ts +50 -0
- package/e2e/session.spec.ts +34 -0
- package/e2e/split-view.spec.ts +21 -0
- package/package.json +16 -3
- package/playwright.config.ts +15 -0
- package/src/main/cli-manager.ts +74 -3
- package/src/main/command-registry.ts +221 -0
- package/src/main/git-manager.test.ts +374 -0
- package/src/main/git-manager.ts +909 -0
- package/src/main/index.ts +31 -1
- package/src/main/ipc-emitter.test.ts +60 -0
- package/src/main/ipc-handlers.ts +295 -3
- package/src/main/ipc-registry.test.ts +75 -0
- package/src/main/layout-presets-manager.ts +268 -0
- package/src/main/model-history-manager.ts +196 -0
- package/src/main/session-manager.ts +102 -30
- package/src/main/session-persistence.test.ts +215 -0
- package/src/main/session-persistence.ts +1 -0
- package/src/main/session-pool.ts +31 -9
- package/src/main/settings-persistence.ts +74 -12
- package/src/renderer/App.tsx +215 -43
- package/src/renderer/components/CustomLayoutBuilder.tsx +143 -0
- package/src/renderer/components/GitPanel.test.tsx +181 -0
- package/src/renderer/components/GitPanel.tsx +1407 -0
- package/src/renderer/components/LayoutPicker.tsx +182 -0
- package/src/renderer/components/LayoutPreviewCard.tsx +175 -0
- package/src/renderer/components/ModelHistoryPanel.tsx +435 -0
- package/src/renderer/components/PaneHeader.test.tsx +96 -0
- package/src/renderer/components/PaneHeader.tsx +28 -0
- package/src/renderer/components/SplitLayout.test.tsx +153 -0
- package/src/renderer/components/SplitLayout.tsx +36 -1
- package/src/renderer/components/Terminal.tsx +10 -10
- package/src/renderer/components/WelcomeWizard.tsx +143 -0
- package/src/renderer/components/WizardStepper.tsx +135 -0
- package/src/renderer/components/ui/ClaudeReadinessProgress.tsx +168 -0
- package/src/renderer/components/ui/CommitDialog.test.tsx +134 -0
- package/src/renderer/components/ui/CommitDialog.tsx +464 -0
- package/src/renderer/components/ui/EmptyState.test.tsx +87 -0
- package/src/renderer/components/ui/EmptyState.tsx +115 -86
- package/src/renderer/components/ui/FeatureShowcase.tsx +187 -0
- package/src/renderer/components/ui/FuelGaugeBar.tsx +59 -0
- package/src/renderer/components/ui/FuelStatusIndicator.tsx +358 -0
- package/src/renderer/components/ui/FuelTooltip.tsx +267 -0
- package/src/renderer/components/ui/HelpButton.tsx +43 -0
- package/src/renderer/components/ui/ModelBadge.tsx +72 -0
- package/src/renderer/components/ui/ModelSwitcher.tsx +180 -0
- package/src/renderer/components/ui/PanelFooter.tsx +90 -0
- package/src/renderer/components/ui/PanelHeader.tsx +87 -0
- package/src/renderer/components/ui/PanelHelpOverlay.tsx +274 -0
- package/src/renderer/components/ui/QuickActionCard.tsx +103 -0
- package/src/renderer/components/ui/RecentSessionsList.tsx +154 -0
- package/src/renderer/components/ui/SessionStatusIndicator.tsx +104 -0
- package/src/renderer/components/ui/SettingsDialog.tsx +94 -0
- package/src/renderer/components/ui/ShortcutsPanel.tsx +433 -0
- package/src/renderer/components/ui/StatusPopover.tsx +344 -0
- package/src/renderer/components/ui/TabBar.test.tsx +124 -0
- package/src/renderer/components/ui/TabBar.tsx +152 -168
- package/src/renderer/components/ui/ToolbarDropdown.tsx +227 -0
- package/src/renderer/components/ui/ToolsDropdown.tsx +119 -0
- package/src/renderer/components/ui/TooltipCoach.tsx +217 -0
- package/src/renderer/components/ui/WelcomeHero.tsx +85 -0
- package/src/renderer/components/ui/index.ts +5 -0
- package/src/renderer/components/wizard/Step1_Welcome.tsx +166 -0
- package/src/renderer/components/wizard/Step2_LayoutPicker.tsx +246 -0
- package/src/renderer/components/wizard/Step3_Features.tsx +278 -0
- package/src/renderer/components/wizard/Step4_Ready.tsx +279 -0
- package/src/renderer/hooks/useGit.test.ts +140 -0
- package/src/renderer/hooks/useGit.ts +395 -0
- package/src/renderer/hooks/useLayoutPicker.ts +77 -0
- package/src/renderer/hooks/useModelHistory.ts +69 -0
- package/src/renderer/hooks/useSessionManager.test.ts +146 -0
- package/src/renderer/hooks/useSessionManager.ts +5 -0
- package/src/renderer/hooks/useSplitView.test.ts +168 -0
- package/src/renderer/hooks/useSplitView.ts +126 -128
- package/src/renderer/styles/globals.css +505 -0
- package/src/renderer/utils/fuzzy-search.test.ts +121 -0
- package/src/renderer/utils/layout-tree.test.ts +310 -0
- package/src/renderer/utils/layout-tree.ts +170 -0
- package/src/renderer/utils/variable-resolver.test.ts +102 -0
- package/src/shared/ipc-contract.ts +157 -0
- package/src/shared/ipc-types.ts +52 -1
- package/src/shared/message-parser.test.ts +79 -0
- package/src/shared/model-detector.test.ts +90 -0
- package/src/shared/model-detector.ts +97 -0
- package/src/shared/types/command-types.ts +26 -0
- package/src/shared/types/git-types.ts +126 -0
- package/src/types/layout-presets.ts +22 -0
- package/test/helpers/electron-api-mock.ts +52 -0
- package/test/setup-main.ts +61 -0
- package/test/setup-renderer.ts +8 -0
- package/tsconfig.json +1 -0
- package/tsconfig.main.json +2 -1
- package/vitest.workspace.ts +37 -0
- package/dist/renderer/assets/index-CR22a7j2.css +0 -32
- package/dist/renderer/assets/index-Dp-eceNq.js +0 -13915
package/dist/renderer/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self' data:;" />
|
|
7
7
|
<title>ClaudeDesk</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-D5O5Ljoo.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BNeYLqV4.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
|
@@ -24,6 +24,11 @@ exports.channels = {
|
|
|
24
24
|
sendSessionInput: 'session:input',
|
|
25
25
|
resizeSession: 'session:resize',
|
|
26
26
|
sessionReady: 'session:ready',
|
|
27
|
+
// Model switching
|
|
28
|
+
switchModel: 'model:switch',
|
|
29
|
+
// Model History
|
|
30
|
+
getModelHistory: 'model:getHistory',
|
|
31
|
+
clearModelHistory: 'model:clearHistory',
|
|
27
32
|
// Window controls
|
|
28
33
|
minimizeWindow: 'window:minimize',
|
|
29
34
|
maximizeWindow: 'window:maximize',
|
|
@@ -35,6 +40,7 @@ exports.channels = {
|
|
|
35
40
|
onSessionUpdated: 'session:updated',
|
|
36
41
|
onSessionOutput: 'session:output',
|
|
37
42
|
onSessionExited: 'session:exited',
|
|
43
|
+
onModelChanged: 'model:changed',
|
|
38
44
|
// Dialogs
|
|
39
45
|
browseDirectory: 'dialog:browseDirectory',
|
|
40
46
|
showSaveDialog: 'dialog:showSaveDialog',
|
|
@@ -97,6 +103,8 @@ exports.channels = {
|
|
|
97
103
|
unlinkSessionFromTeam: 'teams:unlinkSession',
|
|
98
104
|
closeTeam: 'teams:close',
|
|
99
105
|
updateAutoLayoutTeams: 'settings:updateAutoLayout',
|
|
106
|
+
updateUIMode: 'settings:updateUIMode',
|
|
107
|
+
updateDefaultModel: 'settings:updateDefaultModel',
|
|
100
108
|
// Agent Teams events
|
|
101
109
|
onTeamDetected: 'teams:detected',
|
|
102
110
|
onTeammateAdded: 'teams:teammateAdded',
|
|
@@ -108,8 +116,42 @@ exports.channels = {
|
|
|
108
116
|
getAtlasStatus: 'atlas:getStatus',
|
|
109
117
|
getAtlasSettings: 'atlas:getSettings',
|
|
110
118
|
updateAtlasSettings: 'atlas:updateSettings',
|
|
119
|
+
// Command Registry
|
|
120
|
+
searchCommands: 'commands:search',
|
|
121
|
+
getAllCommands: 'commands:getAll',
|
|
122
|
+
executeCommand: 'commands:execute',
|
|
111
123
|
// Repository Atlas events
|
|
112
124
|
onAtlasScanProgress: 'atlas:scanProgress',
|
|
125
|
+
// Layout Presets
|
|
126
|
+
getLayoutPresets: 'layout:getPresets',
|
|
127
|
+
applyLayoutPreset: 'layout:apply',
|
|
128
|
+
applyCustomLayout: 'layout:applyCustom',
|
|
129
|
+
getCurrentLayout: 'layout:getCurrent',
|
|
130
|
+
// Git Integration
|
|
131
|
+
getGitStatus: 'git:status',
|
|
132
|
+
getGitBranches: 'git:branches',
|
|
133
|
+
gitStageFiles: 'git:stage',
|
|
134
|
+
gitUnstageFiles: 'git:unstage',
|
|
135
|
+
gitStageAll: 'git:stageAll',
|
|
136
|
+
gitUnstageAll: 'git:unstageAll',
|
|
137
|
+
gitCommit: 'git:commit',
|
|
138
|
+
gitGenerateMessage: 'git:generateMessage',
|
|
139
|
+
gitPush: 'git:push',
|
|
140
|
+
gitPull: 'git:pull',
|
|
141
|
+
gitFetch: 'git:fetch',
|
|
142
|
+
gitSwitchBranch: 'git:switchBranch',
|
|
143
|
+
gitCreateBranch: 'git:createBranch',
|
|
144
|
+
gitLog: 'git:log',
|
|
145
|
+
gitDiff: 'git:diff',
|
|
146
|
+
gitCommitDiff: 'git:commitDiff',
|
|
147
|
+
gitDiscardFile: 'git:discardFile',
|
|
148
|
+
gitDiscardAll: 'git:discardAll',
|
|
149
|
+
gitInit: 'git:init',
|
|
150
|
+
gitStartWatching: 'git:startWatching',
|
|
151
|
+
gitStopWatching: 'git:stopWatching',
|
|
152
|
+
// Git events
|
|
153
|
+
onGitStatusChanged: 'git:statusChanged',
|
|
154
|
+
onGitRemoteProgress: 'git:remoteProgress',
|
|
113
155
|
// App info
|
|
114
156
|
getVersionInfo: 'app:getVersionInfo',
|
|
115
157
|
};
|
|
@@ -125,6 +167,9 @@ exports.contractKinds = {
|
|
|
125
167
|
sendSessionInput: 'send',
|
|
126
168
|
resizeSession: 'send',
|
|
127
169
|
sessionReady: 'send',
|
|
170
|
+
switchModel: 'invoke',
|
|
171
|
+
getModelHistory: 'invoke',
|
|
172
|
+
clearModelHistory: 'invoke',
|
|
128
173
|
minimizeWindow: 'send',
|
|
129
174
|
maximizeWindow: 'send',
|
|
130
175
|
closeWindow: 'send',
|
|
@@ -134,6 +179,7 @@ exports.contractKinds = {
|
|
|
134
179
|
onSessionUpdated: 'event',
|
|
135
180
|
onSessionOutput: 'event',
|
|
136
181
|
onSessionExited: 'event',
|
|
182
|
+
onModelChanged: 'event',
|
|
137
183
|
browseDirectory: 'invoke',
|
|
138
184
|
showSaveDialog: 'invoke',
|
|
139
185
|
writeFile: 'invoke',
|
|
@@ -157,6 +203,9 @@ exports.contractKinds = {
|
|
|
157
203
|
addTemplate: 'invoke',
|
|
158
204
|
updateTemplate: 'invoke',
|
|
159
205
|
deleteTemplate: 'invoke',
|
|
206
|
+
searchCommands: 'invoke',
|
|
207
|
+
getAllCommands: 'invoke',
|
|
208
|
+
executeCommand: 'invoke',
|
|
160
209
|
getFileInfo: 'invoke',
|
|
161
210
|
readFileContent: 'invoke',
|
|
162
211
|
listHistory: 'invoke',
|
|
@@ -185,6 +234,8 @@ exports.contractKinds = {
|
|
|
185
234
|
unlinkSessionFromTeam: 'invoke',
|
|
186
235
|
closeTeam: 'invoke',
|
|
187
236
|
updateAutoLayoutTeams: 'invoke',
|
|
237
|
+
updateUIMode: 'invoke',
|
|
238
|
+
updateDefaultModel: 'invoke',
|
|
188
239
|
onTeamDetected: 'event',
|
|
189
240
|
onTeammateAdded: 'event',
|
|
190
241
|
onTasksUpdated: 'event',
|
|
@@ -195,5 +246,33 @@ exports.contractKinds = {
|
|
|
195
246
|
getAtlasSettings: 'invoke',
|
|
196
247
|
updateAtlasSettings: 'invoke',
|
|
197
248
|
onAtlasScanProgress: 'event',
|
|
249
|
+
getLayoutPresets: 'invoke',
|
|
250
|
+
applyLayoutPreset: 'invoke',
|
|
251
|
+
applyCustomLayout: 'invoke',
|
|
252
|
+
getCurrentLayout: 'invoke',
|
|
253
|
+
// Git Integration
|
|
254
|
+
getGitStatus: 'invoke',
|
|
255
|
+
getGitBranches: 'invoke',
|
|
256
|
+
gitStageFiles: 'invoke',
|
|
257
|
+
gitUnstageFiles: 'invoke',
|
|
258
|
+
gitStageAll: 'invoke',
|
|
259
|
+
gitUnstageAll: 'invoke',
|
|
260
|
+
gitCommit: 'invoke',
|
|
261
|
+
gitGenerateMessage: 'invoke',
|
|
262
|
+
gitPush: 'invoke',
|
|
263
|
+
gitPull: 'invoke',
|
|
264
|
+
gitFetch: 'invoke',
|
|
265
|
+
gitSwitchBranch: 'invoke',
|
|
266
|
+
gitCreateBranch: 'invoke',
|
|
267
|
+
gitLog: 'invoke',
|
|
268
|
+
gitDiff: 'invoke',
|
|
269
|
+
gitCommitDiff: 'invoke',
|
|
270
|
+
gitDiscardFile: 'invoke',
|
|
271
|
+
gitDiscardAll: 'invoke',
|
|
272
|
+
gitInit: 'invoke',
|
|
273
|
+
gitStartWatching: 'invoke',
|
|
274
|
+
gitStopWatching: 'invoke',
|
|
275
|
+
onGitStatusChanged: 'event',
|
|
276
|
+
onGitRemoteProgress: 'event',
|
|
198
277
|
getVersionInfo: 'invoke',
|
|
199
278
|
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Model Detector — Parse terminal output to detect active Claude model
|
|
4
|
+
*
|
|
5
|
+
* Detects model switches from Claude Code CLI output in two phases:
|
|
6
|
+
* 1. Initial detection: Parse welcome screen for starting model
|
|
7
|
+
* 2. Switch detection: Parse /model command confirmations
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.detectModelFromOutput = detectModelFromOutput;
|
|
11
|
+
// Patterns for detecting model switches via /model command
|
|
12
|
+
const SWITCH_PATTERNS = [
|
|
13
|
+
/Set model to (?:Default )?\(?(Opus|Sonnet|Haiku)/i, // "Set model to Default (Opus 4.6..."
|
|
14
|
+
/Set model to (\w+)/i, // "Set model to opus (claude-opus-4-6)"
|
|
15
|
+
/Kept model as (?:Default )?\(?(Opus|Sonnet|Haiku)/i, // "Kept model as Default (recommended)"
|
|
16
|
+
/Kept model as (\w+)/i, // "Kept model as haiku"
|
|
17
|
+
/Switched to (?:claude[- ])?(\w+)/i,
|
|
18
|
+
/Now using (?:model: )?(\w+)/i,
|
|
19
|
+
/Model changed to (\w+)/i,
|
|
20
|
+
/Using model (\w+)/i,
|
|
21
|
+
];
|
|
22
|
+
// Patterns for detecting initial model from welcome screen
|
|
23
|
+
// IMPORTANT: Pattern 0 requires "·" immediately after version to exclude promo text
|
|
24
|
+
// like "Opus 4.6 is here · $50 free extra usage" (which has "is here" before "·")
|
|
25
|
+
const WELCOME_PATTERNS = [
|
|
26
|
+
/(Opus|Sonnet|Haiku)\s+\d+\.\d+\s*·/i, // "Haiku 4.5 · Claude Max" (v2.1+ format, requires ·)
|
|
27
|
+
/Claude (?:3\.5 |4\.\d+ )?(Sonnet|Opus|Haiku)/i,
|
|
28
|
+
/\((Opus|Sonnet|Haiku)\s+\d+\.\d+/i, // "(Opus 4.6 · Most capable..."
|
|
29
|
+
/Using model[: ]+(\w+)/i,
|
|
30
|
+
/Model[: ]+(\w+)/i,
|
|
31
|
+
/\((\w+)\s+\d+\.\d+\)/i, // e.g., "(Sonnet 4.5)"
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Strip ANSI escape sequences from terminal output.
|
|
35
|
+
* Handles CSI sequences (\x1b[...X), OSC sequences (\x1b]...\x07), and single-char escapes.
|
|
36
|
+
*/
|
|
37
|
+
function stripAnsi(text) {
|
|
38
|
+
return text
|
|
39
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '') // CSI sequences (colors, cursor, etc.)
|
|
40
|
+
.replace(/\x1b\][^\x07]*\x07/g, '') // OSC sequences (title, etc.)
|
|
41
|
+
.replace(/\x1b[()][A-Z0-9]/g, '') // Character set selection
|
|
42
|
+
.replace(/\x1b[=>]/g, ''); // Keypad mode
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Detect model from terminal output.
|
|
46
|
+
*
|
|
47
|
+
* @param text - Terminal output to parse (raw PTY output with ANSI codes is OK)
|
|
48
|
+
* @param isInitial - True for welcome screen detection, false for switch detection
|
|
49
|
+
* @returns Detection result with confidence level
|
|
50
|
+
*/
|
|
51
|
+
function detectModelFromOutput(text, isInitial = false) {
|
|
52
|
+
const clean = stripAnsi(text);
|
|
53
|
+
const patterns = isInitial ? WELCOME_PATTERNS : SWITCH_PATTERNS;
|
|
54
|
+
for (const pattern of patterns) {
|
|
55
|
+
const match = clean.match(pattern);
|
|
56
|
+
if (match) {
|
|
57
|
+
const raw = match[1].toLowerCase();
|
|
58
|
+
const normalized = normalizeModelName(raw);
|
|
59
|
+
if (normalized) {
|
|
60
|
+
return { model: normalized, confidence: 'high' };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { model: null, confidence: 'low' };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Normalize raw model name to canonical ClaudeModel type.
|
|
68
|
+
*/
|
|
69
|
+
function normalizeModelName(raw) {
|
|
70
|
+
const map = {
|
|
71
|
+
'sonnet': 'sonnet',
|
|
72
|
+
'3.5-sonnet': 'sonnet',
|
|
73
|
+
'4-sonnet': 'sonnet',
|
|
74
|
+
'opus': 'opus',
|
|
75
|
+
'3-opus': 'opus',
|
|
76
|
+
'4-opus': 'opus',
|
|
77
|
+
'haiku': 'haiku',
|
|
78
|
+
'3-haiku': 'haiku',
|
|
79
|
+
'4-haiku': 'haiku',
|
|
80
|
+
'auto': 'auto',
|
|
81
|
+
};
|
|
82
|
+
return map[raw] || null;
|
|
83
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PRESET_IDS = void 0;
|
|
4
|
+
// Preset IDs (constants for easy reference)
|
|
5
|
+
exports.PRESET_IDS = {
|
|
6
|
+
SINGLE: 'single',
|
|
7
|
+
TWO_COLUMN: 'two-column',
|
|
8
|
+
THREE_COLUMN: 'three-column',
|
|
9
|
+
QUAD_GRID: 'quad-grid',
|
|
10
|
+
CUSTOM: 'custom',
|
|
11
|
+
};
|