@bakapiano/ccsm 0.22.2 → 0.22.4
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/CLAUDE.md +538 -538
- package/README.md +189 -189
- package/bin/ccsm.js +235 -235
- package/lib/cliActivity.js +139 -139
- package/lib/codexSeed.js +183 -183
- package/lib/config.js +274 -274
- package/lib/devices.js +229 -229
- package/lib/folders.js +124 -124
- package/lib/localCliSessions.js +519 -519
- package/lib/persistedSessions.js +129 -129
- package/lib/tunnel.js +621 -621
- package/lib/webTerminal.js +233 -231
- package/lib/workspace.js +233 -233
- package/package.json +57 -57
- package/public/css/base.css +99 -99
- package/public/css/cards.css +183 -183
- package/public/css/feedback.css +504 -504
- package/public/css/forms.css +453 -453
- package/public/css/layout.css +176 -176
- package/public/css/modal.css +190 -190
- package/public/css/responsive.css +176 -176
- package/public/css/sidebar.css +707 -707
- package/public/css/terminals.css +592 -592
- package/public/css/tokens.css +81 -81
- package/public/css/wco.css +196 -196
- package/public/css/widgets.css +2725 -2725
- package/public/index.html +152 -152
- package/public/js/api.js +371 -371
- package/public/js/backend.js +149 -149
- package/public/js/components/App.js +73 -73
- package/public/js/components/DirectoryPicker.js +203 -203
- package/public/js/components/EntityFormModal.js +153 -153
- package/public/js/components/Modal.js +57 -57
- package/public/js/components/OfflineBanner.js +67 -67
- package/public/js/components/PageTitleBar.js +13 -13
- package/public/js/components/PendingApprovalOverlay.js +128 -128
- package/public/js/components/Picker.js +179 -179
- package/public/js/components/Popover.js +55 -55
- package/public/js/components/RestartOverlay.js +36 -36
- package/public/js/components/Sidebar.js +380 -380
- package/public/js/components/TerminalInstance.js +187 -15
- package/public/js/components/TerminalResizeDebouncer.js +126 -0
- package/public/js/components/XtermTerminal.js +148 -14
- package/public/js/components/useDragSort.js +67 -67
- package/public/js/dialog.js +67 -67
- package/public/js/icons.js +212 -212
- package/public/js/main.js +296 -296
- package/public/js/pages/AboutPage.js +90 -90
- package/public/js/pages/ConfigurePage.js +713 -713
- package/public/js/pages/LaunchPage.js +421 -421
- package/public/js/pages/RemotePage.js +743 -743
- package/public/js/pages/SessionsPage.js +100 -100
- package/public/js/state.js +335 -335
- package/public/manifest.webmanifest +25 -0
- package/public/setup/index.html +567 -0
- package/scripts/dev.js +149 -149
- package/scripts/install.js +153 -153
- package/scripts/restart-helper.js +96 -96
- package/scripts/upgrade-helper.js +687 -687
- package/server.js +1807 -1807
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
// Restart helper · spawned detached by /api/restart.
|
|
5
|
-
//
|
|
6
|
-
// Just like upgrade-helper but skips the `npm i` step. Server kicks
|
|
7
|
-
// this off + gracefulShutdowns; helper waits for the port to free, then
|
|
8
|
-
// respawns ccsm (which finds no live backend and starts a fresh one).
|
|
9
|
-
//
|
|
10
|
-
// Argv: node restart-helper.js <port> <pid>
|
|
11
|
-
|
|
12
|
-
const fs = require('node:fs');
|
|
13
|
-
const path = require('node:path');
|
|
14
|
-
const os = require('node:os');
|
|
15
|
-
const net = require('node:net');
|
|
16
|
-
const { spawn } = require('node:child_process');
|
|
17
|
-
|
|
18
|
-
const oldPort = Number(process.argv[2] || 7777);
|
|
19
|
-
const oldPid = Number(process.argv[3] || 0);
|
|
20
|
-
|
|
21
|
-
const HOME = process.env.CCSM_HOME || path.join(os.homedir(), '.ccsm');
|
|
22
|
-
const LOG = path.join(HOME, 'restart.log');
|
|
23
|
-
try { fs.mkdirSync(HOME, { recursive: true }); } catch {}
|
|
24
|
-
|
|
25
|
-
function log(msg) {
|
|
26
|
-
const line = `[${new Date().toISOString()}] ${msg}\n`;
|
|
27
|
-
try { fs.appendFileSync(LOG, line); } catch {}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
|
|
31
|
-
|
|
32
|
-
function portFree(port, timeoutMs = 800) {
|
|
33
|
-
return new Promise((resolve) => {
|
|
34
|
-
const s = new net.Socket();
|
|
35
|
-
let settled = false;
|
|
36
|
-
const finish = (free) => { if (settled) return; settled = true; try { s.destroy(); } catch {} resolve(free); };
|
|
37
|
-
s.setTimeout(timeoutMs);
|
|
38
|
-
s.once('connect', () => finish(false));
|
|
39
|
-
s.once('timeout', () => finish(true));
|
|
40
|
-
s.once('error', () => finish(true));
|
|
41
|
-
s.connect(port, '127.0.0.1');
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function pidAlive(pid) {
|
|
46
|
-
if (!pid) return false;
|
|
47
|
-
try { process.kill(pid, 0); return true; }
|
|
48
|
-
catch (e) { return e.code === 'EPERM'; }
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
(async () => {
|
|
52
|
-
log(`start · oldPort=${oldPort} oldPid=${oldPid}`);
|
|
53
|
-
|
|
54
|
-
const deadline = Date.now() + 30_000;
|
|
55
|
-
while (Date.now() < deadline) {
|
|
56
|
-
const free = await portFree(oldPort);
|
|
57
|
-
const dead = !pidAlive(oldPid);
|
|
58
|
-
if (free && dead) break;
|
|
59
|
-
await sleep(250);
|
|
60
|
-
}
|
|
61
|
-
log(`old server gone (or 30s elapsed) · respawning`);
|
|
62
|
-
|
|
63
|
-
const isWin = process.platform === 'win32';
|
|
64
|
-
const ccsmCmd = isWin ? 'ccsm.cmd' : 'ccsm';
|
|
65
|
-
// Inherit env but DROP CCSM_NO_BROWSER so the respawned server pops a
|
|
66
|
-
// fresh browser window — the frontend that triggered the restart
|
|
67
|
-
// called window.close() in parallel, and the new window takes its
|
|
68
|
-
// place without the OfflineBanner gap.
|
|
69
|
-
const childEnv = { ...process.env };
|
|
70
|
-
delete childEnv.CCSM_NO_BROWSER;
|
|
71
|
-
let exe, exeArgs;
|
|
72
|
-
if (isWin) {
|
|
73
|
-
exe = process.env.ComSpec || 'cmd.exe';
|
|
74
|
-
exeArgs = ['/d', '/s', '/c', ccsmCmd];
|
|
75
|
-
} else {
|
|
76
|
-
exe = ccsmCmd;
|
|
77
|
-
exeArgs = [];
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
const child = spawn(exe, exeArgs, {
|
|
81
|
-
detached: true,
|
|
82
|
-
stdio: 'ignore',
|
|
83
|
-
windowsHide: true,
|
|
84
|
-
shell: false,
|
|
85
|
-
env: childEnv,
|
|
86
|
-
});
|
|
87
|
-
child.unref();
|
|
88
|
-
log(`respawned ${ccsmCmd} (via ${path.basename(exe)})`);
|
|
89
|
-
} catch (e) {
|
|
90
|
-
log(`respawn failed: ${e.message}`);
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
})().catch((e) => {
|
|
94
|
-
log(`fatal: ${e.message}`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Restart helper · spawned detached by /api/restart.
|
|
5
|
+
//
|
|
6
|
+
// Just like upgrade-helper but skips the `npm i` step. Server kicks
|
|
7
|
+
// this off + gracefulShutdowns; helper waits for the port to free, then
|
|
8
|
+
// respawns ccsm (which finds no live backend and starts a fresh one).
|
|
9
|
+
//
|
|
10
|
+
// Argv: node restart-helper.js <port> <pid>
|
|
11
|
+
|
|
12
|
+
const fs = require('node:fs');
|
|
13
|
+
const path = require('node:path');
|
|
14
|
+
const os = require('node:os');
|
|
15
|
+
const net = require('node:net');
|
|
16
|
+
const { spawn } = require('node:child_process');
|
|
17
|
+
|
|
18
|
+
const oldPort = Number(process.argv[2] || 7777);
|
|
19
|
+
const oldPid = Number(process.argv[3] || 0);
|
|
20
|
+
|
|
21
|
+
const HOME = process.env.CCSM_HOME || path.join(os.homedir(), '.ccsm');
|
|
22
|
+
const LOG = path.join(HOME, 'restart.log');
|
|
23
|
+
try { fs.mkdirSync(HOME, { recursive: true }); } catch {}
|
|
24
|
+
|
|
25
|
+
function log(msg) {
|
|
26
|
+
const line = `[${new Date().toISOString()}] ${msg}\n`;
|
|
27
|
+
try { fs.appendFileSync(LOG, line); } catch {}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
|
|
31
|
+
|
|
32
|
+
function portFree(port, timeoutMs = 800) {
|
|
33
|
+
return new Promise((resolve) => {
|
|
34
|
+
const s = new net.Socket();
|
|
35
|
+
let settled = false;
|
|
36
|
+
const finish = (free) => { if (settled) return; settled = true; try { s.destroy(); } catch {} resolve(free); };
|
|
37
|
+
s.setTimeout(timeoutMs);
|
|
38
|
+
s.once('connect', () => finish(false));
|
|
39
|
+
s.once('timeout', () => finish(true));
|
|
40
|
+
s.once('error', () => finish(true));
|
|
41
|
+
s.connect(port, '127.0.0.1');
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function pidAlive(pid) {
|
|
46
|
+
if (!pid) return false;
|
|
47
|
+
try { process.kill(pid, 0); return true; }
|
|
48
|
+
catch (e) { return e.code === 'EPERM'; }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
(async () => {
|
|
52
|
+
log(`start · oldPort=${oldPort} oldPid=${oldPid}`);
|
|
53
|
+
|
|
54
|
+
const deadline = Date.now() + 30_000;
|
|
55
|
+
while (Date.now() < deadline) {
|
|
56
|
+
const free = await portFree(oldPort);
|
|
57
|
+
const dead = !pidAlive(oldPid);
|
|
58
|
+
if (free && dead) break;
|
|
59
|
+
await sleep(250);
|
|
60
|
+
}
|
|
61
|
+
log(`old server gone (or 30s elapsed) · respawning`);
|
|
62
|
+
|
|
63
|
+
const isWin = process.platform === 'win32';
|
|
64
|
+
const ccsmCmd = isWin ? 'ccsm.cmd' : 'ccsm';
|
|
65
|
+
// Inherit env but DROP CCSM_NO_BROWSER so the respawned server pops a
|
|
66
|
+
// fresh browser window — the frontend that triggered the restart
|
|
67
|
+
// called window.close() in parallel, and the new window takes its
|
|
68
|
+
// place without the OfflineBanner gap.
|
|
69
|
+
const childEnv = { ...process.env };
|
|
70
|
+
delete childEnv.CCSM_NO_BROWSER;
|
|
71
|
+
let exe, exeArgs;
|
|
72
|
+
if (isWin) {
|
|
73
|
+
exe = process.env.ComSpec || 'cmd.exe';
|
|
74
|
+
exeArgs = ['/d', '/s', '/c', ccsmCmd];
|
|
75
|
+
} else {
|
|
76
|
+
exe = ccsmCmd;
|
|
77
|
+
exeArgs = [];
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const child = spawn(exe, exeArgs, {
|
|
81
|
+
detached: true,
|
|
82
|
+
stdio: 'ignore',
|
|
83
|
+
windowsHide: true,
|
|
84
|
+
shell: false,
|
|
85
|
+
env: childEnv,
|
|
86
|
+
});
|
|
87
|
+
child.unref();
|
|
88
|
+
log(`respawned ${ccsmCmd} (via ${path.basename(exe)})`);
|
|
89
|
+
} catch (e) {
|
|
90
|
+
log(`respawn failed: ${e.message}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
})().catch((e) => {
|
|
94
|
+
log(`fatal: ${e.message}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
});
|