pi-studio 0.9.39 → 0.9.40
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/CHANGELOG.md +6 -0
- package/client/studio-client.js +16 -5
- package/index.ts +2 -1
- package/package.json +1 -1
- package/shared/studio-repl-tmux.js +28 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to `pi-studio` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.40] — 2026-08-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Prevented Studio-owned REPL sessions from inheriting terminal-local `PROMPT_COMMAND` hooks without their function definitions, avoiding repeated `__bp_precmd_invoke_cmd` / `__bp_interactive_mode` errors under cmux and Ghostty on macOS Bash 3.2.
|
|
11
|
+
- Show the reliable `Ctrl+Shift+Enter` shortcut on the **Send to REPL** button on macOS while continuing to accept `Cmd+Shift+Enter` where the browser or host does not reserve it.
|
|
12
|
+
|
|
7
13
|
## [0.9.39] — 2026-08-07
|
|
8
14
|
|
|
9
15
|
### Added
|
package/client/studio-client.js
CHANGED
|
@@ -1210,11 +1210,21 @@
|
|
|
1210
1210
|
|
|
1211
1211
|
function getStudioShortcutLabel(kind) {
|
|
1212
1212
|
const mac = isMacShortcutPlatform();
|
|
1213
|
-
if (kind === "repl-send") return mac ? "
|
|
1213
|
+
if (kind === "repl-send") return mac ? "⌃⇧↵" : "Ctrl+Shift+Enter";
|
|
1214
1214
|
if (kind === "run") return mac ? "⌘↵" : "Ctrl+Enter";
|
|
1215
1215
|
return "";
|
|
1216
1216
|
}
|
|
1217
1217
|
|
|
1218
|
+
function getStudioShortcutDescription(kind) {
|
|
1219
|
+
if (kind === "repl-send") {
|
|
1220
|
+
return isMacShortcutPlatform()
|
|
1221
|
+
? "Ctrl+Shift+Enter (Cmd+Shift+Enter also works where available)"
|
|
1222
|
+
: "Ctrl+Shift+Enter";
|
|
1223
|
+
}
|
|
1224
|
+
if (kind === "run") return "Cmd/Ctrl+Enter";
|
|
1225
|
+
return "";
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1218
1228
|
function withStudioShortcutLabel(label, kind) {
|
|
1219
1229
|
const shortcut = getStudioShortcutLabel(kind);
|
|
1220
1230
|
return shortcut ? (label + " " + shortcut) : label;
|
|
@@ -19188,6 +19198,7 @@
|
|
|
19188
19198
|
const canQueueSteering = studioRunChainActive && !critiqueIsStop;
|
|
19189
19199
|
const hasReplSession = Boolean(getActiveReplSessionForCurrentRuntime());
|
|
19190
19200
|
const showReplSend = rightView === "repl";
|
|
19201
|
+
const replSendShortcut = getStudioShortcutDescription("repl-send");
|
|
19191
19202
|
|
|
19192
19203
|
if (isEditorOnlyMode) {
|
|
19193
19204
|
if (sendRunBtn) {
|
|
@@ -19209,8 +19220,8 @@
|
|
|
19209
19220
|
sendReplBtn.textContent = showReplSend ? withStudioShortcutLabel(replSendMode === "literate" ? "Send selection/chunks" : "Send to REPL", "repl-send") : "Send to REPL";
|
|
19210
19221
|
sendReplBtn.title = hasReplSession
|
|
19211
19222
|
? (replSendMode === "literate"
|
|
19212
|
-
? "Literate send: selection, current fenced code chunk, or all matching chunks if the cursor is outside a chunk. Shortcut:
|
|
19213
|
-
: "Raw send: selection, or full editor if no selection. Shortcut:
|
|
19223
|
+
? "Literate send: selection, current fenced code chunk, or all matching chunks if the cursor is outside a chunk. Shortcut: " + replSendShortcut + "."
|
|
19224
|
+
: "Raw send: selection, or full editor if no selection. Shortcut: " + replSendShortcut + ".")
|
|
19214
19225
|
: "Start or select a REPL session in the right pane first.";
|
|
19215
19226
|
const replActionLine = sendReplBtn.closest(".repl-action-line");
|
|
19216
19227
|
if (replActionLine instanceof HTMLElement) replActionLine.hidden = !showReplSend;
|
|
@@ -19270,8 +19281,8 @@
|
|
|
19270
19281
|
sendReplBtn.textContent = showReplSend ? withStudioShortcutLabel(replSendMode === "literate" ? "Send selection/chunks" : "Send to REPL", "repl-send") : "Send to REPL";
|
|
19271
19282
|
sendReplBtn.title = hasReplSession
|
|
19272
19283
|
? (replSendMode === "literate"
|
|
19273
|
-
? "Literate send: selection, current fenced code chunk, or all matching chunks if the cursor is outside a chunk. Shortcut:
|
|
19274
|
-
: "Raw send: selection, or full editor if no selection. Shortcut:
|
|
19284
|
+
? "Literate send: selection, current fenced code chunk, or all matching chunks if the cursor is outside a chunk. Shortcut: " + replSendShortcut + "."
|
|
19285
|
+
: "Raw send: selection, or full editor if no selection. Shortcut: " + replSendShortcut + ".")
|
|
19275
19286
|
: "Start or select a REPL session in the right pane first.";
|
|
19276
19287
|
const replActionLine = sendReplBtn.closest(".repl-action-line");
|
|
19277
19288
|
if (replActionLine instanceof HTMLElement) replActionLine.hidden = !showReplSend;
|
package/index.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from "./shared/studio-markdown-latex-literals.js";
|
|
30
30
|
import { escapeStudioPdfLatexTextFragment } from "./shared/studio-pdf-escape.js";
|
|
31
31
|
import { resolveStudioPdfResourceFile } from "./shared/studio-pdf-resource.js";
|
|
32
|
+
import { buildStudioReplTmuxStartArgs } from "./shared/studio-repl-tmux.js";
|
|
32
33
|
import { buildStudioForwardingHint, buildStudioSshTunnelHint, isStudioSshSession as isSshSession } from "./shared/studio-ssh-hint.js";
|
|
33
34
|
import { renderStudioAnnotationInlineHtml } from "./shared/studio-annotation-render.js";
|
|
34
35
|
import {
|
|
@@ -9626,7 +9627,7 @@ function startStudioReplSession(runtime: StudioReplRuntime, cwd: string, options
|
|
|
9626
9627
|
};
|
|
9627
9628
|
}
|
|
9628
9629
|
const command = getStudioReplRuntimeCommand(runtime, commandOverride);
|
|
9629
|
-
const result = runStudioTmux(
|
|
9630
|
+
const result = runStudioTmux(buildStudioReplTmuxStartArgs(sessionName, cwd || process.cwd(), command), { timeout: 5_000 });
|
|
9630
9631
|
if (!result.ok) return { ok: false, message: result.message || `Failed to start ${STUDIO_REPL_RUNTIME_LABELS[runtime]} REPL.` };
|
|
9631
9632
|
return {
|
|
9632
9633
|
ok: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-studio",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.40",
|
|
4
4
|
"description": "Two-pane browser workspace for pi with prompt/response editing, annotations, critiques, active quiz, prompt/response history, live previews, and tmux-backed REPL/literate REPL workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const STUDIO_REPL_PROMPT_COMMAND_ENVIRONMENT = "PROMPT_COMMAND=";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build the tmux arguments for a Studio-owned REPL session.
|
|
5
|
+
*
|
|
6
|
+
* PROMPT_COMMAND contains shell-local function names on some terminals (notably
|
|
7
|
+
* cmux/Ghostty with macOS Bash 3.2). The variable may be exported to Pi while
|
|
8
|
+
* the corresponding functions cannot be inherited by a child shell, so start
|
|
9
|
+
* each detached REPL with a clean prompt-command environment.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} sessionName
|
|
12
|
+
* @param {string} cwd
|
|
13
|
+
* @param {string} command
|
|
14
|
+
* @returns {string[]}
|
|
15
|
+
*/
|
|
16
|
+
export function buildStudioReplTmuxStartArgs(sessionName, cwd, command) {
|
|
17
|
+
return [
|
|
18
|
+
"new-session",
|
|
19
|
+
"-d",
|
|
20
|
+
"-s",
|
|
21
|
+
sessionName,
|
|
22
|
+
"-c",
|
|
23
|
+
cwd,
|
|
24
|
+
"-e",
|
|
25
|
+
STUDIO_REPL_PROMPT_COMMAND_ENVIRONMENT,
|
|
26
|
+
command,
|
|
27
|
+
];
|
|
28
|
+
}
|