pi-studio 0.5.52 → 0.5.54

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,27 @@ All notable changes to `pi-studio` are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.5.54] — 2026-04-13
8
+
9
+ ### Fixed
10
+ - Markdown editor-preview comment mapping now keeps standalone markdown image blocks aligned with rendered preview figures, preventing later preview comment targets from drifting after figures.
11
+ - Rendered Markdown fenced code blocks now once again support preview-side text-selection comments.
12
+
13
+ ## [0.5.53] — 2026-04-10
14
+
15
+ ### Added
16
+ - Studio now includes a live right-pane **Working** view for following current model/tool activity as it streams.
17
+ - **Working** includes `All` / `Thinking` / `Tools` filters plus **Load visible into editor** and **Copy visible** actions.
18
+ - Markdown preview/PDF regression coverage now includes preservation of literal LaTeX prose commands such as `\cite{...}` and `\ref{...}`.
19
+
20
+ ### Changed
21
+ - The former standalone right-pane **Thinking** mode has been folded into **Working**.
22
+ - Working status/summary chips are quieter and read more like status labels than action buttons.
23
+
24
+ ### Fixed
25
+ - Markdown preview and PDF export now preserve literal LaTeX prose commands like `\cite{...}` and `\ref{...}` instead of silently dropping them outside math/code contexts.
26
+ - Working-pane interaction handlers now survive response-pane replacement, so filters/actions keep working and scrolling up can pause live auto-follow until you return near the bottom.
27
+
7
28
  ## [0.5.52] — 2026-04-09
8
29
 
9
30
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pi-studio
2
2
 
3
- Extension for [pi](https://pi.dev) that opens a local two-pane browser workspace for working with prompts, responses, Markdown and LaTeX documents, code files, and other common text-based files side by side. Annotate responses and files, add local comments, write, edit, and run prompts, browse prompt and response history, request critiques, and use live preview for code, Markdown, and LaTeX.
3
+ Extension for [pi](https://pi.dev) that opens a local two-pane browser workspace for working with prompts, responses, live working details, Markdown and LaTeX documents, code files, and other common text-based files side by side. Annotate responses and files, add local comments, write, edit, and run prompts, browse prompt and response history, request critiques, and use live preview for code, Markdown, and LaTeX.
4
4
 
5
5
  ## Screenshots
6
6
 
@@ -14,16 +14,16 @@ Extension for [pi](https://pi.dev) that opens a local two-pane browser workspace
14
14
 
15
15
  ## What it does
16
16
 
17
- - Opens a two-pane browser workspace: **Editor** (left) + **Response/Thinking/Editor Preview** (right)
17
+ - Opens a two-pane browser workspace: **Editor** (left) + **Response/Working/Editor Preview** (right)
18
18
  - Supports one canonical full Studio view per Pi session, plus additional editor-only companion views when you just want extra editing/preview surfaces
19
19
  - Runs editor text directly, or asks for structured critique (auto/writing/code focus)
20
+ - Includes a live **Working** view for following current model/tool activity, with `All` / `Thinking` / `Tools` filters plus **Load visible into editor** and **Copy visible** actions
20
21
  - Includes a local persistent scratchpad for quick notes you want to keep out of the main editor until you're ready to copy or insert them
21
22
  - Includes a docked **Outline** rail for navigating document structure in the current editor text, with clickable entries that jump in the raw editor and reveal matching preview locations when available
22
23
  - Includes local comments anchored to selections/lines, shown in a docked **Comments** rail, with transient **Comment** / **Jump** actions from raw-editor selections plus editor-preview selections for Markdown, LaTeX, and code/text/diff previews, alongside optional inline `[an: ...]` toggles when you want comments reflected in the document text
23
24
  - Browses response history (`Prev/Next/Last`) and loads either:
24
25
  - response text
25
26
  - critique notes/full critique
26
- - assistant thinking (when available)
27
27
  - the prompt that generated a selected response
28
28
  - Supports an annotation workflow for `[an: ...]` markers:
29
29
  - inserts/removes the annotated-reply header
@@ -187,7 +187,9 @@
187
187
 
188
188
  if (index >= text.length || text[index] !== "]" || text[index + 1] !== "(") return null;
189
189
 
190
+ const label = text.slice(startIndex + 1, index);
190
191
  index += 2;
192
+ const destinationStart = index;
191
193
  let parenDepth = 0;
192
194
  while (index < text.length) {
193
195
  const ch = text[index];
@@ -210,6 +212,8 @@
210
212
  type: "literal",
211
213
  raw: text.slice(startIndex, index + 1),
212
214
  end: index + 1,
215
+ label: label,
216
+ destination: text.slice(destinationStart, index),
213
217
  };
214
218
  }
215
219
  parenDepth -= 1;
@@ -223,6 +227,68 @@
223
227
  return null;
224
228
  }
225
229
 
230
+ function readMarkdownAttributeBlockAt(source, startIndex) {
231
+ const text = String(source || "");
232
+ if (text[startIndex] !== "{") return null;
233
+
234
+ let depth = 0;
235
+ for (let index = startIndex; index < text.length; index += 1) {
236
+ const ch = text[index];
237
+ if (ch === "\\") {
238
+ index += 1;
239
+ continue;
240
+ }
241
+ if (ch === "\n") return null;
242
+ if (ch === "{") {
243
+ depth += 1;
244
+ continue;
245
+ }
246
+ if (ch === "}") {
247
+ depth -= 1;
248
+ if (depth === 0) {
249
+ return {
250
+ raw: text.slice(startIndex, index + 1),
251
+ end: index + 1,
252
+ };
253
+ }
254
+ }
255
+ }
256
+
257
+ return null;
258
+ }
259
+
260
+ function extractStandaloneMarkdownImageCaptionText(text) {
261
+ const source = String(text || "").replace(/\r\n/g, "\n").trim();
262
+ if (!source) return null;
263
+
264
+ const captions = [];
265
+ let index = 0;
266
+ let sawImage = false;
267
+
268
+ while (index < source.length) {
269
+ while (index < source.length && /\s/.test(source[index])) index += 1;
270
+ if (index >= source.length) break;
271
+ if (source[index] !== "!") return null;
272
+
273
+ const imageToken = readInlineMarkdownLinkAt(source, index + 1);
274
+ if (!imageToken) return null;
275
+
276
+ sawImage = true;
277
+ captions.push(normalizePreviewAnnotationLabel(imageToken.label || ""));
278
+ index = imageToken.end;
279
+
280
+ while (index < source.length && /\s/.test(source[index])) index += 1;
281
+ if (index < source.length && source[index] === "{") {
282
+ const attributeBlock = readMarkdownAttributeBlockAt(source, index);
283
+ if (!attributeBlock) return null;
284
+ index = attributeBlock.end;
285
+ }
286
+ }
287
+
288
+ if (!sawImage) return null;
289
+ return captions.filter(Boolean).join(" ").trim();
290
+ }
291
+
226
292
  function readDelimitedPreviewTokenAt(source, startIndex, open, close, allowNewlines) {
227
293
  const text = String(source || "");
228
294
  if (text.slice(startIndex, startIndex + open.length) !== open) return null;
@@ -596,6 +662,7 @@
596
662
  collectInlineAnnotationMarkers: collectInlineAnnotationMarkers,
597
663
  hasAnnotationMarkers: hasAnnotationMarkers,
598
664
  normalizePreviewAnnotationLabel: normalizePreviewAnnotationLabel,
665
+ extractStandaloneMarkdownImageCaptionText: extractStandaloneMarkdownImageCaptionText,
599
666
  prepareMarkdownForPandocPreview: prepareMarkdownForPandocPreview,
600
667
  readInlineAnnotationMarkerAt: readInlineAnnotationMarkerAt,
601
668
  renderPreviewAnnotationHtml: renderPreviewAnnotationHtml,