storymode-cli 1.3.2 → 1.3.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/package.json +1 -1
- package/src/cli.mjs +41 -13
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -199,12 +199,11 @@ export async function run(args) {
|
|
|
199
199
|
const reactive = !flags['no-reactive'];
|
|
200
200
|
|
|
201
201
|
// Auto-detect graphics protocol for HD rendering
|
|
202
|
-
// iTerm2 inside tmux can't clear previous inline images (
|
|
203
|
-
//
|
|
204
|
-
//
|
|
202
|
+
// iTerm2 inside tmux can't clear previous inline images (Kitty has a=d,d=a
|
|
203
|
+
// but iTerm2's \x1b[2J is intercepted by tmux). So for iTerm2 we use native
|
|
204
|
+
// splits (AppleScript) instead of tmux, keeping the companion process direct.
|
|
205
205
|
const renderMode = detectGraphicsProtocol();
|
|
206
|
-
const useHd = renderMode.protocol
|
|
207
|
-
|| (renderMode.protocol === 'iterm2' && !renderMode.inTmux);
|
|
206
|
+
const useHd = !!renderMode.protocol;
|
|
208
207
|
const paneWidth = useHd && size === 'full' ? 80 : size === 'full' ? 62 : size === 'tiny' ? 14 : 22;
|
|
209
208
|
|
|
210
209
|
// If we're already the companion pane (spawned by tmux split), play inline
|
|
@@ -241,21 +240,50 @@ export async function run(args) {
|
|
|
241
240
|
installHooks({ global: true });
|
|
242
241
|
}
|
|
243
242
|
|
|
244
|
-
//
|
|
245
|
-
if (!await ensureTmux()) process.exit(1);
|
|
246
|
-
const inTmux = !!process.env.TMUX;
|
|
243
|
+
// Build companion command flags
|
|
247
244
|
const sextantFlag = flags.sextant ? ' --sextant' : '';
|
|
248
245
|
const reactiveFlag = reactive ? ' --reactive' : '';
|
|
249
246
|
const noAiFlag = noAi ? ' --no-ai' : '';
|
|
250
247
|
const modelFlag = model ? ` --model=${model}` : '';
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
248
|
+
const companionCmd = `STORYMODE_COMPANION=1 npx --yes storymode-cli play ${id} --size=${size}${sextantFlag}${reactiveFlag}${noAiFlag}${modelFlag}`;
|
|
249
|
+
|
|
250
|
+
// iTerm2 (not in tmux): use native split to keep HD working.
|
|
251
|
+
// iTerm2 inline images can't be cleared through tmux passthrough,
|
|
252
|
+
// so we avoid tmux entirely and use AppleScript to split the pane.
|
|
253
|
+
if (renderMode.protocol === 'iterm2' && !renderMode.inTmux) {
|
|
254
|
+
try {
|
|
255
|
+
// Wrap command so errors stay visible (iTerm2 closes pane on exit)
|
|
256
|
+
const wrappedCmd = `${companionCmd} || { echo ""; echo " Companion crashed. Press enter to close."; read; }`;
|
|
257
|
+
const escapedCmd = wrappedCmd.replace(/"/g, '\\"');
|
|
258
|
+
execSync(`osascript -e '
|
|
259
|
+
tell application "iTerm2"
|
|
260
|
+
tell current session of current tab of current window
|
|
261
|
+
set newSession to split vertically with default profile command "${escapedCmd}"
|
|
262
|
+
end tell
|
|
263
|
+
end tell
|
|
264
|
+
'`, { stdio: 'ignore' });
|
|
265
|
+
process.stderr.write(` Companion opened in iTerm2 pane (${size} HD/${renderMode.protocol}).\n`);
|
|
266
|
+
process.stderr.write(' Close the pane or press q in it to stop.\n');
|
|
267
|
+
} catch (err) {
|
|
268
|
+
console.error(` iTerm2 split failed: ${err.message}`);
|
|
269
|
+
console.error(' Falling back to tmux...');
|
|
270
|
+
// Fall through to tmux path below
|
|
271
|
+
renderMode.protocol = null;
|
|
272
|
+
}
|
|
273
|
+
if (renderMode.protocol) break;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Open tmux side pane — install tmux if needed
|
|
277
|
+
if (!await ensureTmux()) process.exit(1);
|
|
278
|
+
const inTmux = !!process.env.TMUX;
|
|
279
|
+
// Enable tmux passthrough for Kitty/Ghostty graphics protocols
|
|
280
|
+
const passthroughPrefix = renderMode.protocol === 'kitty' ? 'tmux set allow-passthrough on; ' : '';
|
|
281
|
+
const tmuxCompanionCmd = `${passthroughPrefix}${companionCmd}`;
|
|
254
282
|
|
|
255
283
|
try {
|
|
256
284
|
if (inTmux) {
|
|
257
285
|
execSync(
|
|
258
|
-
`tmux split-window -h -l ${paneWidth} '${
|
|
286
|
+
`tmux split-window -h -l ${paneWidth} '${tmuxCompanionCmd}'`,
|
|
259
287
|
{ stdio: 'ignore' }
|
|
260
288
|
);
|
|
261
289
|
if (!detach) {
|
|
@@ -280,7 +308,7 @@ export async function run(args) {
|
|
|
280
308
|
process.stderr.write(' Starting tmux session with companion pane...\n');
|
|
281
309
|
execSync(
|
|
282
310
|
`tmux new-session -d -s storymode -x 100 -y 30 \\; ` +
|
|
283
|
-
`split-window -h -l ${paneWidth} '${
|
|
311
|
+
`split-window -h -l ${paneWidth} '${tmuxCompanionCmd}' \\; ` +
|
|
284
312
|
`select-pane -L`,
|
|
285
313
|
{ stdio: 'ignore' }
|
|
286
314
|
);
|