pi-sdk-web 0.5.4 → 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.
@@ -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>
@@ -1485,3 +1485,28 @@ body {
1485
1485
  margin-left: 4px;
1486
1486
  vertical-align: middle;
1487
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
+ }
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.5",
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": {