pi-sdk-web 0.4.4 → 0.4.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.
- package/dist/server.js +5 -0
- package/dist/static/app.js +59 -0
- package/dist/static/index.html +1 -0
- package/dist/static/style.css +69 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -411,6 +411,11 @@ export class PiWebServer {
|
|
|
411
411
|
case "abort":
|
|
412
412
|
await this.session.abort();
|
|
413
413
|
break;
|
|
414
|
+
case "abort_bash":
|
|
415
|
+
// Kill only the running bash (TUI Ctrl+C equivalent), leaving any
|
|
416
|
+
// agent activity untouched.
|
|
417
|
+
this.session.abortBash();
|
|
418
|
+
break;
|
|
414
419
|
case "get_stats":
|
|
415
420
|
this.broadcastStats();
|
|
416
421
|
break;
|
package/dist/static/app.js
CHANGED
|
@@ -1331,6 +1331,43 @@ class PiWebClient {
|
|
|
1331
1331
|
if (!div) {
|
|
1332
1332
|
div = this.createToolBlock('bash', { command: this.pendingBashCommand || '' }, key);
|
|
1333
1333
|
div.className = 'tool-block pending';
|
|
1334
|
+
// Running indicator (spinner + label) - makes it obvious the stream
|
|
1335
|
+
// is still live even when output is quiet; removed on bash_result.
|
|
1336
|
+
const run = document.createElement('span');
|
|
1337
|
+
run.className = 'bash-running';
|
|
1338
|
+
run.textContent = '⟳ running';
|
|
1339
|
+
div.querySelector('.tool-title')?.appendChild(run);
|
|
1340
|
+
// Stop button in the title row (TUI Ctrl+C equivalent): abort_bash
|
|
1341
|
+
// kills only this running bash. Removed when the block finalizes.
|
|
1342
|
+
const stopBtn = document.createElement('button');
|
|
1343
|
+
stopBtn.className = 'bash-stop-btn';
|
|
1344
|
+
stopBtn.textContent = '⏹ stop';
|
|
1345
|
+
stopBtn.title = 'Stop this bash command (Ctrl+C in TUI)';
|
|
1346
|
+
stopBtn.addEventListener('click', (e) => {
|
|
1347
|
+
e.stopPropagation(); // don't toggle expand
|
|
1348
|
+
this.send({ type: 'abort_bash' });
|
|
1349
|
+
stopBtn.disabled = true;
|
|
1350
|
+
stopBtn.textContent = 'stopping...';
|
|
1351
|
+
});
|
|
1352
|
+
div.querySelector('.tool-title')?.appendChild(stopBtn);
|
|
1353
|
+
// The running bash block lives in the #bash-pending area (between the
|
|
1354
|
+
// message flow and the input box) so later messages don't push it
|
|
1355
|
+
// out of view - same as TUI's pendingMessagesContainer. bash_result
|
|
1356
|
+
// moves it into the normal message flow when done.
|
|
1357
|
+
const bashPending = document.getElementById('bash-pending');
|
|
1358
|
+
if (bashPending) {
|
|
1359
|
+
bashPending.appendChild(div);
|
|
1360
|
+
// Area-level status line at the TAIL (always visible even when the
|
|
1361
|
+
// block's own title scrolled out of view while output streams).
|
|
1362
|
+
const statusLine = document.createElement('div');
|
|
1363
|
+
statusLine.className = 'bash-stream-status';
|
|
1364
|
+
statusLine.textContent = '⟳ running…';
|
|
1365
|
+
bashPending.appendChild(statusLine);
|
|
1366
|
+
bashPending.style.display = 'block';
|
|
1367
|
+
bashPending.scrollTop = bashPending.scrollHeight; // keep tail visible
|
|
1368
|
+
} else {
|
|
1369
|
+
this.contentEl.appendChild(div);
|
|
1370
|
+
}
|
|
1334
1371
|
this.bashEls.set(key, div);
|
|
1335
1372
|
}
|
|
1336
1373
|
// Append the delta to the full text and re-apply the preview (respects
|
|
@@ -1338,6 +1375,12 @@ class PiWebClient {
|
|
|
1338
1375
|
const full = (div.dataset.fullOutput || '') + delta;
|
|
1339
1376
|
div.dataset.fullOutput = full;
|
|
1340
1377
|
this.applyToolPreview(div);
|
|
1378
|
+
// Keep the stream tail (and its running status line) visible inside the
|
|
1379
|
+
// pending area while output is coming in.
|
|
1380
|
+
const bashPending = document.getElementById('bash-pending');
|
|
1381
|
+
if (bashPending && bashPending.contains(div)) {
|
|
1382
|
+
bashPending.scrollTop = bashPending.scrollHeight;
|
|
1383
|
+
}
|
|
1341
1384
|
if (this.wasAtBottom()) this.scrollToBottom();
|
|
1342
1385
|
}
|
|
1343
1386
|
|
|
@@ -1355,6 +1398,22 @@ class PiWebClient {
|
|
|
1355
1398
|
if (!(div.dataset.fullOutput && div.dataset.fullOutput.length > 0)) {
|
|
1356
1399
|
this.setToolOutput(div, output);
|
|
1357
1400
|
}
|
|
1401
|
+
// Move the finished block from the bash-pending (fixed) area into the
|
|
1402
|
+
// normal message flow, keeping its accumulated output.
|
|
1403
|
+
const bashPending = document.getElementById('bash-pending');
|
|
1404
|
+
if (bashPending && bashPending.contains(div)) {
|
|
1405
|
+
this.contentEl.appendChild(div);
|
|
1406
|
+
// Remove the area-level running status line, then hide the empty area.
|
|
1407
|
+
bashPending.querySelectorAll('.bash-stream-status').forEach((el) => el.remove());
|
|
1408
|
+
if (bashPending.children.length === 0) {
|
|
1409
|
+
bashPending.style.display = 'none';
|
|
1410
|
+
}
|
|
1411
|
+
this.scrollToBottom();
|
|
1412
|
+
}
|
|
1413
|
+
// Bash done: the running indicator and stop button are no longer
|
|
1414
|
+
// relevant.
|
|
1415
|
+
div.querySelector('.bash-running')?.remove();
|
|
1416
|
+
div.querySelector('.bash-stop-btn')?.remove();
|
|
1358
1417
|
|
|
1359
1418
|
const isError = result.exitCode !== undefined && result.exitCode !== 0;
|
|
1360
1419
|
div.className = isError ? 'tool-block error' : 'tool-block success';
|
package/dist/static/index.html
CHANGED
package/dist/static/style.css
CHANGED
|
@@ -544,6 +544,75 @@ body {
|
|
|
544
544
|
font-size: 12px;
|
|
545
545
|
}
|
|
546
546
|
|
|
547
|
+
/* Running !/!! bash output (streaming) - fixed area between messages and
|
|
548
|
+
input, so later messages don't push it out of view (TUI analog:
|
|
549
|
+
pendingMessagesContainer). Moved into the message flow on completion. */
|
|
550
|
+
#bash-pending {
|
|
551
|
+
display: none;
|
|
552
|
+
padding: 8px 12px;
|
|
553
|
+
margin: 6px 8px 4px;
|
|
554
|
+
border: 1px solid var(--border);
|
|
555
|
+
border-radius: 6px;
|
|
556
|
+
background: var(--code-bg);
|
|
557
|
+
font-size: 13px;
|
|
558
|
+
/* ~10 lines of output visible; scrolling inside the block for more */
|
|
559
|
+
max-height: calc(10 * 1.5em);
|
|
560
|
+
overflow-y: auto;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.bash-stop-btn {
|
|
564
|
+
margin-left: 8px;
|
|
565
|
+
padding: 1px 8px;
|
|
566
|
+
font-size: 11px;
|
|
567
|
+
color: var(--error);
|
|
568
|
+
border: 1px solid var(--error);
|
|
569
|
+
border-radius: 4px;
|
|
570
|
+
background: transparent;
|
|
571
|
+
cursor: pointer;
|
|
572
|
+
vertical-align: middle;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.bash-running {
|
|
576
|
+
margin-left: 8px;
|
|
577
|
+
font-size: 11px;
|
|
578
|
+
color: var(--accent);
|
|
579
|
+
vertical-align: middle;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
.bash-running::before {
|
|
583
|
+
content: '⟳';
|
|
584
|
+
display: inline-block;
|
|
585
|
+
margin-right: 4px;
|
|
586
|
+
animation: bash-spin 1s linear infinite;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
@keyframes bash-spin {
|
|
590
|
+
from { transform: rotate(0deg); }
|
|
591
|
+
to { transform: rotate(360deg); }
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.bash-stream-status {
|
|
595
|
+
margin-top: 2px;
|
|
596
|
+
font-size: 11px;
|
|
597
|
+
color: var(--accent);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
.bash-stream-status::before {
|
|
601
|
+
content: '⟳';
|
|
602
|
+
display: inline-block;
|
|
603
|
+
margin-right: 4px;
|
|
604
|
+
animation: bash-spin 1s linear infinite;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
.bash-stop-btn:hover {
|
|
608
|
+
background: color-mix(in srgb, var(--error) 15%, transparent);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.bash-stop-btn:disabled {
|
|
612
|
+
opacity: 0.6;
|
|
613
|
+
cursor: default;
|
|
614
|
+
}
|
|
615
|
+
|
|
547
616
|
.widget-block {
|
|
548
617
|
margin: 2px 0;
|
|
549
618
|
}
|