pi-studio 0.5.10 → 0.5.11
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 +5 -0
- package/index.ts +86 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,11 @@ All notable changes to `pi-studio` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.5.11] — 2026-03-15
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Studio tabs now show a title attention marker like `● Response ready` or `● Critique ready` when a Studio-started model request finishes while the tab is unfocused, and clear that marker when the tab regains focus or the next Studio request starts.
|
|
11
|
+
|
|
7
12
|
## [0.5.10] — 2026-03-14
|
|
8
13
|
|
|
9
14
|
### Fixed
|
package/index.ts
CHANGED
|
@@ -3539,6 +3539,10 @@ ${cssVarsBlock}
|
|
|
3539
3539
|
let contextPercent = null;
|
|
3540
3540
|
let updateInstalledVersion = null;
|
|
3541
3541
|
let updateLatestVersion = null;
|
|
3542
|
+
let windowHasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : true;
|
|
3543
|
+
let titleAttentionMessage = "";
|
|
3544
|
+
let titleAttentionRequestId = null;
|
|
3545
|
+
let titleAttentionRequestKind = null;
|
|
3542
3546
|
|
|
3543
3547
|
function parseFiniteNumber(value) {
|
|
3544
3548
|
if (value == null || value === "") return null;
|
|
@@ -3899,12 +3903,63 @@ ${cssVarsBlock}
|
|
|
3899
3903
|
return changed;
|
|
3900
3904
|
}
|
|
3901
3905
|
|
|
3906
|
+
function isTitleAttentionRequestKind(kind) {
|
|
3907
|
+
return kind === "annotation" || kind === "critique" || kind === "direct";
|
|
3908
|
+
}
|
|
3909
|
+
|
|
3910
|
+
function armTitleAttentionForRequest(requestId, kind) {
|
|
3911
|
+
if (typeof requestId !== "string" || !isTitleAttentionRequestKind(kind)) {
|
|
3912
|
+
titleAttentionRequestId = null;
|
|
3913
|
+
titleAttentionRequestKind = null;
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
titleAttentionRequestId = requestId;
|
|
3917
|
+
titleAttentionRequestKind = kind;
|
|
3918
|
+
}
|
|
3919
|
+
|
|
3920
|
+
function clearArmedTitleAttention(requestId) {
|
|
3921
|
+
if (typeof requestId === "string" && titleAttentionRequestId && requestId !== titleAttentionRequestId) {
|
|
3922
|
+
return;
|
|
3923
|
+
}
|
|
3924
|
+
titleAttentionRequestId = null;
|
|
3925
|
+
titleAttentionRequestKind = null;
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
function clearTitleAttention() {
|
|
3929
|
+
if (!titleAttentionMessage) return;
|
|
3930
|
+
titleAttentionMessage = "";
|
|
3931
|
+
updateDocumentTitle();
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3934
|
+
function shouldShowTitleAttention() {
|
|
3935
|
+
const focused = typeof document.hasFocus === "function" ? document.hasFocus() : windowHasFocus;
|
|
3936
|
+
return Boolean(document.hidden) || !focused;
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3939
|
+
function getTitleAttentionMessage(kind) {
|
|
3940
|
+
if (kind === "critique") return "● Critique ready";
|
|
3941
|
+
if (kind === "direct") return "● Response ready";
|
|
3942
|
+
return "● Reply ready";
|
|
3943
|
+
}
|
|
3944
|
+
|
|
3945
|
+
function maybeShowTitleAttentionForCompletedRequest(requestId, kind) {
|
|
3946
|
+
const matchedRequest = typeof requestId === "string" && titleAttentionRequestId && requestId === titleAttentionRequestId;
|
|
3947
|
+
const completedKind = isTitleAttentionRequestKind(kind) ? kind : titleAttentionRequestKind;
|
|
3948
|
+
clearArmedTitleAttention(requestId);
|
|
3949
|
+
if (!matchedRequest || !completedKind || !shouldShowTitleAttention()) {
|
|
3950
|
+
return;
|
|
3951
|
+
}
|
|
3952
|
+
titleAttentionMessage = getTitleAttentionMessage(completedKind);
|
|
3953
|
+
updateDocumentTitle();
|
|
3954
|
+
}
|
|
3955
|
+
|
|
3902
3956
|
function updateDocumentTitle() {
|
|
3903
3957
|
const modelText = modelLabel && modelLabel.trim() ? modelLabel.trim() : "none";
|
|
3904
3958
|
const terminalText = terminalSessionLabel && terminalSessionLabel.trim() ? terminalSessionLabel.trim() : "unknown";
|
|
3905
3959
|
const titleParts = ["pi Studio"];
|
|
3906
3960
|
if (terminalText && terminalText !== "unknown") titleParts.push(terminalText);
|
|
3907
3961
|
if (modelText && modelText !== "none") titleParts.push(modelText);
|
|
3962
|
+
if (titleAttentionMessage) titleParts.unshift(titleAttentionMessage);
|
|
3908
3963
|
document.title = titleParts.join(" · ");
|
|
3909
3964
|
}
|
|
3910
3965
|
|
|
@@ -3998,6 +4053,24 @@ ${cssVarsBlock}
|
|
|
3998
4053
|
|
|
3999
4054
|
renderStatus();
|
|
4000
4055
|
|
|
4056
|
+
window.addEventListener("focus", () => {
|
|
4057
|
+
windowHasFocus = true;
|
|
4058
|
+
clearTitleAttention();
|
|
4059
|
+
});
|
|
4060
|
+
|
|
4061
|
+
window.addEventListener("blur", () => {
|
|
4062
|
+
windowHasFocus = false;
|
|
4063
|
+
});
|
|
4064
|
+
|
|
4065
|
+
document.addEventListener("visibilitychange", () => {
|
|
4066
|
+
if (!document.hidden) {
|
|
4067
|
+
windowHasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : windowHasFocus;
|
|
4068
|
+
if (windowHasFocus) {
|
|
4069
|
+
clearTitleAttention();
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
});
|
|
4073
|
+
|
|
4001
4074
|
function updateSourceBadge() {
|
|
4002
4075
|
const label = sourceState && sourceState.label ? sourceState.label : "blank";
|
|
4003
4076
|
sourceBadgeEl.textContent = "Editor origin: " + label;
|
|
@@ -5810,8 +5883,10 @@ ${cssVarsBlock}
|
|
|
5810
5883
|
setStatus("No matching Studio request is running.", "warning");
|
|
5811
5884
|
return false;
|
|
5812
5885
|
}
|
|
5813
|
-
const
|
|
5886
|
+
const requestId = pendingRequestId;
|
|
5887
|
+
const sent = sendMessage({ type: "cancel_request", requestId });
|
|
5814
5888
|
if (!sent) return false;
|
|
5889
|
+
clearArmedTitleAttention(requestId);
|
|
5815
5890
|
setStatus("Stopping request…", "warning");
|
|
5816
5891
|
return true;
|
|
5817
5892
|
}
|
|
@@ -6119,6 +6194,7 @@ ${cssVarsBlock}
|
|
|
6119
6194
|
return;
|
|
6120
6195
|
}
|
|
6121
6196
|
|
|
6197
|
+
const completedRequestId = typeof message.requestId === "string" ? message.requestId : pendingRequestId;
|
|
6122
6198
|
const responseKind =
|
|
6123
6199
|
typeof message.kind === "string"
|
|
6124
6200
|
? message.kind
|
|
@@ -6151,6 +6227,7 @@ ${cssVarsBlock}
|
|
|
6151
6227
|
} else {
|
|
6152
6228
|
setStatus("Response ready.", "success");
|
|
6153
6229
|
}
|
|
6230
|
+
maybeShowTitleAttentionForCompletedRequest(completedRequestId, responseKind);
|
|
6154
6231
|
return;
|
|
6155
6232
|
}
|
|
6156
6233
|
|
|
@@ -6352,6 +6429,9 @@ ${cssVarsBlock}
|
|
|
6352
6429
|
pendingRequestId = null;
|
|
6353
6430
|
pendingKind = null;
|
|
6354
6431
|
}
|
|
6432
|
+
if (typeof message.requestId === "string") {
|
|
6433
|
+
clearArmedTitleAttention(message.requestId);
|
|
6434
|
+
}
|
|
6355
6435
|
stickyStudioKind = null;
|
|
6356
6436
|
setBusy(false);
|
|
6357
6437
|
setWsState("Ready");
|
|
@@ -6367,6 +6447,9 @@ ${cssVarsBlock}
|
|
|
6367
6447
|
pendingRequestId = null;
|
|
6368
6448
|
pendingKind = null;
|
|
6369
6449
|
}
|
|
6450
|
+
if (typeof message.requestId === "string") {
|
|
6451
|
+
clearArmedTitleAttention(message.requestId);
|
|
6452
|
+
}
|
|
6370
6453
|
stickyStudioKind = null;
|
|
6371
6454
|
setBusy(false);
|
|
6372
6455
|
setWsState("Ready");
|
|
@@ -6525,10 +6608,12 @@ ${cssVarsBlock}
|
|
|
6525
6608
|
setStatus("Studio is busy.", "warning");
|
|
6526
6609
|
return null;
|
|
6527
6610
|
}
|
|
6611
|
+
clearTitleAttention();
|
|
6528
6612
|
const requestId = makeRequestId();
|
|
6529
6613
|
pendingRequestId = requestId;
|
|
6530
6614
|
pendingKind = kind;
|
|
6531
6615
|
stickyStudioKind = kind;
|
|
6616
|
+
armTitleAttentionForRequest(requestId, kind);
|
|
6532
6617
|
setBusy(true);
|
|
6533
6618
|
setWsState("Submitting");
|
|
6534
6619
|
setStatus(getStudioBusyStatus(kind), "warning");
|