pi-sdk-web 0.5.4 → 0.5.6

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.
@@ -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' });
@@ -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>
@@ -248,12 +248,16 @@ body {
248
248
  overflow-x: hidden;
249
249
  padding: 8px;
250
250
  min-width: 0;
251
+ /* Bordered, rounded message area (distinct region vs sidebar/footer) */
252
+ border: 1px solid var(--border);
253
+ border-radius: 6px;
254
+ margin: 3px 0;
251
255
  }
252
256
 
253
257
  #sidebar {
254
258
  width: 200px;
255
259
  flex-shrink: 0;
256
- border-left: 1px solid var(--border);
260
+ /* scroll-view now has its own right border - no duplicate divider */
257
261
  padding: 8px;
258
262
  overflow-y: auto;
259
263
  }
@@ -1485,3 +1489,28 @@ body {
1485
1489
  margin-left: 4px;
1486
1490
  vertical-align: middle;
1487
1491
  }
1492
+
1493
+ /* Input history navigation (↑/↓ buttons beside the input box) */
1494
+ .history-nav {
1495
+ display: flex;
1496
+ flex-direction: column;
1497
+ justify-content: center;
1498
+ gap: 2px;
1499
+ }
1500
+
1501
+ .history-nav button {
1502
+ width: 24px;
1503
+ height: 20px;
1504
+ font-size: 11px;
1505
+ line-height: 1;
1506
+ color: var(--dim);
1507
+ background: transparent;
1508
+ border: 1px solid var(--border);
1509
+ border-radius: 4px;
1510
+ cursor: pointer;
1511
+ }
1512
+
1513
+ .history-nav button:hover {
1514
+ color: var(--text);
1515
+ border-color: var(--accent);
1516
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-sdk-web",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "Browser Web access for Pi (AI coding agent) via the Pi SDK - standalone module, zero modification to Pi itself",
5
5
  "type": "module",
6
6
  "bin": {