clideck 1.30.6 → 1.30.8
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/config.js +26 -1
- package/package.json +1 -1
- package/public/js/app.js +3 -0
- package/public/js/creator.js +39 -2
- package/server.js +6 -1
- package/utils.js +8 -2
package/config.js
CHANGED
|
@@ -107,6 +107,23 @@ function matchPreset(cmd) {
|
|
|
107
107
|
return PRESETS.find(p => binName(p.command) === bin);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
function firstCommandToken(command) {
|
|
111
|
+
const raw = String(command || '').trim();
|
|
112
|
+
const m = raw.match(/^(['"])(.*?)\1|^(\S+)/);
|
|
113
|
+
return m ? (m[2] || m[3] || '') : '';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function commandPathMissing(command) {
|
|
117
|
+
const token = firstCommandToken(command);
|
|
118
|
+
return !token || (token.startsWith('/') && !existsSync(token));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function isShellCommand(cmd, preset) {
|
|
122
|
+
return preset?.presetId === 'shell'
|
|
123
|
+
|| cmd.presetId === 'shell'
|
|
124
|
+
|| (!cmd.isAgent && !cmd.presetId && String(cmd.label || '').toLowerCase() === 'shell');
|
|
125
|
+
}
|
|
126
|
+
|
|
110
127
|
function migrate(cfg) {
|
|
111
128
|
// Migrate profiles → defaultTheme
|
|
112
129
|
if (cfg.profiles && !cfg.defaultTheme) {
|
|
@@ -118,7 +135,15 @@ function migrate(cfg) {
|
|
|
118
135
|
if (!cfg.defaultTheme || cfg.defaultTheme === 'solarized-dark') cfg.defaultTheme = 'catppuccin-mocha';
|
|
119
136
|
// Backfill and sync fields from presets
|
|
120
137
|
for (const cmd of cfg.commands) {
|
|
121
|
-
|
|
138
|
+
let preset = cmd.presetId ? PRESETS.find(p => p.presetId === cmd.presetId) : matchPreset(cmd);
|
|
139
|
+
if (isShellCommand(cmd, preset)) {
|
|
140
|
+
preset = PRESETS.find(p => p.presetId === 'shell') || preset;
|
|
141
|
+
cmd.presetId = 'shell';
|
|
142
|
+
cmd.label = cmd.label || 'Shell';
|
|
143
|
+
}
|
|
144
|
+
if (preset?.presetId === 'shell' && commandPathMissing(cmd.command)) {
|
|
145
|
+
cmd.command = defaultShell;
|
|
146
|
+
}
|
|
122
147
|
// Stamp presetId for reliable lookup
|
|
123
148
|
if (preset && !cmd.presetId) cmd.presetId = preset.presetId;
|
|
124
149
|
// Icon always syncs from preset — the preset is the source of truth for logos
|
package/package.json
CHANGED
package/public/js/app.js
CHANGED
|
@@ -55,6 +55,9 @@ function connect() {
|
|
|
55
55
|
state.resumable = msg.list;
|
|
56
56
|
renderResumable();
|
|
57
57
|
break;
|
|
58
|
+
case 'error':
|
|
59
|
+
showToast(msg.message || 'CliDeck action failed.', { type: 'error', title: 'CliDeck Error', duration: 5000 });
|
|
60
|
+
break;
|
|
58
61
|
case 'sessions':
|
|
59
62
|
{
|
|
60
63
|
const liveIds = new Set(msg.list.map(s => s.id));
|
package/public/js/creator.js
CHANGED
|
@@ -134,6 +134,40 @@ function ensureCommandForPreset(preset) {
|
|
|
134
134
|
return cmd;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
function ensureShellCommand() {
|
|
138
|
+
const shellPreset = state.presets.find(p => p.presetId === 'shell');
|
|
139
|
+
const command = shellPreset?.command || state.cfg.defaultShell;
|
|
140
|
+
let cmd = state.cfg.commands.find(c => c.presetId === 'shell' || (!c.isAgent && !c.presetId && String(c.label || '').toLowerCase() === 'shell'));
|
|
141
|
+
if (cmd) {
|
|
142
|
+
if (!cmd.command || (cmd.command === '/bin/zsh' && command && command !== '/bin/zsh')) {
|
|
143
|
+
cmd.presetId = 'shell';
|
|
144
|
+
cmd.command = command;
|
|
145
|
+
send({ type: 'config.update', config: state.cfg });
|
|
146
|
+
}
|
|
147
|
+
return cmd;
|
|
148
|
+
}
|
|
149
|
+
if (!command) return null;
|
|
150
|
+
cmd = {
|
|
151
|
+
id: crypto.randomUUID(),
|
|
152
|
+
presetId: 'shell',
|
|
153
|
+
label: 'Shell',
|
|
154
|
+
icon: shellPreset?.icon || 'terminal',
|
|
155
|
+
command,
|
|
156
|
+
enabled: true,
|
|
157
|
+
defaultPath: '',
|
|
158
|
+
isAgent: false,
|
|
159
|
+
canResume: false,
|
|
160
|
+
resumeCommand: null,
|
|
161
|
+
sessionIdPattern: null,
|
|
162
|
+
outputMarker: null,
|
|
163
|
+
telemetryEnabled: false,
|
|
164
|
+
telemetryStatus: null,
|
|
165
|
+
};
|
|
166
|
+
state.cfg.commands.push(cmd);
|
|
167
|
+
send({ type: 'config.update', config: state.cfg });
|
|
168
|
+
return cmd;
|
|
169
|
+
}
|
|
170
|
+
|
|
137
171
|
export function openCreator() {
|
|
138
172
|
// Toggle off if already open
|
|
139
173
|
if (document.getElementById('session-creator')) {
|
|
@@ -348,8 +382,11 @@ function showInstallToast(preset) {
|
|
|
348
382
|
setTimeout(() => send({ type: 'telemetry.autosetup', presetId: preset.presetId }), 1000);
|
|
349
383
|
}
|
|
350
384
|
// Find or create the shell command, then spawn a session running the install
|
|
351
|
-
const shellCmd =
|
|
352
|
-
if (!shellCmd)
|
|
385
|
+
const shellCmd = ensureShellCommand();
|
|
386
|
+
if (!shellCmd) {
|
|
387
|
+
showToast('Could not find a shell command to run the installer.', { type: 'error', title: 'Install Failed' });
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
353
390
|
const installId = crypto.randomUUID();
|
|
354
391
|
send({ type: 'create', commandId: shellCmd.id, name: `Installing ${preset.name}`, installId, ...estimateSize() });
|
|
355
392
|
const handler = (e) => {
|
package/server.js
CHANGED
|
@@ -8,6 +8,10 @@ function terminalLink(url, text = url) {
|
|
|
8
8
|
return `\u001B]8;;${url}\u0007${text}\u001B]8;;\u0007`;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
function openUrlHint() {
|
|
12
|
+
return process.platform === 'darwin' ? 'Cmd+click to open' : 'Ctrl+click to open';
|
|
13
|
+
}
|
|
14
|
+
|
|
11
15
|
// --- Self-update check (runs before server starts) ---
|
|
12
16
|
const currentVersion = require('./package.json').version;
|
|
13
17
|
const { execFile, execSync } = require('child_process');
|
|
@@ -291,6 +295,7 @@ server.listen(PORT, HOST, () => {
|
|
|
291
295
|
const v = require('./package.json').version;
|
|
292
296
|
const url = `http://${HOST === '0.0.0.0' ? 'localhost' : HOST}:${PORT}`;
|
|
293
297
|
const clickableUrl = terminalLink(url);
|
|
298
|
+
const urlHint = openUrlHint();
|
|
294
299
|
console.log(`
|
|
295
300
|
\x1b[38;5;105m ╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸\x1b[0m
|
|
296
301
|
|
|
@@ -305,7 +310,7 @@ server.listen(PORT, HOST, () => {
|
|
|
305
310
|
|
|
306
311
|
\x1b[38;5;245m v${v}\x1b[0m
|
|
307
312
|
|
|
308
|
-
\x1b[38;5;252m ▸ Ready at \x1b[38;5;44m${clickableUrl}\x1b[38;5;245m (
|
|
313
|
+
\x1b[38;5;252m ▸ Ready at \x1b[38;5;44m${clickableUrl}\x1b[38;5;245m (${urlHint})\x1b[0m
|
|
309
314
|
\x1b[38;5;245m ▸ Stop with \x1b[38;5;252mCtrl+C\x1b[38;5;245m · Restart anytime with \x1b[38;5;252mclideck\x1b[0m
|
|
310
315
|
${HOST !== '127.0.0.1' ? '\x1b[38;5;208m ▸ Warning: listening on ' + HOST + ' — no authentication, anyone on the network can connect\x1b[0m\n' : ''}`);
|
|
311
316
|
});
|
package/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { chmodSync, statSync, readdirSync } = require('fs');
|
|
1
|
+
const { chmodSync, existsSync, statSync, readdirSync } = require('fs');
|
|
2
2
|
const { dirname, join } = require('path');
|
|
3
3
|
|
|
4
4
|
function ensurePtyHelper() {
|
|
@@ -55,7 +55,13 @@ function listDirs(path, showHidden) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
function resolveDefaultShell() {
|
|
59
|
+
if (process.platform === 'win32') return process.env.COMSPEC || 'cmd.exe';
|
|
60
|
+
const candidates = [process.env.SHELL, '/bin/zsh', '/bin/bash', '/bin/sh'].filter(Boolean);
|
|
61
|
+
return candidates.find(shell => existsSync(shell)) || '/bin/sh';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const defaultShell = resolveDefaultShell();
|
|
59
65
|
|
|
60
66
|
function binName(command) {
|
|
61
67
|
const m = command.match(/^(['"])(.*?)\1/);
|