pilotswarm 0.5.0 → 0.5.1
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/package.json +2 -2
- package/tui/src/app.js +36 -5
- package/ui/core/src/commands.js +6 -0
- package/ui/core/src/controller.js +137 -2
- package/ui/core/src/reducer.js +31 -1
- package/ui/core/src/selectors.js +391 -15
- package/ui/core/src/state.js +2 -0
- package/ui/react/src/chat-status.js +22 -0
- package/ui/react/src/components.js +68 -6
- package/ui/react/src/web-app.js +18 -2
- package/web/dist/assets/{index-B8ge3rzb.js → index-BmqU2WsR.js} +2 -2
- package/web/dist/assets/{index-DXRIxmIv.css → index-D2-7fi56.css} +1 -1
- package/web/dist/assets/pilotswarm-cIaYAE9e.js +90 -0
- package/web/dist/assets/{react-IRUjK5Iz.js → react-CRYBfNR4.js} +1 -1
- package/web/dist/index.html +4 -4
- package/web/dist/assets/pilotswarm-Dt1qY6hD.js +0 -90
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { appendAnimatedDotsToRuns, useAnimatedDots } from "./chat-status.js";
|
|
2
|
+
import { appendAnimatedDotsToRuns, useAnimatedDots, useSpinnerFrame } from "./chat-status.js";
|
|
3
3
|
import {
|
|
4
4
|
applyActiveHighlightRuns,
|
|
5
5
|
computeLegacyLayout,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
selectAdminConsole,
|
|
9
9
|
selectAdminGhcpKeyEditorModal,
|
|
10
10
|
selectChatPaneChrome,
|
|
11
|
+
selectLiveActivityLines,
|
|
11
12
|
selectChatLines,
|
|
12
13
|
selectActivityPane,
|
|
13
14
|
selectArtifactUploadModal,
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
selectSessionOwnerFilterModal,
|
|
28
29
|
selectStatusBar,
|
|
29
30
|
selectThemePickerModal,
|
|
31
|
+
selectHelpModal,
|
|
30
32
|
selectConfirmModal,
|
|
31
33
|
selectVisibleSessionRows,
|
|
32
34
|
} from "pilotswarm/ui-core";
|
|
@@ -375,6 +377,20 @@ const ChatPane = React.memo(function ChatPane({ controller, width, height, frame
|
|
|
375
377
|
{ text: "Check env credentials and model provider config, then relaunch.", color: "yellow" },
|
|
376
378
|
]
|
|
377
379
|
: selectChatLines(selectorState, contentWidth)), [chatView.branding.splash, chatView.connectionError, contentWidth, selectorState, startupError]);
|
|
380
|
+
const running = String(chatView.activeSession?.status || "").toLowerCase() === "running";
|
|
381
|
+
const spinnerFrame = useSpinnerFrame(running);
|
|
382
|
+
const liveActivityLines = React.useMemo(
|
|
383
|
+
() => (startupError ? [] : selectLiveActivityLines(selectorState, { spinnerFrame, maxWidth: contentWidth })),
|
|
384
|
+
[selectorState, startupError, spinnerFrame, contentWidth],
|
|
385
|
+
);
|
|
386
|
+
// Concat the isolated live-activity block so the spinner tick only recomputes
|
|
387
|
+
// the small block, not the whole transcript.
|
|
388
|
+
const chatLines = React.useMemo(
|
|
389
|
+
() => (liveActivityLines.length > 0
|
|
390
|
+
? [...elements, [{ text: "", color: null }], ...liveActivityLines]
|
|
391
|
+
: elements),
|
|
392
|
+
[elements, liveActivityLines],
|
|
393
|
+
);
|
|
378
394
|
|
|
379
395
|
return React.createElement(platform.Panel, {
|
|
380
396
|
title: chrome.title,
|
|
@@ -383,7 +399,7 @@ const ChatPane = React.memo(function ChatPane({ controller, width, height, frame
|
|
|
383
399
|
focused: chatView.focused,
|
|
384
400
|
width,
|
|
385
401
|
height,
|
|
386
|
-
lines:
|
|
402
|
+
lines: chatLines,
|
|
387
403
|
scrollOffset: chatView.chatScroll,
|
|
388
404
|
scrollMode: "bottom",
|
|
389
405
|
paneId: "chat",
|
|
@@ -568,6 +584,8 @@ const InspectorSequencePane = React.memo(function InspectorSequencePane({ contro
|
|
|
568
584
|
? state.orchestration.bySessionId?.[state.sessions.activeSessionId] || null
|
|
569
585
|
: null,
|
|
570
586
|
histories: state.history.bySessionId,
|
|
587
|
+
expandedTurns: state.ui.sequenceExpandedTurns,
|
|
588
|
+
selectedTurn: state.ui.sequenceSelectedTurn,
|
|
571
589
|
}), shallowEqualObject);
|
|
572
590
|
const selectorState = React.useMemo(() => ({
|
|
573
591
|
sessions: {
|
|
@@ -592,8 +610,14 @@ const InspectorSequencePane = React.memo(function InspectorSequencePane({ contro
|
|
|
592
610
|
sequenceState.histories,
|
|
593
611
|
]);
|
|
594
612
|
const inspector = React.useMemo(
|
|
595
|
-
() => selectInspector(selectorState, {
|
|
596
|
-
|
|
613
|
+
() => selectInspector(selectorState, {
|
|
614
|
+
width: contentWidth,
|
|
615
|
+
sequenceExpansion: {
|
|
616
|
+
expandedTurns: sequenceState.expandedTurns || [],
|
|
617
|
+
selectedTurn: sequenceState.selectedTurn ?? null,
|
|
618
|
+
},
|
|
619
|
+
}),
|
|
620
|
+
[contentWidth, selectorState, sequenceState.expandedTurns, sequenceState.selectedTurn],
|
|
597
621
|
);
|
|
598
622
|
|
|
599
623
|
return renderInspectorPanel(platform, inspector, meta, width, height, frame);
|
|
@@ -1497,6 +1521,41 @@ function ArtifactPickerModalContainer({ controller }) {
|
|
|
1497
1521
|
return React.createElement(ArtifactPickerModal, { state });
|
|
1498
1522
|
}
|
|
1499
1523
|
|
|
1524
|
+
function HelpModal({ state }) {
|
|
1525
|
+
const platform = useUiPlatform();
|
|
1526
|
+
const modal = selectHelpModal(state);
|
|
1527
|
+
if (!modal) return null;
|
|
1528
|
+
const viewport = typeof platform.getViewport === "function"
|
|
1529
|
+
? platform.getViewport()
|
|
1530
|
+
: { width: 120, height: 40 };
|
|
1531
|
+
const width = Math.max(56, Math.min(modal.idealWidth || 80, (viewport.width || 120) - 8));
|
|
1532
|
+
const height = Math.max(10, Math.min(modal.rows.length + 2, (viewport.height || 40) - 6));
|
|
1533
|
+
const contentRows = Math.max(1, height - 2);
|
|
1534
|
+
const maxOffset = Math.max(0, modal.rows.length - contentRows);
|
|
1535
|
+
const scrollOffset = Math.max(0, Math.min(modal.selectedRowIndex - Math.floor(contentRows / 2), maxOffset));
|
|
1536
|
+
return React.createElement(platform.Overlay, null,
|
|
1537
|
+
React.createElement(platform.Column, { width },
|
|
1538
|
+
React.createElement(platform.Panel, {
|
|
1539
|
+
title: modal.title,
|
|
1540
|
+
color: "cyan",
|
|
1541
|
+
focused: false,
|
|
1542
|
+
width,
|
|
1543
|
+
height,
|
|
1544
|
+
lines: modal.rows,
|
|
1545
|
+
scrollOffset,
|
|
1546
|
+
scrollMode: "top",
|
|
1547
|
+
fillColor: "surface",
|
|
1548
|
+
}),
|
|
1549
|
+
));
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
function HelpModalContainer({ controller }) {
|
|
1553
|
+
const state = useControllerSelector(controller, (rootState) => ({
|
|
1554
|
+
ui: { modal: rootState.ui.modal },
|
|
1555
|
+
}), shallowEqualObject);
|
|
1556
|
+
return React.createElement(HelpModal, { state });
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1500
1559
|
function renderFilterModal(platform, modal) {
|
|
1501
1560
|
if (!modal) return null;
|
|
1502
1561
|
const viewport = typeof platform.getViewport === "function"
|
|
@@ -1849,6 +1908,8 @@ export function SharedPilotSwarmApp({ controller, versionLabel = null }) {
|
|
|
1849
1908
|
const platform = useUiPlatform();
|
|
1850
1909
|
const layoutState = useControllerSelector(controller, (state) => ({
|
|
1851
1910
|
paneAdjust: state.ui.layout?.paneAdjust ?? 0,
|
|
1911
|
+
sessionPaneAdjust: state.ui.layout?.sessionPaneAdjust ?? 0,
|
|
1912
|
+
activityPaneAdjust: state.ui.layout?.activityPaneAdjust ?? 0,
|
|
1852
1913
|
promptRows: getPromptInputRows(state.ui.prompt),
|
|
1853
1914
|
inspectorTab: state.ui.inspectorTab,
|
|
1854
1915
|
filesFullscreen: Boolean(state.files?.fullscreen),
|
|
@@ -1862,8 +1923,8 @@ export function SharedPilotSwarmApp({ controller, versionLabel = null }) {
|
|
|
1862
1923
|
const viewportWidth = layoutState.viewportWidth;
|
|
1863
1924
|
const viewportHeight = layoutState.viewportHeight;
|
|
1864
1925
|
const layout = React.useMemo(
|
|
1865
|
-
() => computeLegacyLayout({ width: viewportWidth, height: viewportHeight }, layoutState.paneAdjust, layoutState.promptRows,
|
|
1866
|
-
[layoutState.fullscreenPane, layoutState.paneAdjust, layoutState.promptRows, viewportHeight, viewportWidth],
|
|
1926
|
+
() => computeLegacyLayout({ width: viewportWidth, height: viewportHeight }, layoutState.paneAdjust, layoutState.promptRows, layoutState.sessionPaneAdjust, layoutState.activityPaneAdjust, layoutState.fullscreenPane),
|
|
1927
|
+
[layoutState.fullscreenPane, layoutState.paneAdjust, layoutState.sessionPaneAdjust, layoutState.activityPaneAdjust, layoutState.promptRows, viewportHeight, viewportWidth],
|
|
1867
1928
|
);
|
|
1868
1929
|
const frames = buildWorkspacePaneFrames(layout);
|
|
1869
1930
|
const sessionRows = Math.max(3, (layout.fullscreenPane === "sessions" ? layout.bodyHeight : layout.sessionPaneHeight) - 2);
|
|
@@ -1973,6 +2034,7 @@ export function SharedPilotSwarmApp({ controller, versionLabel = null }) {
|
|
|
1973
2034
|
React.createElement(RenameSessionModalContainer, { controller }),
|
|
1974
2035
|
React.createElement(ArtifactUploadModalContainer, { controller }),
|
|
1975
2036
|
React.createElement(ArtifactPickerModalContainer, { controller }),
|
|
2037
|
+
React.createElement(HelpModalContainer, { controller }),
|
|
1976
2038
|
React.createElement(ModelPickerModalContainer, { controller }),
|
|
1977
2039
|
React.createElement(ReasoningEffortPickerModalContainer, { controller }),
|
|
1978
2040
|
React.createElement(ThemePickerModalContainer, { controller }),
|
package/ui/react/src/web-app.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { appendAnimatedDotsToRuns, useAnimatedDots } from "./chat-status.js";
|
|
2
|
+
import { appendAnimatedDotsToRuns, useAnimatedDots, useSpinnerFrame } from "./chat-status.js";
|
|
3
3
|
import {
|
|
4
4
|
UI_COMMANDS,
|
|
5
5
|
INSPECTOR_TABS,
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
selectAdminConsole,
|
|
18
18
|
selectArtifactPickerModal,
|
|
19
19
|
selectArtifactUploadModal,
|
|
20
|
+
selectLiveActivityLines,
|
|
20
21
|
selectChatLines,
|
|
21
22
|
selectChatPaneChrome,
|
|
22
23
|
selectOutboxOverlayLines,
|
|
@@ -2059,6 +2060,7 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
|
|
|
2059
2060
|
inspectorTab: state.ui.inspectorTab,
|
|
2060
2061
|
chatViewMode: state.ui.chatViewMode || "transcript",
|
|
2061
2062
|
activeSessionIsGroup: Boolean(activeSessionId && state.sessions.byId[activeSessionId]?.isGroup),
|
|
2063
|
+
activeSessionStatus: activeSessionId ? String(state.sessions.byId[activeSessionId]?.status || "").toLowerCase() : "",
|
|
2062
2064
|
focused: state.ui.focusRegion === "chat",
|
|
2063
2065
|
scroll: state.ui.scroll.chat,
|
|
2064
2066
|
contentWidth,
|
|
@@ -2110,6 +2112,20 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
|
|
|
2110
2112
|
() => selectChatLines(selectorState, viewState.contentWidth, { tableMode: "sentinel" }),
|
|
2111
2113
|
[selectorState, viewState.contentWidth],
|
|
2112
2114
|
);
|
|
2115
|
+
const spinnerFrame = useSpinnerFrame(viewState.activeSessionStatus === "running");
|
|
2116
|
+
const liveActivityLines = React.useMemo(
|
|
2117
|
+
() => selectLiveActivityLines(selectorState, { spinnerFrame, maxWidth: viewState.contentWidth }),
|
|
2118
|
+
[selectorState, spinnerFrame, viewState.contentWidth],
|
|
2119
|
+
);
|
|
2120
|
+
// Concatenate the isolated live-activity block onto the (expensive) message
|
|
2121
|
+
// lines so the spinner tick only recomputes the small block, not the whole
|
|
2122
|
+
// transcript. The block clears itself once the reply lands.
|
|
2123
|
+
const chatLines = React.useMemo(
|
|
2124
|
+
() => (liveActivityLines.length > 0
|
|
2125
|
+
? [...lines, [{ text: "", color: null }], ...liveActivityLines]
|
|
2126
|
+
: lines),
|
|
2127
|
+
[lines, liveActivityLines],
|
|
2128
|
+
);
|
|
2113
2129
|
const outboxLines = React.useMemo(
|
|
2114
2130
|
() => selectOutboxOverlayLines(selectorState, viewState.contentWidth, { tableMode: "sentinel" }),
|
|
2115
2131
|
[selectorState, viewState.contentWidth],
|
|
@@ -2128,7 +2144,7 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
|
|
|
2128
2144
|
actions: null,
|
|
2129
2145
|
color: chrome.color,
|
|
2130
2146
|
focused: viewState.focused,
|
|
2131
|
-
lines,
|
|
2147
|
+
lines: chatLines,
|
|
2132
2148
|
bottomStickyLines: outboxLines,
|
|
2133
2149
|
scrollOffset: viewState.scroll,
|
|
2134
2150
|
scrollMode: "bottom",
|