pi-sdk-web 0.5.3 → 0.5.5
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 +10 -0
- package/dist/static/app.js +61 -2
- package/dist/static/index.html +4 -0
- package/dist/static/style.css +35 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -581,6 +581,11 @@ export class PiWebServer {
|
|
|
581
581
|
break;
|
|
582
582
|
}
|
|
583
583
|
case "get_scoped_models":
|
|
584
|
+
// Refresh model catalogs (e.g. pi-deepinfra's lazy catalog swap)
|
|
585
|
+
// before broadcasting, so late-swapped models (zai-org/GLM-5.3-
|
|
586
|
+
// Flash etc.) appear in the list like they do in the TUI. Timeout
|
|
587
|
+
// is bounded by the refresh implementation (network wait).
|
|
588
|
+
await this.session.modelRuntime.refresh().catch(() => { });
|
|
584
589
|
this.broadcast({
|
|
585
590
|
type: "scoped_models",
|
|
586
591
|
data: {
|
|
@@ -590,6 +595,11 @@ export class PiWebServer {
|
|
|
590
595
|
thinkingLevel: s.thinkingLevel,
|
|
591
596
|
})),
|
|
592
597
|
available: this.session.modelRuntime.getAvailableSnapshot(),
|
|
598
|
+
// Settings' enabled-model patterns. TUI's scoped-models selector
|
|
599
|
+
// also shows configured patterns that have no matching provider
|
|
600
|
+
// model (diagnostic no-match) - mirror that so configured models
|
|
601
|
+
// (e.g. deepinfra/zai-org/GLM-5.3-Flash) aren't missing here.
|
|
602
|
+
configured: this.session.settingsManager.getEnabledModels() ?? [],
|
|
593
603
|
},
|
|
594
604
|
});
|
|
595
605
|
break;
|
package/dist/static/app.js
CHANGED
|
@@ -189,6 +189,12 @@ class PiWebClient {
|
|
|
189
189
|
this.loadedResourcesEl = document.getElementById('loaded-resources');
|
|
190
190
|
this.footerEl = document.getElementById('footer-line');
|
|
191
191
|
this.inputEl = document.getElementById('input');
|
|
192
|
+
// Input history (TUI parity): all submitted inputs (messages, !bash,
|
|
193
|
+
// /commands) plus this session's user messages from history, browsed
|
|
194
|
+
// with the ↑/↓ buttons next to the input box.
|
|
195
|
+
this.inputHistory = [];
|
|
196
|
+
this.historyIndex = -1; // -1 = not browsing (composing new input)
|
|
197
|
+
this.historyDraft = '';
|
|
192
198
|
this.sendBtn = document.getElementById('send-btn');
|
|
193
199
|
this.abortBtn = document.getElementById('abort-btn');
|
|
194
200
|
this.commandMenuEl = document.getElementById('command-menu');
|
|
@@ -1117,6 +1123,11 @@ class PiWebClient {
|
|
|
1117
1123
|
|
|
1118
1124
|
appendUserMessage(message) {
|
|
1119
1125
|
const text = this.messageText(message);
|
|
1126
|
+
// History population (TUI renderInitialMessages populateHistory):
|
|
1127
|
+
// session user messages seed the input history, deduped.
|
|
1128
|
+
if (text && this.inputHistory[this.inputHistory.length - 1] !== text) {
|
|
1129
|
+
this.inputHistory.push(text);
|
|
1130
|
+
}
|
|
1120
1131
|
const div = document.createElement('div');
|
|
1121
1132
|
div.className = 'message user';
|
|
1122
1133
|
const role = document.createElement('div');
|
|
@@ -1570,9 +1581,41 @@ class PiWebClient {
|
|
|
1570
1581
|
// Input
|
|
1571
1582
|
// ------------------------------------------------------------------
|
|
1572
1583
|
|
|
1584
|
+
navigateHistory(dir) {
|
|
1585
|
+
// dir: -1 = previous (older), +1 = next (newer). Browsing starts from
|
|
1586
|
+
// the newest entry when the input is empty; editing resets the browse.
|
|
1587
|
+
if (this.inputHistory.length === 0) return;
|
|
1588
|
+
if (this.historyIndex === -1) {
|
|
1589
|
+
// Not browsing yet: stash the current draft, start at newest entry.
|
|
1590
|
+
this.historyDraft = this.inputEl.value;
|
|
1591
|
+
this.historyIndex = this.inputHistory.length - 1;
|
|
1592
|
+
} else {
|
|
1593
|
+
this.historyIndex += dir;
|
|
1594
|
+
}
|
|
1595
|
+
if (this.historyIndex >= this.inputHistory.length) {
|
|
1596
|
+
// Past the newest entry: restore the draft, stop browsing.
|
|
1597
|
+
this.historyIndex = -1;
|
|
1598
|
+
this.inputEl.value = this.historyDraft;
|
|
1599
|
+
} else if (this.historyIndex < 0) {
|
|
1600
|
+
this.historyIndex = 0;
|
|
1601
|
+
this.inputEl.value = this.inputHistory[0];
|
|
1602
|
+
} else {
|
|
1603
|
+
this.inputEl.value = this.inputHistory[this.historyIndex];
|
|
1604
|
+
}
|
|
1605
|
+
// Keep caret at end, keep focus in the box.
|
|
1606
|
+
this.inputEl.setSelectionRange(this.inputEl.value.length, this.inputEl.value.length);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1573
1609
|
sendMessage() {
|
|
1574
1610
|
const text = this.inputEl.value.trim();
|
|
1575
1611
|
if (!text) return;
|
|
1612
|
+
// Record every submitted input (messages, !bash, /commands) in the
|
|
1613
|
+
// history - TUI parity (handleSubmit addToHistory on all paths).
|
|
1614
|
+
if (this.inputHistory[this.inputHistory.length - 1] !== text) {
|
|
1615
|
+
this.inputHistory.push(text);
|
|
1616
|
+
}
|
|
1617
|
+
this.historyIndex = -1;
|
|
1618
|
+
this.historyDraft = '';
|
|
1576
1619
|
if (text.startsWith('!')) {
|
|
1577
1620
|
// TUI parity: "!cmd" runs bash (output goes to LLM context);
|
|
1578
1621
|
// "!!cmd" runs bash with excludeFromContext (output NOT sent to LLM).
|
|
@@ -1682,6 +1725,11 @@ class PiWebClient {
|
|
|
1682
1725
|
if (this.sendBtn) {
|
|
1683
1726
|
this.sendBtn.addEventListener('click', () => this.sendMessage());
|
|
1684
1727
|
}
|
|
1728
|
+
// Input history navigation (↑/↓ buttons beside the input box)
|
|
1729
|
+
const histPrev = document.getElementById('history-prev');
|
|
1730
|
+
const histNext = document.getElementById('history-next');
|
|
1731
|
+
if (histPrev) histPrev.addEventListener('click', () => this.navigateHistory(-1));
|
|
1732
|
+
if (histNext) histNext.addEventListener('click', () => this.navigateHistory(1));
|
|
1685
1733
|
if (this.abortBtn) {
|
|
1686
1734
|
this.abortBtn.addEventListener('click', () => {
|
|
1687
1735
|
this.send({ type: 'abort' });
|
|
@@ -2369,7 +2417,18 @@ class PiWebClient {
|
|
|
2369
2417
|
|
|
2370
2418
|
handleScopedModels(data) {
|
|
2371
2419
|
if (this.modalMode !== 'scoped-models') return;
|
|
2372
|
-
|
|
2420
|
+
const available = data.available || [];
|
|
2421
|
+
// Merge settings' configured model patterns (e.g. deepinfra/zai-org/
|
|
2422
|
+
// GLM-5.3-Flash) that have no matching provider model - TUI's selector
|
|
2423
|
+
// shows these as configured entries (no-match diagnostics) too.
|
|
2424
|
+
const known = new Set(available.map((m) => `${m.provider}/${m.id}`));
|
|
2425
|
+
const configured = (data.configured || [])
|
|
2426
|
+
.filter((p) => !known.has(p))
|
|
2427
|
+
.map((p) => {
|
|
2428
|
+
const slash = p.indexOf('/');
|
|
2429
|
+
return { provider: p.slice(0, slash), id: p.slice(slash + 1), configured: true };
|
|
2430
|
+
});
|
|
2431
|
+
this.scopedModelsAll = [...available, ...configured];
|
|
2373
2432
|
this.scopedModelsData = data;
|
|
2374
2433
|
this.scopedModelsSelected = new Set(
|
|
2375
2434
|
(data.scoped || []).map((s) => `${s.provider}/${s.id}`),
|
|
@@ -2395,7 +2454,7 @@ class PiWebClient {
|
|
|
2395
2454
|
return (
|
|
2396
2455
|
`<div class="modal-item scoped-model ${checked ? 'selected' : ''}" data-key="${key}">` +
|
|
2397
2456
|
`<span class="modal-check">${checked ? '☑' : '☐'}</span>` +
|
|
2398
|
-
`<span class="modal-item-name">${this.escapeHtml(key)}</span>` +
|
|
2457
|
+
`<span class="modal-item-name">${this.escapeHtml(key)}${m.configured ? ' <span class="configured-badge">[configured]</span>' : ''}</span>` +
|
|
2399
2458
|
`</div>`
|
|
2400
2459
|
);
|
|
2401
2460
|
})
|
package/dist/static/index.html
CHANGED
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
<div id="footer-stats"></div>
|
|
41
41
|
<div id="command-menu"></div>
|
|
42
42
|
<div class="input-row">
|
|
43
|
+
<div class="history-nav">
|
|
44
|
+
<button id="history-prev" title="Previous input (↑)">↑</button>
|
|
45
|
+
<button id="history-next" title="Next input (↓)">↓</button>
|
|
46
|
+
</div>
|
|
43
47
|
<textarea id="input" placeholder="Send a message... (Enter to send, Shift+Enter for newline)"></textarea>
|
|
44
48
|
<button id="send-btn" title="Send (Enter)">Send</button>
|
|
45
49
|
<button id="abort-btn" title="Abort current operation" style="display:none">Abort</button>
|
package/dist/static/style.css
CHANGED
|
@@ -1475,3 +1475,38 @@ body {
|
|
|
1475
1475
|
#usage-close:hover {
|
|
1476
1476
|
color: var(--text);
|
|
1477
1477
|
}
|
|
1478
|
+
|
|
1479
|
+
.configured-badge {
|
|
1480
|
+
font-size: 9px;
|
|
1481
|
+
color: var(--dim);
|
|
1482
|
+
background: var(--tool-pending-bg);
|
|
1483
|
+
padding: 1px 4px;
|
|
1484
|
+
border-radius: 3px;
|
|
1485
|
+
margin-left: 4px;
|
|
1486
|
+
vertical-align: middle;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
/* Input history navigation (↑/↓ buttons beside the input box) */
|
|
1490
|
+
.history-nav {
|
|
1491
|
+
display: flex;
|
|
1492
|
+
flex-direction: column;
|
|
1493
|
+
justify-content: center;
|
|
1494
|
+
gap: 2px;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
.history-nav button {
|
|
1498
|
+
width: 24px;
|
|
1499
|
+
height: 20px;
|
|
1500
|
+
font-size: 11px;
|
|
1501
|
+
line-height: 1;
|
|
1502
|
+
color: var(--dim);
|
|
1503
|
+
background: transparent;
|
|
1504
|
+
border: 1px solid var(--border);
|
|
1505
|
+
border-radius: 4px;
|
|
1506
|
+
cursor: pointer;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
.history-nav button:hover {
|
|
1510
|
+
color: var(--text);
|
|
1511
|
+
border-color: var(--accent);
|
|
1512
|
+
}
|