@sealant/mend 0.36.0-next.632 → 0.36.0-next.645
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 +4 -1
- package/dist/{chunk-OHOMU7JP.js → chunk-ASHAV3UV.js} +334 -3
- package/dist/{dashboard-34ZANJ24.js → dashboard-4J2WMT3G.js} +142 -17
- package/dist/main.js +646 -461
- package/man/mend-accounts.1 +1 -1
- package/man/mend-adopt.1 +1 -1
- package/man/mend-attach.1 +1 -1
- package/man/mend-codex.1 +3 -1
- package/man/mend-completions.1 +1 -1
- package/man/mend-connect-pi.1 +1 -1
- package/man/mend-connect.1 +3 -1
- package/man/mend-continue.1 +1 -1
- package/man/mend-doctor.1 +1 -1
- package/man/mend-dotfiles-repo.1 +1 -1
- package/man/mend-dotfiles-sync.1 +1 -1
- package/man/mend-dotfiles.1 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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-memory-import.1 +1 -1
- package/man/mend-memory-rm.1 +1 -1
- package/man/mend-memory-show.1 +1 -1
- package/man/mend-memory.1 +1 -1
- package/man/mend-models.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 +1 -1
- package/man/mend-refresh.1 +1 -1
- package/man/mend-rejoin.1 +1 -1
- package/man/mend-resume.1 +1 -1
- package/man/mend-run.1 +1 -1
- package/man/mend-secrets-add.1 +1 -1
- package/man/mend-secrets-rm.1 +1 -1
- package/man/mend-secrets.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 +1 -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 +13 -3
- package/man/mend-sessions.1 +3 -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 +1 -1
- package/man/mend-ssh-setup.1 +1 -1
- package/man/mend-ssh.1 +1 -1
- package/man/mend-stop.1 +1 -1
- package/man/mend-ui.1 +1 -1
- package/man/mend-uninstall.1 +1 -1
- package/man/mend-version.1 +1 -1
- package/man/mend-workspace-replace.1 +24 -0
- package/man/mend-worktrees-rm.1 +1 -1
- package/man/mend-worktrees.1 +1 -1
- package/man/mend.1 +5 -2
- package/package.json +2 -2
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
createSseParser,
|
|
9
9
|
cwdFacts,
|
|
10
10
|
eventFamilies,
|
|
11
|
+
hasPersonFacts,
|
|
11
12
|
isPendingId,
|
|
12
13
|
launchPhaseOf,
|
|
13
14
|
matchProjectByCwd,
|
|
@@ -16,8 +17,13 @@ import {
|
|
|
16
17
|
pendingId,
|
|
17
18
|
repositoryCloneUrlIssue,
|
|
18
19
|
servicesHoldLine,
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
sessionWorkspaceLines,
|
|
21
|
+
withoutLaunchPhase,
|
|
22
|
+
workspaceLineList,
|
|
23
|
+
workspaceReadsOf,
|
|
24
|
+
worktreeJoinLine,
|
|
25
|
+
wrapWords
|
|
26
|
+
} from "./chunk-ASHAV3UV.js";
|
|
21
27
|
|
|
22
28
|
// src/dashboard.tsx
|
|
23
29
|
import { CliRenderEvents, createCliRenderer } from "@opentui/core";
|
|
@@ -271,6 +277,10 @@ var startingWordsOf = (session) => {
|
|
|
271
277
|
return phase.words.endsWith("is saving") ? "waiting for the previous save" : "waiting for the previous session";
|
|
272
278
|
case "booting":
|
|
273
279
|
return "booting";
|
|
280
|
+
case "queued":
|
|
281
|
+
return "queued";
|
|
282
|
+
case "building":
|
|
283
|
+
return "building the image";
|
|
274
284
|
case "preparing":
|
|
275
285
|
return "preparing the workspace";
|
|
276
286
|
}
|
|
@@ -283,6 +293,10 @@ var startingExplanationOf = (session) => {
|
|
|
283
293
|
return phase.words.endsWith("is saving") ? "the previous session in this worktree is still saving \xB7 this one starts from its save" : phase.words;
|
|
284
294
|
case "booting":
|
|
285
295
|
return "the workspace is booting \xB7 the agent starts when it is up";
|
|
296
|
+
case "queued":
|
|
297
|
+
return "the launch waits for a worker \xB7 it starts when one takes it";
|
|
298
|
+
case "building":
|
|
299
|
+
return `${phase.words} \xB7 the agent starts once it is built and booted`;
|
|
286
300
|
case "preparing":
|
|
287
301
|
return "the workspace has no runtime yet \xB7 after an update, building its image takes about 8 minutes";
|
|
288
302
|
}
|
|
@@ -533,6 +547,51 @@ var fitHints = (hints, width) => {
|
|
|
533
547
|
return kept.length === 0 ? "\u2026" : `${kept.join(" \xB7 ")} \u2026`;
|
|
534
548
|
};
|
|
535
549
|
var clampIndex = (length, index) => length === 0 ? 0 : Math.max(0, Math.min(length - 1, index));
|
|
550
|
+
var VIEWER_KEY = ["viewer"];
|
|
551
|
+
var viewerNeeded = (data) => data !== void 0 && [...data.details.values()].some((detail) => hasPersonFacts(detail.sessions));
|
|
552
|
+
var fetchViewer = async (ctx) => {
|
|
553
|
+
const [view, members] = await Promise.all([
|
|
554
|
+
ctx.api("GET", "/organization").catch(() => null),
|
|
555
|
+
ctx.api("GET", "/organization/members").catch(() => [])
|
|
556
|
+
]);
|
|
557
|
+
return { userId: view?.userId ?? null, members };
|
|
558
|
+
};
|
|
559
|
+
var WORKSPACE_FACTS_KEY = (sessionId, reads) => [
|
|
560
|
+
"workspace-facts",
|
|
561
|
+
sessionId,
|
|
562
|
+
reads.waiting,
|
|
563
|
+
reads.retirement
|
|
564
|
+
];
|
|
565
|
+
var fetchWorkspaceFacts = async (api, sessionId, reads) => {
|
|
566
|
+
const [wait, retirement] = await Promise.all([
|
|
567
|
+
reads.waiting ? api("GET", `/sessions/${sessionId}/waiting`).catch(() => null) : null,
|
|
568
|
+
reads.retirement ? api(
|
|
569
|
+
"GET",
|
|
570
|
+
`/sessions/${sessionId}/workspace-retirement`
|
|
571
|
+
).catch(() => null) : null
|
|
572
|
+
]);
|
|
573
|
+
return { wait, retirement };
|
|
574
|
+
};
|
|
575
|
+
var workspaceFactRows = (session, viewer, facts, width) => workspaceLineList(
|
|
576
|
+
sessionWorkspaceLines({
|
|
577
|
+
sessionId: session.id,
|
|
578
|
+
livePeople: session.livePeople ?? [],
|
|
579
|
+
viewer: viewer?.userId ?? null,
|
|
580
|
+
wait: facts?.wait ?? null,
|
|
581
|
+
retirement: facts?.retirement ?? null,
|
|
582
|
+
members: viewer?.members ?? []
|
|
583
|
+
})
|
|
584
|
+
).flatMap((line) => {
|
|
585
|
+
const indent = line.startsWith(" ") ? " " : "";
|
|
586
|
+
return wrapWords(line, width - indent.length).map((row) => `${indent}${row}`);
|
|
587
|
+
});
|
|
588
|
+
var worktreeJoinRows = (data, projectId, worktree, viewerId, width) => {
|
|
589
|
+
const detail = data?.details.get(projectId);
|
|
590
|
+
const id = "id" in worktree ? worktree.id : detail?.worktrees?.find((candidate) => candidate.name === worktree.name)?.id;
|
|
591
|
+
if (detail === void 0 || id === void 0) return [];
|
|
592
|
+
const line = worktreeJoinLine(detail.sessions, id, viewerId);
|
|
593
|
+
return line === null ? [] : wrapWords(line, width);
|
|
594
|
+
};
|
|
536
595
|
var KEY_BINDINGS = [
|
|
537
596
|
{
|
|
538
597
|
verb: "moveUp",
|
|
@@ -2437,7 +2496,8 @@ var SessionFacts = ({
|
|
|
2437
2496
|
group,
|
|
2438
2497
|
item,
|
|
2439
2498
|
rows,
|
|
2440
|
-
tunnels
|
|
2499
|
+
tunnels,
|
|
2500
|
+
workspaceRows
|
|
2441
2501
|
}) => {
|
|
2442
2502
|
const { session, annotation, services } = item;
|
|
2443
2503
|
const color = STATUS_COLOR[session.status] ?? MUTED;
|
|
@@ -2468,6 +2528,18 @@ var SessionFacts = ({
|
|
|
2468
2528
|
/* @__PURE__ */ jsx3("span", { fg: MUTED, children: session.branch }),
|
|
2469
2529
|
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: session.baseSha === "" ? "" : ` vs ${session.baseRef ?? session.baseSha.slice(0, 12)}` })
|
|
2470
2530
|
] }, "status"),
|
|
2531
|
+
// Who else is live here, what a turn waits for, a workspace waiting to be replaced: right
|
|
2532
|
+
// under the status, before the facts a short pane may drop.
|
|
2533
|
+
...workspaceRows.map((row, index) => /* @__PURE__ */ jsx3(
|
|
2534
|
+
"text",
|
|
2535
|
+
{
|
|
2536
|
+
height: 1,
|
|
2537
|
+
bg: "transparent",
|
|
2538
|
+
fg: row.startsWith(" ") ? MUTED : INK_2,
|
|
2539
|
+
children: ` ${row}`
|
|
2540
|
+
},
|
|
2541
|
+
`workspace-${index}`
|
|
2542
|
+
)),
|
|
2471
2543
|
/* @__PURE__ */ jsx3("text", { height: 1, bg: "transparent", fg: FAINT, children: [
|
|
2472
2544
|
...timeAgo(session.createdAt) === "" ? [] : [`created ${timeAgo(session.createdAt)}`],
|
|
2473
2545
|
isPendingId(session.id) ? "provisioning" : session.id.slice(0, 8),
|
|
@@ -2630,6 +2702,28 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2630
2702
|
refetchInterval: previewLive ? 8e3 : false,
|
|
2631
2703
|
retry: 1
|
|
2632
2704
|
});
|
|
2705
|
+
const viewer = useQuery2({
|
|
2706
|
+
queryKey: VIEWER_KEY,
|
|
2707
|
+
queryFn: () => fetchViewer(ctx),
|
|
2708
|
+
enabled: viewerNeeded(data),
|
|
2709
|
+
staleTime: Number.POSITIVE_INFINITY,
|
|
2710
|
+
retry: false
|
|
2711
|
+
});
|
|
2712
|
+
const workspaceReads = selectedSession === null ? { waiting: false, retirement: false } : workspaceReadsOf(selectedSession);
|
|
2713
|
+
const workspaceFacts = useQuery2({
|
|
2714
|
+
queryKey: WORKSPACE_FACTS_KEY(previewSessionId ?? "none", workspaceReads),
|
|
2715
|
+
queryFn: () => fetchWorkspaceFacts(ctx.api, previewSessionId ?? "", workspaceReads),
|
|
2716
|
+
enabled: previewSessionId !== null && previewLive && detailWidth > 0 && (workspaceReads.waiting || workspaceReads.retirement),
|
|
2717
|
+
staleTime: 3e3,
|
|
2718
|
+
refetchInterval: previewLive ? 8e3 : false,
|
|
2719
|
+
retry: 1
|
|
2720
|
+
});
|
|
2721
|
+
const workspaceRows = selectedSession === null || !previewLive || detailWidth === 0 ? [] : workspaceFactRows(
|
|
2722
|
+
selectedSession,
|
|
2723
|
+
viewer.data,
|
|
2724
|
+
workspaceFacts.data,
|
|
2725
|
+
Math.max(16, detailWidth - 4)
|
|
2726
|
+
);
|
|
2633
2727
|
const preview = useMemo2(
|
|
2634
2728
|
() => transcript.data === void 0 ? [] : previewLines(transcript.data, {
|
|
2635
2729
|
width: Math.max(16, detailWidth - 6),
|
|
@@ -2638,7 +2732,10 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2638
2732
|
[transcript.data, detailWidth]
|
|
2639
2733
|
);
|
|
2640
2734
|
const [previewOffset, setPreviewOffset] = useState3(0);
|
|
2641
|
-
const factRows = Math.max(
|
|
2735
|
+
const factRows = Math.max(
|
|
2736
|
+
0,
|
|
2737
|
+
Math.min(SESSION_FACT_ROWS + workspaceRows.length, layout.detailRows - 2)
|
|
2738
|
+
);
|
|
2642
2739
|
const showFactRule = factRows > 0 && layout.detailRows - factRows > 1;
|
|
2643
2740
|
const waiting = selectedSession !== null && (selectedSession.status === "starting" || isPendingId(selectedSession.id));
|
|
2644
2741
|
const snake = useSnake({
|
|
@@ -3606,6 +3703,22 @@ ${tunneled}
|
|
|
3606
3703
|
return COLUMN_TITLE[column];
|
|
3607
3704
|
};
|
|
3608
3705
|
const pickerTitle = picker === null ? "" : picker.worktree === void 0 ? picker.session === null ? "new session \xB7 pick a harness" : `resume ${sessionDisplayName(picker.session)} \xB7 pick a harness` : `new session in ${picker.worktree.name} \xB7 pick a harness`;
|
|
3706
|
+
const modalWidth = Math.min(74, terminalCols - 4);
|
|
3707
|
+
const pickerJoinRows = picker?.worktree?.id == null || selectedProject === null ? [] : worktreeJoinRows(
|
|
3708
|
+
data,
|
|
3709
|
+
selectedProject.project.id,
|
|
3710
|
+
{ id: picker.worktree.id },
|
|
3711
|
+
viewer.data?.userId ?? null,
|
|
3712
|
+
modalWidth - 4
|
|
3713
|
+
);
|
|
3714
|
+
const pickerJoinHeight = pickerJoinRows.length === 0 ? 0 : pickerJoinRows.length + 1;
|
|
3715
|
+
const creatingJoinRows = creating === null || !creating.joins ? [] : worktreeJoinRows(
|
|
3716
|
+
data,
|
|
3717
|
+
creating.projectId,
|
|
3718
|
+
{ name: creating.name },
|
|
3719
|
+
viewer.data?.userId ?? null,
|
|
3720
|
+
modalWidth - 7
|
|
3721
|
+
);
|
|
3609
3722
|
const creatingHeight = 2 + 1 + 1 + 6 + 1 + deriveHarnesses(null).length;
|
|
3610
3723
|
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";
|
|
3611
3724
|
const loadFailure = data === void 0 && failureReason !== null ? errorText(failureReason) : null;
|
|
@@ -3778,7 +3891,8 @@ ${tunneled}
|
|
|
3778
3891
|
group: selectedGroup,
|
|
3779
3892
|
item: selectedItem,
|
|
3780
3893
|
rows: factRows,
|
|
3781
|
-
tunnels: openTunnels
|
|
3894
|
+
tunnels: openTunnels,
|
|
3895
|
+
workspaceRows
|
|
3782
3896
|
}
|
|
3783
3897
|
),
|
|
3784
3898
|
showFactRule ? /* @__PURE__ */ jsx3("text", { height: 1, bg: "transparent", fg: FAINT, children: ` ${"\u2500".repeat(Math.max(4, detailWidth - 4))}` }) : null,
|
|
@@ -3873,15 +3987,18 @@ ${tunneled}
|
|
|
3873
3987
|
]
|
|
3874
3988
|
}
|
|
3875
3989
|
) : null,
|
|
3876
|
-
picker === null ? null : /* @__PURE__ */
|
|
3990
|
+
picker === null ? null : /* @__PURE__ */ jsxs3(
|
|
3877
3991
|
"box",
|
|
3878
3992
|
{
|
|
3879
3993
|
position: "absolute",
|
|
3880
3994
|
zIndex: 12,
|
|
3881
3995
|
left: Math.max(1, Math.floor((terminalCols - Math.min(74, terminalCols - 4)) / 2)),
|
|
3882
|
-
top: Math.max(
|
|
3996
|
+
top: Math.max(
|
|
3997
|
+
1,
|
|
3998
|
+
Math.floor((terminalRows - (2 + pickerItems.length + pickerJoinHeight)) / 2)
|
|
3999
|
+
),
|
|
3883
4000
|
width: Math.min(74, terminalCols - 4),
|
|
3884
|
-
height: 2 + pickerItems.length,
|
|
4001
|
+
height: 2 + pickerItems.length + pickerJoinHeight,
|
|
3885
4002
|
border: true,
|
|
3886
4003
|
borderStyle: "rounded",
|
|
3887
4004
|
borderColor: ACCENT,
|
|
@@ -3889,15 +4006,19 @@ ${tunneled}
|
|
|
3889
4006
|
titleAlignment: "left",
|
|
3890
4007
|
backgroundColor: SURFACE,
|
|
3891
4008
|
flexDirection: "column",
|
|
3892
|
-
children:
|
|
3893
|
-
|
|
3894
|
-
{
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
4009
|
+
children: [
|
|
4010
|
+
pickerJoinRows.map((row, index) => /* @__PURE__ */ jsx3("text", { height: 1, bg: SURFACE, fg: INK_2, children: ` ${row}` }, `join-${index}`)),
|
|
4011
|
+
pickerJoinRows.length === 0 ? null : /* @__PURE__ */ jsx3("text", { height: 1, bg: SURFACE, children: " " }),
|
|
4012
|
+
pickerItems.map((item, index) => /* @__PURE__ */ jsx3(
|
|
4013
|
+
HarnessRow,
|
|
4014
|
+
{
|
|
4015
|
+
item,
|
|
4016
|
+
selected: index === pickerIndex,
|
|
4017
|
+
background: SURFACE
|
|
4018
|
+
},
|
|
4019
|
+
String(item.harness)
|
|
4020
|
+
))
|
|
4021
|
+
]
|
|
3901
4022
|
}
|
|
3902
4023
|
),
|
|
3903
4024
|
editing === null ? null : /* @__PURE__ */ jsx3(
|
|
@@ -4053,6 +4174,10 @@ ${tunneled}
|
|
|
4053
4174
|
const branch = creating.joins || creating.branches === null ? void 0 : filterBranches(creating.branches, creating.query)[index];
|
|
4054
4175
|
const active = creating.step === "base";
|
|
4055
4176
|
if (branch === void 0) {
|
|
4177
|
+
const joinRow = creatingJoinRows[index];
|
|
4178
|
+
if (joinRow !== void 0) {
|
|
4179
|
+
return /* @__PURE__ */ jsx3("text", { height: 1, bg: SURFACE, fg: INK_2, children: ` ${joinRow}` }, `slot-${index}`);
|
|
4180
|
+
}
|
|
4056
4181
|
const notice = creating.joins ? null : baseStepNotice(creating);
|
|
4057
4182
|
return /* @__PURE__ */ jsx3(
|
|
4058
4183
|
"text",
|