tmux-ide 2.9.0-beta.32 → 2.9.0-beta.33
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/bin/cli.js +1 -1
- package/package.json +1 -1
- package/packages/daemon/dist/tui/mirror/runtime/application-home-agent-roster.jsx +8 -1
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +8 -3
- package/packages/daemon/dist/tui/mirror/ui/agent-badge.jsx +7 -9
- package/packages/daemon/dist/tui/mirror/ui/agent-status-marker.js +61 -0
- package/packages/daemon/dist/tui/mirror/workspace/terminal-pane-header.jsx +1 -1
- package/packages/daemon/src/tui/mirror/runtime/__snapshots__/application-shell-view-renderer.test.tsx.snap +4 -4
- package/packages/daemon/src/tui/mirror/runtime/application-home-agent-roster.tsx +8 -1
- package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +8 -3
- package/packages/daemon/src/tui/mirror/runtime/application-shell-sidebar.tsx +8 -1
- package/packages/daemon/src/tui/mirror/ui/agent-badge.tsx +9 -6
- package/packages/daemon/src/tui/mirror/ui/agent-status-marker.ts +69 -0
- package/packages/daemon/src/tui/mirror/workspace/terminal-pane-header.tsx +1 -0
package/bin/cli.js
CHANGED
|
@@ -11279,7 +11279,7 @@ var require_package = __commonJS({
|
|
|
11279
11279
|
"package.json"(exports, module) {
|
|
11280
11280
|
module.exports = {
|
|
11281
11281
|
name: "tmux-ide",
|
|
11282
|
-
version: "2.9.0-beta.
|
|
11282
|
+
version: "2.9.0-beta.33",
|
|
11283
11283
|
description: "A visual, agent-aware IDE for any tmux session, with optional workspace presets",
|
|
11284
11284
|
type: "module",
|
|
11285
11285
|
bin: {
|
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import { TuiButton } from "../ui/button.jsx";
|
|
|
6
6
|
import { useKeyboardRoute } from "../ui/keyboard-router.jsx";
|
|
7
7
|
import { applicationPaneRenameKeyAction, applicationPaneRenamePaste, } from "./application-pane-rename-input.js";
|
|
8
8
|
import { HomeAgentSearch } from "../ui/home-agent-search.jsx";
|
|
9
|
+
import { createAgentStatusMarker } from "../ui/agent-status-marker.js";
|
|
9
10
|
import { ActivityIndicator } from "../ui/activity-indicator.jsx";
|
|
10
11
|
import { componentPalette } from "../ui/state.js";
|
|
11
12
|
import { homeAgentStatusLabel, } from "./application-home-agents.js";
|
|
@@ -181,6 +182,12 @@ export function HomeAgentRoster(props) {
|
|
|
181
182
|
<For each={keys()}>
|
|
182
183
|
{(key) => {
|
|
183
184
|
const row = () => byKey().get(key);
|
|
185
|
+
const marker = createAgentStatusMarker({
|
|
186
|
+
theme: () => props.theme,
|
|
187
|
+
status: () => row().activity,
|
|
188
|
+
attention: () => row().attention,
|
|
189
|
+
unavailable: () => stale(row()),
|
|
190
|
+
});
|
|
184
191
|
return (<box height={rowHeight()} flexDirection="column" backgroundColor={componentPalette(props.theme, {
|
|
185
192
|
selected: props.selection.selectedKey === key,
|
|
186
193
|
disabled: row().paneId === null || stale(row()),
|
|
@@ -197,7 +204,7 @@ export function HomeAgentRoster(props) {
|
|
|
197
204
|
: padCells(row().name, columns().agent) +
|
|
198
205
|
padCells([row().machineLabel, row().serverLabel, row().sessionName]
|
|
199
206
|
.filter(Boolean)
|
|
200
|
-
.join(" / "), columns().session)} detail={padCells(`${
|
|
207
|
+
.join(" / "), columns().session)} detail={padCells(`${marker()} ${stale(row()) ? "last seen" : homeAgentStatusLabel(row().activity).toLowerCase()}`, columns().status)} detailAlign="end" marker=" " selected={props.selection.selectedKey === key} focused={props.inputActive && !editing() && props.selection.selectedKey === key} hovered={hovered() === key} status={stale(row()) ? "unknown" : statusTone(row())} disabled={row().paneId === null || stale(row())} onActivate={(source) => {
|
|
201
208
|
if (!props.inputActive || row().paneId === null || stale(row()))
|
|
202
209
|
return;
|
|
203
210
|
props.onSelect(key);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createAgentStatusMarker } from "../ui/agent-status-marker.js";
|
|
1
2
|
import { fleetHostColor, summarizeFleetActivity } from "./fleet-presentation.js";
|
|
2
3
|
import { TuiButton } from "../ui/button.jsx";
|
|
3
4
|
/* @jsxImportSource @opentui/solid */
|
|
@@ -345,6 +346,12 @@ export function ApplicationMachineSidebar(props) {
|
|
|
345
346
|
return current().agentHeading;
|
|
346
347
|
},
|
|
347
348
|
};
|
|
349
|
+
const agentMarker = createAgentStatusMarker({
|
|
350
|
+
theme: () => props.theme,
|
|
351
|
+
status: () => row.agent?.activity,
|
|
352
|
+
attention: () => Boolean(row.agent?.attention),
|
|
353
|
+
unavailable: () => row.group.state !== "ready" || Boolean(row.agent?.disabled),
|
|
354
|
+
});
|
|
348
355
|
return (<box width={Math.max(1, props.width - 1)} height={rowHeight(row)} flexShrink={0} flexDirection="column">
|
|
349
356
|
<box height={sectionGap(row)} flexShrink={0}/>
|
|
350
357
|
<Show when={row.serverHeading}>
|
|
@@ -368,9 +375,7 @@ export function ApplicationMachineSidebar(props) {
|
|
|
368
375
|
: row.group.label} marker={row.server
|
|
369
376
|
? " "
|
|
370
377
|
: row.agent
|
|
371
|
-
?
|
|
372
|
-
? "!"
|
|
373
|
-
: " "
|
|
378
|
+
? agentMarker()
|
|
374
379
|
: row.session
|
|
375
380
|
? props.model.favorites?.().includes(row.session.id)
|
|
376
381
|
? " ★"
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
+
import { createAgentStatusMarker } from "./agent-status-marker.js";
|
|
1
2
|
import { Badge } from "./badge.jsx";
|
|
2
3
|
/** Agent-specific semantic badge. Agent lifecycle remains outside this presentation primitive. */
|
|
3
4
|
export function AgentBadge(props) {
|
|
4
|
-
const marker = (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return props.theme.glyphs.check;
|
|
11
|
-
return props.theme.glyphs.inactive;
|
|
12
|
-
};
|
|
5
|
+
const marker = createAgentStatusMarker({
|
|
6
|
+
theme: () => props.theme,
|
|
7
|
+
status: () => props.activity ?? props.status,
|
|
8
|
+
attention: () => Boolean(props.attention),
|
|
9
|
+
unavailable: () => Boolean(props.disabled),
|
|
10
|
+
});
|
|
13
11
|
return (<Badge theme={props.theme} label={props.label} tone={props.status} marker={marker()} width={props.width} selected={props.selected} focused={props.focused} hovered={props.hovered} pressed={props.pressed} disabled={props.disabled} attention={props.attention || props.status === "blocked"} loading={props.loading} empty={props.empty} status={props.status}/>);
|
|
14
12
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { batch, createEffect, createSignal, onCleanup } from "solid-js";
|
|
2
|
+
const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
3
|
+
const listeners = new Set();
|
|
4
|
+
let timer;
|
|
5
|
+
let frame = 0;
|
|
6
|
+
/** One clock for mounted working indicators, with no daemon or inventory work. */
|
|
7
|
+
function subscribe(listener) {
|
|
8
|
+
listeners.add(listener);
|
|
9
|
+
listener(frame);
|
|
10
|
+
if (!timer) {
|
|
11
|
+
timer = setInterval(() => {
|
|
12
|
+
frame = (frame + 1) % FRAMES.length;
|
|
13
|
+
batch(() => listeners.forEach((update) => update(frame)));
|
|
14
|
+
}, 80);
|
|
15
|
+
timer.unref?.();
|
|
16
|
+
}
|
|
17
|
+
return () => {
|
|
18
|
+
listeners.delete(listener);
|
|
19
|
+
if (listeners.size === 0 && timer) {
|
|
20
|
+
clearInterval(timer);
|
|
21
|
+
timer = undefined;
|
|
22
|
+
frame = 0;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** Presentation only: never infer activity from animation or process liveness. */
|
|
27
|
+
export function createAgentStatusMarker(options) {
|
|
28
|
+
const [current, setCurrent] = createSignal(0);
|
|
29
|
+
const working = () => options.status() === "running" || options.status() === "working";
|
|
30
|
+
const animated = () => working() &&
|
|
31
|
+
!options.attention?.() &&
|
|
32
|
+
!options.unavailable?.() &&
|
|
33
|
+
!options.theme().accessibility.reducedMotion;
|
|
34
|
+
createEffect(() => {
|
|
35
|
+
if (animated())
|
|
36
|
+
onCleanup(subscribe(setCurrent));
|
|
37
|
+
});
|
|
38
|
+
return () => {
|
|
39
|
+
if (options.unavailable?.())
|
|
40
|
+
return "·";
|
|
41
|
+
if (options.attention?.())
|
|
42
|
+
return "!";
|
|
43
|
+
switch (options.status()) {
|
|
44
|
+
case "running":
|
|
45
|
+
case "working":
|
|
46
|
+
return animated() ? FRAMES[current()] : options.theme().glyphs.active;
|
|
47
|
+
case "waiting":
|
|
48
|
+
case "blocked":
|
|
49
|
+
return "!";
|
|
50
|
+
case "complete":
|
|
51
|
+
case "done":
|
|
52
|
+
return options.theme().glyphs.check;
|
|
53
|
+
case "failed":
|
|
54
|
+
return "×";
|
|
55
|
+
case "idle":
|
|
56
|
+
return options.theme().glyphs.inactive;
|
|
57
|
+
default:
|
|
58
|
+
return "·";
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -153,7 +153,7 @@ export function PaneTitleBar(props) {
|
|
|
153
153
|
? "accent"
|
|
154
154
|
: "done"} selected={props.selected} focused={props.keyboardFocused || props.terminalFocused}/>)}
|
|
155
155
|
</Show>
|
|
156
|
-
{showBadge() ? (<AgentBadge theme={props.theme} label={statusLabel()} status={status()} width={badgeWidth(statusLabel())} selected={props.selected} focused={props.keyboardFocused || props.terminalFocused} hovered={hovered()} attention={props.attention}/>) : null}
|
|
156
|
+
{showBadge() ? (<AgentBadge theme={props.theme} label={statusLabel()} status={status()} activity={props.activity} width={badgeWidth(statusLabel())} selected={props.selected} focused={props.keyboardFocused || props.terminalFocused} hovered={hovered()} attention={props.attention}/>) : null}
|
|
157
157
|
{actionWidth() > 0 ? (<box width={actionWidth()} height={1} flexShrink={0}>
|
|
158
158
|
<IconButton theme={props.theme} icon={actionsVisible() ? "⋯" : " "} label="Pane actions" variant="ghost" width={actionWidth()} focused={props.menuFocused} selected={props.menuOpen} disabled={props.menuDisabled} background={palette().background} onPress={() => activateMenu()}/>
|
|
159
159
|
</box>) : null}
|
|
@@ -7,7 +7,7 @@ exports[`production ApplicationShellView retains shell, window strip, pane chrom
|
|
|
7
7
|
○ website CANONICAL-CELL
|
|
8
8
|
|
|
9
9
|
Agents
|
|
10
|
-
|
|
10
|
+
● Codex [WORKING]
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
@@ -23,7 +23,7 @@ exports[`production ApplicationShellView retains shell, window strip, pane chrom
|
|
|
23
23
|
○ website CANONICAL-CELL
|
|
24
24
|
|
|
25
25
|
Agents
|
|
26
|
-
|
|
26
|
+
● Codex [WORKING]
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
|
|
@@ -39,7 +39,7 @@ exports[`production ApplicationShellView retains shell, window strip, pane chrom
|
|
|
39
39
|
○ website CANONICAL-CELL
|
|
40
40
|
|
|
41
41
|
Agents
|
|
42
|
-
|
|
42
|
+
● Codex [WORKING]
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
|
|
@@ -76,7 +76,7 @@ exports[`production ApplicationShellView preserves canonical attention while pri
|
|
|
76
76
|
● main ● Codex ● working ⋯ ! Scout ! idle
|
|
77
77
|
CANONICAL-CELL CANONICAL-CELL
|
|
78
78
|
Agents
|
|
79
|
-
|
|
79
|
+
● Codex [WORKING]
|
|
80
80
|
! Scout ! [IDLE]
|
|
81
81
|
|
|
82
82
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
applicationPaneRenamePaste,
|
|
11
11
|
} from "./application-pane-rename-input.ts";
|
|
12
12
|
import { HomeAgentSearch } from "../ui/home-agent-search.tsx";
|
|
13
|
+
import { createAgentStatusMarker } from "../ui/agent-status-marker.ts";
|
|
13
14
|
import { ActivityIndicator } from "../ui/activity-indicator.tsx";
|
|
14
15
|
import { componentPalette, type ComponentInteractionState } from "../ui/state.ts";
|
|
15
16
|
import {
|
|
@@ -266,6 +267,12 @@ export function HomeAgentRoster(props: HomeAgentRosterProps) {
|
|
|
266
267
|
<For each={keys()}>
|
|
267
268
|
{(key) => {
|
|
268
269
|
const row = () => byKey().get(key)!;
|
|
270
|
+
const marker = createAgentStatusMarker({
|
|
271
|
+
theme: () => props.theme,
|
|
272
|
+
status: () => row().activity,
|
|
273
|
+
attention: () => row().attention,
|
|
274
|
+
unavailable: () => stale(row()),
|
|
275
|
+
});
|
|
269
276
|
return (
|
|
270
277
|
<box
|
|
271
278
|
height={rowHeight()}
|
|
@@ -305,7 +312,7 @@ export function HomeAgentRoster(props: HomeAgentRosterProps) {
|
|
|
305
312
|
)
|
|
306
313
|
}
|
|
307
314
|
detail={padCells(
|
|
308
|
-
`${
|
|
315
|
+
`${marker()} ${stale(row()) ? "last seen" : homeAgentStatusLabel(row().activity).toLowerCase()}`,
|
|
309
316
|
columns().status,
|
|
310
317
|
)}
|
|
311
318
|
detailAlign="end"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createAgentStatusMarker } from "../ui/agent-status-marker.ts";
|
|
1
2
|
import type { TmuxServerDescriptor, TmuxServerScope } from "@tmux-ide/contracts";
|
|
2
3
|
import { fleetHostColor, summarizeFleetActivity } from "./fleet-presentation.ts";
|
|
3
4
|
import { TuiButton } from "../ui/button.tsx";
|
|
@@ -528,6 +529,12 @@ export function ApplicationMachineSidebar(props: {
|
|
|
528
529
|
return current().agentHeading;
|
|
529
530
|
},
|
|
530
531
|
};
|
|
532
|
+
const agentMarker = createAgentStatusMarker({
|
|
533
|
+
theme: () => props.theme,
|
|
534
|
+
status: () => row.agent?.activity,
|
|
535
|
+
attention: () => Boolean(row.agent?.attention),
|
|
536
|
+
unavailable: () => row.group.state !== "ready" || Boolean(row.agent?.disabled),
|
|
537
|
+
});
|
|
531
538
|
return (
|
|
532
539
|
<box
|
|
533
540
|
width={Math.max(1, props.width - 1)}
|
|
@@ -573,9 +580,7 @@ export function ApplicationMachineSidebar(props: {
|
|
|
573
580
|
row.server
|
|
574
581
|
? " "
|
|
575
582
|
: row.agent
|
|
576
|
-
?
|
|
577
|
-
? "!"
|
|
578
|
-
: " "
|
|
583
|
+
? agentMarker()
|
|
579
584
|
: row.session
|
|
580
585
|
? props.model.favorites?.().includes(row.session.id)
|
|
581
586
|
? " ★"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createAgentStatusMarker } from "../ui/agent-status-marker.ts";
|
|
1
2
|
/* @jsxImportSource @opentui/solid */
|
|
2
3
|
import type { AgentActivity } from "@tmux-ide/contracts";
|
|
3
4
|
import type { JSX } from "solid-js";
|
|
@@ -156,6 +157,12 @@ export function ApplicationSidebarAgents(
|
|
|
156
157
|
<For each={props.shell.semantic.sidebar.agents}>
|
|
157
158
|
{(agent) => {
|
|
158
159
|
const status = () => agentStatus(agent.activity);
|
|
160
|
+
const marker = createAgentStatusMarker({
|
|
161
|
+
theme: () => props.theme,
|
|
162
|
+
status: () => agent.activity,
|
|
163
|
+
attention: () => agent.attention,
|
|
164
|
+
unavailable: () => !agent.paneId,
|
|
165
|
+
});
|
|
159
166
|
return (
|
|
160
167
|
<NavigationRow
|
|
161
168
|
theme={props.theme}
|
|
@@ -165,7 +172,7 @@ export function ApplicationSidebarAgents(
|
|
|
165
172
|
detailMarker={agent.attention ? "!" : undefined}
|
|
166
173
|
detailAlign="adjacent"
|
|
167
174
|
width={rowWidth()}
|
|
168
|
-
marker={
|
|
175
|
+
marker={marker()}
|
|
169
176
|
focused={sidebarFocused() && agent.paneId === focusedAgentPane()}
|
|
170
177
|
status={status()}
|
|
171
178
|
attention={agent.attention || status() === "blocked"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* @jsxImportSource @opentui/solid */
|
|
2
|
+
import type { AgentActivity } from "@tmux-ide/contracts";
|
|
2
3
|
import type { SemanticThemeSnapshot } from "../theme.ts";
|
|
4
|
+
import { createAgentStatusMarker } from "./agent-status-marker.ts";
|
|
3
5
|
import { Badge } from "./badge.tsx";
|
|
4
6
|
import type { ComponentInteractionState } from "./state.ts";
|
|
5
7
|
|
|
@@ -9,17 +11,18 @@ export interface AgentBadgeProps extends ComponentInteractionState {
|
|
|
9
11
|
theme: SemanticThemeSnapshot;
|
|
10
12
|
label: string;
|
|
11
13
|
status: AgentBadgeStatus;
|
|
14
|
+
activity?: AgentActivity;
|
|
12
15
|
width?: number;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
/** Agent-specific semantic badge. Agent lifecycle remains outside this presentation primitive. */
|
|
16
19
|
export function AgentBadge(props: AgentBadgeProps) {
|
|
17
|
-
const marker = (
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
};
|
|
20
|
+
const marker = createAgentStatusMarker({
|
|
21
|
+
theme: () => props.theme,
|
|
22
|
+
status: () => props.activity ?? props.status,
|
|
23
|
+
attention: () => Boolean(props.attention),
|
|
24
|
+
unavailable: () => Boolean(props.disabled),
|
|
25
|
+
});
|
|
23
26
|
return (
|
|
24
27
|
<Badge
|
|
25
28
|
theme={props.theme}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { batch, createEffect, createSignal, onCleanup } from "solid-js";
|
|
2
|
+
import type { AgentActivity } from "@tmux-ide/contracts";
|
|
3
|
+
import type { SemanticThemeSnapshot } from "../theme.ts";
|
|
4
|
+
|
|
5
|
+
const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
6
|
+
const listeners = new Set<(frame: number) => void>();
|
|
7
|
+
let timer: ReturnType<typeof setInterval> | undefined;
|
|
8
|
+
let frame = 0;
|
|
9
|
+
|
|
10
|
+
/** One clock for mounted working indicators, with no daemon or inventory work. */
|
|
11
|
+
function subscribe(listener: (frame: number) => void): () => void {
|
|
12
|
+
listeners.add(listener);
|
|
13
|
+
listener(frame);
|
|
14
|
+
if (!timer) {
|
|
15
|
+
timer = setInterval(() => {
|
|
16
|
+
frame = (frame + 1) % FRAMES.length;
|
|
17
|
+
batch(() => listeners.forEach((update) => update(frame)));
|
|
18
|
+
}, 80);
|
|
19
|
+
timer.unref?.();
|
|
20
|
+
}
|
|
21
|
+
return () => {
|
|
22
|
+
listeners.delete(listener);
|
|
23
|
+
if (listeners.size === 0 && timer) {
|
|
24
|
+
clearInterval(timer);
|
|
25
|
+
timer = undefined;
|
|
26
|
+
frame = 0;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Presentation only: never infer activity from animation or process liveness. */
|
|
32
|
+
export function createAgentStatusMarker(options: {
|
|
33
|
+
theme: () => SemanticThemeSnapshot;
|
|
34
|
+
status: () => AgentActivity | "working" | "blocked" | "done" | "unknown" | undefined;
|
|
35
|
+
attention?: () => boolean;
|
|
36
|
+
unavailable?: () => boolean;
|
|
37
|
+
}) {
|
|
38
|
+
const [current, setCurrent] = createSignal(0);
|
|
39
|
+
const working = () => options.status() === "running" || options.status() === "working";
|
|
40
|
+
const animated = () =>
|
|
41
|
+
working() &&
|
|
42
|
+
!options.attention?.() &&
|
|
43
|
+
!options.unavailable?.() &&
|
|
44
|
+
!options.theme().accessibility.reducedMotion;
|
|
45
|
+
createEffect(() => {
|
|
46
|
+
if (animated()) onCleanup(subscribe(setCurrent));
|
|
47
|
+
});
|
|
48
|
+
return () => {
|
|
49
|
+
if (options.unavailable?.()) return "·";
|
|
50
|
+
if (options.attention?.()) return "!";
|
|
51
|
+
switch (options.status()) {
|
|
52
|
+
case "running":
|
|
53
|
+
case "working":
|
|
54
|
+
return animated() ? FRAMES[current()]! : options.theme().glyphs.active;
|
|
55
|
+
case "waiting":
|
|
56
|
+
case "blocked":
|
|
57
|
+
return "!";
|
|
58
|
+
case "complete":
|
|
59
|
+
case "done":
|
|
60
|
+
return options.theme().glyphs.check;
|
|
61
|
+
case "failed":
|
|
62
|
+
return "×";
|
|
63
|
+
case "idle":
|
|
64
|
+
return options.theme().glyphs.inactive;
|
|
65
|
+
default:
|
|
66
|
+
return "·";
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -290,6 +290,7 @@ export function PaneTitleBar(props: PaneTitleBarProps) {
|
|
|
290
290
|
theme={props.theme}
|
|
291
291
|
label={statusLabel()!}
|
|
292
292
|
status={status()!}
|
|
293
|
+
activity={props.activity}
|
|
293
294
|
width={badgeWidth(statusLabel())}
|
|
294
295
|
selected={props.selected}
|
|
295
296
|
focused={props.keyboardFocused || props.terminalFocused}
|