@bakapiano/ccsm 0.21.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/codexSeed.js +14 -7
- package/lib/webTerminal.js +7 -1
- package/package.json +1 -1
- package/public/js/components/TerminalView.js +24 -0
- package/server.js +19 -2
package/lib/codexSeed.js
CHANGED
|
@@ -52,16 +52,23 @@ function execWithTimeout(exe, args, { timeoutMs = 8000 } = {}) {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
// the
|
|
59
|
-
//
|
|
60
|
-
//
|
|
55
|
+
// Pull CODEX_HOME out of a wrapper's `doctor` (or `--version`) output. Two
|
|
56
|
+
// shapes appear, and we must handle BOTH:
|
|
57
|
+
// 1. Diagnostic table: `CODEX_HOME <path> (dir)` — only when `doctor`
|
|
58
|
+
// fully succeeds. Variable whitespace; the `(dir)`/`(file)` suffix marks
|
|
59
|
+
// the path end.
|
|
60
|
+
// 2. Wrapper banner: `CODEX_HOME=<path>` — printed on EVERY invocation.
|
|
61
|
+
// Critical because in ccsm's non-interactive spawn `doctor` often exits
|
|
62
|
+
// non-zero (skipping the table) yet still prints this banner line, so it's
|
|
63
|
+
// the reliable source. Without it the probe returns null and the seed
|
|
64
|
+
// lands in ~/.codex instead of the wrapper's relocated home, breaking
|
|
65
|
+
// `resume <id>` ("No saved session found with ID …").
|
|
66
|
+
// Some wrappers colour the label (`\x1b[7mCODEX_HOME\x1b[0m`); strip ANSI first.
|
|
61
67
|
function parseCodexHomeFromDoctor(text) {
|
|
62
68
|
if (!text) return null;
|
|
63
69
|
const clean = String(text).replace(/\x1b\[[0-9;]*m/g, '');
|
|
64
|
-
|
|
70
|
+
let m = clean.match(/\bCODEX_HOME\s+(.+?)\s*\((?:dir|file)\)/); // table form
|
|
71
|
+
if (!m) m = clean.match(/\bCODEX_HOME=(.+?)\s*$/m); // banner form
|
|
65
72
|
if (!m) return null;
|
|
66
73
|
const p = m[1].trim();
|
|
67
74
|
return p || null;
|
package/lib/webTerminal.js
CHANGED
|
@@ -54,7 +54,13 @@ function spawn({ command, args = [], cwd, env, cols = 120, rows = 30, meta = {},
|
|
|
54
54
|
name: 'xterm-256color',
|
|
55
55
|
cols, rows,
|
|
56
56
|
cwd: cwd ? path.resolve(cwd) : process.cwd(),
|
|
57
|
-
|
|
57
|
+
// Advertise 24-bit colour. xterm.js renders truecolor, and CLIs like
|
|
58
|
+
// claude paint their diffs with 24-bit DARK red/green backgrounds +
|
|
59
|
+
// white text when COLORTERM says so. Without it they downgrade to the
|
|
60
|
+
// bright ANSI-16 red/green backgrounds, which wash the white foreground
|
|
61
|
+
// out (the "white text gets buried" report). VSCode sets the same on its
|
|
62
|
+
// terminal PTYs; our ANSI-16 palette already matches VSCode's verbatim.
|
|
63
|
+
env: { ...process.env, ...(env || {}), COLORTERM: 'truecolor' },
|
|
58
64
|
};
|
|
59
65
|
if (process.platform === 'win32') {
|
|
60
66
|
ptyOpts.useConpty = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bakapiano/ccsm",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"description": "Claude Code Session Manager — Windows web UI to manage many concurrent claude sessions: live list, snapshot/restore, focus existing window, new session in an isolated workspace with repo clones",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "server.js",
|
|
@@ -183,6 +183,30 @@ export function TerminalView({ terminalId, cliType }) {
|
|
|
183
183
|
|
|
184
184
|
const host = hostRef.current;
|
|
185
185
|
term.open(host);
|
|
186
|
+
|
|
187
|
+
// Answer OSC 10/11 (default foreground / background colour) queries with
|
|
188
|
+
// the LIVE theme colours. CLIs like claude probe the terminal background
|
|
189
|
+
// (`OSC 11 ; ? ST`) to pick a light- or dark-tuned syntax theme. xterm.js
|
|
190
|
+
// doesn't answer these by default, so claude assumes a dark terminal and
|
|
191
|
+
// paints near-white tokens (comments, f-string interpolations, call
|
|
192
|
+
// names) that vanish on our light background — the "字体颜色和背景重复"
|
|
193
|
+
// bug. VSCode answers them; we match. Reply format is the xterm/X11
|
|
194
|
+
// `rgb:RRRR/GGGG/BBBB` (16-bit-per-channel) the query expects.
|
|
195
|
+
const answerColorOsc = (code, getHex) => (data) => {
|
|
196
|
+
if (data !== '?') return false; // only the query form
|
|
197
|
+
const hex = getHex(); // '#rrggbb'
|
|
198
|
+
const ch = (i) => parseInt(hex.slice(i, i + 2), 16);
|
|
199
|
+
const w = (v) => (v * 257).toString(16).padStart(4, '0'); // 8-bit → 16-bit
|
|
200
|
+
const reply = `\x1b]${code};rgb:${w(ch(1))}/${w(ch(3))}/${w(ch(5))}\x07`;
|
|
201
|
+
const ws = wsRef.current;
|
|
202
|
+
if (ws && ws.readyState === 1) ws.send(JSON.stringify({ type: 'input', data: reply }));
|
|
203
|
+
return true;
|
|
204
|
+
};
|
|
205
|
+
try {
|
|
206
|
+
term.parser.registerOscHandler(11, answerColorOsc(11, () => themeRef.current.background));
|
|
207
|
+
term.parser.registerOscHandler(10, answerColorOsc(10, () => themeRef.current.foreground));
|
|
208
|
+
} catch {}
|
|
209
|
+
|
|
186
210
|
// Robust fit scheduler. A single requestAnimationFrame works most
|
|
187
211
|
// of the time but races on tab/session switches: the .tab-panel
|
|
188
212
|
// just flipped from display:none to display:flex and although the
|
package/server.js
CHANGED
|
@@ -291,15 +291,32 @@ function spawnCliSession({ cli, cwd, sessionId, meta, extraArgs = [] }) {
|
|
|
291
291
|
// extraArgs into the single quoted command string — otherwise extraArgs
|
|
292
292
|
// would become args to the shell itself, not the wrapped command.
|
|
293
293
|
// Re-resolve here when extraArgs is present so the quoting is correct.
|
|
294
|
+
// Force a session-scoped theme=auto for claude so its syntax/diff colours
|
|
295
|
+
// follow the ccsm terminal background (which we report via OSC 10/11 in
|
|
296
|
+
// TerminalView). claude's DEFAULT theme is *dark*, whose near-white tokens
|
|
297
|
+
// (comments, f-string interpolations, call names) vanish on our light
|
|
298
|
+
// terminal — the "字体颜色和背景重复" bug. --settings is session-scoped, so
|
|
299
|
+
// the user's global ~/.claude/settings.json is left untouched, and ccsm
|
|
300
|
+
// sessions Just Work on a fresh machine without anyone running /theme auto.
|
|
301
|
+
// (Injected here as an integration arg, like --session-id — not via the
|
|
302
|
+
// user-editable cli.args, so it reaches existing configs too.)
|
|
303
|
+
// Skip the injection entirely if the user already put their own --settings
|
|
304
|
+
// in cli.args — claude deep-merges multiple --settings (verified: later ones
|
|
305
|
+
// win per-key), so ours would silently override a theme they set on purpose.
|
|
306
|
+
// Respect the user's explicit choice instead.
|
|
307
|
+
const userHasSettings = (cli.args || []).some(
|
|
308
|
+
(a) => a === '--settings' || String(a).startsWith('--settings='));
|
|
309
|
+
const baseArgs = [...(cli.args || [])];
|
|
310
|
+
if (cli.type === 'claude' && !userHasSettings) baseArgs.push('--settings', '{"theme":"auto"}');
|
|
294
311
|
const resolved = resolveCommand(
|
|
295
312
|
cli.command,
|
|
296
|
-
[...
|
|
313
|
+
[...baseArgs, ...extraArgs],
|
|
297
314
|
cli.shell || 'direct',
|
|
298
315
|
);
|
|
299
316
|
const { exe, prefixArgs, fallbackExe, consumesUserArgs } = resolved;
|
|
300
317
|
const args = consumesUserArgs
|
|
301
318
|
? prefixArgs
|
|
302
|
-
: [...prefixArgs, ...
|
|
319
|
+
: [...prefixArgs, ...baseArgs, ...extraArgs];
|
|
303
320
|
// Merge user-scope PATH from registry into the env we hand the PTY.
|
|
304
321
|
// spawnEnv() also strips duplicate path-case keys so our override
|
|
305
322
|
// doesn't get shadowed by the inherited `Path` from process.env.
|