tmux-ide 2.9.0-beta.41 → 2.9.0-beta.45
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 +2 -2
- package/package.json +2 -2
- package/packages/daemon/dist/tui/mirror/runtime/application-home-agent-roster.jsx +47 -90
- package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +82 -109
- package/packages/daemon/dist/tui/mirror/runtime/application-shell-home.jsx +94 -29
- package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace.jsx +33 -2
- package/packages/daemon/dist/tui/mirror/shell-chrome.js +5 -7
- package/packages/daemon/dist/tui/mirror/ui/agent-row.jsx +60 -0
- package/packages/daemon/dist/tui/mirror/ui/home-agent-search.jsx +8 -5
- package/packages/daemon/dist/tui/mirror/ui/input-surface.jsx +11 -0
- package/packages/daemon/dist/tui/mirror/ui/navigation-row.jsx +7 -2
- package/packages/daemon/dist/tui/mirror/ui/pane-interaction-presentation.js +72 -0
- package/packages/daemon/dist/tui/mirror/ui/pane-interaction.jsx +76 -0
- package/packages/daemon/dist/tui/mirror/ui/pane-mode-control.jsx +23 -0
- package/packages/daemon/dist/tui/mirror/ui/section-heading.jsx +6 -0
- package/packages/daemon/dist/tui/mirror/ui/status-presentation.js +41 -0
- package/packages/daemon/dist/tui/mirror/ui/tabs.jsx +22 -5
- package/packages/daemon/dist/tui/mirror/workspace/terminal-pane-header.jsx +35 -54
- package/packages/daemon/src/tui/mirror/__snapshots__/shell-chrome-renderer.test.tsx.snap +3 -3
- package/packages/daemon/src/tui/mirror/runtime/__snapshots__/application-shell-view-renderer.test.tsx.snap +12 -12
- package/packages/daemon/src/tui/mirror/runtime/application-home-agent-roster.tsx +119 -178
- package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +116 -148
- package/packages/daemon/src/tui/mirror/runtime/application-reference-sheet.tsx +9 -0
- package/packages/daemon/src/tui/mirror/runtime/application-shell-home.tsx +155 -42
- package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +34 -0
- package/packages/daemon/src/tui/mirror/runtime/application-terminal-workspace.tsx +56 -2
- package/packages/daemon/src/tui/mirror/shell-chrome.ts +4 -5
- package/packages/daemon/src/tui/mirror/ui/agent-row.tsx +120 -0
- package/packages/daemon/src/tui/mirror/ui/home-agent-search.tsx +17 -17
- package/packages/daemon/src/tui/mirror/ui/input-surface.tsx +39 -0
- package/packages/daemon/src/tui/mirror/ui/navigation-row.tsx +8 -1
- package/packages/daemon/src/tui/mirror/ui/overlay-search-field.tsx +5 -12
- package/packages/daemon/src/tui/mirror/ui/pane-interaction-presentation.ts +90 -0
- package/packages/daemon/src/tui/mirror/ui/pane-interaction.tsx +127 -0
- package/packages/daemon/src/tui/mirror/ui/pane-mode-control.tsx +47 -0
- package/packages/daemon/src/tui/mirror/ui/section-heading.tsx +15 -0
- package/packages/daemon/src/tui/mirror/ui/status-presentation.ts +54 -0
- package/packages/daemon/src/tui/mirror/ui/tabs.tsx +30 -7
- package/packages/daemon/src/tui/mirror/workspace/__snapshots__/application-shell-renderer.test.tsx.snap +3 -3
- package/packages/daemon/src/tui/mirror/workspace/terminal-pane-header.tsx +56 -68
- package/packages/daemon/dist/tui/mirror/ui/detail-row.jsx +0 -22
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.45",
|
|
11283
11283
|
description: "A visual, agent-aware IDE for any tmux session, with optional workspace presets",
|
|
11284
11284
|
type: "module",
|
|
11285
11285
|
bin: {
|
|
@@ -11343,7 +11343,7 @@ var require_package = __commonJS({
|
|
|
11343
11343
|
postinstall: "node scripts/postinstall.js",
|
|
11344
11344
|
docs: "turbo run dev --filter=@tmux-ide/docs",
|
|
11345
11345
|
"demo:tui": "bun --preload @opentui/solid/preload docs/scripts/render-tui-demo.tsx",
|
|
11346
|
-
"test:tui-renderer": "bun test --preload @opentui/solid/preload --preload ./packages/daemon/test-support/opentui-renderer-preload.ts ./packages/daemon/src/tui/mirror/automatic-contrast-renderer.test.tsx ./packages/daemon/src/tui/mirror/pane-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/native-grid-projection-renderer.test.tsx ./packages/daemon/src/tui/mirror/widget-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/missions-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/recipes-gallery-renderer.test.tsx ./packages/daemon/src/tui/mirror/shell-chrome-renderer.test.tsx ./packages/daemon/src/tui/mirror/sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/home-files-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/changes-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/activity-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/files/session-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-view-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-root-error-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-backpressure-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-demand-cadence-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/files-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/changes-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/missions-activity-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/dialogs-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/optional-feature-registry-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/palette-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/pane-scoped-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/rich-preview/feature.test.ts ./packages/daemon/src/tui/mirror/runtime/rich-preview-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/application-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/pane-frame-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-chrome-view.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-window-strip-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-dock-dual-host-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/agent-terminal-canvas-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/command-palette-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/opentui-insertion-stability-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-home-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-header-polish-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-roster-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-flow-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/guided-tour-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-sidebar-catalog-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/ui-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-machine-sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-add-machine-dialog-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-switcher-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-palette-preview-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-palette-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-session-actions-renderer.test.tsx",
|
|
11346
|
+
"test:tui-renderer": "bun test --preload @opentui/solid/preload --preload ./packages/daemon/test-support/opentui-renderer-preload.ts ./packages/daemon/src/tui/mirror/automatic-contrast-renderer.test.tsx ./packages/daemon/src/tui/mirror/pane-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/native-grid-projection-renderer.test.tsx ./packages/daemon/src/tui/mirror/widget-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/missions-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/recipes-gallery-renderer.test.tsx ./packages/daemon/src/tui/mirror/shell-chrome-renderer.test.tsx ./packages/daemon/src/tui/mirror/sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/home-files-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/changes-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/activity-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/files/session-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-view-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-root-error-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-backpressure-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-demand-cadence-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/files-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/changes-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/missions-activity-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/dialogs-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/optional-feature-registry-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/palette-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/pane-scoped-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/rich-preview/feature.test.ts ./packages/daemon/src/tui/mirror/runtime/rich-preview-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/application-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/pane-frame-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-chrome-view.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-window-strip-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-dock-dual-host-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/agent-terminal-canvas-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/command-palette-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/opentui-insertion-stability-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-home-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-header-polish-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-roster-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-flow-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/guided-tour-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-sidebar-catalog-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/ui-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/pane-interaction-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-machine-sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-add-machine-dialog-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-switcher-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-palette-preview-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-palette-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-session-actions-renderer.test.tsx",
|
|
11347
11347
|
"test:tui-smoke": "bun scripts/smoke-tui-missions.mjs",
|
|
11348
11348
|
"test:tui-live": "node scripts/tui-testdrive.mjs smoke",
|
|
11349
11349
|
"test:tui-testdrive": "node --test scripts/lib/tui-testdrive-clipboard-hook.test.mjs scripts/lib/tui-testdrive-input.test.mjs",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tmux-ide",
|
|
3
|
-
"version": "2.9.0-beta.
|
|
3
|
+
"version": "2.9.0-beta.45",
|
|
4
4
|
"description": "A visual, agent-aware IDE for any tmux session, with optional workspace presets",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"postinstall": "node scripts/postinstall.js",
|
|
65
65
|
"docs": "turbo run dev --filter=@tmux-ide/docs",
|
|
66
66
|
"demo:tui": "bun --preload @opentui/solid/preload docs/scripts/render-tui-demo.tsx",
|
|
67
|
-
"test:tui-renderer": "bun test --preload @opentui/solid/preload --preload ./packages/daemon/test-support/opentui-renderer-preload.ts ./packages/daemon/src/tui/mirror/automatic-contrast-renderer.test.tsx ./packages/daemon/src/tui/mirror/pane-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/native-grid-projection-renderer.test.tsx ./packages/daemon/src/tui/mirror/widget-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/missions-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/recipes-gallery-renderer.test.tsx ./packages/daemon/src/tui/mirror/shell-chrome-renderer.test.tsx ./packages/daemon/src/tui/mirror/sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/home-files-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/changes-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/activity-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/files/session-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-view-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-root-error-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-backpressure-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-demand-cadence-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/files-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/changes-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/missions-activity-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/dialogs-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/optional-feature-registry-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/palette-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/pane-scoped-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/rich-preview/feature.test.ts ./packages/daemon/src/tui/mirror/runtime/rich-preview-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/application-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/pane-frame-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-chrome-view.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-window-strip-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-dock-dual-host-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/agent-terminal-canvas-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/command-palette-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/opentui-insertion-stability-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-home-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-header-polish-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-roster-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-flow-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/guided-tour-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-sidebar-catalog-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/ui-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-machine-sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-add-machine-dialog-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-switcher-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-palette-preview-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-palette-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-session-actions-renderer.test.tsx",
|
|
67
|
+
"test:tui-renderer": "bun test --preload @opentui/solid/preload --preload ./packages/daemon/test-support/opentui-renderer-preload.ts ./packages/daemon/src/tui/mirror/automatic-contrast-renderer.test.tsx ./packages/daemon/src/tui/mirror/pane-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/native-grid-projection-renderer.test.tsx ./packages/daemon/src/tui/mirror/widget-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/missions-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/recipes-gallery-renderer.test.tsx ./packages/daemon/src/tui/mirror/shell-chrome-renderer.test.tsx ./packages/daemon/src/tui/mirror/sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/home-files-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/changes-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/activity-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/files/session-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-view-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-root-error-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-backpressure-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-demand-cadence-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/files-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/changes-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/missions-activity-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/dialogs-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/optional-feature-registry-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/palette-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/pane-scoped-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/rich-preview/feature.test.ts ./packages/daemon/src/tui/mirror/runtime/rich-preview-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/application-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/pane-frame-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-chrome-view.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-window-strip-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-dock-dual-host-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/agent-terminal-canvas-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/command-palette-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/opentui-insertion-stability-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-home-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-header-polish-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-roster-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-flow-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/guided-tour-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-sidebar-catalog-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/ui-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/pane-interaction-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-machine-sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-add-machine-dialog-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-switcher-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-palette-preview-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-palette-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-session-actions-renderer.test.tsx",
|
|
68
68
|
"test:tui-smoke": "bun scripts/smoke-tui-missions.mjs",
|
|
69
69
|
"test:tui-live": "node scripts/tui-testdrive.mjs smoke",
|
|
70
70
|
"test:tui-testdrive": "node --test scripts/lib/tui-testdrive-clipboard-hook.test.mjs scripts/lib/tui-testdrive-input.test.mjs",
|
|
@@ -2,29 +2,13 @@
|
|
|
2
2
|
import { HOME_ACTIONS, HOME_ACTIVITY_ACTIONS, } from "../workspace/application-action-descriptions.js";
|
|
3
3
|
import { createEffect, createMemo, createSignal, For, Show } from "solid-js";
|
|
4
4
|
import { clipTerminal, terminalDisplayWidth } from "../terminal-text.js";
|
|
5
|
-
import {
|
|
5
|
+
import { AgentRow } from "../ui/agent-row.jsx";
|
|
6
6
|
import { KeyHint } from "../ui/key-hint.jsx";
|
|
7
7
|
import { TuiButton } from "../ui/button.jsx";
|
|
8
8
|
import { useKeyboardRoute } from "../ui/keyboard-router.jsx";
|
|
9
9
|
import { applicationPaneRenameKeyAction, applicationPaneRenamePaste, } from "./application-pane-rename-input.js";
|
|
10
10
|
import { HomeAgentSearch } from "../ui/home-agent-search.jsx";
|
|
11
|
-
import { createAgentStatusMarker } from "../ui/agent-status-marker.js";
|
|
12
11
|
import { ActivityIndicator } from "../ui/activity-indicator.jsx";
|
|
13
|
-
import { componentPalette } from "../ui/state.js";
|
|
14
|
-
import { homeAgentStatusLabel, } from "./application-home-agents.js";
|
|
15
|
-
function padCells(text, width) {
|
|
16
|
-
const clipped = clipTerminal(text, Math.max(0, width));
|
|
17
|
-
return clipped + " ".repeat(Math.max(0, width - terminalDisplayWidth(clipped)));
|
|
18
|
-
}
|
|
19
|
-
function statusTone(row) {
|
|
20
|
-
if (row.activity === "waiting" || row.activity === "failed")
|
|
21
|
-
return "blocked";
|
|
22
|
-
if (row.activity === "running")
|
|
23
|
-
return "working";
|
|
24
|
-
if (row.activity === "complete")
|
|
25
|
-
return "done";
|
|
26
|
-
return row.activity === "idle" ? "idle" : "unknown";
|
|
27
|
-
}
|
|
28
12
|
/** A flat projected roster; no subscriptions, navigation effects, or terminal input ingress. */
|
|
29
13
|
export function HomeAgentRoster(props) {
|
|
30
14
|
const [hovered, setHovered] = createSignal(null);
|
|
@@ -37,10 +21,12 @@ export function HomeAgentRoster(props) {
|
|
|
37
21
|
const showRecovery = () => Boolean(((props.snapshot.phase === "unavailable" || props.snapshot.unavailableSessions > 0) &&
|
|
38
22
|
props.onRetry) ||
|
|
39
23
|
(props.snapshot.truncatedSessions > 0 && props.onLoadMore));
|
|
40
|
-
const rowHeight = () => (
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
24
|
+
const rowHeight = () => (height() >= 14 ? 2 : 1);
|
|
25
|
+
const compact = () => height() < 8;
|
|
26
|
+
const filterRows = () => (compact() ? 0 : props.onSetActivityFilter && width() < 70 ? 2 : 1);
|
|
27
|
+
const searchRows = () => (props.onQueryChange ? (compact() ? 1 : 2) : 0);
|
|
28
|
+
const visibleCount = () => Math.max(0, Math.floor((height() - (compact() ? 1 : 4) - filterRows() - searchRows() - (showRecovery() ? 1 : 0)) /
|
|
29
|
+
rowHeight()));
|
|
44
30
|
const openSelected = (source = "keyboard") => {
|
|
45
31
|
const row = props.snapshot.rows.find((row) => row.key === props.selection.selectedKey);
|
|
46
32
|
if (props.inputActive && visibleCount() > 0 && row?.paneId && !stale(row))
|
|
@@ -53,12 +39,6 @@ export function HomeAgentRoster(props) {
|
|
|
53
39
|
const keys = createMemo(() => visible().map((row) => row.key), undefined, {
|
|
54
40
|
equals: (a, b) => a.length === b.length && a.every((key, index) => key === b[index]),
|
|
55
41
|
});
|
|
56
|
-
const columns = () => {
|
|
57
|
-
const status = Math.min(12, Math.max(0, width() - 4));
|
|
58
|
-
const label = Math.max(0, width() - status - 3);
|
|
59
|
-
const session = width() >= 44 ? Math.floor(label * 0.43) : 0;
|
|
60
|
-
return { status, agent: label - session, session };
|
|
61
|
-
};
|
|
62
42
|
const filtered = () => Boolean(props.query || (props.activityFilter && props.activityFilter !== "all"));
|
|
63
43
|
const title = () => {
|
|
64
44
|
if (props.snapshot.phase === "unavailable")
|
|
@@ -143,7 +123,9 @@ export function HomeAgentRoster(props) {
|
|
|
143
123
|
props.onMove(delta);
|
|
144
124
|
return true;
|
|
145
125
|
});
|
|
146
|
-
return (<box position="relative" width={width()} height={
|
|
126
|
+
return (<box position="relative" width={width()} height={props.fitContent && props.snapshot.rows.length > 0
|
|
127
|
+
? height() - (visibleCount() - visible().length) * rowHeight()
|
|
128
|
+
: height()} flexShrink={0} flexDirection="column" overflow="hidden" onMouseScroll={(event) => {
|
|
147
129
|
if (!props.inputActive)
|
|
148
130
|
return;
|
|
149
131
|
const direction = event.scroll?.direction;
|
|
@@ -154,16 +136,19 @@ export function HomeAgentRoster(props) {
|
|
|
154
136
|
props.onMove(direction === "up" ? -1 : 1);
|
|
155
137
|
}} onMouseOut={() => setHovered(null)}>
|
|
156
138
|
<box height={searchRows()} flexShrink={0}/>
|
|
157
|
-
<
|
|
158
|
-
<
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
{
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
139
|
+
<Show when={!compact()}>
|
|
140
|
+
<box width={width()} height={1} flexShrink={0} flexDirection="row">
|
|
141
|
+
<Show when={props.snapshot.phase === "loading" || props.snapshot.loadingSessions > 0}>
|
|
142
|
+
<ActivityIndicator theme={props.theme} active={props.inputActive}/>
|
|
143
|
+
</Show>
|
|
144
|
+
<text height={1} flexGrow={1} fg={props.theme.roles.text.muted}>
|
|
145
|
+
{clipTerminal(title(), width())}
|
|
146
|
+
</text>
|
|
147
|
+
</box>
|
|
148
|
+
</Show>
|
|
149
|
+
<Show when={!compact()}>
|
|
150
|
+
<box width={width()} height={filterRows()} flexShrink={0} flexDirection={filterRows() > 1 ? "column" : "row"} overflow="hidden">
|
|
151
|
+
<KeyHint theme={props.theme} keys={HOME_ACTIONS.machine.keys} label={props.filterLabel?.split(" · ")[0] ?? "All machines"} width={props.onSetActivityFilter && filterRows() === 1
|
|
167
152
|
? Math.max(1, width() - 47)
|
|
168
153
|
: props.onSetActivityFilter
|
|
169
154
|
? Math.min(width(), 28)
|
|
@@ -171,20 +156,21 @@ export function HomeAgentRoster(props) {
|
|
|
171
156
|
if (props.inputActive)
|
|
172
157
|
props.onCycleMachine?.();
|
|
173
158
|
}}/>
|
|
174
|
-
|
|
175
|
-
|
|
159
|
+
<box height={1} flexShrink={0} flexDirection="row" overflow="hidden" width={Math.min(width(), 47)}>
|
|
160
|
+
<Show when={props.onSetActivityFilter} fallback={<KeyHint theme={props.theme} keys={HOME_ACTIONS.attention.keys} label="Attention" quiet button onPress={() => {
|
|
176
161
|
if (props.inputActive)
|
|
177
162
|
props.onToggleAttention?.();
|
|
178
163
|
}}/>}>
|
|
179
|
-
|
|
180
|
-
|
|
164
|
+
<For each={HOME_ACTIVITY_ACTIONS}>
|
|
165
|
+
{(filter) => (<KeyHint theme={props.theme} keys={filter.keys} label={filter.value === "attention" && width() < 47 ? "Attention" : filter.label} quiet button selected={(props.activityFilter ?? "all") === filter.value} onPress={() => {
|
|
181
166
|
if (props.inputActive)
|
|
182
167
|
props.onSetActivityFilter?.(filter.value);
|
|
183
168
|
}}/>)}
|
|
184
|
-
|
|
185
|
-
|
|
169
|
+
</For>
|
|
170
|
+
</Show>
|
|
171
|
+
</box>
|
|
186
172
|
</box>
|
|
187
|
-
</
|
|
173
|
+
</Show>
|
|
188
174
|
<Show when={props.snapshot.rows.length > 0} fallback={<box height={Math.max(0, visibleCount() * rowHeight() + 1)} flexShrink={0} flexDirection="column" overflow="hidden">
|
|
189
175
|
<Show when={props.snapshot.phase === "live" && !props.query}>
|
|
190
176
|
<text height={1} width={width()} fg={props.theme.roles.text.primary}>
|
|
@@ -197,51 +183,20 @@ export function HomeAgentRoster(props) {
|
|
|
197
183
|
</text>
|
|
198
184
|
</Show>
|
|
199
185
|
</box>}>
|
|
200
|
-
<box height={1} flexShrink={0}/>
|
|
201
|
-
<box height={visibleCount() * rowHeight()} width={width()} flexShrink={0} flexDirection="column" overflow="hidden">
|
|
186
|
+
<box height={compact() ? 0 : 1} flexShrink={0}/>
|
|
187
|
+
<box height={(props.fitContent ? visible().length : visibleCount()) * rowHeight()} width={width()} flexShrink={0} flexDirection="column" overflow="hidden">
|
|
202
188
|
<For each={keys()}>
|
|
203
189
|
{(key) => {
|
|
204
190
|
const row = () => byKey().get(key);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
unavailable: () => stale(row()),
|
|
210
|
-
});
|
|
211
|
-
return (<box height={rowHeight()} flexDirection="column" backgroundColor={componentPalette(props.theme, {
|
|
212
|
-
selected: props.selection.selectedKey === key,
|
|
213
|
-
hovered: hovered() === key,
|
|
214
|
-
disabled: row().paneId === null || stale(row()),
|
|
215
|
-
}).background} width={width()} flexShrink={0} onMouseDown={(event) => {
|
|
216
|
-
if (!props.inputActive || event.button !== 0 || !row().paneId || stale(row()))
|
|
217
|
-
return;
|
|
218
|
-
event.preventDefault();
|
|
219
|
-
event.stopPropagation();
|
|
220
|
-
props.onSelect(key);
|
|
221
|
-
props.onOpen(row(), "mouse");
|
|
222
|
-
}} onMouseOver={() => setHovered(key)} onMouseMove={() => setHovered(key)}>
|
|
223
|
-
<NavigationRow theme={props.theme} id={`home-agent:${key}`} width={width()} label={rowHeight() > 1
|
|
224
|
-
? row().name
|
|
225
|
-
: padCells(row().name, columns().agent) +
|
|
226
|
-
padCells([row().machineLabel, row().serverLabel, row().sessionName]
|
|
227
|
-
.filter(Boolean)
|
|
228
|
-
.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) => {
|
|
191
|
+
return (<box height={rowHeight()} width={width()} flexShrink={0} onMouseOver={() => setHovered(key)} onMouseMove={() => setHovered(key)}>
|
|
192
|
+
<AgentRow surface="canvas" theme={props.theme} id={`home-agent:${key}`} name={row().name} context={[row().machineLabel, row().serverLabel, row().sessionName]
|
|
193
|
+
.filter(Boolean)
|
|
194
|
+
.join(" · ")} width={width()} compact={rowHeight() === 1} interaction={props.interactionForAgent?.(row())} paneName={props.paneName} activity={row().activity} attention={row().attention} unavailable={row().paneId === null || stale(row())} selected={props.selection.selectedKey === key} focused={props.inputActive && !editing() && props.selection.selectedKey === key} hovered={hovered() === key} onOpen={(source) => {
|
|
229
195
|
if (!props.inputActive || row().paneId === null || stale(row()))
|
|
230
196
|
return;
|
|
231
197
|
props.onSelect(key);
|
|
232
198
|
props.onOpen(row(), source);
|
|
233
199
|
}}/>
|
|
234
|
-
<Show when={rowHeight() > 1}>
|
|
235
|
-
<text width={width()} height={1} fg={props.selection.selectedKey === key
|
|
236
|
-
? props.theme.roles.selection.selectionText
|
|
237
|
-
: props.theme.roles.text.muted} bg={componentPalette(props.theme, {
|
|
238
|
-
selected: props.selection.selectedKey === key,
|
|
239
|
-
hovered: hovered() === key,
|
|
240
|
-
disabled: row().paneId === null || stale(row()),
|
|
241
|
-
}).background}>
|
|
242
|
-
{clipTerminal(` ${[row().sessionName, row().machineLabel, row().serverLabel, row().harness].filter(Boolean).join(" · ")}`, width())}
|
|
243
|
-
</text>
|
|
244
|
-
</Show>
|
|
245
200
|
</box>);
|
|
246
201
|
}}
|
|
247
202
|
</For>
|
|
@@ -259,14 +214,16 @@ export function HomeAgentRoster(props) {
|
|
|
259
214
|
<text width={width()} height={1} flexShrink={0} fg={props.theme.roles.text.muted}>
|
|
260
215
|
{clipTerminal(coverage(), width())}
|
|
261
216
|
</text>
|
|
262
|
-
<
|
|
263
|
-
<
|
|
264
|
-
{
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
<
|
|
268
|
-
|
|
269
|
-
|
|
217
|
+
<Show when={!compact()}>
|
|
218
|
+
<box width={width()} height={1} flexShrink={0} flexDirection="row" overflow="hidden">
|
|
219
|
+
<text width={Math.min(Math.max(0, width() - (footer().endsWith("Enter open") && width() >= 20 ? 12 : 0)), terminalDisplayWidth(footer().replace(/ Enter open$/u, "")))} fg={props.theme.roles.text.muted}>
|
|
220
|
+
{clipTerminal(footer().replace(/ Enter open$/u, ""), width())}
|
|
221
|
+
</text>
|
|
222
|
+
<Show when={footer().endsWith("Enter open") && width() >= 20}>
|
|
223
|
+
<KeyHint theme={props.theme} keys={HOME_ACTIONS.open.keys} label={HOME_ACTIONS.open.label} quiet button onPress={() => openSelected("mouse")}/>
|
|
224
|
+
</Show>
|
|
225
|
+
</box>
|
|
226
|
+
</Show>
|
|
270
227
|
<Show when={showRecovery()}>
|
|
271
228
|
<box height={1} width={width()} flexShrink={0} flexDirection="row" gap={1}>
|
|
272
229
|
<Show when={(props.snapshot.phase === "unavailable" || props.snapshot.unavailableSessions > 0) &&
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { CHROME_ACTIONS, SIDEBAR_ACTIONS } from "../workspace/application-action-descriptions.js";
|
|
2
|
-
import {
|
|
3
|
-
import { fleetHostColor
|
|
4
|
-
import { WorkingSessions } from "../ui/working-sessions.jsx";
|
|
2
|
+
import { AgentRow } from "../ui/agent-row.jsx";
|
|
3
|
+
import { fleetHostColor } from "./fleet-presentation.js";
|
|
5
4
|
/* @jsxImportSource @opentui/solid */
|
|
6
5
|
import { fleetConnectionMessage, } from "@tmux-ide/daemon-client/fleet-connection-status";
|
|
7
|
-
import { terminalAgentStatusLabel } from "./application-terminal-workspace-policy.js";
|
|
8
6
|
import { For, Show, createEffect, createMemo, createSignal, } from "solid-js";
|
|
9
|
-
import {
|
|
7
|
+
import { friendlySessionLabel } from "../terminal-text.js";
|
|
10
8
|
import { KeyHint } from "../ui/key-hint.jsx";
|
|
11
9
|
import { NavigationRow } from "../ui/navigation-row.jsx";
|
|
12
10
|
import { Surface } from "../ui/surface.jsx";
|
|
@@ -24,22 +22,16 @@ export function ApplicationMachineSidebar(props) {
|
|
|
24
22
|
: 0;
|
|
25
23
|
const controlsHeight = () => (props.height >= 8 && controlGroup() ? 4 : 0);
|
|
26
24
|
const searchHeight = () => (props.model.onOpenSwitcher ? 1 : 0) + (props.model.onOpenAttention ? 1 : 0);
|
|
27
|
-
const [workingFocused, setWorkingFocused] = createSignal(true);
|
|
28
|
-
const tabHeight = () => (props.model.tabs?.().length ?? 0) > 0 && props.height >= 12
|
|
29
|
-
? 1 +
|
|
30
|
-
Math.min(props.model.tabs().length, Math.max(1, Math.floor((props.height / 2 - 1) / 3))) *
|
|
31
|
-
3
|
|
32
|
-
: 0;
|
|
33
25
|
const machineHeight = () => Math.max(0, props.height -
|
|
34
26
|
1 -
|
|
35
27
|
(props.model.onAddMachine ? 1 : 0) -
|
|
36
28
|
agentHeight() -
|
|
37
29
|
controlsHeight() -
|
|
38
|
-
searchHeight()
|
|
39
|
-
tabHeight());
|
|
30
|
+
searchHeight());
|
|
40
31
|
const active = (row) => row.group.id === props.model.activeMachineId() &&
|
|
41
32
|
(row.agent
|
|
42
33
|
? row.group.state === "ready" &&
|
|
34
|
+
row.group.agentsAvailable !== false &&
|
|
43
35
|
!row.agent.disabled &&
|
|
44
36
|
row.agent.sessionName === props.model.activeSessionName() &&
|
|
45
37
|
(!props.model.activeSessionKey ||
|
|
@@ -52,44 +44,50 @@ export function ApplicationMachineSidebar(props) {
|
|
|
52
44
|
? row.session?.id === props.model.activeSessionKey()
|
|
53
45
|
: row.session?.name === props.model.activeSessionName());
|
|
54
46
|
const preferenceKey = (group) => group.environmentId ?? group.id;
|
|
55
|
-
const rows = createMemo(() =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.map((session, index, sessions) => ({
|
|
65
|
-
serverHeading: (group.servers?.length ??
|
|
66
|
-
new Set(group.sessions.map((row) => row.server?.serverId)).size) > 1 &&
|
|
67
|
-
session.server &&
|
|
68
|
-
(index === 0 || sessions[index - 1]?.server?.serverId !== session.server.serverId)
|
|
69
|
-
? `${session.serverLabel ?? "Server"} · ${session.server.serverId.slice(-6)}`
|
|
70
|
-
: undefined,
|
|
71
|
-
key: JSON.stringify([group.id, "session", session.id]),
|
|
47
|
+
const rows = createMemo(() => [
|
|
48
|
+
...props.model.groups().flatMap((group) => (group.agents ?? []).map((agent) => ({
|
|
49
|
+
key: JSON.stringify([
|
|
50
|
+
group.id,
|
|
51
|
+
"agent",
|
|
52
|
+
agent.server?.serverId,
|
|
53
|
+
agent.server?.generation,
|
|
54
|
+
agent.id,
|
|
55
|
+
]),
|
|
72
56
|
group,
|
|
73
|
-
|
|
74
|
-
})),
|
|
75
|
-
...(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.filter((
|
|
79
|
-
.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
57
|
+
agent,
|
|
58
|
+
}))),
|
|
59
|
+
...props.model.groups().flatMap((group) => [
|
|
60
|
+
{ key: JSON.stringify([group.id]), group },
|
|
61
|
+
...group.sessions
|
|
62
|
+
.filter((session) => !collapsed().has(preferenceKey(group)) ||
|
|
63
|
+
props.model.favorites?.().includes(session.id) ||
|
|
64
|
+
(group.id === props.model.activeMachineId() &&
|
|
65
|
+
(props.model.activeSessionKey
|
|
66
|
+
? session.id === props.model.activeSessionKey()
|
|
67
|
+
: session.name === props.model.activeSessionName())))
|
|
68
|
+
.map((session, index, sessions) => ({
|
|
69
|
+
serverHeading: (group.servers?.length ??
|
|
70
|
+
new Set(group.sessions.map((row) => row.server?.serverId)).size) > 1 &&
|
|
71
|
+
session.server &&
|
|
72
|
+
(index === 0 || sessions[index - 1]?.server?.serverId !== session.server.serverId)
|
|
73
|
+
? `${session.serverLabel ?? "Server"} · ${session.server.serverId.slice(-6)}`
|
|
74
|
+
: undefined,
|
|
75
|
+
key: JSON.stringify([group.id, "session", session.id]),
|
|
87
76
|
group,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
77
|
+
session,
|
|
78
|
+
})),
|
|
79
|
+
...(collapsed().has(preferenceKey(group))
|
|
80
|
+
? []
|
|
81
|
+
: (group.servers ?? [])
|
|
82
|
+
.filter((server) => !group.sessions.some((session) => session.server?.serverId === server.serverId))
|
|
83
|
+
.map((server) => ({
|
|
84
|
+
key: JSON.stringify([group.id, "server", server.serverId]),
|
|
85
|
+
group,
|
|
86
|
+
server,
|
|
87
|
+
}))),
|
|
88
|
+
]),
|
|
89
|
+
]);
|
|
90
|
+
const hasAgents = createMemo(() => rows().some((row) => row.agent));
|
|
93
91
|
const rowsByKey = createMemo(() => new Map(rows().map((row) => [row.key, row])));
|
|
94
92
|
const index = () => Math.max(0, rows().findIndex((row) => row.key === selectedKey()));
|
|
95
93
|
const controlGroup = () => {
|
|
@@ -101,10 +99,6 @@ export function ApplicationMachineSidebar(props) {
|
|
|
101
99
|
? group
|
|
102
100
|
: null;
|
|
103
101
|
};
|
|
104
|
-
const activity = (row) => summarizeFleetActivity((row.group.agents ?? []).filter((agent) => !row.session ||
|
|
105
|
-
(agent.sessionName === row.session.name &&
|
|
106
|
-
agent.server?.serverId === row.session.server?.serverId &&
|
|
107
|
-
agent.server?.generation === row.session.server?.generation)), row.group.state === "ready" && row.group.agentsAvailable !== false && !row.session?.disabled);
|
|
108
102
|
const connectionDetail = (group) => {
|
|
109
103
|
const diagnostic = group.diagnostic;
|
|
110
104
|
if (!diagnostic)
|
|
@@ -133,7 +127,6 @@ export function ApplicationMachineSidebar(props) {
|
|
|
133
127
|
props.model.onCollapse?.(preferenceKey(group), value);
|
|
134
128
|
};
|
|
135
129
|
const activate = (row, source) => {
|
|
136
|
-
setWorkingFocused(false);
|
|
137
130
|
setSelectedKey(row.key);
|
|
138
131
|
setLocalFocused(true);
|
|
139
132
|
props.model.onFocus?.();
|
|
@@ -147,6 +140,7 @@ export function ApplicationMachineSidebar(props) {
|
|
|
147
140
|
}
|
|
148
141
|
if (row.agent) {
|
|
149
142
|
if (row.group.state === "ready" &&
|
|
143
|
+
row.group.agentsAvailable !== false &&
|
|
150
144
|
!row.agent.disabled &&
|
|
151
145
|
row.agent.paneId &&
|
|
152
146
|
props.model.onOpenAgent) {
|
|
@@ -165,12 +159,12 @@ export function ApplicationMachineSidebar(props) {
|
|
|
165
159
|
else
|
|
166
160
|
toggle(row.group);
|
|
167
161
|
};
|
|
168
|
-
const sectionGap = (row) => !row.session && !row.agent && !row.server
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
162
|
+
const sectionGap = (row) => (!row.session && !row.agent && !row.server ? 1 : 0);
|
|
163
|
+
const rowHeight = (row) => (row.agent ? 2 : row.serverHeading ? 2 : 1) +
|
|
164
|
+
sectionGap(row) +
|
|
165
|
+
(hasAgents() && row.key === JSON.stringify([props.model.groups()[0]?.id]) ? 1 : 0);
|
|
172
166
|
const revealFocusedRow = () => {
|
|
173
|
-
if (!focused() ||
|
|
167
|
+
if (!focused() || !scroll)
|
|
174
168
|
return;
|
|
175
169
|
const y = rows()
|
|
176
170
|
.slice(0, index())
|
|
@@ -192,14 +186,16 @@ export function ApplicationMachineSidebar(props) {
|
|
|
192
186
|
if (!focused() || event.eventType !== "press" || event.meta)
|
|
193
187
|
return false;
|
|
194
188
|
let key = event.name.toLowerCase();
|
|
195
|
-
if (key === "tab"
|
|
196
|
-
|
|
189
|
+
if (key === "tab") {
|
|
190
|
+
const target = rows()[index()]?.agent
|
|
191
|
+
? rows().find((row) => !row.agent)
|
|
192
|
+
: rows().find((row) => row.agent);
|
|
193
|
+
if (target)
|
|
194
|
+
setSelectedKey(target.key);
|
|
197
195
|
event.preventDefault();
|
|
198
196
|
event.stopPropagation();
|
|
199
197
|
return true;
|
|
200
198
|
}
|
|
201
|
-
if (workingFocused() && tabHeight() && !["escape", "?", "question", "/", "a"].includes(key))
|
|
202
|
-
return false;
|
|
203
199
|
if (event.ctrl && key === "d")
|
|
204
200
|
key = "halfdown";
|
|
205
201
|
else if (event.ctrl && key === "u")
|
|
@@ -306,22 +302,10 @@ export function ApplicationMachineSidebar(props) {
|
|
|
306
302
|
});
|
|
307
303
|
return (<Surface id="application-machine-sidebar" theme={props.theme} variant="panel" width={props.width} height={props.height} flexShrink={0} flexDirection="column" overflow="hidden">
|
|
308
304
|
<box height={1} flexShrink={0} flexDirection="row" overflow="hidden">
|
|
309
|
-
<text fg={props.theme.roles.text.secondary}>
|
|
310
|
-
{tabHeight() ? " Workspace" : " Machines"}
|
|
311
|
-
</text>
|
|
305
|
+
<text fg={props.theme.roles.text.secondary}>{hasAgents() ? " Agents" : " Machines"}</text>
|
|
312
306
|
<box flexGrow={1}/>
|
|
313
|
-
<Show when={props.model.tabs?.().length && props.width >= 28}>
|
|
314
|
-
<KeyHint theme={props.theme} keys={CHROME_ACTIONS.tabs.keys} label={CHROME_ACTIONS.tabs.label} quiet/>
|
|
315
|
-
</Show>
|
|
316
307
|
<KeyHint theme={props.theme} keys={SIDEBAR_ACTIONS.help.keys} label={props.width >= 20 ? SIDEBAR_ACTIONS.help.label : undefined} quiet button onPress={() => props.onHelp?.("mouse")}/>
|
|
317
308
|
</box>
|
|
318
|
-
<Show when={tabHeight() > 0}>
|
|
319
|
-
<WorkingSessions theme={props.theme} rows={props.model.tabs?.() ?? []} width={props.width} height={tabHeight()} focused={focused() && workingFocused()} onFocus={() => {
|
|
320
|
-
setWorkingFocused(true);
|
|
321
|
-
setLocalFocused(true);
|
|
322
|
-
props.model.onFocus?.();
|
|
323
|
-
}} onOpen={(key) => props.model.onOpenTab?.(key)} onClose={props.model.onCloseTab}/>
|
|
324
|
-
</Show>
|
|
325
309
|
<scrollbox ref={(value) => {
|
|
326
310
|
scroll = value;
|
|
327
311
|
const resized = value.content.onSizeChange;
|
|
@@ -352,16 +336,7 @@ export function ApplicationMachineSidebar(props) {
|
|
|
352
336
|
get serverHeading() {
|
|
353
337
|
return current().serverHeading;
|
|
354
338
|
},
|
|
355
|
-
get agentHeading() {
|
|
356
|
-
return current().agentHeading;
|
|
357
|
-
},
|
|
358
339
|
};
|
|
359
|
-
const agentMarker = createAgentStatusMarker({
|
|
360
|
-
theme: () => props.theme,
|
|
361
|
-
status: () => row.agent?.activity,
|
|
362
|
-
attention: () => Boolean(row.agent?.attention),
|
|
363
|
-
unavailable: () => row.group.state !== "ready" || Boolean(row.agent?.disabled),
|
|
364
|
-
});
|
|
365
340
|
return (<box width={Math.max(1, props.width - 1)} height={rowHeight(row)} flexShrink={0} flexDirection="column">
|
|
366
341
|
<box height={sectionGap(row)} flexShrink={0}/>
|
|
367
342
|
<Show when={row.serverHeading}>
|
|
@@ -370,22 +345,18 @@ export function ApplicationMachineSidebar(props) {
|
|
|
370
345
|
props.model.onSelectServer?.(row.group.id, row.session.server);
|
|
371
346
|
}}/>
|
|
372
347
|
</Show>
|
|
373
|
-
<Show when={row.
|
|
348
|
+
<Show when={hasAgents() && row.key === JSON.stringify([props.model.groups()[0]?.id])}>
|
|
374
349
|
<text height={1} fg={props.theme.roles.text.secondary}>
|
|
375
350
|
{" "}
|
|
376
|
-
|
|
351
|
+
Machines
|
|
377
352
|
</text>
|
|
378
353
|
</Show>
|
|
379
|
-
<NavigationRow theme={props.theme} id={`machine:${row.key}`} width={Math.max(1, props.width - 1)} labelColor={!row.
|
|
380
|
-
|
|
381
|
-
: row.agent
|
|
382
|
-
? row.agent.name
|
|
354
|
+
<Show when={row.agent} fallback={<NavigationRow theme={props.theme} id={`machine:${row.key}`} width={Math.max(1, props.width - 1)} labelColor={!row.session ? fleetHostColor(row.group) : undefined} label={row.server
|
|
355
|
+
? ` ${row.server.label} · ${row.server.serverId.slice(-6)}`
|
|
383
356
|
: row.session
|
|
384
357
|
? friendlySessionLabel(row.session.name)
|
|
385
358
|
: row.group.label} marker={row.server
|
|
386
|
-
|
|
387
|
-
: row.agent
|
|
388
|
-
? agentMarker()
|
|
359
|
+
? " "
|
|
389
360
|
: row.session
|
|
390
361
|
? props.model.favorites?.().includes(row.session.id)
|
|
391
362
|
? " ★"
|
|
@@ -393,24 +364,26 @@ export function ApplicationMachineSidebar(props) {
|
|
|
393
364
|
: collapsed().has(preferenceKey(row.group))
|
|
394
365
|
? "▸"
|
|
395
366
|
: "▾"} detail={row.server
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
: row.agent
|
|
400
|
-
? row.group.state !== "ready" || row.agent.disabled
|
|
401
|
-
? "unavailable"
|
|
402
|
-
: terminalAgentStatusLabel(row.agent.activity).toLowerCase()
|
|
367
|
+
? row.server.state === "offline"
|
|
368
|
+
? "offline"
|
|
369
|
+
: "empty"
|
|
403
370
|
: row.session
|
|
404
371
|
? row.group.state !== "ready" || row.session.disabled
|
|
405
372
|
? "unavailable"
|
|
406
|
-
: `${row.session.paneCount}p
|
|
407
|
-
: row.group.
|
|
408
|
-
?
|
|
409
|
-
:
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
373
|
+
: `${row.session.paneCount}p`
|
|
374
|
+
: row.group.state === "ready"
|
|
375
|
+
? undefined
|
|
376
|
+
: connectionDetail(row.group)} selected={Boolean(row.session && active(row))} focused={focused() && row.key === selectedKey()} onActivate={(source) => activate(row, source)}/>}>
|
|
377
|
+
{(agent) => (<AgentRow theme={props.theme} id={`machine:${row.key}`} name={agent().name} context={[
|
|
378
|
+
row.group.label,
|
|
379
|
+
row.group.sessions.find((session) => session.server?.serverId === agent().server?.serverId)?.serverLabel,
|
|
380
|
+
friendlySessionLabel(agent().sessionName),
|
|
381
|
+
]
|
|
382
|
+
.filter(Boolean)
|
|
383
|
+
.join(" · ")} width={Math.max(1, props.width - 1)} interaction={props.interactionForAgent?.(agent())} paneName={props.paneName} activity={agent().activity} attention={agent().attention} unavailable={row.group.state !== "ready" ||
|
|
384
|
+
row.group.agentsAvailable === false ||
|
|
385
|
+
!!agent().disabled ||
|
|
386
|
+
!agent().paneId} selected={active(row)} focused={focused() && row.key === selectedKey()} onOpen={(source) => activate(row, source)}/>)}
|
|
414
387
|
</Show>
|
|
415
388
|
</box>);
|
|
416
389
|
}}
|