pi-studio 0.9.31 → 0.9.32

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 CHANGED
@@ -4,6 +4,14 @@ All notable changes to `pi-studio` are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.32] — 2026-06-10
8
+
9
+ ### Added
10
+ - Added `Cmd/Ctrl+Alt+W` to switch the right pane directly to Working, matching the existing direct Preview shortcut.
11
+
12
+ ### Fixed
13
+ - Preserved expanded Working-view detail sections while live working updates stream in.
14
+
7
15
  ## [0.9.31] — 2026-06-09
8
16
 
9
17
  ### Fixed
package/README.md CHANGED
@@ -22,7 +22,7 @@ Extension for [pi](https://pi.dev) that opens a local two-pane browser workspace
22
22
  - Supports one canonical full Studio view per Pi session, plus additional editor-only companion views when you want extra editing/preview surfaces; editor-only views can also browse files and use the Studio REPL send controls without taking over the full Studio session view
23
23
  - Includes a global **Zen** mode for hiding secondary Studio chrome without changing the current left/right pane layout
24
24
  - Runs editor text directly, asks for structured critique (auto/writing/code focus), offers a manual **Suggest completion** action for short cursor-aware continuations (`Option/Alt+Tab` where available or `Cmd/Ctrl+Shift+Space` from the editor, `Tab` to insert a visible suggestion) with an optional editor-plus-latest-response context mode, or opens **Quiz me** for a Studio-native active-recall loop over the current editor text, selection, current file, folder, or repo, with optional focus guidance for shaping question selection
25
- - Includes a live **Working** view for following current model/tool activity, with `All` / `Thinking` / `Tools` filters, image previews for image-producing tool outputs, plus **Load visible into editor** and **Copy visible** actions; when cycling response history, Working follows saved working details for the selected response when available
25
+ - Includes a live **Working** view for following current model/tool activity, with `All` / `Thinking` / `Tools` filters, image previews for image-producing tool outputs, plus **Load visible into editor** and **Copy visible** actions; when cycling response history, Working follows saved working details for the selected response when available, and `Cmd/Ctrl+Alt+W` switches the right pane directly to Working
26
26
  - Includes a right-pane **Changes** view for browsing the current git diff by file, previewing per-file diffs, opening changed files, loading the full diff into the editor, and copying the diff
27
27
  - Includes a right-pane **Files** view for browsing the current Pi session/resource directory, opening folders, opening the Files root in Finder/the system file manager, loading text/code/CSV/TSV documents into the editor, previewing PDFs/images, opening PDF/image previews in a new Studio tab, converting DOCX/ODT documents to editable Markdown when Pandoc is available after confirmation, copying paths, setting the current folder as the Studio working directory, and revealing files in the file manager
28
28
  - Includes an optional tmux-backed **REPL** view for Shell, Python, IPython, Julia, R, GHCi, and Clojure sessions, with Raw/Literate send modes, `Cmd/Ctrl+Shift+Enter` **Send to REPL**, session start/stop/interrupt controls, a compact refresh-persistent **Studio REPL Record** of user and Pi-sent code, a secondary raw tmux mirror, agent-facing `studio_repl_status` / `studio_repl_send` tools, and Markdown/PDF/HTML export
@@ -270,7 +270,7 @@
270
270
  });
271
271
  rightViewSelect.title = isEditorOnlyMode
272
272
  ? "Editor-only views: editor preview, Changes, Files, or REPL. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview."
273
- : "Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview.";
273
+ : "Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview; Cmd/Ctrl+Alt+W switches directly to Working.";
274
274
  }
275
275
 
276
276
  function getInitialRightView(source) {
@@ -302,6 +302,7 @@
302
302
  let traceAutoScroll = true;
303
303
  let traceRenderRaf = null;
304
304
  const traceExpandedOutputs = new Set();
305
+ const traceOpenDetails = new Set();
305
306
  let gitChangesState = {
306
307
  status: "idle",
307
308
  requestId: null,
@@ -683,6 +684,7 @@
683
684
  traceState = normalizeTraceState(nextState);
684
685
  if ((traceState.runId || null) !== previousRunId) {
685
686
  traceExpandedOutputs.clear();
687
+ traceOpenDetails.clear();
686
688
  }
687
689
  renderTraceViewIfActive();
688
690
  }
@@ -3804,6 +3806,17 @@
3804
3806
  setStatus("Right pane view: " + String(label || "Preview") + ".");
3805
3807
  }
3806
3808
 
3809
+ function switchRightPaneToWorking() {
3810
+ if (isEditorOnlyMode) {
3811
+ setStatus("Working view is unavailable in editor-only Studio views.", "warning");
3812
+ return;
3813
+ }
3814
+ const snapshot = snapshotStudioScrollablePositions();
3815
+ setRightView("trace");
3816
+ scheduleStudioScrollablePositionRestore(snapshot);
3817
+ setStatus("Right pane view: Working.");
3818
+ }
3819
+
3807
3820
  function cycleActivePaneView(direction) {
3808
3821
  if (activePane === "right") {
3809
3822
  if (!rightViewSelect || rightViewSelect.disabled) {
@@ -4112,6 +4125,16 @@
4112
4125
  return;
4113
4126
  }
4114
4127
 
4128
+ const isWorkingShortcut = (key.toLowerCase() === "w" || code === "KeyW")
4129
+ && (event.metaKey || event.ctrlKey)
4130
+ && event.altKey
4131
+ && !event.shiftKey;
4132
+ if (isWorkingShortcut) {
4133
+ event.preventDefault();
4134
+ switchRightPaneToWorking();
4135
+ return;
4136
+ }
4137
+
4115
4138
  const isContentFocusShortcut = key === "F8" && !event.metaKey && !event.ctrlKey && !event.altKey;
4116
4139
  if (isContentFocusShortcut) {
4117
4140
  event.preventDefault();
@@ -7757,6 +7780,20 @@
7757
7780
  }
7758
7781
  }
7759
7782
 
7783
+ function handleTraceDetailsToggle(event) {
7784
+ if (rightView !== "trace") return;
7785
+ const target = event.target;
7786
+ if (!(target instanceof Element) || !target.matches("details[data-trace-details-key]")) return;
7787
+ const key = target.getAttribute("data-trace-details-key") || "";
7788
+ if (!key) return;
7789
+ if (target.open) {
7790
+ traceOpenDetails.add(key);
7791
+ } else {
7792
+ traceOpenDetails.delete(key);
7793
+ }
7794
+ traceAutoScroll = false;
7795
+ }
7796
+
7760
7797
  async function handleTracePaneClick(event) {
7761
7798
  if (rightView !== "trace") return;
7762
7799
  const target = event.target;
@@ -7951,6 +7988,7 @@
7951
7988
  function attachResponsePaneInteractionHandlers() {
7952
7989
  if (!critiqueViewEl) return;
7953
7990
  critiqueViewEl.addEventListener("scroll", handleTracePaneScroll);
7991
+ critiqueViewEl.addEventListener("toggle", handleTraceDetailsToggle, true);
7954
7992
  critiqueViewEl.addEventListener("click", handleTracePaneClick);
7955
7993
  critiqueViewEl.addEventListener("click", handleReplPaneClick);
7956
7994
  critiqueViewEl.addEventListener("click", handleFilesPaneClick);
@@ -9189,8 +9227,9 @@
9189
9227
  const value = String(inputText || "").trim();
9190
9228
  if (!value) return "";
9191
9229
  const rawKey = outputKey + ":raw-input";
9192
- const openAttr = traceExpandedOutputs.has(rawKey) ? " open" : "";
9193
- return "<details class='trace-tool-details trace-tool-raw-input'" + openAttr + ">"
9230
+ const detailsKey = rawKey;
9231
+ const openAttr = traceOpenDetails.has(detailsKey) || traceExpandedOutputs.has(rawKey) ? " open" : "";
9232
+ return "<details class='trace-tool-details trace-tool-raw-input' data-trace-details-key='" + escapeHtml(detailsKey) + "'" + openAttr + ">"
9194
9233
  + "<summary>Raw input</summary>"
9195
9234
  + "<div class='trace-tool-details-body'>"
9196
9235
  + renderTraceOutput(value, rawKey, { label: "Raw input" })
@@ -9201,8 +9240,9 @@
9201
9240
  function renderTraceToolTextDetails(summary, text, outputKey, label, options) {
9202
9241
  const value = String(text || "");
9203
9242
  const emptyText = options && typeof options.emptyText === "string" ? options.emptyText : "[empty]";
9204
- const openAttr = traceExpandedOutputs.has(outputKey) ? " open" : "";
9205
- return "<details class='trace-tool-details" + (options && options.className ? " " + escapeHtml(options.className) : "") + "'" + openAttr + ">"
9243
+ const detailsKey = outputKey;
9244
+ const openAttr = traceOpenDetails.has(detailsKey) || traceExpandedOutputs.has(outputKey) ? " open" : "";
9245
+ return "<details class='trace-tool-details" + (options && options.className ? " " + escapeHtml(options.className) : "") + "' data-trace-details-key='" + escapeHtml(detailsKey) + "'" + openAttr + ">"
9206
9246
  + "<summary>" + escapeHtml(summary) + "</summary>"
9207
9247
  + "<div class='trace-tool-details-body'>"
9208
9248
  + renderTraceOutput(value || emptyText, outputKey, { label })
@@ -9234,8 +9274,9 @@
9234
9274
  const newMetrics = formatTraceTextMetrics(edit.newText);
9235
9275
  const oldKey = entry.id + ":edit:" + edit.index + ":old";
9236
9276
  const newKey = entry.id + ":edit:" + edit.index + ":new";
9237
- const openAttr = traceExpandedOutputs.has(oldKey) || traceExpandedOutputs.has(newKey) ? " open" : "";
9238
- return "<details class='trace-tool-details trace-tool-change'" + openAttr + ">"
9277
+ const detailsKey = entry.id + ":edit:" + edit.index;
9278
+ const openAttr = traceOpenDetails.has(detailsKey) || traceExpandedOutputs.has(oldKey) || traceExpandedOutputs.has(newKey) ? " open" : "";
9279
+ return "<details class='trace-tool-details trace-tool-change' data-trace-details-key='" + escapeHtml(detailsKey) + "'" + openAttr + ">"
9239
9280
  + "<summary>Replacement " + escapeHtml(String(displayIndex + 1)) + " · " + escapeHtml(oldMetrics) + " → " + escapeHtml(newMetrics) + "</summary>"
9240
9281
  + "<div class='trace-tool-change-body'>"
9241
9282
  + "<div class='trace-tool-change-grid'>"
package/index.ts CHANGED
@@ -10514,7 +10514,7 @@ ${cssVarsBlock}
10514
10514
  <section id="rightPane">
10515
10515
  <div id="rightSectionHeader" class="section-header">
10516
10516
  <div class="section-header-main">
10517
- <select id="rightViewSelect" aria-label="Response view mode" title="Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview.">
10517
+ <select id="rightViewSelect" aria-label="Response view mode" title="Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview; Cmd/Ctrl+Alt+W switches directly to Working.">
10518
10518
  <option value="markdown">Response (Raw)</option>
10519
10519
  <option value="preview" selected>Response (Preview)</option>
10520
10520
  <option value="editor-preview">Editor (Preview)</option>
@@ -10609,6 +10609,7 @@ ${cssVarsBlock}
10609
10609
  <div><dt>F6</dt><dd>Switch between editor and right pane</dd></div>
10610
10610
  <div><dt>F7 / Shift+F7</dt><dd>Cycle the active pane's view</dd></div>
10611
10611
  <div><dt>Cmd/Ctrl+Alt+P</dt><dd>Switch the right pane directly to Preview</dd></div>
10612
+ <div><dt>Cmd/Ctrl+Alt+W</dt><dd>Switch the right pane directly to Working</dd></div>
10612
10613
  <div><dt>F8</dt><dd>Focus editor text</dd></div>
10613
10614
  <div><dt>Shift+F8</dt><dd>Focus right-pane content</dd></div>
10614
10615
  <div><dt>F9</dt><dd>Toggle Zen mode</dd></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-studio",
3
- "version": "0.9.31",
3
+ "version": "0.9.32",
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",