pi-sdk-web 0.2.2 → 0.2.4
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 +61 -1
- package/dist/static/app.js +45 -11
- package/dist/static/index.html +1 -0
- package/dist/static/style.css +38 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -251,7 +251,9 @@ export class PiWebServer {
|
|
|
251
251
|
buildHistory() {
|
|
252
252
|
try {
|
|
253
253
|
return {
|
|
254
|
-
|
|
254
|
+
// Match TUI's initial rendering: the current context view
|
|
255
|
+
// (compaction collapses older entries into a summary; branch-aware)
|
|
256
|
+
entries: this.session.sessionManager.buildContextEntries(),
|
|
255
257
|
leafId: this.session.sessionManager.getLeafId(),
|
|
256
258
|
};
|
|
257
259
|
}
|
|
@@ -485,10 +487,68 @@ export class PiWebServer {
|
|
|
485
487
|
await this.executeCommand(name, args);
|
|
486
488
|
break;
|
|
487
489
|
}
|
|
490
|
+
case "session":
|
|
491
|
+
// Read-only session info (TUI /session equivalent)
|
|
492
|
+
this.broadcastSessionInfo();
|
|
493
|
+
break;
|
|
488
494
|
default:
|
|
489
495
|
throw new Error(`Unsupported command: ${cmdType}`);
|
|
490
496
|
}
|
|
491
497
|
}
|
|
498
|
+
/** TUI /session equivalent: show session info as a modal (read-only). */
|
|
499
|
+
broadcastSessionInfo() {
|
|
500
|
+
try {
|
|
501
|
+
const stats = this.session.getSessionStats();
|
|
502
|
+
const sm = this.session.sessionManager;
|
|
503
|
+
const entries = sm.getEntries();
|
|
504
|
+
const model = this.session.model;
|
|
505
|
+
const lines = [];
|
|
506
|
+
lines.push("## Session Info", "");
|
|
507
|
+
const name = sm.getSessionName();
|
|
508
|
+
if (name)
|
|
509
|
+
lines.push(`**Name:** ${name}`);
|
|
510
|
+
lines.push(`**ID:** ${this.session.sessionId}`);
|
|
511
|
+
if (stats.sessionFile)
|
|
512
|
+
lines.push(`**File:** ${stats.sessionFile}`);
|
|
513
|
+
if (model)
|
|
514
|
+
lines.push(`**Model:** ${model.provider}/${model.id}`);
|
|
515
|
+
lines.push(`**Thinking:** ${this.session.thinkingLevel}`, "");
|
|
516
|
+
lines.push("### Messages");
|
|
517
|
+
lines.push(`- User: ${stats.userMessages}`);
|
|
518
|
+
lines.push(`- Assistant: ${stats.assistantMessages}`);
|
|
519
|
+
lines.push(`- Tool calls: ${stats.toolCalls}`);
|
|
520
|
+
lines.push(`- Tool results: ${stats.toolResults}`);
|
|
521
|
+
lines.push(`- Total: ${stats.totalMessages}`);
|
|
522
|
+
lines.push(`- Entries: ${entries.length}`, "");
|
|
523
|
+
const t = stats.tokens;
|
|
524
|
+
if (t) {
|
|
525
|
+
lines.push("### Tokens");
|
|
526
|
+
lines.push(`- Input: ${t.input}`);
|
|
527
|
+
lines.push(`- Output: ${t.output}`);
|
|
528
|
+
lines.push(`- Cache read: ${t.cacheRead}`);
|
|
529
|
+
lines.push(`- Cache write: ${t.cacheWrite}`);
|
|
530
|
+
lines.push(`- Total: ${t.total}`, "");
|
|
531
|
+
}
|
|
532
|
+
lines.push("### Cost");
|
|
533
|
+
lines.push(`$${stats.cost.toFixed(4)}`);
|
|
534
|
+
const cu = stats.contextUsage;
|
|
535
|
+
if (cu?.contextWindow) {
|
|
536
|
+
lines.push("", "### Context");
|
|
537
|
+
lines.push(`- ${cu.percent}% / ${cu.contextWindow} tokens`);
|
|
538
|
+
}
|
|
539
|
+
this.broadcast({
|
|
540
|
+
type: "extension_ui_request",
|
|
541
|
+
id: crypto.randomUUID(),
|
|
542
|
+
method: "notify",
|
|
543
|
+
title: "/session",
|
|
544
|
+
message: lines.join("\n"),
|
|
545
|
+
notifyType: "info",
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
catch {
|
|
549
|
+
// session info unavailable - skip
|
|
550
|
+
}
|
|
551
|
+
}
|
|
492
552
|
/**
|
|
493
553
|
* Execute an extension slash command (e.g. /ctx-status) by invoking its
|
|
494
554
|
* registered handler with a command context.
|
package/dist/static/app.js
CHANGED
|
@@ -8,6 +8,7 @@ const BUILTIN_COMMANDS = [
|
|
|
8
8
|
{ name: 'compact', description: 'Manually compact the session context', builtin: true, action: 'compact' },
|
|
9
9
|
{ name: 'reload', description: 'Reload session resources and extensions', builtin: true, action: 'reload' },
|
|
10
10
|
{ name: 'export', description: 'Export session to HTML (or .jsonl)', builtin: true, action: 'export' },
|
|
11
|
+
{ name: 'session', description: 'Show session information', builtin: true, action: 'session' },
|
|
11
12
|
{ name: 'name', description: 'Set session display name', builtin: true, action: 'name' },
|
|
12
13
|
{ name: 'login', description: 'Configure provider authentication (not supported in web)', builtin: true, unsupported: true },
|
|
13
14
|
{ name: 'logout', description: 'Remove provider authentication (not supported in web)', builtin: true, unsupported: true },
|
|
@@ -1202,6 +1203,8 @@ class PiWebClient {
|
|
|
1202
1203
|
} else if (cmd.action === 'export') {
|
|
1203
1204
|
const path = (args || '').trim();
|
|
1204
1205
|
this.send({ type: 'export', path: path });
|
|
1206
|
+
} else if (cmd.action === 'session') {
|
|
1207
|
+
this.send({ type: 'session' });
|
|
1205
1208
|
} else if (cmd.action === 'name') {
|
|
1206
1209
|
const newName = window.prompt('Set session display name:', '');
|
|
1207
1210
|
if (newName && newName.trim()) {
|
|
@@ -1469,12 +1472,30 @@ class PiWebClient {
|
|
|
1469
1472
|
}
|
|
1470
1473
|
|
|
1471
1474
|
openExtensionNotify(req) {
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1475
|
+
// Command output notifications (title starts with "/", e.g. /ctx-status) keep
|
|
1476
|
+
// the modal. Other extension notifies are lightweight toasts (TUI shows
|
|
1477
|
+
// notify as a transient status message, not a dialog).
|
|
1478
|
+
if (req.title && String(req.title).startsWith('/')) {
|
|
1479
|
+
this.openModal(req.title || 'Notification', 'extension-notify');
|
|
1480
|
+
this.currentExtRequest = req;
|
|
1481
|
+
this.modalSearch.style.display = 'none';
|
|
1482
|
+
this.modalList.innerHTML = `<div class="modal-message body-text">${this.renderMarkdown(req.message || '')}</div>`;
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
this.showToast(req.message || '', req.notifyType);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
showToast(message, type) {
|
|
1489
|
+
let container = document.getElementById('toast-container');
|
|
1490
|
+
if (!container) return;
|
|
1491
|
+
const toast = document.createElement('div');
|
|
1492
|
+
toast.className = 'toast' + (type ? ` toast-${type}` : '');
|
|
1493
|
+
toast.textContent = message;
|
|
1494
|
+
container.appendChild(toast);
|
|
1495
|
+
setTimeout(() => {
|
|
1496
|
+
toast.classList.add('toast-hide');
|
|
1497
|
+
setTimeout(() => toast.remove(), 300);
|
|
1498
|
+
}, type === 'error' ? 8000 : 5000);
|
|
1478
1499
|
}
|
|
1479
1500
|
|
|
1480
1501
|
handleModels(models) {
|
|
@@ -1614,11 +1635,24 @@ class PiWebClient {
|
|
|
1614
1635
|
...((this.lastState && this.lastState.commands) || []),
|
|
1615
1636
|
...BUILTIN_COMMANDS,
|
|
1616
1637
|
];
|
|
1617
|
-
const filtered = commands
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1638
|
+
const filtered = commands
|
|
1639
|
+
.filter((c) => {
|
|
1640
|
+
const name = (c.name || '').replace(/^skill:/, '').toLowerCase();
|
|
1641
|
+
const desc = (c.description || c.source || '').toLowerCase();
|
|
1642
|
+
return name.includes(query) || desc.includes(query);
|
|
1643
|
+
})
|
|
1644
|
+
.sort((a, b) => {
|
|
1645
|
+
// Exact-name match first, then name-prefix, then name-contains,
|
|
1646
|
+
// then description-contains (avoids unrelated commands flooding the list)
|
|
1647
|
+
const score = (c) => {
|
|
1648
|
+
const name = (c.name || '').replace(/^skill:/, '').toLowerCase();
|
|
1649
|
+
if (name === query) return 0;
|
|
1650
|
+
if (name.startsWith(query)) return 1;
|
|
1651
|
+
if (name.includes(query)) return 2;
|
|
1652
|
+
return 3;
|
|
1653
|
+
};
|
|
1654
|
+
return score(a) - score(b);
|
|
1655
|
+
});
|
|
1622
1656
|
|
|
1623
1657
|
if (filtered.length === 0) {
|
|
1624
1658
|
this.hideCommandMenu();
|
package/dist/static/index.html
CHANGED
package/dist/static/style.css
CHANGED
|
@@ -734,6 +734,44 @@ body {
|
|
|
734
734
|
color: var(--text);
|
|
735
735
|
}
|
|
736
736
|
|
|
737
|
+
/* Lightweight extension notifications (TUI shows notify as transient status) */
|
|
738
|
+
#toast-container {
|
|
739
|
+
position: fixed;
|
|
740
|
+
top: 12px;
|
|
741
|
+
right: 12px;
|
|
742
|
+
z-index: 200;
|
|
743
|
+
display: flex;
|
|
744
|
+
flex-direction: column;
|
|
745
|
+
gap: 8px;
|
|
746
|
+
max-width: 420px;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
.toast {
|
|
750
|
+
background: var(--modal-bg);
|
|
751
|
+
border: 1px solid var(--border);
|
|
752
|
+
border-left: 3px solid var(--accent);
|
|
753
|
+
border-radius: 6px;
|
|
754
|
+
padding: 8px 12px;
|
|
755
|
+
color: var(--text);
|
|
756
|
+
font-size: 13px;
|
|
757
|
+
line-height: 1.5;
|
|
758
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
759
|
+
opacity: 1;
|
|
760
|
+
transition: opacity 0.3s;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.toast-warning {
|
|
764
|
+
border-left-color: var(--warning);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
.toast-error {
|
|
768
|
+
border-left-color: var(--error);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
.toast-hide {
|
|
772
|
+
opacity: 0;
|
|
773
|
+
}
|
|
774
|
+
|
|
737
775
|
.modal-message {
|
|
738
776
|
color: var(--text);
|
|
739
777
|
font-size: 13px;
|