pi-studio 0.9.18 → 0.9.20
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 +17 -0
- package/README.md +2 -2
- package/client/studio-client.js +662 -100
- package/client/studio.css +49 -4
- package/index.ts +88 -14
- package/package.json +1 -1
package/client/studio.css
CHANGED
|
@@ -392,7 +392,6 @@
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
body[data-studio-mode="editor-only"] #editorViewSelect,
|
|
395
|
-
body[data-studio-mode="editor-only"] #rightViewSelect,
|
|
396
395
|
body[data-studio-mode="editor-only"] #sendRunBtn,
|
|
397
396
|
body[data-studio-mode="editor-only"] #queueSteerBtn,
|
|
398
397
|
body[data-studio-mode="editor-only"] #sendEditorBtn,
|
|
@@ -424,7 +423,7 @@
|
|
|
424
423
|
}
|
|
425
424
|
|
|
426
425
|
body[data-studio-mode="editor-only"] #rightSectionHeader .section-header-main::before {
|
|
427
|
-
content: "
|
|
426
|
+
content: "View";
|
|
428
427
|
font-weight: 600;
|
|
429
428
|
font-size: 14px;
|
|
430
429
|
}
|
|
@@ -2506,6 +2505,35 @@
|
|
|
2506
2505
|
white-space: nowrap;
|
|
2507
2506
|
}
|
|
2508
2507
|
|
|
2508
|
+
.rendered-markdown .studio-html-artifact-comment-btn {
|
|
2509
|
+
flex: 0 0 auto;
|
|
2510
|
+
min-height: 24px;
|
|
2511
|
+
padding: 0 9px;
|
|
2512
|
+
border: 1px solid var(--control-border);
|
|
2513
|
+
border-radius: 999px;
|
|
2514
|
+
background: var(--panel);
|
|
2515
|
+
color: var(--text);
|
|
2516
|
+
font: inherit;
|
|
2517
|
+
font-size: 11px;
|
|
2518
|
+
line-height: 1;
|
|
2519
|
+
cursor: pointer;
|
|
2520
|
+
white-space: nowrap;
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
.rendered-markdown .studio-html-artifact-comment-btn:not(:disabled):hover,
|
|
2524
|
+
.rendered-markdown .studio-html-artifact-comment-btn:focus-visible {
|
|
2525
|
+
background: var(--control-hover-bg, var(--inline-code-bg));
|
|
2526
|
+
border-color: var(--control-border-hover, var(--accent));
|
|
2527
|
+
outline: none;
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
.rendered-markdown .studio-html-artifact-comment-btn.is-active,
|
|
2531
|
+
.rendered-markdown .studio-html-artifact-shell.is-comment-mode .studio-html-artifact-comment-btn.is-active {
|
|
2532
|
+
background: var(--accent-soft);
|
|
2533
|
+
border-color: var(--accent);
|
|
2534
|
+
color: var(--accent);
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2509
2537
|
.rendered-markdown .studio-html-artifact-zoom-controls {
|
|
2510
2538
|
flex: 0 0 auto;
|
|
2511
2539
|
display: inline-flex;
|
|
@@ -3153,7 +3181,7 @@
|
|
|
3153
3181
|
.trace-card {
|
|
3154
3182
|
display: flex;
|
|
3155
3183
|
flex-direction: column;
|
|
3156
|
-
gap:
|
|
3184
|
+
gap: 10px;
|
|
3157
3185
|
padding: 10px 12px;
|
|
3158
3186
|
border: 1px solid var(--panel-border);
|
|
3159
3187
|
border-radius: 10px;
|
|
@@ -3179,10 +3207,23 @@
|
|
|
3179
3207
|
.trace-section {
|
|
3180
3208
|
display: flex;
|
|
3181
3209
|
flex-direction: column;
|
|
3182
|
-
gap:
|
|
3210
|
+
gap: 6px;
|
|
3211
|
+
padding: 8px;
|
|
3212
|
+
border: 1px solid var(--border-subtle);
|
|
3213
|
+
border-radius: 10px;
|
|
3214
|
+
background: var(--panel);
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
.trace-section + .trace-section {
|
|
3218
|
+
margin-top: 2px;
|
|
3183
3219
|
}
|
|
3184
3220
|
|
|
3185
3221
|
.trace-section-label {
|
|
3222
|
+
align-self: flex-start;
|
|
3223
|
+
padding: 2px 7px;
|
|
3224
|
+
border: 1px solid var(--border-subtle);
|
|
3225
|
+
border-radius: 999px;
|
|
3226
|
+
background: var(--panel-2);
|
|
3186
3227
|
font-size: 11px;
|
|
3187
3228
|
font-weight: 600;
|
|
3188
3229
|
color: var(--muted);
|
|
@@ -4023,6 +4064,10 @@
|
|
|
4023
4064
|
line-height: 1.35;
|
|
4024
4065
|
}
|
|
4025
4066
|
|
|
4067
|
+
body[data-studio-mode="editor-only"] .shortcuts-full-only {
|
|
4068
|
+
display: none !important;
|
|
4069
|
+
}
|
|
4070
|
+
|
|
4026
4071
|
.scratchpad-textarea {
|
|
4027
4072
|
width: 100%;
|
|
4028
4073
|
min-height: 280px;
|
package/index.ts
CHANGED
|
@@ -209,6 +209,8 @@ interface InitialStudioDocument {
|
|
|
209
209
|
resourceDir?: string;
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
type PersistedStudioReviewNoteAnchorKind = "source" | "html-selection" | "html-element" | "html-page";
|
|
213
|
+
|
|
212
214
|
interface PersistedStudioReviewNote {
|
|
213
215
|
id: string;
|
|
214
216
|
text: string;
|
|
@@ -220,6 +222,11 @@ interface PersistedStudioReviewNote {
|
|
|
220
222
|
lineEnd: number;
|
|
221
223
|
selectedText: string;
|
|
222
224
|
selectedDisplayText?: string;
|
|
225
|
+
anchorKind?: PersistedStudioReviewNoteAnchorKind;
|
|
226
|
+
htmlSelector?: string;
|
|
227
|
+
htmlTag?: string;
|
|
228
|
+
htmlLabel?: string;
|
|
229
|
+
htmlPreviewTitle?: string;
|
|
223
230
|
}
|
|
224
231
|
|
|
225
232
|
interface StudioPersistentState {
|
|
@@ -257,6 +264,7 @@ interface StudioTraceToolEntry {
|
|
|
257
264
|
toolName: string;
|
|
258
265
|
label: string | null;
|
|
259
266
|
argsSummary: string | null;
|
|
267
|
+
args: string | null;
|
|
260
268
|
output: string;
|
|
261
269
|
images: StudioTraceImage[];
|
|
262
270
|
startedAt: number;
|
|
@@ -429,6 +437,7 @@ interface SaveOverRequestMessage {
|
|
|
429
437
|
interface RefreshFromDiskRequestMessage {
|
|
430
438
|
type: "refresh_from_disk_request";
|
|
431
439
|
requestId: string;
|
|
440
|
+
path?: string;
|
|
432
441
|
}
|
|
433
442
|
|
|
434
443
|
interface SendToEditorRequestMessage {
|
|
@@ -517,6 +526,7 @@ const MAX_PREPARED_PDF_EXPORTS = 8;
|
|
|
517
526
|
const MAX_PREPARED_HTML_EXPORTS = 8;
|
|
518
527
|
const STUDIO_TRACE_SNAPSHOT_MAX_ENTRIES = 80;
|
|
519
528
|
const STUDIO_TRACE_SNAPSHOT_MAX_FIELD_CHARS = 20_000;
|
|
529
|
+
const STUDIO_TRACE_TOOL_ARGS_MAX_CHARS = 20_000;
|
|
520
530
|
const STUDIO_TRACE_IMAGE_MAX_COUNT = 8;
|
|
521
531
|
const STUDIO_TRACE_IMAGE_MAX_BASE64_CHARS = 2_500_000;
|
|
522
532
|
const STUDIO_TRACE_SNAPSHOT_MAX_IMAGES = 12;
|
|
@@ -722,6 +732,10 @@ function createEmptyStudioPersistentState(): StudioPersistentState {
|
|
|
722
732
|
};
|
|
723
733
|
}
|
|
724
734
|
|
|
735
|
+
function normalizePersistedStudioReviewNoteAnchorKind(value: unknown): PersistedStudioReviewNoteAnchorKind {
|
|
736
|
+
return value === "html-selection" || value === "html-element" || value === "html-page" ? value : "source";
|
|
737
|
+
}
|
|
738
|
+
|
|
725
739
|
function normalizePersistedStudioReviewNote(value: unknown): PersistedStudioReviewNote | null {
|
|
726
740
|
if (!value || typeof value !== "object") return null;
|
|
727
741
|
const candidate = value as Partial<PersistedStudioReviewNote>;
|
|
@@ -756,6 +770,11 @@ function normalizePersistedStudioReviewNote(value: unknown): PersistedStudioRevi
|
|
|
756
770
|
lineEnd,
|
|
757
771
|
selectedText: typeof candidate.selectedText === "string" ? candidate.selectedText : "",
|
|
758
772
|
selectedDisplayText: typeof candidate.selectedDisplayText === "string" ? candidate.selectedDisplayText : "",
|
|
773
|
+
anchorKind: normalizePersistedStudioReviewNoteAnchorKind(candidate.anchorKind),
|
|
774
|
+
htmlSelector: typeof candidate.htmlSelector === "string" ? candidate.htmlSelector : "",
|
|
775
|
+
htmlTag: typeof candidate.htmlTag === "string" ? candidate.htmlTag : "",
|
|
776
|
+
htmlLabel: typeof candidate.htmlLabel === "string" ? candidate.htmlLabel : "",
|
|
777
|
+
htmlPreviewTitle: typeof candidate.htmlPreviewTitle === "string" ? candidate.htmlPreviewTitle : "",
|
|
759
778
|
};
|
|
760
779
|
}
|
|
761
780
|
|
|
@@ -8140,10 +8159,15 @@ function parseIncomingMessage(data: RawData): IncomingStudioMessage | null {
|
|
|
8140
8159
|
};
|
|
8141
8160
|
}
|
|
8142
8161
|
|
|
8143
|
-
if (
|
|
8162
|
+
if (
|
|
8163
|
+
msg.type === "refresh_from_disk_request"
|
|
8164
|
+
&& typeof msg.requestId === "string"
|
|
8165
|
+
&& (msg.path === undefined || typeof msg.path === "string")
|
|
8166
|
+
) {
|
|
8144
8167
|
return {
|
|
8145
8168
|
type: "refresh_from_disk_request",
|
|
8146
8169
|
requestId: msg.requestId,
|
|
8170
|
+
path: typeof msg.path === "string" ? msg.path : undefined,
|
|
8147
8171
|
};
|
|
8148
8172
|
}
|
|
8149
8173
|
|
|
@@ -8567,15 +8591,17 @@ function createStudioTraceSnapshot(source: StudioTraceState): { traceState: Stud
|
|
|
8567
8591
|
};
|
|
8568
8592
|
}
|
|
8569
8593
|
const argsSummary = truncateStudioTraceSnapshotText(entry.argsSummary ?? "");
|
|
8594
|
+
const args = truncateStudioTraceSnapshotText(entry.args ?? entry.argsSummary ?? "");
|
|
8570
8595
|
const output = truncateStudioTraceSnapshotText(entry.output);
|
|
8571
8596
|
const snapshotImages = copyStudioTraceImagesForSnapshot(entry.images, imageBudget);
|
|
8572
|
-
truncated = truncated || argsSummary.truncated || output.truncated || snapshotImages.omitted > 0;
|
|
8597
|
+
truncated = truncated || argsSummary.truncated || args.truncated || output.truncated || snapshotImages.omitted > 0;
|
|
8573
8598
|
const omittedImageNote = snapshotImages.omitted > 0
|
|
8574
8599
|
? `[${snapshotImages.omitted} image preview${snapshotImages.omitted === 1 ? "" : "s"} omitted from saved Working view to keep history bounded.]`
|
|
8575
8600
|
: "";
|
|
8576
8601
|
return {
|
|
8577
8602
|
...entry,
|
|
8578
8603
|
argsSummary: argsSummary.text || null,
|
|
8604
|
+
args: args.text || null,
|
|
8579
8605
|
output: [output.text, omittedImageNote].filter(Boolean).join("\n"),
|
|
8580
8606
|
images: snapshotImages.images,
|
|
8581
8607
|
};
|
|
@@ -8786,6 +8812,34 @@ function summarizeStudioTraceToolArgs(toolName: string, args: unknown): string |
|
|
|
8786
8812
|
}
|
|
8787
8813
|
}
|
|
8788
8814
|
|
|
8815
|
+
function truncateStudioTraceToolArgs(text: string): string {
|
|
8816
|
+
const value = sanitizeStudioTraceOutputText(String(text || "").trim());
|
|
8817
|
+
if (!value || value.length <= STUDIO_TRACE_TOOL_ARGS_MAX_CHARS) return value;
|
|
8818
|
+
const keepHead = Math.max(1_000, Math.floor(STUDIO_TRACE_TOOL_ARGS_MAX_CHARS * 0.65));
|
|
8819
|
+
const keepTail = Math.max(1_000, STUDIO_TRACE_TOOL_ARGS_MAX_CHARS - keepHead - 160);
|
|
8820
|
+
const omitted = value.length - keepHead - keepTail;
|
|
8821
|
+
return `${value.slice(0, keepHead)}\n\n… ${omitted} chars omitted from tool input …\n\n${value.slice(value.length - keepTail)}`;
|
|
8822
|
+
}
|
|
8823
|
+
|
|
8824
|
+
function formatStudioTraceToolArgs(toolName: string, args: unknown): string | null {
|
|
8825
|
+
const normalizedTool = String(toolName || "").trim().toLowerCase();
|
|
8826
|
+
const payload = (args && typeof args === "object") ? (args as Record<string, unknown>) : {};
|
|
8827
|
+
let raw = "";
|
|
8828
|
+
if (normalizedTool === "bash" && typeof payload.command === "string") {
|
|
8829
|
+
raw = payload.command;
|
|
8830
|
+
} else if ((normalizedTool === "repl_send" || normalizedTool === "studio_repl_send") && typeof payload.code === "string") {
|
|
8831
|
+
raw = payload.code;
|
|
8832
|
+
} else {
|
|
8833
|
+
try {
|
|
8834
|
+
raw = JSON.stringify(args, null, 2);
|
|
8835
|
+
} catch {
|
|
8836
|
+
raw = String(args ?? "");
|
|
8837
|
+
}
|
|
8838
|
+
}
|
|
8839
|
+
const truncated = truncateStudioTraceToolArgs(raw);
|
|
8840
|
+
return truncated ? truncated : null;
|
|
8841
|
+
}
|
|
8842
|
+
|
|
8789
8843
|
function isStudioReplRuntime(value: unknown): value is StudioReplRuntime {
|
|
8790
8844
|
return value === "shell"
|
|
8791
8845
|
|| value === "python"
|
|
@@ -9827,7 +9881,7 @@ ${cssVarsBlock}
|
|
|
9827
9881
|
<button id="saveOverBtn" type="button" title="Overwrite current file with editor content. Shortcut: Cmd/Ctrl+S.">Save editor</button>
|
|
9828
9882
|
<button id="refreshFromDiskBtn" type="button" title="Reload the current file-backed document from disk.">Refresh from disk</button>
|
|
9829
9883
|
<button id="clearWorkspaceBtn" type="button" title="Clear editor text and reset this tab to a fresh blank draft. Saved files and responses are not changed.">Reset editor</button>
|
|
9830
|
-
<label class="file-label" title="
|
|
9884
|
+
<label class="file-label" title="Import a browser-selected text file into the editor as an unsaved copy. It will not be refreshable from disk until you save it.">Import file copy…<input id="fileInput" type="file" accept=".md,.markdown,.mdx,.qmd,.js,.mjs,.cjs,.jsx,.ts,.mts,.cts,.tsx,.py,.pyw,.sh,.bash,.zsh,.json,.jsonc,.json5,.rs,.c,.h,.cpp,.cxx,.cc,.hpp,.hxx,.jl,.f90,.f95,.f03,.f,.for,.r,.R,.m,.tex,.latex,.diff,.patch,.java,.go,.rb,.swift,.html,.htm,.css,.xml,.yaml,.yml,.toml,.lua,.txt,.rst,.adoc" /></label>
|
|
9831
9885
|
<button id="loadGitDiffBtn" type="button" title="Load the current git diff from the Studio context into the editor.">Load git diff</button>
|
|
9832
9886
|
<button id="getEditorBtn" type="button" title="Load the current terminal editor draft into Studio.">Load from pi editor</button>
|
|
9833
9887
|
<button id="zenModeBtn" class="zen-mode-btn" type="button" title="Hide secondary Studio controls. Shortcut: F9.">Zen</button>
|
|
@@ -10004,14 +10058,14 @@ ${cssVarsBlock}
|
|
|
10004
10058
|
<div class="scratchpad-header">
|
|
10005
10059
|
<div>
|
|
10006
10060
|
<h2 id="reviewNotesTitle">Comments</h2>
|
|
10007
|
-
<p class="scratchpad-description">Local comments for editor text.
|
|
10061
|
+
<p class="scratchpad-description">Local comments for editor text and editor previews. They stay out of the text; source-anchored comments can be converted into inline <span class="review-notes-inline-token">[an: ...]</span> annotations.</p>
|
|
10008
10062
|
</div>
|
|
10009
10063
|
<button id="reviewNotesCloseBtn" type="button" class="scratchpad-close-btn" aria-label="Hide comments" title="Hide comments">✕</button>
|
|
10010
10064
|
</div>
|
|
10011
10065
|
<div class="review-notes-toolbar">
|
|
10012
10066
|
<span id="reviewNotesMeta" class="scratchpad-meta">No comments</span>
|
|
10013
10067
|
</div>
|
|
10014
|
-
<div id="reviewNotesEmptyState" class="review-notes-empty">No comments yet for this document. Select text in <strong>Editor (Raw)</strong> or <strong>Editor (Preview)</strong> and use <em>Comment</em>,
|
|
10068
|
+
<div id="reviewNotesEmptyState" class="review-notes-empty">No comments yet for this document. Select text in <strong>Editor (Raw)</strong> or <strong>Editor (Preview)</strong> and use <em>Comment</em>, use <em>Line comment</em> in <strong>Editor (Raw)</strong>, or use <em>Comment mode</em> in an editor HTML preview.</div>
|
|
10015
10069
|
<div id="reviewNotesList" class="review-notes-list" aria-live="polite"></div>
|
|
10016
10070
|
<div class="review-notes-dock-footer">
|
|
10017
10071
|
<div class="scratchpad-actions">
|
|
@@ -10143,14 +10197,14 @@ ${cssVarsBlock}
|
|
|
10143
10197
|
<h3>Editor</h3>
|
|
10144
10198
|
<dl>
|
|
10145
10199
|
<div><dt>Cmd/Ctrl+S</dt><dd>Save editor</dd></div>
|
|
10146
|
-
<div><dt>Cmd/Ctrl+Enter</dt><dd>Run editor text, or queue steering during an active run</dd></div>
|
|
10200
|
+
<div class="shortcuts-full-only"><dt>Cmd/Ctrl+Enter</dt><dd>Run editor text, or queue steering during an active run</dd></div>
|
|
10147
10201
|
<div><dt>Option/Alt+Tab or Cmd/Ctrl+Shift+Space</dt><dd>Suggest a completion at the editor cursor</dd></div>
|
|
10148
10202
|
<div><dt>Tab</dt><dd>Insert a visible completion suggestion; otherwise indent selected editor text</dd></div>
|
|
10149
10203
|
<div><dt>Esc</dt><dd>Dismiss a visible completion suggestion, close overlays, exit pane focus, or stop an active request</dd></div>
|
|
10150
10204
|
<div><dt>Shift+Tab</dt><dd>Unindent selected editor text</dd></div>
|
|
10151
10205
|
</dl>
|
|
10152
10206
|
</section>
|
|
10153
|
-
<section class="shortcuts-group">
|
|
10207
|
+
<section class="shortcuts-group shortcuts-full-only">
|
|
10154
10208
|
<h3>Response</h3>
|
|
10155
10209
|
<dl>
|
|
10156
10210
|
<div><dt>Alt/Option+←</dt><dd>Previous response when not editing text</dd></div>
|
|
@@ -11040,7 +11094,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
11040
11094
|
const existingId = studioTraceToolEntryIds.get(toolCallId);
|
|
11041
11095
|
if (existingId) {
|
|
11042
11096
|
const existing = studioTraceState.entries.find((entry) => entry.id === existingId);
|
|
11043
|
-
if (existing && existing.type === "tool")
|
|
11097
|
+
if (existing && existing.type === "tool") {
|
|
11098
|
+
if (args !== undefined) {
|
|
11099
|
+
existing.toolName = toolName;
|
|
11100
|
+
existing.label = deriveToolActivityLabel(toolName, args);
|
|
11101
|
+
existing.argsSummary = summarizeStudioTraceToolArgs(toolName, args);
|
|
11102
|
+
existing.args = formatStudioTraceToolArgs(toolName, args);
|
|
11103
|
+
existing.updatedAt = Date.now();
|
|
11104
|
+
upsertStudioTraceEntry(existing);
|
|
11105
|
+
}
|
|
11106
|
+
return existing;
|
|
11107
|
+
}
|
|
11044
11108
|
}
|
|
11045
11109
|
if (studioTraceState.runId == null || studioTraceState.status === "idle") {
|
|
11046
11110
|
resetStudioTraceForRun();
|
|
@@ -11053,6 +11117,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
11053
11117
|
toolName,
|
|
11054
11118
|
label: deriveToolActivityLabel(toolName, args),
|
|
11055
11119
|
argsSummary: summarizeStudioTraceToolArgs(toolName, args),
|
|
11120
|
+
args: formatStudioTraceToolArgs(toolName, args),
|
|
11056
11121
|
output: "",
|
|
11057
11122
|
images: [],
|
|
11058
11123
|
startedAt: now,
|
|
@@ -11075,6 +11140,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
11075
11140
|
images?: StudioTraceImage[],
|
|
11076
11141
|
) => {
|
|
11077
11142
|
const entry = ensureStudioTraceToolEntry(toolCallId, toolName, args);
|
|
11143
|
+
if (!entry.argsSummary) entry.argsSummary = summarizeStudioTraceToolArgs(toolName, args);
|
|
11144
|
+
if (!entry.args) entry.args = formatStudioTraceToolArgs(toolName, args);
|
|
11078
11145
|
entry.output = output;
|
|
11079
11146
|
if (Array.isArray(images)) entry.images = images;
|
|
11080
11147
|
entry.status = status;
|
|
@@ -12225,16 +12292,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
12225
12292
|
sendToClient(client, { type: "busy", requestId: msg.requestId, message: "Studio is busy." });
|
|
12226
12293
|
return;
|
|
12227
12294
|
}
|
|
12228
|
-
|
|
12295
|
+
const requestedPath = typeof msg.path === "string" && msg.path.trim() ? msg.path.trim() : "";
|
|
12296
|
+
const refreshPath = requestedPath || initialStudioDocument?.path || "";
|
|
12297
|
+
if (!refreshPath) {
|
|
12229
12298
|
sendToClient(client, {
|
|
12230
12299
|
type: "error",
|
|
12231
12300
|
requestId: msg.requestId,
|
|
12232
|
-
message: "Refresh from disk
|
|
12301
|
+
message: "Refresh from disk needs a file path. Use Files → Open here, Files → Open file tab, or /studio-editor-only <path> for a refreshable editor tab.",
|
|
12233
12302
|
});
|
|
12234
12303
|
return;
|
|
12235
12304
|
}
|
|
12236
12305
|
|
|
12237
|
-
const refreshed = readStudioFile(
|
|
12306
|
+
const refreshed = readStudioFile(refreshPath, studioCwd);
|
|
12238
12307
|
if (refreshed.ok === false) {
|
|
12239
12308
|
sendToClient(client, {
|
|
12240
12309
|
type: "error",
|
|
@@ -12244,18 +12313,21 @@ export default function (pi: ExtensionAPI) {
|
|
|
12244
12313
|
return;
|
|
12245
12314
|
}
|
|
12246
12315
|
|
|
12247
|
-
|
|
12316
|
+
const refreshedDocument: InitialStudioDocument = {
|
|
12248
12317
|
text: refreshed.text,
|
|
12249
12318
|
label: refreshed.label,
|
|
12250
12319
|
source: "file",
|
|
12251
12320
|
path: refreshed.resolvedPath,
|
|
12252
12321
|
resourceDir: dirname(refreshed.resolvedPath),
|
|
12253
12322
|
};
|
|
12323
|
+
if (!requestedPath || initialStudioDocument?.path === refreshed.resolvedPath) {
|
|
12324
|
+
initialStudioDocument = refreshedDocument;
|
|
12325
|
+
}
|
|
12254
12326
|
|
|
12255
|
-
|
|
12327
|
+
sendToClient(client, {
|
|
12256
12328
|
type: "studio_document",
|
|
12257
12329
|
requestId: msg.requestId,
|
|
12258
|
-
document:
|
|
12330
|
+
document: refreshedDocument,
|
|
12259
12331
|
message: `Reloaded ${refreshed.label} from disk.`,
|
|
12260
12332
|
});
|
|
12261
12333
|
return;
|
|
@@ -13666,7 +13738,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
13666
13738
|
if (!agentBusy) return;
|
|
13667
13739
|
const toolName = typeof event.toolName === "string" ? event.toolName : "";
|
|
13668
13740
|
const input = (event as { input?: unknown }).input;
|
|
13741
|
+
const toolCallId = typeof event.toolCallId === "string" ? event.toolCallId : "";
|
|
13669
13742
|
const label = deriveToolActivityLabel(toolName, input);
|
|
13743
|
+
if (toolCallId) ensureStudioTraceToolEntry(toolCallId, toolName, input);
|
|
13670
13744
|
emitDebugEvent("tool_call", { toolName, label, activeRequestId: activeRequest?.id ?? null, activeRequestKind: activeRequest?.kind ?? null });
|
|
13671
13745
|
setTerminalActivity("tool", toolName, label);
|
|
13672
13746
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-studio",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.20",
|
|
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",
|