@sealant/mend 0.29.2 → 0.31.0
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/README.md +3 -0
- package/dist/{chunk-AIW6XFT5.js → chunk-J3TR4UAG.js} +486 -66
- package/dist/{dashboard-AREQGMNK.js → dashboard-3HNFSQZD.js} +511 -234
- package/dist/main.js +1839 -830
- package/man/mend-accounts.1 +1 -1
- package/man/mend-adopt.1 +1 -1
- package/man/mend-attach.1 +9 -3
- package/man/mend-codex.1 +13 -3
- package/man/mend-completions.1 +1 -1
- package/man/mend-connect.1 +1 -1
- package/man/mend-continue.1 +1 -1
- package/man/mend-doctor.1 +1 -1
- package/man/mend-dotfiles-repo.1 +38 -0
- package/man/mend-dotfiles-sync.1 +3 -3
- package/man/mend-dotfiles.1 +3 -3
- package/man/mend-env-cluster.1 +1 -1
- package/man/mend-env-load.1 +1 -1
- package/man/mend-env-show.1 +1 -1
- package/man/mend-folder-create.1 +1 -1
- package/man/mend-folder-list.1 +1 -1
- package/man/mend-folder-push.1 +1 -1
- package/man/mend-folder-rm.1 +1 -1
- package/man/mend-git-author.1 +24 -0
- package/man/mend-help.1 +1 -1
- package/man/mend-invite.1 +1 -1
- package/man/mend-keys-init.1 +1 -1
- package/man/mend-keys-mode.1 +1 -1
- package/man/mend-keys-share.1 +1 -1
- package/man/mend-keys-show.1 +1 -1
- package/man/mend-land.1 +48 -0
- package/man/mend-login.1 +1 -1
- package/man/mend-logout.1 +1 -1
- package/man/mend-man.1 +1 -1
- package/man/mend-members.1 +1 -1
- package/man/mend-operator-exposure.1 +1 -1
- package/man/mend-operator-gate.1 +1 -1
- package/man/mend-operator-grant-owner.1 +1 -1
- package/man/mend-operator-org-create.1 +1 -1
- package/man/mend-operator-org-invite-owner.1 +1 -1
- package/man/mend-operator-org-list.1 +1 -1
- package/man/mend-operator-org-rename.1 +1 -1
- package/man/mend-operator-reset-link.1 +1 -1
- package/man/mend-pair.1 +1 -1
- package/man/mend-projects.1 +1 -1
- package/man/mend-pull.1 +29 -0
- package/man/mend-refresh.1 +1 -1
- package/man/mend-rejoin.1 +7 -2
- package/man/mend-resume.1 +1 -1
- package/man/mend-run.1 +1 -1
- package/man/mend-server-logs.1 +1 -1
- package/man/mend-server-restart.1 +1 -1
- package/man/mend-server-setup.1 +1 -1
- package/man/mend-server-start.1 +1 -1
- package/man/mend-server-status.1 +1 -1
- package/man/mend-server-stop.1 +1 -1
- package/man/mend-server-upgrade.1 +1 -1
- package/man/mend-server.1 +1 -1
- package/man/mend-service-add.1 +1 -1
- package/man/mend-service-connect.1 +3 -1
- package/man/mend-service-init.1 +1 -1
- package/man/mend-service-list.1 +1 -1
- package/man/mend-service-logs.1 +1 -1
- package/man/mend-service-restart.1 +1 -1
- package/man/mend-service-run.1 +1 -1
- package/man/mend-service-stop.1 +1 -1
- package/man/mend-session-share.1 +1 -1
- package/man/mend-sessions.1 +1 -1
- package/man/mend-shell.1 +1 -1
- package/man/mend-skills-push.1 +1 -1
- package/man/mend-skills.1 +1 -1
- package/man/mend-snake.1 +13 -0
- package/man/mend-ssh-setup.1 +1 -1
- package/man/mend-ssh.1 +1 -1
- package/man/mend-stop.1 +8 -1
- package/man/mend-ui.1 +9 -3
- package/man/mend-uninstall.1 +1 -1
- package/man/mend-version.1 +1 -1
- package/man/mend-worktrees.1 +1 -1
- package/man/mend.1 +17 -2
- package/package.json +1 -1
|
@@ -2,13 +2,18 @@ import {
|
|
|
2
2
|
HARNESS_COMMANDS,
|
|
3
3
|
LIVE_STATUSES,
|
|
4
4
|
RepositoryCloneUrl,
|
|
5
|
+
agentIsLive,
|
|
6
|
+
agentOutcome,
|
|
7
|
+
createSseParser,
|
|
5
8
|
cwdFacts,
|
|
9
|
+
eventFamilies,
|
|
6
10
|
isPendingId,
|
|
7
11
|
matchProjectByCwd,
|
|
8
12
|
normalizeProjectName,
|
|
9
13
|
pendingId,
|
|
10
|
-
repositoryCloneUrlIssue
|
|
11
|
-
|
|
14
|
+
repositoryCloneUrlIssue,
|
|
15
|
+
servicesHoldLine
|
|
16
|
+
} from "./chunk-J3TR4UAG.js";
|
|
12
17
|
|
|
13
18
|
// src/dashboard.tsx
|
|
14
19
|
import { CliRenderEvents, createCliRenderer } from "@opentui/core";
|
|
@@ -20,7 +25,7 @@ import {
|
|
|
20
25
|
useQuery as useQuery2,
|
|
21
26
|
useQueryClient as useQueryClient2
|
|
22
27
|
} from "@tanstack/react-query";
|
|
23
|
-
import { useEffect as
|
|
28
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState3, useSyncExternalStore } from "react";
|
|
24
29
|
|
|
25
30
|
// src/dashboard-adoption.ts
|
|
26
31
|
var deriveAdoptOffer = (facts) => {
|
|
@@ -265,17 +270,31 @@ var createLaunchGate = () => {
|
|
|
265
270
|
var markSessionStopped = (data, sessionId) => {
|
|
266
271
|
const processesBySession = new Map(data.processesBySession);
|
|
267
272
|
processesBySession.delete(sessionId);
|
|
268
|
-
const servicesBySession = new Map(data.servicesBySession);
|
|
269
|
-
servicesBySession.delete(sessionId);
|
|
270
273
|
return {
|
|
271
274
|
...mapWorkbenchSessions(
|
|
272
275
|
data,
|
|
273
276
|
(session) => session.id === sessionId ? { ...session, status: "stopped" } : session
|
|
274
277
|
),
|
|
275
|
-
processesBySession
|
|
276
|
-
servicesBySession
|
|
278
|
+
processesBySession
|
|
277
279
|
};
|
|
278
280
|
};
|
|
281
|
+
var markServicesStopped = (data, sessionId) => {
|
|
282
|
+
const servicesBySession = new Map(data.servicesBySession);
|
|
283
|
+
servicesBySession.delete(sessionId);
|
|
284
|
+
return { ...data, servicesBySession };
|
|
285
|
+
};
|
|
286
|
+
var AGENT_WORKING = /* @__PURE__ */ new Set(["starting", "running", "waiting"]);
|
|
287
|
+
var sessionHold = (item) => {
|
|
288
|
+
const agent = item.annotation?.currentAgent ?? null;
|
|
289
|
+
const agentProcessLive = item.processes.some(
|
|
290
|
+
(process2) => process2.kind !== "shell" && process2.exitedAt === null
|
|
291
|
+
);
|
|
292
|
+
return servicesHoldLine({
|
|
293
|
+
agentLive: agent === null ? agentProcessLive || AGENT_WORKING.has(item.session.status) : agentIsLive(item.session, agent),
|
|
294
|
+
agentOutcome: agentOutcome(agent),
|
|
295
|
+
liveServices: Math.max(item.annotation?.liveServices ?? 0, item.services.length)
|
|
296
|
+
});
|
|
297
|
+
};
|
|
279
298
|
var removeWorktreeGroup = (data, projectId, group) => {
|
|
280
299
|
const memberIds = new Set(group.sessions.map((item) => item.session.id));
|
|
281
300
|
const detail = data.details.get(projectId);
|
|
@@ -993,6 +1012,7 @@ var stateColor = (state) => state === "draft" || state === "open" ? INK : state
|
|
|
993
1012
|
var anchorOf = (comment) => comment.file === null ? "change" : `${comment.file}${comment.line === null ? "" : `:${comment.line}${comment.endLine === null || comment.endLine === comment.line ? "" : `-${comment.endLine}`}`}`;
|
|
994
1013
|
var passFact = (pass) => {
|
|
995
1014
|
const label = pass.kind === "suggest" ? "suggestions" : pass.kind;
|
|
1015
|
+
if (pass.status === "queued") return { text: `${label} queued`, color: MUTED };
|
|
996
1016
|
if (pass.status === "running") return { text: `${label} running`, color: INK_2 };
|
|
997
1017
|
if (pass.status === "failed") return { text: `${label} failed`, color: ERROR };
|
|
998
1018
|
return {
|
|
@@ -1948,56 +1968,181 @@ function ReviewScreen({
|
|
|
1948
1968
|
);
|
|
1949
1969
|
}
|
|
1950
1970
|
|
|
1951
|
-
// src/
|
|
1952
|
-
|
|
1953
|
-
|
|
1971
|
+
// src/snake.tsx
|
|
1972
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1973
|
+
|
|
1974
|
+
// src/snake-game.ts
|
|
1975
|
+
var OPPOSITE = {
|
|
1976
|
+
up: "down",
|
|
1977
|
+
down: "up",
|
|
1978
|
+
left: "right",
|
|
1979
|
+
right: "left"
|
|
1980
|
+
};
|
|
1981
|
+
var STEP = {
|
|
1982
|
+
up: { x: 0, y: -1 },
|
|
1983
|
+
down: { x: 0, y: 1 },
|
|
1984
|
+
left: { x: -1, y: 0 },
|
|
1985
|
+
right: { x: 1, y: 0 }
|
|
1986
|
+
};
|
|
1987
|
+
var same = (a, b) => a.x === b.x && a.y === b.y;
|
|
1988
|
+
var placeFood = (width, height, snake, random) => {
|
|
1989
|
+
const free = [];
|
|
1990
|
+
for (let y = 0; y < height; y += 1)
|
|
1991
|
+
for (let x = 0; x < width; x += 1)
|
|
1992
|
+
if (!snake.some((cell) => cell.x === x && cell.y === y)) free.push({ x, y });
|
|
1993
|
+
if (free.length === 0) return snake[0] ?? { x: 0, y: 0 };
|
|
1994
|
+
return free[Math.min(free.length - 1, Math.floor(random() * free.length))] ?? free[0];
|
|
1995
|
+
};
|
|
1996
|
+
var newSnakeGame = (width, height, random) => {
|
|
1997
|
+
const w = Math.max(8, width);
|
|
1998
|
+
const h = Math.max(4, height);
|
|
1999
|
+
const y = Math.floor(h / 2);
|
|
2000
|
+
const x = Math.floor(w / 2);
|
|
2001
|
+
const snake = [
|
|
2002
|
+
{ x, y },
|
|
2003
|
+
{ x: x - 1, y },
|
|
2004
|
+
{ x: x - 2, y }
|
|
2005
|
+
];
|
|
1954
2006
|
return {
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
const data = frame.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice("data:".length).replace(/^ /, "")).join("\n");
|
|
1964
|
-
if (data !== "") payloads.push(data);
|
|
1965
|
-
}
|
|
1966
|
-
return payloads;
|
|
1967
|
-
}
|
|
2007
|
+
width: w,
|
|
2008
|
+
height: h,
|
|
2009
|
+
snake,
|
|
2010
|
+
direction: "right",
|
|
2011
|
+
pending: null,
|
|
2012
|
+
food: placeFood(w, h, snake, random),
|
|
2013
|
+
score: 0,
|
|
2014
|
+
over: false
|
|
1968
2015
|
};
|
|
1969
2016
|
};
|
|
1970
|
-
var
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
return ["workbench", "review", "transcript"];
|
|
1988
|
-
case "agent-conversation":
|
|
1989
|
-
return ["workbench", "review"];
|
|
1990
|
-
// A comment moves the review AND the dashboard's open-comment counts.
|
|
1991
|
-
case "session-change":
|
|
1992
|
-
case "review-comment":
|
|
1993
|
-
return ["workbench", "review"];
|
|
1994
|
-
default:
|
|
1995
|
-
return [];
|
|
2017
|
+
var turn = (game, direction) => {
|
|
2018
|
+
if (game.over) return game;
|
|
2019
|
+
if (direction === OPPOSITE[game.direction] || direction === game.direction) return game;
|
|
2020
|
+
return { ...game, pending: direction };
|
|
2021
|
+
};
|
|
2022
|
+
var tick = (game, random) => {
|
|
2023
|
+
if (game.over) return game;
|
|
2024
|
+
const direction = game.pending ?? game.direction;
|
|
2025
|
+
const head = game.snake[0];
|
|
2026
|
+
const next = {
|
|
2027
|
+
x: (head.x + STEP[direction].x + game.width) % game.width,
|
|
2028
|
+
y: (head.y + STEP[direction].y + game.height) % game.height
|
|
2029
|
+
};
|
|
2030
|
+
const eats = same(next, game.food);
|
|
2031
|
+
const body = eats ? game.snake : game.snake.slice(0, -1);
|
|
2032
|
+
if (body.some((cell) => same(cell, next))) {
|
|
2033
|
+
return { ...game, direction, pending: null, over: true };
|
|
1996
2034
|
}
|
|
2035
|
+
const snake = [next, ...body];
|
|
2036
|
+
return {
|
|
2037
|
+
...game,
|
|
2038
|
+
snake,
|
|
2039
|
+
direction,
|
|
2040
|
+
pending: null,
|
|
2041
|
+
score: eats ? game.score + 1 : game.score,
|
|
2042
|
+
food: eats ? placeFood(game.width, game.height, snake, random) : game.food
|
|
2043
|
+
};
|
|
2044
|
+
};
|
|
2045
|
+
var render = (game) => {
|
|
2046
|
+
const rows = [];
|
|
2047
|
+
for (let y = 0; y < game.height; y += 1) rows.push(Array.from({ length: game.width }, () => "\xB7"));
|
|
2048
|
+
rows[game.food.y][game.food.x] = "\u25CF";
|
|
2049
|
+
game.snake.forEach((cell, index) => {
|
|
2050
|
+
rows[cell.y][cell.x] = index === 0 ? "\u25C6" : "\u2588";
|
|
2051
|
+
});
|
|
2052
|
+
return rows.map((row) => row.join(""));
|
|
1997
2053
|
};
|
|
1998
2054
|
|
|
1999
|
-
// src/
|
|
2055
|
+
// src/snake.tsx
|
|
2000
2056
|
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "@opentui/react/jsx-runtime";
|
|
2057
|
+
var TICK_MS = 140;
|
|
2058
|
+
var useSnake = (options) => {
|
|
2059
|
+
const { width, height, enabled } = options;
|
|
2060
|
+
const [game, setGame] = useState2(() => newSnakeGame(width, height, Math.random));
|
|
2061
|
+
const [paused, setPaused] = useState2(false);
|
|
2062
|
+
useEffect2(() => {
|
|
2063
|
+
if (enabled) {
|
|
2064
|
+
setGame(newSnakeGame(width, height, Math.random));
|
|
2065
|
+
setPaused(false);
|
|
2066
|
+
}
|
|
2067
|
+
}, [width, height, enabled]);
|
|
2068
|
+
useEffect2(() => {
|
|
2069
|
+
if (!enabled || paused) return;
|
|
2070
|
+
const timer = setInterval(() => setGame((current) => tick(current, Math.random)), TICK_MS);
|
|
2071
|
+
return () => clearInterval(timer);
|
|
2072
|
+
}, [enabled, paused]);
|
|
2073
|
+
const steer = (direction) => {
|
|
2074
|
+
setPaused(false);
|
|
2075
|
+
setGame(
|
|
2076
|
+
(current) => current.over ? newSnakeGame(current.width, current.height, Math.random) : turn(current, direction)
|
|
2077
|
+
);
|
|
2078
|
+
};
|
|
2079
|
+
const togglePause = () => setPaused((current) => !current);
|
|
2080
|
+
return { game, paused, steer, togglePause };
|
|
2081
|
+
};
|
|
2082
|
+
var SnakeHeading = ({
|
|
2083
|
+
handle,
|
|
2084
|
+
hint
|
|
2085
|
+
}) => {
|
|
2086
|
+
const { game, paused } = handle;
|
|
2087
|
+
const state = game.over ? "over \xB7 any arrow starts again" : paused ? "paused" : null;
|
|
2088
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2089
|
+
/* @__PURE__ */ jsxs2("text", { height: 1, bg: "transparent", children: [
|
|
2090
|
+
/* @__PURE__ */ jsx2("span", { children: " " }),
|
|
2091
|
+
/* @__PURE__ */ jsx2("span", { fg: INK, children: "play snake while you wait" }),
|
|
2092
|
+
/* @__PURE__ */ jsx2("span", { fg: FAINT, children: " \xB7 score " }),
|
|
2093
|
+
/* @__PURE__ */ jsx2("span", { fg: game.over ? MUTED : ACCENT, children: String(game.score) }),
|
|
2094
|
+
state === null ? null : /* @__PURE__ */ jsx2("span", { fg: FAINT, children: ` \xB7 ${state}` })
|
|
2095
|
+
] }),
|
|
2096
|
+
/* @__PURE__ */ jsx2("text", { height: 1, bg: "transparent", fg: FAINT, children: ` ${hint}` })
|
|
2097
|
+
] });
|
|
2098
|
+
};
|
|
2099
|
+
var SnakeBoard = ({
|
|
2100
|
+
handle,
|
|
2101
|
+
focused
|
|
2102
|
+
}) => {
|
|
2103
|
+
const { game } = handle;
|
|
2104
|
+
const rows = render(game);
|
|
2105
|
+
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
2106
|
+
/* @__PURE__ */ jsx2(
|
|
2107
|
+
SnakeHeading,
|
|
2108
|
+
{
|
|
2109
|
+
handle,
|
|
2110
|
+
hint: focused ? "arrows steer \xB7 space pauses \xB7 esc puts it away" : "focus this pane to play \xB7 esc puts it away"
|
|
2111
|
+
}
|
|
2112
|
+
),
|
|
2113
|
+
/* @__PURE__ */ jsx2(
|
|
2114
|
+
"box",
|
|
2115
|
+
{
|
|
2116
|
+
border: true,
|
|
2117
|
+
borderStyle: "rounded",
|
|
2118
|
+
borderColor: focused ? ACCENT : RULE,
|
|
2119
|
+
width: game.width + 2,
|
|
2120
|
+
height: game.height + 2,
|
|
2121
|
+
flexShrink: 0,
|
|
2122
|
+
marginLeft: 2,
|
|
2123
|
+
children: rows.map((row, index) => /* @__PURE__ */ jsx2("text", { height: 1, bg: "transparent", children: [...row].map((cell, x) => /* @__PURE__ */ jsx2(
|
|
2124
|
+
"span",
|
|
2125
|
+
{
|
|
2126
|
+
fg: cell === "\u25C6" ? ACCENT : cell === "\u2588" ? GREEN : cell === "\u25CF" ? INK : FAINT,
|
|
2127
|
+
children: cell === "\xB7" ? " " : cell
|
|
2128
|
+
},
|
|
2129
|
+
x
|
|
2130
|
+
)) }, index))
|
|
2131
|
+
}
|
|
2132
|
+
)
|
|
2133
|
+
] });
|
|
2134
|
+
};
|
|
2135
|
+
var SnakeRows = ({ game }) => /* @__PURE__ */ jsx2(Fragment2, { children: render(game).map((row, index) => /* @__PURE__ */ jsx2("text", { height: 1, bg: "transparent", children: [...row].map((cell, x) => /* @__PURE__ */ jsx2(
|
|
2136
|
+
"span",
|
|
2137
|
+
{
|
|
2138
|
+
fg: cell === "\u25C6" ? ACCENT : cell === "\u2588" ? GREEN : cell === "\u25CF" ? INK : FAINT,
|
|
2139
|
+
children: cell === "\xB7" ? " " : cell
|
|
2140
|
+
},
|
|
2141
|
+
x
|
|
2142
|
+
)) }, index)) });
|
|
2143
|
+
|
|
2144
|
+
// src/dashboard.tsx
|
|
2145
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "@opentui/react/jsx-runtime";
|
|
2001
2146
|
var STATUS_COLOR = {
|
|
2002
2147
|
starting: INK_2,
|
|
2003
2148
|
running: INK,
|
|
@@ -2028,7 +2173,7 @@ var COLUMN_TITLE = {
|
|
|
2028
2173
|
};
|
|
2029
2174
|
var WORKTREE_ROW_HEIGHT = 2;
|
|
2030
2175
|
var SESSION_ROW_HEIGHT = 2;
|
|
2031
|
-
var Gutter = ({ selected }) => /* @__PURE__ */
|
|
2176
|
+
var Gutter = ({ selected }) => /* @__PURE__ */ jsx3("span", { fg: selected ? ACCENT : FAINT, children: selected ? "\u258C " : " " });
|
|
2032
2177
|
var Pane = ({
|
|
2033
2178
|
title,
|
|
2034
2179
|
focused,
|
|
@@ -2036,7 +2181,7 @@ var Pane = ({
|
|
|
2036
2181
|
width,
|
|
2037
2182
|
height,
|
|
2038
2183
|
grow
|
|
2039
|
-
}) => /* @__PURE__ */
|
|
2184
|
+
}) => /* @__PURE__ */ jsx3(
|
|
2040
2185
|
"box",
|
|
2041
2186
|
{
|
|
2042
2187
|
border: true,
|
|
@@ -2062,10 +2207,10 @@ var SummaryRow = ({
|
|
|
2062
2207
|
}) => {
|
|
2063
2208
|
const factWidth = fact === "" ? 0 : Math.min(fact.length, Math.max(0, width - 8));
|
|
2064
2209
|
const nameWidth = Math.max(4, width - factWidth - 3);
|
|
2065
|
-
return /* @__PURE__ */
|
|
2066
|
-
/* @__PURE__ */
|
|
2067
|
-
/* @__PURE__ */
|
|
2068
|
-
factWidth === 0 ? null : /* @__PURE__ */
|
|
2210
|
+
return /* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2211
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " " }),
|
|
2212
|
+
/* @__PURE__ */ jsx3("span", { fg: empty ? FAINT : INK_2, children: fit(name, nameWidth - 1).padEnd(nameWidth) }),
|
|
2213
|
+
factWidth === 0 ? null : /* @__PURE__ */ jsx3("span", { fg: FAINT, children: fit(fact, factWidth) })
|
|
2069
2214
|
] });
|
|
2070
2215
|
};
|
|
2071
2216
|
var paneScrollStyle = {
|
|
@@ -2074,17 +2219,17 @@ var paneScrollStyle = {
|
|
|
2074
2219
|
viewportOptions: { backgroundColor: "transparent" },
|
|
2075
2220
|
contentOptions: { backgroundColor: "transparent" }
|
|
2076
2221
|
};
|
|
2077
|
-
var EmptyNote = ({ text }) => /* @__PURE__ */
|
|
2222
|
+
var EmptyNote = ({ text }) => /* @__PURE__ */ jsx3("text", { height: 1, fg: FAINT, bg: "transparent", children: ` ${text}` });
|
|
2078
2223
|
var ProjectRow = ({
|
|
2079
2224
|
item,
|
|
2080
2225
|
selected,
|
|
2081
2226
|
width
|
|
2082
2227
|
}) => {
|
|
2083
2228
|
const nameWidth = Math.max(6, width - 9);
|
|
2084
|
-
return /* @__PURE__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
2229
|
+
return /* @__PURE__ */ jsx3("box", { height: 1, flexShrink: 0, backgroundColor: selected ? WASH : "transparent", children: /* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2230
|
+
/* @__PURE__ */ jsx3(Gutter, { selected }),
|
|
2231
|
+
/* @__PURE__ */ jsx3("span", { fg: INK, children: fit(item.project.name, nameWidth).padEnd(nameWidth + 1) }),
|
|
2232
|
+
/* @__PURE__ */ jsx3("span", { fg: item.live > 0 ? MUTED : FAINT, children: item.live > 0 ? `${item.live}/${item.total}` : String(item.total) })
|
|
2088
2233
|
] }) });
|
|
2089
2234
|
};
|
|
2090
2235
|
var WorktreeRow = ({
|
|
@@ -2109,13 +2254,13 @@ var WorktreeRow = ({
|
|
|
2109
2254
|
],
|
|
2110
2255
|
factWidth
|
|
2111
2256
|
);
|
|
2112
|
-
return /* @__PURE__ */
|
|
2113
|
-
/* @__PURE__ */
|
|
2114
|
-
/* @__PURE__ */
|
|
2115
|
-
/* @__PURE__ */
|
|
2116
|
-
/* @__PURE__ */
|
|
2257
|
+
return /* @__PURE__ */ jsxs3("box", { flexShrink: 0, flexDirection: "column", backgroundColor: selected ? WASH : "transparent", children: [
|
|
2258
|
+
/* @__PURE__ */ jsx3("box", { height: 1, flexShrink: 0, backgroundColor: "transparent", children: /* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2259
|
+
/* @__PURE__ */ jsx3(Gutter, { selected }),
|
|
2260
|
+
/* @__PURE__ */ jsx3("span", { fg: INK, children: fit(group.name, nameWidth - 1).padEnd(nameWidth) }),
|
|
2261
|
+
/* @__PURE__ */ jsx3("span", { fg: color, children: status })
|
|
2117
2262
|
] }) }),
|
|
2118
|
-
/* @__PURE__ */
|
|
2263
|
+
/* @__PURE__ */ jsx3("box", { height: 1, flexShrink: 0, backgroundColor: "transparent", children: /* @__PURE__ */ jsx3("text", { height: 1, bg: "transparent", fg: FAINT, children: ` ${facts}` }) })
|
|
2119
2264
|
] });
|
|
2120
2265
|
};
|
|
2121
2266
|
var SessionRow = ({
|
|
@@ -2130,33 +2275,35 @@ var SessionRow = ({
|
|
|
2130
2275
|
const shells = processes.filter((process2) => process2.kind === "shell").length;
|
|
2131
2276
|
const nameWidth = Math.max(6, width - 5 - status.length);
|
|
2132
2277
|
const factWidth = Math.max(8, width - 3);
|
|
2278
|
+
const hold = sessionHold(item);
|
|
2133
2279
|
const facts = fitHints(
|
|
2134
2280
|
[
|
|
2281
|
+
...hold === null ? [] : [hold],
|
|
2135
2282
|
session.harness,
|
|
2136
2283
|
shortAge(session.createdAt),
|
|
2137
2284
|
...shells > 0 ? [`${shells} shell`] : [],
|
|
2138
2285
|
...agents > 0 ? [`${agents} agent`] : [],
|
|
2139
|
-
...services.length > 0 ? [`${services.length} service`] : []
|
|
2286
|
+
...hold === null && services.length > 0 ? [`${services.length} service`] : []
|
|
2140
2287
|
],
|
|
2141
2288
|
factWidth
|
|
2142
2289
|
);
|
|
2143
|
-
return /* @__PURE__ */
|
|
2144
|
-
/* @__PURE__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
2146
|
-
/* @__PURE__ */
|
|
2147
|
-
/* @__PURE__ */
|
|
2290
|
+
return /* @__PURE__ */ jsxs3("box", { flexShrink: 0, flexDirection: "column", backgroundColor: selected ? WASH : "transparent", children: [
|
|
2291
|
+
/* @__PURE__ */ jsx3("box", { height: 1, flexShrink: 0, backgroundColor: "transparent", children: /* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2292
|
+
/* @__PURE__ */ jsx3(Gutter, { selected }),
|
|
2293
|
+
/* @__PURE__ */ jsx3("span", { fg: INK, children: fit(sessionDisplayName(session), nameWidth - 1).padEnd(nameWidth) }),
|
|
2294
|
+
/* @__PURE__ */ jsx3("span", { fg: color, children: status })
|
|
2148
2295
|
] }) }),
|
|
2149
|
-
/* @__PURE__ */
|
|
2296
|
+
/* @__PURE__ */ jsx3("box", { height: 1, flexShrink: 0, backgroundColor: "transparent", children: /* @__PURE__ */ jsx3("text", { height: 1, bg: "transparent", fg: FAINT, children: ` ${facts}` }) })
|
|
2150
2297
|
] });
|
|
2151
2298
|
};
|
|
2152
2299
|
var HarnessRow = ({
|
|
2153
2300
|
item,
|
|
2154
2301
|
selected,
|
|
2155
2302
|
background
|
|
2156
|
-
}) => /* @__PURE__ */
|
|
2157
|
-
/* @__PURE__ */
|
|
2158
|
-
/* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2303
|
+
}) => /* @__PURE__ */ jsx3("box", { height: 1, flexShrink: 0, backgroundColor: selected ? WASH : background, children: /* @__PURE__ */ jsxs3("text", { height: 1, bg: selected ? WASH : background, children: [
|
|
2304
|
+
/* @__PURE__ */ jsx3(Gutter, { selected }),
|
|
2305
|
+
/* @__PURE__ */ jsx3("span", { fg: INK, children: item.label.padEnd(12) }),
|
|
2306
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: item.hint })
|
|
2160
2307
|
] }) });
|
|
2161
2308
|
var PREVIEW_GLYPH = {
|
|
2162
2309
|
user: "\u203A ",
|
|
@@ -2176,68 +2323,77 @@ var PREVIEW_COLOR = {
|
|
|
2176
2323
|
meta: FAINT,
|
|
2177
2324
|
blank: FAINT
|
|
2178
2325
|
};
|
|
2179
|
-
var PreviewRow = ({ line }) => /* @__PURE__ */
|
|
2180
|
-
/* @__PURE__ */
|
|
2181
|
-
/* @__PURE__ */
|
|
2326
|
+
var PreviewRow = ({ line }) => /* @__PURE__ */ jsx3("box", { height: 1, flexShrink: 0, backgroundColor: "transparent", children: /* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2327
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: line.lead ? PREVIEW_GLYPH[line.kind] : " " }),
|
|
2328
|
+
/* @__PURE__ */ jsx3("span", { fg: PREVIEW_COLOR[line.kind], children: line.text })
|
|
2182
2329
|
] }) });
|
|
2183
2330
|
var SessionFacts = ({
|
|
2184
2331
|
group,
|
|
2185
2332
|
item,
|
|
2186
|
-
rows
|
|
2333
|
+
rows,
|
|
2334
|
+
tunnels
|
|
2187
2335
|
}) => {
|
|
2188
2336
|
const { session, annotation, services } = item;
|
|
2189
2337
|
const color = STATUS_COLOR[session.status] ?? MUTED;
|
|
2338
|
+
const hold = sessionHold(item);
|
|
2190
2339
|
const summary = session.summary?.split("\n")[0] ?? null;
|
|
2191
2340
|
const change = annotation ?? group?.annotation;
|
|
2192
2341
|
const lines = [
|
|
2193
|
-
/* @__PURE__ */
|
|
2194
|
-
/* @__PURE__ */
|
|
2195
|
-
/* @__PURE__ */
|
|
2196
|
-
/* @__PURE__ */
|
|
2342
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2343
|
+
/* @__PURE__ */ jsx3("span", { children: " " }),
|
|
2344
|
+
/* @__PURE__ */ jsx3("span", { fg: INK, children: sessionDisplayName(session) }),
|
|
2345
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: ` \xB7 ${session.harness}` })
|
|
2197
2346
|
] }, "name"),
|
|
2198
|
-
/* @__PURE__ */
|
|
2199
|
-
/* @__PURE__ */
|
|
2200
|
-
/* @__PURE__ */
|
|
2201
|
-
/* @__PURE__ */
|
|
2202
|
-
|
|
2203
|
-
|
|
2347
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2348
|
+
/* @__PURE__ */ jsx3("span", { children: " " }),
|
|
2349
|
+
/* @__PURE__ */ jsx3("span", { fg: color, children: session.status }),
|
|
2350
|
+
hold === null ? null : /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
2351
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
2352
|
+
/* @__PURE__ */ jsx3("span", { fg: INK_2, children: hold })
|
|
2353
|
+
] }),
|
|
2354
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
2355
|
+
/* @__PURE__ */ jsx3("span", { fg: MUTED, children: session.branch }),
|
|
2356
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: session.baseSha === "" ? "" : ` vs ${session.baseRef ?? session.baseSha.slice(0, 12)}` })
|
|
2204
2357
|
] }, "status"),
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */
|
|
2208
|
-
services.length === 0 ? /* @__PURE__ */
|
|
2209
|
-
|
|
2210
|
-
/* @__PURE__ */
|
|
2211
|
-
|
|
2212
|
-
|
|
2358
|
+
/* @__PURE__ */ jsx3("text", { height: 1, bg: "transparent", fg: FAINT, children: ` started ${timeAgo(session.createdAt)} \xB7 ${isPendingId(session.id) ? "provisioning" : session.id.slice(0, 8)}` }, "started"),
|
|
2359
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2360
|
+
/* @__PURE__ */ jsx3("span", { children: " " }),
|
|
2361
|
+
services.length === 0 ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: "no services running" }) : services.slice(0, 2).map((service, index) => {
|
|
2362
|
+
const tunnel = tunnels.find((candidate) => candidate.service.id === service.id);
|
|
2363
|
+
return /* @__PURE__ */ jsxs3("span", { children: [
|
|
2364
|
+
index > 0 ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }) : null,
|
|
2365
|
+
/* @__PURE__ */ jsx3("span", { fg: service.status === "reachable" ? INK_2 : MUTED, children: tunnel === void 0 ? `${service.label ?? service.id.slice(0, 6)} :${service.workspacePort ?? "?"}${service.protocol === "udp" ? "u" : ""}\u2192${service.hostPort ?? "?"} ${service.status}` : tunnel.line })
|
|
2366
|
+
] }, service.id);
|
|
2367
|
+
}),
|
|
2368
|
+
services.length > 2 ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: ` \xB7 +${services.length - 2} more` }) : null
|
|
2213
2369
|
] }, "services"),
|
|
2214
|
-
/* @__PURE__ */
|
|
2215
|
-
/* @__PURE__ */
|
|
2216
|
-
change === void 0 || change.openComments === 0 ? /* @__PURE__ */
|
|
2370
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2371
|
+
/* @__PURE__ */ jsx3("span", { children: " " }),
|
|
2372
|
+
change === void 0 || change.openComments === 0 ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: "no open review comments" }) : /* @__PURE__ */ jsxs3("span", { fg: INK_2, children: [
|
|
2217
2373
|
change.openComments,
|
|
2218
2374
|
" open comment",
|
|
2219
2375
|
change.openComments === 1 ? "" : "s"
|
|
2220
2376
|
] }),
|
|
2221
|
-
change?.pendingFollowUp === true ? /* @__PURE__ */
|
|
2222
|
-
/* @__PURE__ */
|
|
2223
|
-
/* @__PURE__ */
|
|
2377
|
+
change?.pendingFollowUp === true ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
2378
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
2379
|
+
/* @__PURE__ */ jsx3("span", { fg: INK_2, children: "follow-up pending" })
|
|
2224
2380
|
] }) : null,
|
|
2225
|
-
change?.changeId == null ? null : /* @__PURE__ */
|
|
2226
|
-
/* @__PURE__ */
|
|
2227
|
-
/* @__PURE__ */
|
|
2381
|
+
change?.changeId == null ? null : /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
2382
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
2383
|
+
/* @__PURE__ */ jsx3("span", { fg: MUTED, children: "v reviews the change" })
|
|
2228
2384
|
] })
|
|
2229
2385
|
] }, "comments"),
|
|
2230
|
-
/* @__PURE__ */
|
|
2386
|
+
/* @__PURE__ */ jsx3("text", { height: 1, bg: "transparent", fg: summary === null ? FAINT : MUTED, children: ` ${fit(summary ?? "no summary yet", 200)}` }, "summary")
|
|
2231
2387
|
];
|
|
2232
|
-
return /* @__PURE__ */
|
|
2388
|
+
return /* @__PURE__ */ jsx3("box", { flexShrink: 0, flexDirection: "column", backgroundColor: "transparent", children: lines.slice(0, Math.max(0, rows)) });
|
|
2233
2389
|
};
|
|
2234
2390
|
var StatusLine = ({
|
|
2235
2391
|
busy,
|
|
2236
2392
|
busyStarted,
|
|
2237
2393
|
status
|
|
2238
2394
|
}) => {
|
|
2239
|
-
const [now, setNow] =
|
|
2240
|
-
|
|
2395
|
+
const [now, setNow] = useState3(() => Date.now());
|
|
2396
|
+
useEffect3(() => {
|
|
2241
2397
|
if (busy !== null) {
|
|
2242
2398
|
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
2243
2399
|
return () => clearInterval(timer);
|
|
@@ -2249,7 +2405,7 @@ var StatusLine = ({
|
|
|
2249
2405
|
return void 0;
|
|
2250
2406
|
}, [busy, status]);
|
|
2251
2407
|
const text = busy === null ? status !== null && Date.now() - status.at < 5e3 ? ` ${status.text}` : "" : ` ${busy} ${Math.max(0, Math.round((now - busyStarted) / 1e3))}s`;
|
|
2252
|
-
return /* @__PURE__ */
|
|
2408
|
+
return /* @__PURE__ */ jsx3("text", { height: 1, fg: INK_2, bg: "transparent", children: text });
|
|
2253
2409
|
};
|
|
2254
2410
|
var errorText = (error) => error instanceof Error ? error.message : String(error);
|
|
2255
2411
|
var keepSpanVisible = (scroll, top, height, viewRows) => {
|
|
@@ -2261,6 +2417,8 @@ var keepSpanVisible = (scroll, top, height, viewRows) => {
|
|
|
2261
2417
|
var PREVIEW_MAX_LINES = 300;
|
|
2262
2418
|
var SESSION_FACT_ROWS = 6;
|
|
2263
2419
|
var noShare = () => "off";
|
|
2420
|
+
var NO_TUNNELS = [];
|
|
2421
|
+
var noTunnels = () => NO_TUNNELS;
|
|
2264
2422
|
var App = ({ ctx, onQuit }) => {
|
|
2265
2423
|
const renderer = useRenderer();
|
|
2266
2424
|
const queryClient = useQueryClient2();
|
|
@@ -2271,30 +2429,35 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2271
2429
|
retry: true,
|
|
2272
2430
|
retryDelay: 1e3
|
|
2273
2431
|
});
|
|
2274
|
-
const [focus, setFocusState] =
|
|
2275
|
-
const [lastNav, setLastNav] =
|
|
2276
|
-
const [projectKey, setProjectKey] =
|
|
2277
|
-
const [worktreeKey, setWorktreeKey] =
|
|
2278
|
-
const [sessionKey, setSessionKey] =
|
|
2279
|
-
const [picker, setPicker] =
|
|
2280
|
-
const [pickerIndex, setPickerIndex] =
|
|
2281
|
-
const [busy, setBusy] =
|
|
2282
|
-
const [busyStarted, setBusyStarted] =
|
|
2283
|
-
const [status, setStatus] =
|
|
2432
|
+
const [focus, setFocusState] = useState3("sessions");
|
|
2433
|
+
const [lastNav, setLastNav] = useState3("sessions");
|
|
2434
|
+
const [projectKey, setProjectKey] = useState3(null);
|
|
2435
|
+
const [worktreeKey, setWorktreeKey] = useState3(null);
|
|
2436
|
+
const [sessionKey, setSessionKey] = useState3(null);
|
|
2437
|
+
const [picker, setPicker] = useState3(null);
|
|
2438
|
+
const [pickerIndex, setPickerIndex] = useState3(0);
|
|
2439
|
+
const [busy, setBusy] = useState3(null);
|
|
2440
|
+
const [busyStarted, setBusyStarted] = useState3(0);
|
|
2441
|
+
const [status, setStatus] = useState3(null);
|
|
2284
2442
|
const shareState = useSyncExternalStore(
|
|
2285
2443
|
(onChange) => ctx.agentShare?.subscribe(() => onChange()) ?? (() => {
|
|
2286
2444
|
}),
|
|
2287
2445
|
ctx.agentShare === null ? noShare : ctx.agentShare.snapshot
|
|
2288
2446
|
);
|
|
2289
|
-
const
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2447
|
+
const openTunnels = useSyncExternalStore(
|
|
2448
|
+
(onChange) => ctx.tunnels?.subscribe(onChange) ?? (() => {
|
|
2449
|
+
}),
|
|
2450
|
+
ctx.tunnels === null ? noTunnels : ctx.tunnels.current
|
|
2451
|
+
);
|
|
2452
|
+
const [editing, setEditing] = useState3(null);
|
|
2453
|
+
const [stopArmed, setStopArmed] = useState3(null);
|
|
2454
|
+
const [removeArmed, setRemoveArmed] = useState3(null);
|
|
2455
|
+
const [creating, setCreating] = useState3(null);
|
|
2456
|
+
const [adoptOffer, setAdoptOffer] = useState3(null);
|
|
2294
2457
|
const adoptOfferDecided = useRef2(false);
|
|
2295
|
-
const [reviewing, setReviewing] =
|
|
2458
|
+
const [reviewing, setReviewing] = useState3(null);
|
|
2296
2459
|
const lockRef = useRef2(false);
|
|
2297
|
-
const [gate] =
|
|
2460
|
+
const [gate] = useState3(createLaunchGate);
|
|
2298
2461
|
const creatingRef = useRef2(creating);
|
|
2299
2462
|
creatingRef.current = creating;
|
|
2300
2463
|
const branchRequest = useRef2(0);
|
|
@@ -2325,6 +2488,12 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2325
2488
|
const sectionRows = (section) => layout.sections.find((entry) => entry.section === section)?.rows ?? 0;
|
|
2326
2489
|
const previewSessionId = selectedSession !== null && !isPendingId(selectedSession.id) ? selectedSession.id : null;
|
|
2327
2490
|
const previewLive = selectedSession !== null && LIVE_STATUSES.has(selectedSession.status);
|
|
2491
|
+
useEffect3(() => {
|
|
2492
|
+
const tunnels = ctx.tunnels;
|
|
2493
|
+
if (tunnels === null) return;
|
|
2494
|
+
const timer = setTimeout(() => void tunnels.focus(previewSessionId), 600);
|
|
2495
|
+
return () => clearTimeout(timer);
|
|
2496
|
+
}, [ctx.tunnels, previewSessionId]);
|
|
2328
2497
|
const transcript = useQuery2({
|
|
2329
2498
|
queryKey: TRANSCRIPT_KEY(previewSessionId ?? "none"),
|
|
2330
2499
|
queryFn: () => fetchTranscript(ctx.api, previewSessionId ?? ""),
|
|
@@ -2342,9 +2511,26 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2342
2511
|
}),
|
|
2343
2512
|
[transcript.data, detailWidth]
|
|
2344
2513
|
);
|
|
2345
|
-
const [previewOffset, setPreviewOffset] =
|
|
2514
|
+
const [previewOffset, setPreviewOffset] = useState3(0);
|
|
2346
2515
|
const factRows = Math.max(0, Math.min(SESSION_FACT_ROWS, layout.detailRows - 2));
|
|
2347
2516
|
const showFactRule = factRows > 0 && layout.detailRows - factRows > 1;
|
|
2517
|
+
const waiting = selectedSession !== null && (selectedSession.status === "starting" || isPendingId(selectedSession.id));
|
|
2518
|
+
const snake = useSnake({
|
|
2519
|
+
width: Math.max(8, Math.min(40, detailWidth - 4)),
|
|
2520
|
+
// The pane minus the facts, the rule, the starting line, two lines of hints and the border.
|
|
2521
|
+
height: Math.max(4, Math.min(14, layout.detailRows - factRows - 8)),
|
|
2522
|
+
enabled: waiting
|
|
2523
|
+
});
|
|
2524
|
+
const [snakeAwayFor, setSnakeAwayFor] = useState3(null);
|
|
2525
|
+
const snakeShown = waiting && snakeAwayFor !== selectedSession?.id;
|
|
2526
|
+
const [snakeOverlay, setSnakeOverlay] = useState3(ctx.openSnake === true);
|
|
2527
|
+
const overlayWidth = Math.max(16, Math.min(60, terminalCols - 8));
|
|
2528
|
+
const overlayHeight = Math.max(6, Math.min(20, terminalRows - 10));
|
|
2529
|
+
const overlaySnake = useSnake({
|
|
2530
|
+
width: overlayWidth,
|
|
2531
|
+
height: overlayHeight,
|
|
2532
|
+
enabled: snakeOverlay
|
|
2533
|
+
});
|
|
2348
2534
|
const previewRows = Math.max(1, layout.detailRows - factRows - (showFactRule ? 1 : 0));
|
|
2349
2535
|
const previewView = previewWindow(preview, previewRows, previewOffset);
|
|
2350
2536
|
const setFocus = (column) => {
|
|
@@ -2357,7 +2543,7 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2357
2543
|
};
|
|
2358
2544
|
const say = (text) => setStatus({ text, at: Date.now() });
|
|
2359
2545
|
const refetch = () => void queryClient.invalidateQueries({ queryKey: WORKBENCH_KEY });
|
|
2360
|
-
|
|
2546
|
+
useEffect3(() => {
|
|
2361
2547
|
const share = ctx.agentShare;
|
|
2362
2548
|
if (share === null) return;
|
|
2363
2549
|
return share.subscribe((event) => {
|
|
@@ -2368,7 +2554,7 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2368
2554
|
else if (event.kind === "not-signed") say(`\u2717 not signed \u2014 ${event.message}`);
|
|
2369
2555
|
});
|
|
2370
2556
|
}, [ctx.agentShare]);
|
|
2371
|
-
|
|
2557
|
+
useEffect3(() => {
|
|
2372
2558
|
if (data === void 0 || adoptOfferDecided.current) return;
|
|
2373
2559
|
if (homeProject !== void 0) return;
|
|
2374
2560
|
adoptOfferDecided.current = true;
|
|
@@ -2380,10 +2566,10 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2380
2566
|
const projectRows = sectionRows("projects");
|
|
2381
2567
|
const worktreeRows = sectionRows("worktrees");
|
|
2382
2568
|
const sessionRows = sectionRows("sessions");
|
|
2383
|
-
|
|
2569
|
+
useEffect3(() => {
|
|
2384
2570
|
keepSpanVisible(projectScrollRef.current, projectIndex, 1, projectRows);
|
|
2385
2571
|
}, [projectIndex, projectRows]);
|
|
2386
|
-
|
|
2572
|
+
useEffect3(() => {
|
|
2387
2573
|
keepSpanVisible(
|
|
2388
2574
|
worktreeScrollRef.current,
|
|
2389
2575
|
worktreeIndex * WORKTREE_ROW_HEIGHT,
|
|
@@ -2391,7 +2577,7 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2391
2577
|
worktreeRows
|
|
2392
2578
|
);
|
|
2393
2579
|
}, [worktreeIndex, worktreeRows]);
|
|
2394
|
-
|
|
2580
|
+
useEffect3(() => {
|
|
2395
2581
|
keepSpanVisible(
|
|
2396
2582
|
sessionScrollRef.current,
|
|
2397
2583
|
sessionIndex * SESSION_ROW_HEIGHT,
|
|
@@ -2403,10 +2589,14 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2403
2589
|
const short = session.id.slice(0, 8);
|
|
2404
2590
|
lockRef.current = true;
|
|
2405
2591
|
renderer.suspend();
|
|
2406
|
-
|
|
2592
|
+
const tunneled = openTunnels.filter((tunnel) => tunnel.service.sessionId === session.id).map((tunnel) => `\u25CF ${tunnel.line} \xB7 tunnel
|
|
2593
|
+
`).join("");
|
|
2594
|
+
process.stdout.write(
|
|
2595
|
+
`
|
|
2407
2596
|
attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
2408
|
-
|
|
2409
|
-
`
|
|
2597
|
+
${tunneled}
|
|
2598
|
+
`
|
|
2599
|
+
);
|
|
2410
2600
|
let outcome;
|
|
2411
2601
|
try {
|
|
2412
2602
|
outcome = await ctx.attachTty(session.id, session.harness);
|
|
@@ -2614,6 +2804,23 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
2614
2804
|
},
|
|
2615
2805
|
onSettled: settleRefetch
|
|
2616
2806
|
});
|
|
2807
|
+
const stopServicesMutation = useMutation2({
|
|
2808
|
+
mutationFn: (session) => ctx.api("POST", `/sessions/${session.id}/services/stop`),
|
|
2809
|
+
onMutate: async (session) => {
|
|
2810
|
+
await queryClient.cancelQueries({ queryKey: WORKBENCH_KEY });
|
|
2811
|
+
patchWorkbench((current) => markServicesStopped(current, session.id));
|
|
2812
|
+
},
|
|
2813
|
+
onSuccess: (result, session) => {
|
|
2814
|
+
say(
|
|
2815
|
+
`stopped ${result.stopped} service${result.stopped === 1 ? "" : "s"} \xB7 ${sessionDisplayName(session)} \u2014 the workspace ends once nothing is live`
|
|
2816
|
+
);
|
|
2817
|
+
},
|
|
2818
|
+
onError: (error) => {
|
|
2819
|
+
say(errorText(error));
|
|
2820
|
+
refetch();
|
|
2821
|
+
},
|
|
2822
|
+
onSettled: settleRefetch
|
|
2823
|
+
});
|
|
2617
2824
|
const stopMutation = useMutation2({
|
|
2618
2825
|
mutationFn: (session) => ctx.api("POST", `/sessions/${session.id}/stop`),
|
|
2619
2826
|
onMutate: async (session) => {
|
|
@@ -2778,6 +2985,17 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
2778
2985
|
}
|
|
2779
2986
|
const session = selectedSession;
|
|
2780
2987
|
if (session === null || isPendingId(session.id)) return;
|
|
2988
|
+
const hold = selectedItem === null ? null : sessionHold(selectedItem);
|
|
2989
|
+
if (hold !== null) {
|
|
2990
|
+
if (stopArmed === `svc:${session.id}` && confirmationVisible("press \u21E7K again")) {
|
|
2991
|
+
setStopArmed(null);
|
|
2992
|
+
stopServicesMutation.mutate(session);
|
|
2993
|
+
return;
|
|
2994
|
+
}
|
|
2995
|
+
setStopArmed(`svc:${session.id}`);
|
|
2996
|
+
say(`press \u21E7K again to stop the services \xB7 ${sessionDisplayName(session)} \u2014 ${hold}`);
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2781
2999
|
if (!LIVE_STATUSES.has(session.status)) {
|
|
2782
3000
|
say("nothing to stop \u2014 the session is settled");
|
|
2783
3001
|
return;
|
|
@@ -3022,6 +3240,28 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3022
3240
|
if (reviewing !== null) return;
|
|
3023
3241
|
if (lockRef.current) return;
|
|
3024
3242
|
if (key.ctrl && key.name === "c") return onQuit();
|
|
3243
|
+
if (snakeOverlay) {
|
|
3244
|
+
if (key.name === "up" || key.name === "down" || key.name === "left" || key.name === "right") {
|
|
3245
|
+
overlaySnake.steer(key.name);
|
|
3246
|
+
} else if (key.name === "space") {
|
|
3247
|
+
overlaySnake.togglePause();
|
|
3248
|
+
} else if (key.name === "escape" || key.name === "q") {
|
|
3249
|
+
setSnakeOverlay(false);
|
|
3250
|
+
}
|
|
3251
|
+
return;
|
|
3252
|
+
}
|
|
3253
|
+
if (waiting && focus === "detail" && picker === null && editing === null && creating === null) {
|
|
3254
|
+
if (snakeShown) {
|
|
3255
|
+
if (key.name === "up" || key.name === "down" || key.name === "left" || key.name === "right") {
|
|
3256
|
+
snake.steer(key.name);
|
|
3257
|
+
return;
|
|
3258
|
+
}
|
|
3259
|
+
if (key.name === "space") return snake.togglePause();
|
|
3260
|
+
if (key.name === "escape") return setSnakeAwayFor(selectedSession?.id ?? null);
|
|
3261
|
+
} else if (key.name === "space") {
|
|
3262
|
+
return setSnakeAwayFor(null);
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3025
3265
|
const verb = verbForKey(key.name ?? "", key.shift === true);
|
|
3026
3266
|
if (verb !== "stop") setStopArmed(null);
|
|
3027
3267
|
if (verb !== "remove") setRemoveArmed(null);
|
|
@@ -3222,7 +3462,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3222
3462
|
const footerText = adoptOffer === null ? editing === null ? creating === null ? picker === null ? ` ${fitHints(verbHints(focus), Math.max(12, terminalCols - 2))}` : " \u2191\u2193 move \xB7 enter start \xB7 esc cancel" : creating.step === "name" ? " enter continue \xB7 esc cancel" : creating.step === "base" ? " type to filter \xB7 \u2191\u2193 move \xB7 enter choose base \xB7 esc back" : " \u2191\u2193 move \xB7 enter launch \xB7 esc back" : " enter save \xB7 esc cancel" : " enter adopt \xB7 \u2190\u2192 auth mode \xB7 esc not now";
|
|
3223
3463
|
const loadFailure = data === void 0 && failureReason !== null ? errorText(failureReason) : null;
|
|
3224
3464
|
if (reviewing !== null) {
|
|
3225
|
-
return /* @__PURE__ */
|
|
3465
|
+
return /* @__PURE__ */ jsx3(
|
|
3226
3466
|
ReviewScreen,
|
|
3227
3467
|
{
|
|
3228
3468
|
ctx,
|
|
@@ -3258,13 +3498,13 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3258
3498
|
const renderSection = (entry) => {
|
|
3259
3499
|
const inner = Math.max(4, layout.sidebarWidth - 2);
|
|
3260
3500
|
if (!entry.expanded) {
|
|
3261
|
-
return /* @__PURE__ */
|
|
3501
|
+
return /* @__PURE__ */ jsx3(
|
|
3262
3502
|
Pane,
|
|
3263
3503
|
{
|
|
3264
3504
|
title: paneTitle(entry.section, layout.sidebarWidth),
|
|
3265
3505
|
focused: false,
|
|
3266
3506
|
height: entry.height,
|
|
3267
|
-
children: /* @__PURE__ */
|
|
3507
|
+
children: /* @__PURE__ */ jsx3(
|
|
3268
3508
|
SummaryRow,
|
|
3269
3509
|
{
|
|
3270
3510
|
name: breadcrumbValue(entry.section),
|
|
@@ -3280,13 +3520,13 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3280
3520
|
const focused = focus === entry.section;
|
|
3281
3521
|
switch (entry.section) {
|
|
3282
3522
|
case "projects":
|
|
3283
|
-
return /* @__PURE__ */
|
|
3523
|
+
return /* @__PURE__ */ jsx3(
|
|
3284
3524
|
Pane,
|
|
3285
3525
|
{
|
|
3286
3526
|
title: paneTitle("projects", layout.sidebarWidth),
|
|
3287
3527
|
focused,
|
|
3288
3528
|
grow: true,
|
|
3289
|
-
children: /* @__PURE__ */
|
|
3529
|
+
children: /* @__PURE__ */ jsxs3(
|
|
3290
3530
|
"scrollbox",
|
|
3291
3531
|
{
|
|
3292
3532
|
ref: projectScrollRef,
|
|
@@ -3295,7 +3535,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3295
3535
|
minHeight: 0,
|
|
3296
3536
|
style: paneScrollStyle,
|
|
3297
3537
|
children: [
|
|
3298
|
-
projectItems.map((item, index) => /* @__PURE__ */
|
|
3538
|
+
projectItems.map((item, index) => /* @__PURE__ */ jsx3(
|
|
3299
3539
|
ProjectRow,
|
|
3300
3540
|
{
|
|
3301
3541
|
item,
|
|
@@ -3304,7 +3544,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3304
3544
|
},
|
|
3305
3545
|
item.project.id
|
|
3306
3546
|
)),
|
|
3307
|
-
data !== void 0 && projectItems.length === 0 ? /* @__PURE__ */
|
|
3547
|
+
data !== void 0 && projectItems.length === 0 ? /* @__PURE__ */ jsx3(EmptyNote, { text: "none adopted yet" }) : null
|
|
3308
3548
|
]
|
|
3309
3549
|
}
|
|
3310
3550
|
)
|
|
@@ -3312,13 +3552,13 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3312
3552
|
entry.section
|
|
3313
3553
|
);
|
|
3314
3554
|
case "worktrees":
|
|
3315
|
-
return /* @__PURE__ */
|
|
3555
|
+
return /* @__PURE__ */ jsx3(
|
|
3316
3556
|
Pane,
|
|
3317
3557
|
{
|
|
3318
3558
|
title: paneTitle("worktrees", layout.sidebarWidth),
|
|
3319
3559
|
focused,
|
|
3320
3560
|
grow: true,
|
|
3321
|
-
children: /* @__PURE__ */
|
|
3561
|
+
children: /* @__PURE__ */ jsxs3(
|
|
3322
3562
|
"scrollbox",
|
|
3323
3563
|
{
|
|
3324
3564
|
ref: worktreeScrollRef,
|
|
@@ -3327,7 +3567,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3327
3567
|
minHeight: 0,
|
|
3328
3568
|
style: paneScrollStyle,
|
|
3329
3569
|
children: [
|
|
3330
|
-
worktreeGroups.map((group, index) => /* @__PURE__ */
|
|
3570
|
+
worktreeGroups.map((group, index) => /* @__PURE__ */ jsx3(
|
|
3331
3571
|
WorktreeRow,
|
|
3332
3572
|
{
|
|
3333
3573
|
group,
|
|
@@ -3336,7 +3576,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3336
3576
|
},
|
|
3337
3577
|
group.key
|
|
3338
3578
|
)),
|
|
3339
|
-
data !== void 0 && worktreeGroups.length === 0 ? /* @__PURE__ */
|
|
3579
|
+
data !== void 0 && worktreeGroups.length === 0 ? /* @__PURE__ */ jsx3(EmptyNote, { text: "no worktrees \u2014 w starts one" }) : null
|
|
3340
3580
|
]
|
|
3341
3581
|
}
|
|
3342
3582
|
)
|
|
@@ -3344,13 +3584,13 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3344
3584
|
entry.section
|
|
3345
3585
|
);
|
|
3346
3586
|
case "sessions":
|
|
3347
|
-
return /* @__PURE__ */
|
|
3587
|
+
return /* @__PURE__ */ jsx3(
|
|
3348
3588
|
Pane,
|
|
3349
3589
|
{
|
|
3350
3590
|
title: paneTitle("sessions", layout.sidebarWidth),
|
|
3351
3591
|
focused,
|
|
3352
3592
|
grow: true,
|
|
3353
|
-
children: /* @__PURE__ */
|
|
3593
|
+
children: /* @__PURE__ */ jsxs3(
|
|
3354
3594
|
"scrollbox",
|
|
3355
3595
|
{
|
|
3356
3596
|
ref: sessionScrollRef,
|
|
@@ -3359,7 +3599,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3359
3599
|
minHeight: 0,
|
|
3360
3600
|
style: paneScrollStyle,
|
|
3361
3601
|
children: [
|
|
3362
|
-
sessionItems.map((item, index) => /* @__PURE__ */
|
|
3602
|
+
sessionItems.map((item, index) => /* @__PURE__ */ jsx3(
|
|
3363
3603
|
SessionRow,
|
|
3364
3604
|
{
|
|
3365
3605
|
item,
|
|
@@ -3368,13 +3608,13 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3368
3608
|
},
|
|
3369
3609
|
item.session.id
|
|
3370
3610
|
)),
|
|
3371
|
-
data !== void 0 && sessionItems.length === 0 ? /* @__PURE__ */
|
|
3611
|
+
data !== void 0 && sessionItems.length === 0 ? /* @__PURE__ */ jsx3(
|
|
3372
3612
|
EmptyNote,
|
|
3373
3613
|
{
|
|
3374
3614
|
text: selectedGroup === null ? "no worktree selected" : "no sessions \u2014 n starts one"
|
|
3375
3615
|
}
|
|
3376
3616
|
) : null,
|
|
3377
|
-
loadFailure === null ? null : /* @__PURE__ */
|
|
3617
|
+
loadFailure === null ? null : /* @__PURE__ */ jsx3("text", { height: 1, fg: INK_2, bg: "transparent", children: ` ${loadFailure} \u2014 retrying` })
|
|
3378
3618
|
]
|
|
3379
3619
|
}
|
|
3380
3620
|
)
|
|
@@ -3383,52 +3623,67 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3383
3623
|
);
|
|
3384
3624
|
}
|
|
3385
3625
|
};
|
|
3386
|
-
const renderDetail = () => /* @__PURE__ */
|
|
3387
|
-
/* @__PURE__ */
|
|
3388
|
-
|
|
3389
|
-
|
|
3626
|
+
const renderDetail = () => /* @__PURE__ */ jsx3(Pane, { title: paneTitle("detail", detailWidth + 2), focused: focus === "detail", grow: true, children: selectedItem === null ? /* @__PURE__ */ jsx3(EmptyNote, { text: "no session selected \u2014 n starts one" }) : /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3627
|
+
/* @__PURE__ */ jsx3(
|
|
3628
|
+
SessionFacts,
|
|
3629
|
+
{
|
|
3630
|
+
group: selectedGroup,
|
|
3631
|
+
item: selectedItem,
|
|
3632
|
+
rows: factRows,
|
|
3633
|
+
tunnels: openTunnels
|
|
3634
|
+
}
|
|
3635
|
+
),
|
|
3636
|
+
showFactRule ? /* @__PURE__ */ jsx3("text", { height: 1, bg: "transparent", fg: FAINT, children: ` ${"\u2500".repeat(Math.max(4, detailWidth - 4))}` }) : null,
|
|
3637
|
+
/* @__PURE__ */ jsx3("box", { flexGrow: 1, flexShrink: 1, minHeight: 0, flexDirection: "column", children: waiting ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3638
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
3639
|
+
/* @__PURE__ */ jsx3("span", { children: " " }),
|
|
3640
|
+
/* @__PURE__ */ jsx3("span", { fg: INK_2, children: "starting" }),
|
|
3641
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 the image builds, then the session boots \xB7 a first build on a new setup takes about 7 minutes" })
|
|
3642
|
+
] }),
|
|
3643
|
+
snakeShown ? /* @__PURE__ */ jsx3(SnakeBoard, { handle: snake, focused: focus === "detail" }) : /* @__PURE__ */ jsx3(EmptyNote, { text: "snake is put away \xB7 space brings it back" })
|
|
3644
|
+
] }) : previewSessionId === null ? /* @__PURE__ */ jsx3(EmptyNote, { text: "provisioning \u2014 no record yet" }) : selectedSession?.harness === "shell" ? /* @__PURE__ */ jsx3(EmptyNote, { text: "shell \u2014 no conversation record; a attaches if live" }) : transcript.isPending ? /* @__PURE__ */ jsx3(EmptyNote, { text: "reading the record\u2026" }) : transcript.error === null ? previewView.lines.length === 0 ? /* @__PURE__ */ jsx3(EmptyNote, { text: "no conversation recorded yet" }) : previewView.lines.map((line, index) => /* @__PURE__ */ jsx3(PreviewRow, { line }, `${index}-${line.kind}`)) : /* @__PURE__ */ jsx3("text", { height: 1, fg: INK_2, bg: "transparent", children: ` could not read the record \u2014 ${errorText(transcript.error)}` }) })
|
|
3390
3645
|
] }) });
|
|
3391
3646
|
const offNav = layout.offscreen.filter(isNavSection);
|
|
3392
3647
|
const detailOffscreen = layout.offscreen.includes("detail");
|
|
3393
|
-
return /* @__PURE__ */
|
|
3394
|
-
/* @__PURE__ */
|
|
3395
|
-
/* @__PURE__ */
|
|
3396
|
-
/* @__PURE__ */
|
|
3397
|
-
/* @__PURE__ */
|
|
3648
|
+
return /* @__PURE__ */ jsxs3("box", { flexGrow: 1, flexDirection: "column", backgroundColor: CANVAS, children: [
|
|
3649
|
+
/* @__PURE__ */ jsxs3("box", { height: 1, flexDirection: "row", justifyContent: "space-between", children: [
|
|
3650
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
3651
|
+
/* @__PURE__ */ jsx3("span", { fg: INK, children: " mend" }),
|
|
3652
|
+
/* @__PURE__ */ jsxs3("span", { fg: MUTED, children: [
|
|
3398
3653
|
" ",
|
|
3399
3654
|
projectItems.length,
|
|
3400
3655
|
" project",
|
|
3401
3656
|
projectItems.length === 1 ? "" : "s"
|
|
3402
3657
|
] }),
|
|
3403
|
-
/* @__PURE__ */
|
|
3404
|
-
/* @__PURE__ */
|
|
3658
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
3659
|
+
/* @__PURE__ */ jsxs3("span", { fg: liveTotal > 0 ? MUTED : FAINT, children: [
|
|
3405
3660
|
liveTotal,
|
|
3406
3661
|
" live"
|
|
3407
3662
|
] }),
|
|
3408
|
-
gate.count() > 0 ? /* @__PURE__ */
|
|
3409
|
-
/* @__PURE__ */
|
|
3410
|
-
/* @__PURE__ */
|
|
3663
|
+
gate.count() > 0 ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3664
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
3665
|
+
/* @__PURE__ */ jsxs3("span", { fg: INK_2, children: [
|
|
3411
3666
|
gate.count(),
|
|
3412
3667
|
" starting"
|
|
3413
3668
|
] })
|
|
3414
3669
|
] }) : null,
|
|
3415
|
-
shareState === "off" ? null : /* @__PURE__ */
|
|
3416
|
-
/* @__PURE__ */
|
|
3417
|
-
/* @__PURE__ */
|
|
3670
|
+
shareState === "off" ? null : /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
3671
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
3672
|
+
/* @__PURE__ */ jsx3("span", { fg: shareState === "connected" ? MUTED : FAINT, children: shareState === "connected" ? "agent shared" : "agent share reconnecting" })
|
|
3418
3673
|
] })
|
|
3419
3674
|
] }),
|
|
3420
|
-
/* @__PURE__ */
|
|
3675
|
+
/* @__PURE__ */ jsx3("text", { height: 1, fg: FAINT, bg: "transparent", children: `${ctx.config.url} ` })
|
|
3421
3676
|
] }),
|
|
3422
|
-
!layout.breadcrumb ? null : /* @__PURE__ */
|
|
3423
|
-
/* @__PURE__ */
|
|
3424
|
-
offNav.map((column, index) => /* @__PURE__ */
|
|
3425
|
-
index > 0 ? /* @__PURE__ */
|
|
3426
|
-
/* @__PURE__ */
|
|
3677
|
+
!layout.breadcrumb ? null : /* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
3678
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " " }),
|
|
3679
|
+
offNav.map((column, index) => /* @__PURE__ */ jsxs3("span", { children: [
|
|
3680
|
+
index > 0 ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \u25B8 " }) : null,
|
|
3681
|
+
/* @__PURE__ */ jsx3("span", { fg: index === offNav.length - 1 ? INK_2 : MUTED, children: fit(breadcrumbValue(column), 28) })
|
|
3427
3682
|
] }, column)),
|
|
3428
|
-
/* @__PURE__ */
|
|
3683
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: detailOffscreen ? `${offNav.length > 0 ? " \xB7 " : ""}record hidden \xB7 \u2192 opens it` : " \u25B8" })
|
|
3429
3684
|
] }),
|
|
3430
|
-
/* @__PURE__ */
|
|
3431
|
-
layout.sidebarWidth === 0 ? null : /* @__PURE__ */
|
|
3685
|
+
/* @__PURE__ */ jsxs3("box", { flexGrow: 1, flexShrink: 1, minHeight: 0, flexDirection: "row", children: [
|
|
3686
|
+
layout.sidebarWidth === 0 ? null : /* @__PURE__ */ jsx3(
|
|
3432
3687
|
"box",
|
|
3433
3688
|
{
|
|
3434
3689
|
width: layout.sidebarWidth,
|
|
@@ -3441,7 +3696,29 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3441
3696
|
),
|
|
3442
3697
|
detailWidth === 0 ? null : renderDetail()
|
|
3443
3698
|
] }),
|
|
3444
|
-
|
|
3699
|
+
snakeOverlay ? /* @__PURE__ */ jsxs3(
|
|
3700
|
+
"box",
|
|
3701
|
+
{
|
|
3702
|
+
position: "absolute",
|
|
3703
|
+
zIndex: 13,
|
|
3704
|
+
left: Math.max(1, Math.floor((terminalCols - (overlayWidth + 4)) / 2)),
|
|
3705
|
+
top: Math.max(1, Math.floor((terminalRows - (overlayHeight + 5)) / 2)),
|
|
3706
|
+
width: overlayWidth + 4,
|
|
3707
|
+
height: overlayHeight + 5,
|
|
3708
|
+
border: true,
|
|
3709
|
+
borderStyle: "rounded",
|
|
3710
|
+
borderColor: ACCENT,
|
|
3711
|
+
title: " snake ",
|
|
3712
|
+
titleAlignment: "left",
|
|
3713
|
+
backgroundColor: SURFACE,
|
|
3714
|
+
flexDirection: "column",
|
|
3715
|
+
children: [
|
|
3716
|
+
/* @__PURE__ */ jsx3(SnakeHeading, { handle: overlaySnake, hint: "arrows steer \xB7 space pauses \xB7 esc closes" }),
|
|
3717
|
+
/* @__PURE__ */ jsx3("box", { marginLeft: 1, flexDirection: "column", children: /* @__PURE__ */ jsx3(SnakeRows, { game: overlaySnake.game }) })
|
|
3718
|
+
]
|
|
3719
|
+
}
|
|
3720
|
+
) : null,
|
|
3721
|
+
picker === null ? null : /* @__PURE__ */ jsx3(
|
|
3445
3722
|
"box",
|
|
3446
3723
|
{
|
|
3447
3724
|
position: "absolute",
|
|
@@ -3457,7 +3734,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3457
3734
|
titleAlignment: "left",
|
|
3458
3735
|
backgroundColor: SURFACE,
|
|
3459
3736
|
flexDirection: "column",
|
|
3460
|
-
children: pickerItems.map((item, index) => /* @__PURE__ */
|
|
3737
|
+
children: pickerItems.map((item, index) => /* @__PURE__ */ jsx3(
|
|
3461
3738
|
HarnessRow,
|
|
3462
3739
|
{
|
|
3463
3740
|
item,
|
|
@@ -3468,7 +3745,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3468
3745
|
))
|
|
3469
3746
|
}
|
|
3470
3747
|
),
|
|
3471
|
-
editing === null ? null : /* @__PURE__ */
|
|
3748
|
+
editing === null ? null : /* @__PURE__ */ jsx3(
|
|
3472
3749
|
"box",
|
|
3473
3750
|
{
|
|
3474
3751
|
position: "absolute",
|
|
@@ -3484,7 +3761,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3484
3761
|
backgroundColor: SURFACE,
|
|
3485
3762
|
height: 3,
|
|
3486
3763
|
flexShrink: 0,
|
|
3487
|
-
children: /* @__PURE__ */
|
|
3764
|
+
children: /* @__PURE__ */ jsx3(
|
|
3488
3765
|
"input",
|
|
3489
3766
|
{
|
|
3490
3767
|
focused: true,
|
|
@@ -3504,7 +3781,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3504
3781
|
)
|
|
3505
3782
|
}
|
|
3506
3783
|
),
|
|
3507
|
-
adoptOffer === null ? null : /* @__PURE__ */
|
|
3784
|
+
adoptOffer === null ? null : /* @__PURE__ */ jsxs3(
|
|
3508
3785
|
"box",
|
|
3509
3786
|
{
|
|
3510
3787
|
position: "absolute",
|
|
@@ -3521,25 +3798,25 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3521
3798
|
backgroundColor: SURFACE,
|
|
3522
3799
|
flexDirection: "column",
|
|
3523
3800
|
children: [
|
|
3524
|
-
/* @__PURE__ */
|
|
3525
|
-
/* @__PURE__ */
|
|
3526
|
-
/* @__PURE__ */
|
|
3527
|
-
/* @__PURE__ */
|
|
3801
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: SURFACE, children: [
|
|
3802
|
+
/* @__PURE__ */ jsx3("span", { children: " " }),
|
|
3803
|
+
/* @__PURE__ */ jsx3("span", { fg: INK, children: adoptOffer.name }),
|
|
3804
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 not in the store yet" })
|
|
3528
3805
|
] }),
|
|
3529
|
-
/* @__PURE__ */
|
|
3530
|
-
/* @__PURE__ */
|
|
3531
|
-
/* @__PURE__ */
|
|
3532
|
-
ADOPT_AUTH_MODES.map((candidate, index) => /* @__PURE__ */
|
|
3533
|
-
index > 0 ? /* @__PURE__ */
|
|
3534
|
-
/* @__PURE__ */
|
|
3806
|
+
/* @__PURE__ */ jsx3("text", { height: 1, bg: SURFACE, fg: MUTED, children: ` ${adoptOffer.source}` }),
|
|
3807
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: SURFACE, children: [
|
|
3808
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " auth " }),
|
|
3809
|
+
ADOPT_AUTH_MODES.map((candidate, index) => /* @__PURE__ */ jsxs3("span", { children: [
|
|
3810
|
+
index > 0 ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }) : null,
|
|
3811
|
+
/* @__PURE__ */ jsx3("span", { fg: index === adoptOffer.modeIndex ? ACCENT : FAINT, children: index === adoptOffer.modeIndex ? `\u25B8 ${candidate.label}` : candidate.label })
|
|
3535
3812
|
] }, candidate.mode))
|
|
3536
3813
|
] }),
|
|
3537
|
-
/* @__PURE__ */
|
|
3538
|
-
/* @__PURE__ */
|
|
3814
|
+
/* @__PURE__ */ jsx3("text", { height: 1, bg: SURFACE, fg: FAINT, children: ` ${ADOPT_AUTH_MODES[adoptOffer.modeIndex]?.hint ?? ""}` }),
|
|
3815
|
+
/* @__PURE__ */ jsx3("text", { height: 1, bg: SURFACE, fg: FAINT, children: " enter adopt \xB7 \u2190\u2192 auth mode \xB7 esc not now" })
|
|
3539
3816
|
]
|
|
3540
3817
|
}
|
|
3541
3818
|
),
|
|
3542
|
-
creating === null ? null : /* @__PURE__ */
|
|
3819
|
+
creating === null ? null : /* @__PURE__ */ jsxs3(
|
|
3543
3820
|
"box",
|
|
3544
3821
|
{
|
|
3545
3822
|
position: "absolute",
|
|
@@ -3556,14 +3833,14 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3556
3833
|
backgroundColor: SURFACE,
|
|
3557
3834
|
flexDirection: "column",
|
|
3558
3835
|
children: [
|
|
3559
|
-
/* @__PURE__ */
|
|
3560
|
-
/* @__PURE__ */
|
|
3561
|
-
/* @__PURE__ */
|
|
3562
|
-
/* @__PURE__ */
|
|
3563
|
-
creating.step === "name" ? null : /* @__PURE__ */
|
|
3564
|
-
creating.joins ? /* @__PURE__ */
|
|
3836
|
+
/* @__PURE__ */ jsxs3("box", { height: 1, flexShrink: 0, flexDirection: "row", backgroundColor: SURFACE, children: [
|
|
3837
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: SURFACE, children: [
|
|
3838
|
+
/* @__PURE__ */ jsx3(Gutter, { selected: creating.step === "name" }),
|
|
3839
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: "name " }),
|
|
3840
|
+
creating.step === "name" ? null : /* @__PURE__ */ jsx3("span", { fg: INK, children: creating.name === "" ? "auto" : creating.name }),
|
|
3841
|
+
creating.joins ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 joins the existing worktree" }) : null
|
|
3565
3842
|
] }),
|
|
3566
|
-
creating.step === "name" ? /* @__PURE__ */
|
|
3843
|
+
creating.step === "name" ? /* @__PURE__ */ jsx3(
|
|
3567
3844
|
"input",
|
|
3568
3845
|
{
|
|
3569
3846
|
focused: true,
|
|
@@ -3588,13 +3865,13 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3588
3865
|
}
|
|
3589
3866
|
) : null
|
|
3590
3867
|
] }),
|
|
3591
|
-
/* @__PURE__ */
|
|
3592
|
-
/* @__PURE__ */
|
|
3593
|
-
/* @__PURE__ */
|
|
3594
|
-
/* @__PURE__ */
|
|
3595
|
-
creating.step === "base" ? null : /* @__PURE__ */
|
|
3868
|
+
/* @__PURE__ */ jsxs3("box", { height: 1, flexShrink: 0, flexDirection: "row", backgroundColor: SURFACE, children: [
|
|
3869
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: SURFACE, children: [
|
|
3870
|
+
/* @__PURE__ */ jsx3(Gutter, { selected: creating.step === "base" }),
|
|
3871
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: "base " }),
|
|
3872
|
+
creating.step === "base" ? null : /* @__PURE__ */ jsx3("span", { fg: creating.step === "name" && !creating.joins ? FAINT : INK, children: creating.joins ? "fixed by the existing worktree" : creating.base ?? "default branch" })
|
|
3596
3873
|
] }),
|
|
3597
|
-
creating.step === "base" && creating.branches !== null ? /* @__PURE__ */
|
|
3874
|
+
creating.step === "base" && creating.branches !== null ? /* @__PURE__ */ jsx3(
|
|
3598
3875
|
"input",
|
|
3599
3876
|
{
|
|
3600
3877
|
focused: true,
|
|
@@ -3622,7 +3899,7 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3622
3899
|
const active = creating.step === "base";
|
|
3623
3900
|
if (branch === void 0) {
|
|
3624
3901
|
const notice = creating.joins ? null : baseStepNotice(creating);
|
|
3625
|
-
return /* @__PURE__ */
|
|
3902
|
+
return /* @__PURE__ */ jsx3(
|
|
3626
3903
|
"text",
|
|
3627
3904
|
{
|
|
3628
3905
|
height: 1,
|
|
@@ -3634,42 +3911,42 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3634
3911
|
);
|
|
3635
3912
|
}
|
|
3636
3913
|
const highlighted = active && index === creating.baseIndex;
|
|
3637
|
-
return /* @__PURE__ */
|
|
3914
|
+
return /* @__PURE__ */ jsx3(
|
|
3638
3915
|
"box",
|
|
3639
3916
|
{
|
|
3640
3917
|
height: 1,
|
|
3641
3918
|
flexShrink: 0,
|
|
3642
3919
|
backgroundColor: highlighted ? WASH : SURFACE,
|
|
3643
|
-
children: /* @__PURE__ */
|
|
3644
|
-
/* @__PURE__ */
|
|
3645
|
-
/* @__PURE__ */
|
|
3646
|
-
/* @__PURE__ */
|
|
3647
|
-
/* @__PURE__ */
|
|
3648
|
-
/* @__PURE__ */
|
|
3649
|
-
branch.isDefault ? /* @__PURE__ */
|
|
3920
|
+
children: /* @__PURE__ */ jsxs3("text", { height: 1, bg: highlighted ? WASH : SURFACE, children: [
|
|
3921
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " " }),
|
|
3922
|
+
/* @__PURE__ */ jsx3(Gutter, { selected: highlighted }),
|
|
3923
|
+
/* @__PURE__ */ jsx3("span", { fg: active ? INK : FAINT, children: branch.name.slice(0, 40).padEnd(41) }),
|
|
3924
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: branch.sha.slice(0, 8).padEnd(10) }),
|
|
3925
|
+
/* @__PURE__ */ jsx3("span", { fg: active ? MUTED : FAINT, children: shortAge(branch.committedAt).padEnd(6) }),
|
|
3926
|
+
branch.isDefault ? /* @__PURE__ */ jsx3("span", { fg: FAINT, children: "default" }) : null
|
|
3650
3927
|
] })
|
|
3651
3928
|
},
|
|
3652
3929
|
branch.name
|
|
3653
3930
|
);
|
|
3654
3931
|
}),
|
|
3655
|
-
/* @__PURE__ */
|
|
3656
|
-
/* @__PURE__ */
|
|
3657
|
-
/* @__PURE__ */
|
|
3932
|
+
/* @__PURE__ */ jsxs3("text", { height: 1, bg: SURFACE, children: [
|
|
3933
|
+
/* @__PURE__ */ jsx3(Gutter, { selected: creating.step === "harness" }),
|
|
3934
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: "harness" })
|
|
3658
3935
|
] }),
|
|
3659
3936
|
deriveHarnesses(null).map((item, index) => {
|
|
3660
3937
|
const active = creating.step === "harness";
|
|
3661
3938
|
const highlighted = active && index === creating.harnessIndex;
|
|
3662
|
-
return /* @__PURE__ */
|
|
3939
|
+
return /* @__PURE__ */ jsx3(
|
|
3663
3940
|
"box",
|
|
3664
3941
|
{
|
|
3665
3942
|
height: 1,
|
|
3666
3943
|
flexShrink: 0,
|
|
3667
3944
|
backgroundColor: highlighted ? WASH : SURFACE,
|
|
3668
|
-
children: /* @__PURE__ */
|
|
3669
|
-
/* @__PURE__ */
|
|
3670
|
-
/* @__PURE__ */
|
|
3671
|
-
/* @__PURE__ */
|
|
3672
|
-
/* @__PURE__ */
|
|
3945
|
+
children: /* @__PURE__ */ jsxs3("text", { height: 1, bg: highlighted ? WASH : SURFACE, children: [
|
|
3946
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " " }),
|
|
3947
|
+
/* @__PURE__ */ jsx3(Gutter, { selected: highlighted }),
|
|
3948
|
+
/* @__PURE__ */ jsx3("span", { fg: active ? INK : FAINT, children: item.label.padEnd(12) }),
|
|
3949
|
+
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: active ? item.hint : "" })
|
|
3673
3950
|
] })
|
|
3674
3951
|
},
|
|
3675
3952
|
String(item.harness)
|
|
@@ -3678,8 +3955,8 @@ attached \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
|
3678
3955
|
]
|
|
3679
3956
|
}
|
|
3680
3957
|
),
|
|
3681
|
-
loadFailure === null ? /* @__PURE__ */
|
|
3682
|
-
/* @__PURE__ */
|
|
3958
|
+
loadFailure === null ? /* @__PURE__ */ jsx3(StatusLine, { busy, busyStarted, status }) : /* @__PURE__ */ jsx3("text", { height: 1, fg: ERROR, bg: "transparent", children: ` could not load workbench \u2014 ${loadFailure} \xB7 retrying` }),
|
|
3959
|
+
/* @__PURE__ */ jsx3("text", { height: 1, fg: FAINT, bg: "transparent", children: footerText })
|
|
3683
3960
|
] });
|
|
3684
3961
|
};
|
|
3685
3962
|
var runDashboard = async (ctx) => {
|
|
@@ -3743,7 +4020,7 @@ var runDashboard = async (ctx) => {
|
|
|
3743
4020
|
};
|
|
3744
4021
|
void watch();
|
|
3745
4022
|
createRoot(renderer).render(
|
|
3746
|
-
/* @__PURE__ */
|
|
4023
|
+
/* @__PURE__ */ jsx3(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx3(App, { ctx, onQuit: quit }) })
|
|
3747
4024
|
);
|
|
3748
4025
|
await new Promise((resolve) => {
|
|
3749
4026
|
renderer.once(CliRenderEvents.DESTROY, () => resolve());
|