pi-sdk-web 0.4.9 → 0.4.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/dist/server.js +34 -4
- package/dist/static/app.js +13 -4
- package/dist/static/style.css +22 -0
- package/dist/ui-context.js +7 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -764,10 +764,38 @@ export class PiWebServer {
|
|
|
764
764
|
}
|
|
765
765
|
};
|
|
766
766
|
const unsubscribe = this.session.subscribe(listener);
|
|
767
|
+
// hasUI by extension: most extensions degrade gracefully to notify()
|
|
768
|
+
// (our notify -> browser dialog/toast), but a few (magic-context) use
|
|
769
|
+
// ctx.ui.custom() - an extension-drawn TUI panel we can't render. For
|
|
770
|
+
// those, hasUI:false routes them to their own text fallback
|
|
771
|
+
// (appendEntry -> modal), same as before.
|
|
772
|
+
const cmdPath = (cmd.sourceInfo && cmd.sourceInfo.path) || "";
|
|
773
|
+
const customOnly = /pi-magic-context|magic-context/.test(cmdPath);
|
|
774
|
+
const ui = this.uiContext;
|
|
775
|
+
const originalSink = ui.sink;
|
|
767
776
|
try {
|
|
768
|
-
|
|
777
|
+
// While the command runs, notify() broadcasts are tagged with the
|
|
778
|
+
// command name as title, so the browser shows them as a titled modal
|
|
779
|
+
// (colored, Markdown-rendered) instead of a plain stream line.
|
|
780
|
+
ui.sink = (obj) => {
|
|
781
|
+
const req = obj;
|
|
782
|
+
if (req && req.method === "notify") {
|
|
783
|
+
// Tag command-time notifies with the command name as title so the
|
|
784
|
+
// browser renders them as a titled modal (colored, Markdown).
|
|
785
|
+
originalSink({ ...obj, title: `/${name}` });
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
originalSink(obj);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
await cmd.handler(args, this.buildCommandContext(customOnly ? false : true));
|
|
792
|
+
}
|
|
793
|
+
catch (e) {
|
|
794
|
+
ui.sink = originalSink;
|
|
795
|
+
throw e;
|
|
769
796
|
}
|
|
770
797
|
finally {
|
|
798
|
+
ui.sink = originalSink;
|
|
771
799
|
unsubscribe();
|
|
772
800
|
}
|
|
773
801
|
// Show command output as a modal (TUI-like). The session entry remains
|
|
@@ -790,13 +818,15 @@ export class PiWebServer {
|
|
|
790
818
|
});
|
|
791
819
|
}
|
|
792
820
|
}
|
|
793
|
-
buildCommandContext() {
|
|
821
|
+
buildCommandContext(hasUI) {
|
|
794
822
|
const sm = this.session.sessionManager;
|
|
795
823
|
return {
|
|
796
824
|
ui: this.uiContext,
|
|
797
|
-
//
|
|
825
|
+
// hasUI is decided per command (see executeCommand): true for
|
|
826
|
+
// extensions that degrade to notify(), false for custom-panel-only
|
|
827
|
+
// extensions (magic-context) so they use their text fallback.
|
|
798
828
|
mode: "print",
|
|
799
|
-
hasUI
|
|
829
|
+
hasUI,
|
|
800
830
|
cwd: sm.getCwd(),
|
|
801
831
|
sessionManager: sm,
|
|
802
832
|
modelRegistry: new ModelRegistry(this.session.modelRuntime),
|
package/dist/static/app.js
CHANGED
|
@@ -443,7 +443,7 @@ class PiWebClient {
|
|
|
443
443
|
sections.push(this.resourceSection('Prompts', groups.prompt.map((c) => c.name)));
|
|
444
444
|
}
|
|
445
445
|
if (groups.extension.length > 0) {
|
|
446
|
-
sections.push(this.resourceSection('
|
|
446
|
+
sections.push(this.resourceSection('Extension Cmds', groups.extension.map((c) => c.name)));
|
|
447
447
|
}
|
|
448
448
|
body.innerHTML = sections.join('');
|
|
449
449
|
|
|
@@ -1915,8 +1915,9 @@ class PiWebClient {
|
|
|
1915
1915
|
|
|
1916
1916
|
openExtensionNotify(req) {
|
|
1917
1917
|
// Command output notifications (title starts with "/", e.g. /ctx-status) keep
|
|
1918
|
-
// the modal. Other extension notifies are
|
|
1919
|
-
//
|
|
1918
|
+
// the modal. Other extension notifies are appended to the chat stream as
|
|
1919
|
+
// persistent status lines, matching TUI's notify -> showStatus (a dim text
|
|
1920
|
+
// appended to the chat container; NOT a transient toast).
|
|
1920
1921
|
if (req.title && String(req.title).startsWith('/')) {
|
|
1921
1922
|
this.openModal(req.title || 'Notification', 'extension-notify');
|
|
1922
1923
|
this.currentExtRequest = req;
|
|
@@ -1924,7 +1925,15 @@ class PiWebClient {
|
|
|
1924
1925
|
this.modalList.innerHTML = `<div class="modal-message body-text">${this.renderMarkdown(req.message || '')}</div>`;
|
|
1925
1926
|
return;
|
|
1926
1927
|
}
|
|
1927
|
-
this.
|
|
1928
|
+
this.appendNotifyLine(req.message || '', req.notifyType);
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
appendNotifyLine(message, type) {
|
|
1932
|
+
const div = document.createElement('div');
|
|
1933
|
+
div.className = 'notify-line' + (type ? ` notify-${type}` : '');
|
|
1934
|
+
div.innerHTML = ansiToHtml(String(message));
|
|
1935
|
+
this.contentEl.appendChild(div);
|
|
1936
|
+
this.scrollToBottom();
|
|
1928
1937
|
}
|
|
1929
1938
|
|
|
1930
1939
|
showToast(message, type) {
|
package/dist/static/style.css
CHANGED
|
@@ -907,6 +907,7 @@ body {
|
|
|
907
907
|
color: var(--text);
|
|
908
908
|
font-size: 13px;
|
|
909
909
|
line-height: 1.5;
|
|
910
|
+
white-space: pre-wrap;
|
|
910
911
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
911
912
|
opacity: 1;
|
|
912
913
|
transition: opacity 0.3s;
|
|
@@ -920,6 +921,27 @@ body {
|
|
|
920
921
|
border-left-color: var(--error);
|
|
921
922
|
}
|
|
922
923
|
|
|
924
|
+
/* Extension notify lines appended to the chat stream (TUI showStatus
|
|
925
|
+
equivalent): persistent dim status text, colored by type. */
|
|
926
|
+
.notify-line {
|
|
927
|
+
color: var(--dim);
|
|
928
|
+
font-size: 12px;
|
|
929
|
+
padding: 2px 12px;
|
|
930
|
+
white-space: pre-wrap;
|
|
931
|
+
overflow-wrap: anywhere;
|
|
932
|
+
border-left: 3px solid transparent;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
.notify-warning {
|
|
936
|
+
color: var(--warning);
|
|
937
|
+
border-left-color: var(--warning);
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
.notify-error {
|
|
941
|
+
color: var(--error);
|
|
942
|
+
border-left-color: var(--error);
|
|
943
|
+
}
|
|
944
|
+
|
|
923
945
|
.toast-hide {
|
|
924
946
|
opacity: 0;
|
|
925
947
|
}
|
package/dist/ui-context.js
CHANGED
|
@@ -199,6 +199,13 @@ export class WebUIContext {
|
|
|
199
199
|
setFooter() { }
|
|
200
200
|
setHeader() { }
|
|
201
201
|
custom() {
|
|
202
|
+
// Pi's custom() shows an extension-drawn TUI component. Web has no TUI
|
|
203
|
+
// renderer, so a full component can't be displayed. Same headless stub
|
|
204
|
+
// as Pi's RPC mode (rpc-mode.ts: "Custom UI not supported in RPC mode"):
|
|
205
|
+
// settle immediately so commands awaiting the panel don't hang.
|
|
206
|
+
// Commands whose extensions branch on hasUI (magic-context ctx-status)
|
|
207
|
+
// are routed to their text fallback by executeCommand (hasUI:false);
|
|
208
|
+
// any other custom() caller just gets a no-op close.
|
|
202
209
|
return Promise.resolve(undefined);
|
|
203
210
|
}
|
|
204
211
|
pasteToEditor() { }
|