pilotswarm-cli 0.1.7 → 0.1.8
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/cli/tui.js +84 -0
- package/package.json +1 -1
package/cli/tui.js
CHANGED
|
@@ -2683,6 +2683,7 @@ function recolorWorkerPanes() {
|
|
|
2683
2683
|
|
|
2684
2684
|
function showCopilotMessage(raw, orchId) {
|
|
2685
2685
|
const _ph = perfStart("showCopilotMessage");
|
|
2686
|
+
stopChatSpinner(orchId);
|
|
2686
2687
|
|
|
2687
2688
|
appendActivity(`{green-fg}[obs] showCopilotMessage called for ${orchId === activeOrchId ? "ACTIVE" : "background"} session, len=${raw?.length || 0}{/green-fg}`, orchId);
|
|
2688
2689
|
|
|
@@ -3543,6 +3544,60 @@ const sessionRecoveredTurnResult = new Map(); // orchId → normalized completed
|
|
|
3543
3544
|
const sessionObservers = new Map(); // orchId → AbortController
|
|
3544
3545
|
const sessionLiveStatus = new Map(); // orchId → "idle"|"running"|"waiting"|"input_required"
|
|
3545
3546
|
const sessionPendingTurns = new Set(); // orchIds with a locally-sent turn awaiting first live status
|
|
3547
|
+
|
|
3548
|
+
// ─── Inline chat spinner ─────────────────────────────────────────
|
|
3549
|
+
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
3550
|
+
const sessionSpinnerIndex = new Map(); // orchId → buffer line index where spinner lives
|
|
3551
|
+
let _spinnerFrame = 0;
|
|
3552
|
+
let _spinnerTimer = null;
|
|
3553
|
+
|
|
3554
|
+
function startChatSpinner(orchId) {
|
|
3555
|
+
const buf = sessionChatBuffers.get(orchId);
|
|
3556
|
+
if (!buf) return;
|
|
3557
|
+
// Remove existing spinner if any
|
|
3558
|
+
stopChatSpinner(orchId);
|
|
3559
|
+
const line = `{gray-fg}${SPINNER_FRAMES[0]} Thinking…{/gray-fg}`;
|
|
3560
|
+
buf.push("");
|
|
3561
|
+
buf.push(line);
|
|
3562
|
+
sessionSpinnerIndex.set(orchId, buf.length - 1);
|
|
3563
|
+
if (orchId === activeOrchId) invalidateChat("bottom");
|
|
3564
|
+
// Start global animation timer if not running
|
|
3565
|
+
if (!_spinnerTimer) {
|
|
3566
|
+
_spinnerTimer = setInterval(() => {
|
|
3567
|
+
_spinnerFrame = (_spinnerFrame + 1) % SPINNER_FRAMES.length;
|
|
3568
|
+
let anyActive = false;
|
|
3569
|
+
for (const [sid, idx] of sessionSpinnerIndex) {
|
|
3570
|
+
const b = sessionChatBuffers.get(sid);
|
|
3571
|
+
if (b && idx < b.length) {
|
|
3572
|
+
b[idx] = `{gray-fg}${SPINNER_FRAMES[_spinnerFrame]} Thinking…{/gray-fg}`;
|
|
3573
|
+
if (sid === activeOrchId) { invalidateChat(); anyActive = true; }
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
if (!anyActive && sessionSpinnerIndex.size === 0) {
|
|
3577
|
+
clearInterval(_spinnerTimer);
|
|
3578
|
+
_spinnerTimer = null;
|
|
3579
|
+
}
|
|
3580
|
+
}, 80);
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
|
|
3584
|
+
function stopChatSpinner(orchId) {
|
|
3585
|
+
const idx = sessionSpinnerIndex.get(orchId);
|
|
3586
|
+
if (idx == null) return;
|
|
3587
|
+
const buf = sessionChatBuffers.get(orchId);
|
|
3588
|
+
if (buf && idx < buf.length) {
|
|
3589
|
+
// Remove spinner line and the blank line before it
|
|
3590
|
+
const startIdx = (idx > 0 && buf[idx - 1] === "") ? idx - 1 : idx;
|
|
3591
|
+
buf.splice(startIdx, idx - startIdx + 1);
|
|
3592
|
+
}
|
|
3593
|
+
sessionSpinnerIndex.delete(orchId);
|
|
3594
|
+
if (orchId === activeOrchId) invalidateChat();
|
|
3595
|
+
// Stop global timer if no spinners remain
|
|
3596
|
+
if (sessionSpinnerIndex.size === 0 && _spinnerTimer) {
|
|
3597
|
+
clearInterval(_spinnerTimer);
|
|
3598
|
+
_spinnerTimer = null;
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3546
3601
|
const sessionPendingQuestions = new Map(); // orchId → latest input-required question awaiting a user answer
|
|
3547
3602
|
const sessionLastSeenResponseVersion = new Map(); // orchId → latest KV-backed response version rendered
|
|
3548
3603
|
const sessionLastSeenCommandVersion = new Map(); // orchId → latest KV-backed command response version rendered
|
|
@@ -3756,6 +3811,33 @@ function handleDbRecovered() {
|
|
|
3756
3811
|
if (_dbOffline) {
|
|
3757
3812
|
appendLog(`{green-fg}Database connection restored.{/green-fg}`);
|
|
3758
3813
|
setStatus("Database connection restored.");
|
|
3814
|
+
|
|
3815
|
+
// The orchestration list poll uses its own management client pool, but
|
|
3816
|
+
// the active session's CMS event stream and reconstructed history may
|
|
3817
|
+
// still be stale after a DB outage. Re-prime the active session view so
|
|
3818
|
+
// chat/activity panes resume updating without requiring a manual switch.
|
|
3819
|
+
const recoveredOrchId = activeOrchId;
|
|
3820
|
+
if (recoveredOrchId) {
|
|
3821
|
+
stopCmsPoller();
|
|
3822
|
+
loadCmsHistory(recoveredOrchId, { force: true })
|
|
3823
|
+
.then(() => {
|
|
3824
|
+
if (recoveredOrchId === activeOrchId) {
|
|
3825
|
+
startCmsPoller(recoveredOrchId);
|
|
3826
|
+
invalidateChat();
|
|
3827
|
+
invalidateActivity();
|
|
3828
|
+
redrawActiveViews();
|
|
3829
|
+
scheduleLightRefresh("dbRecovered", recoveredOrchId);
|
|
3830
|
+
}
|
|
3831
|
+
})
|
|
3832
|
+
.catch(() => {
|
|
3833
|
+
if (recoveredOrchId === activeOrchId) {
|
|
3834
|
+
startCmsPoller(recoveredOrchId);
|
|
3835
|
+
invalidateChat();
|
|
3836
|
+
invalidateActivity();
|
|
3837
|
+
redrawActiveViews();
|
|
3838
|
+
}
|
|
3839
|
+
});
|
|
3840
|
+
}
|
|
3759
3841
|
}
|
|
3760
3842
|
_dbOffline = false;
|
|
3761
3843
|
_dbNextRetryAt = 0;
|
|
@@ -5205,6 +5287,7 @@ function startObserver(orchId) {
|
|
|
5205
5287
|
|
|
5206
5288
|
function renderResponsePayload(response, cs, source) {
|
|
5207
5289
|
if (!response) return;
|
|
5290
|
+
stopChatSpinner(orchId);
|
|
5208
5291
|
if (response.type === "completed" && response.content) {
|
|
5209
5292
|
appendActivity(`{green-fg}[obs] ✓ SHOWING ${source}: version=${response.version} type=completed content=${response.content.slice(0, 80)}{/green-fg}`, orchId);
|
|
5210
5293
|
renderCompletedContent(response.content);
|
|
@@ -6121,6 +6204,7 @@ async function handleInput(text) {
|
|
|
6121
6204
|
}
|
|
6122
6205
|
|
|
6123
6206
|
appendChatRaw(`{white-fg}[${ts()}]{/white-fg} {white-fg}{bold}You:{/bold} ${trimmed}{/white-fg}`, targetOrchId);
|
|
6207
|
+
startChatSpinner(targetOrchId);
|
|
6124
6208
|
inputBar.clearValue();
|
|
6125
6209
|
focusInput();
|
|
6126
6210
|
setSessionPendingTurn(targetOrchId, true);
|