@sealant/mend 0.34.2 → 0.34.5
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/dist/{chunk-JJ66V76Y.js → chunk-5DORQXQT.js} +106 -7
- package/dist/{dashboard-OADX3PHI.js → dashboard-KZ4XGZ6W.js} +32 -13
- package/dist/main.js +378 -89
- 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 +1 -1
- 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 +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-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-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 +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 +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-worktrees.1 +1 -1
- package/man/mend.1 +1 -1
- package/package.json +3 -3
|
@@ -4,6 +4,26 @@ var __export = (target, all3) => {
|
|
|
4
4
|
__defProp(target, name, { get: all3[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
+
// ../../packages/domain/src/workbench/harness-launch.ts
|
|
8
|
+
var EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
9
|
+
var PERMISSION_MODES = ["bypass", "ask"];
|
|
10
|
+
|
|
11
|
+
// ../../packages/domain/src/workbench/agent-start.ts
|
|
12
|
+
var agentStartingLine = (label, facts, elapsedMs) => `${label} is starting${facts.freshMachine ? " on the new machine" : ""} \xB7 ${Math.max(0, Math.round(elapsedMs / 1e3))}s`;
|
|
13
|
+
var MAX_TRUSTED_ELAPSED_MS = 60 * 60 * 1e3;
|
|
14
|
+
var timeOf = (value3) => value3 === void 0 ? Number.NaN : typeof value3 === "string" ? Date.parse(value3) : value3.getTime();
|
|
15
|
+
var agentStartingFacts = (currentAgent, processes, now2) => {
|
|
16
|
+
if (currentAgent === null || currentAgent === void 0) {
|
|
17
|
+
return { startedAt: null, freshMachine: false };
|
|
18
|
+
}
|
|
19
|
+
const created = timeOf(currentAgent.createdAt);
|
|
20
|
+
const trusted = Number.isFinite(created) && created <= now2 && now2 - created <= MAX_TRUSTED_ELAPSED_MS;
|
|
21
|
+
const freshMachine = processes !== void 0 && currentAgent.sealantWorkspaceId !== void 0 && Number.isFinite(created) && !processes.some(
|
|
22
|
+
(process2) => process2.id !== currentAgent.id && process2.sealantWorkspaceId === currentAgent.sealantWorkspaceId && timeOf(process2.createdAt) < created
|
|
23
|
+
);
|
|
24
|
+
return { startedAt: trusted ? created : null, freshMachine };
|
|
25
|
+
};
|
|
26
|
+
|
|
7
27
|
// ../../node_modules/.pnpm/effect@4.0.0-beta.93/node_modules/effect/dist/Pipeable.js
|
|
8
28
|
var pipeArguments = (self, args2) => {
|
|
9
29
|
switch (args2.length) {
|
|
@@ -27325,7 +27345,7 @@ var leftWords = (facts) => {
|
|
|
27325
27345
|
return null;
|
|
27326
27346
|
};
|
|
27327
27347
|
var utcTime = (at) => `${at.toISOString().slice(11, 19)} UTC`;
|
|
27328
|
-
var
|
|
27348
|
+
var timeOf2 = (at) => {
|
|
27329
27349
|
if (at === null || at === void 0) return null;
|
|
27330
27350
|
const date2 = typeof at === "string" ? new Date(at) : at;
|
|
27331
27351
|
return Number.isNaN(date2.getTime()) ? null : date2;
|
|
@@ -27357,7 +27377,7 @@ var captureStatusLine = (facts) => {
|
|
|
27357
27377
|
].join(" \xB7 ");
|
|
27358
27378
|
}
|
|
27359
27379
|
if (overdue !== null) return overdue;
|
|
27360
|
-
const failingSince =
|
|
27380
|
+
const failingSince = timeOf2(facts.captureFailingSince);
|
|
27361
27381
|
if (failingSince !== null) {
|
|
27362
27382
|
const error = facts.captureFailingError ?? null;
|
|
27363
27383
|
return [
|
|
@@ -27366,7 +27386,7 @@ var captureStatusLine = (facts) => {
|
|
|
27366
27386
|
].join(" \xB7 ");
|
|
27367
27387
|
}
|
|
27368
27388
|
if ((facts.captureRefused ?? 0) > 0) return `not saved \xB7 ${facts.captureRefused} refused`;
|
|
27369
|
-
const discardedAt =
|
|
27389
|
+
const discardedAt = timeOf2(facts.captureDiscardedAt);
|
|
27370
27390
|
if (discardedAt !== null) {
|
|
27371
27391
|
const by = facts.captureDiscardedBy ?? null;
|
|
27372
27392
|
return `unsaved work discarded${by === null || by === "" ? "" : ` by ${by}`} at ${utcTime(discardedAt)}`;
|
|
@@ -27560,10 +27580,6 @@ var FollowUp = class extends Schema_exports.Class("FollowUp")({
|
|
|
27560
27580
|
}) {
|
|
27561
27581
|
};
|
|
27562
27582
|
|
|
27563
|
-
// ../../packages/domain/src/workbench/harness-launch.ts
|
|
27564
|
-
var EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
27565
|
-
var PERMISSION_MODES = ["bypass", "ask"];
|
|
27566
|
-
|
|
27567
27583
|
// ../../packages/domain/src/workbench/mount.ts
|
|
27568
27584
|
var ProjectMount = class extends Schema_exports.Class("ProjectMount")({
|
|
27569
27585
|
id: ProjectMountId,
|
|
@@ -28125,6 +28141,15 @@ var SessionProcess = class extends Schema_exports.Class("SessionProcess")({
|
|
|
28125
28141
|
/** Services: the host port Mend binds on its private interfaces. */
|
|
28126
28142
|
hostPort: Schema_exports.NullOr(Schema_exports.Int),
|
|
28127
28143
|
createdAt: Timestamp,
|
|
28144
|
+
/**
|
|
28145
|
+
* When the process's record first carried output: the first screen an agent drew. Null while
|
|
28146
|
+
* it has drawn nothing, for a process with no run of ours, and on rows from before it was
|
|
28147
|
+
* observed. Older servers omit it.
|
|
28148
|
+
*/
|
|
28149
|
+
firstOutputAt: Schema_exports.NullOr(Timestamp).pipe(
|
|
28150
|
+
Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)),
|
|
28151
|
+
Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
|
|
28152
|
+
),
|
|
28128
28153
|
exitedAt: Schema_exports.NullOr(Timestamp),
|
|
28129
28154
|
updatedAt: Timestamp
|
|
28130
28155
|
}) {
|
|
@@ -28799,6 +28824,73 @@ var trackBracketedPaste = (output, current) => {
|
|
|
28799
28824
|
};
|
|
28800
28825
|
var pasteBytes = (text, bracketed) => Buffer.from(bracketed ? `\x1B[200~${text}\x1B[201~` : text, "utf8");
|
|
28801
28826
|
|
|
28827
|
+
// src/server-request.ts
|
|
28828
|
+
var MendRequestError = class extends Error {
|
|
28829
|
+
kind;
|
|
28830
|
+
status;
|
|
28831
|
+
constructor(kind, message, status = null) {
|
|
28832
|
+
super(message);
|
|
28833
|
+
this.name = "MendRequestError";
|
|
28834
|
+
this.kind = kind;
|
|
28835
|
+
this.status = status;
|
|
28836
|
+
}
|
|
28837
|
+
};
|
|
28838
|
+
var TIMEOUT_CODES = /* @__PURE__ */ new Set([
|
|
28839
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
28840
|
+
"UND_ERR_BODY_TIMEOUT"
|
|
28841
|
+
]);
|
|
28842
|
+
var DROPPED_CODES = /* @__PURE__ */ new Set([
|
|
28843
|
+
"UND_ERR_SOCKET",
|
|
28844
|
+
"UND_ERR_CLOSED",
|
|
28845
|
+
"ECONNRESET",
|
|
28846
|
+
"EPIPE"
|
|
28847
|
+
]);
|
|
28848
|
+
var codeOf = (value3) => {
|
|
28849
|
+
if (typeof value3 !== "object" || value3 === null || !("code" in value3)) return null;
|
|
28850
|
+
return typeof value3.code === "string" ? value3.code : null;
|
|
28851
|
+
};
|
|
28852
|
+
var nameOf = (value3) => {
|
|
28853
|
+
if (typeof value3 !== "object" || value3 === null || !("name" in value3)) return null;
|
|
28854
|
+
return typeof value3.name === "string" ? value3.name : null;
|
|
28855
|
+
};
|
|
28856
|
+
var noAnswerOf = (error) => {
|
|
28857
|
+
const name = nameOf(error);
|
|
28858
|
+
if (name === "TimeoutError" || name === "AbortError") return "timeout";
|
|
28859
|
+
const cause = typeof error === "object" && error !== null && "cause" in error ? error.cause : null;
|
|
28860
|
+
const code = codeOf(cause) ?? codeOf(error);
|
|
28861
|
+
if (code !== null && TIMEOUT_CODES.has(code)) return "timeout";
|
|
28862
|
+
if (code !== null && DROPPED_CODES.has(code)) return "dropped";
|
|
28863
|
+
return "unreachable";
|
|
28864
|
+
};
|
|
28865
|
+
var spoken = (ms) => {
|
|
28866
|
+
const seconds2 = Math.round(ms / 1e3);
|
|
28867
|
+
if (seconds2 < 90) return `${seconds2}s`;
|
|
28868
|
+
return `${Math.round(seconds2 / 60)} min`;
|
|
28869
|
+
};
|
|
28870
|
+
var noAnswerMessage = (kind, serverUrl, call, waitedMs) => {
|
|
28871
|
+
if (kind === "unreachable")
|
|
28872
|
+
return `cannot reach the Mend server at ${serverUrl} \u2014 is it running?`;
|
|
28873
|
+
if (kind === "timeout") {
|
|
28874
|
+
return `${call} has had no answer from ${serverUrl} after ${spoken(waitedMs)} \u2014 the server accepted it and may still be working on it`;
|
|
28875
|
+
}
|
|
28876
|
+
return `the connection to ${serverUrl} closed before ${call} answered \u2014 the server may still be working on it`;
|
|
28877
|
+
};
|
|
28878
|
+
var noAnswerError = (error, serverUrl, call, waitedMs) => {
|
|
28879
|
+
const kind = noAnswerOf(error);
|
|
28880
|
+
return new MendRequestError(kind, noAnswerMessage(kind, serverUrl, call, waitedMs));
|
|
28881
|
+
};
|
|
28882
|
+
var GATEWAY_STATUSES = /* @__PURE__ */ new Set([
|
|
28883
|
+
502,
|
|
28884
|
+
503,
|
|
28885
|
+
504,
|
|
28886
|
+
520,
|
|
28887
|
+
521,
|
|
28888
|
+
522,
|
|
28889
|
+
523,
|
|
28890
|
+
524
|
|
28891
|
+
]);
|
|
28892
|
+
var mayStillBeWorking = (error) => error instanceof MendRequestError && (error.kind === "timeout" || error.kind === "dropped" || error.kind === "http" && error.status !== null && GATEWAY_STATUSES.has(error.status));
|
|
28893
|
+
|
|
28802
28894
|
// src/workbench-events.ts
|
|
28803
28895
|
var createSseParser = () => {
|
|
28804
28896
|
let buffer = "";
|
|
@@ -28848,6 +28940,8 @@ var eventFamilies = (payload) => {
|
|
|
28848
28940
|
};
|
|
28849
28941
|
|
|
28850
28942
|
export {
|
|
28943
|
+
agentStartingLine,
|
|
28944
|
+
agentStartingFacts,
|
|
28851
28945
|
repositoryCloneUrlIssue,
|
|
28852
28946
|
RepositoryCloneUrl,
|
|
28853
28947
|
landingFactsFromWire,
|
|
@@ -28879,6 +28973,11 @@ export {
|
|
|
28879
28973
|
isPasteChunk,
|
|
28880
28974
|
trackBracketedPaste,
|
|
28881
28975
|
pasteBytes,
|
|
28976
|
+
MendRequestError,
|
|
28977
|
+
spoken,
|
|
28978
|
+
noAnswerError,
|
|
28979
|
+
GATEWAY_STATUSES,
|
|
28980
|
+
mayStillBeWorking,
|
|
28882
28981
|
createSseParser,
|
|
28883
28982
|
eventFamilies
|
|
28884
28983
|
};
|
|
@@ -10,11 +10,12 @@ import {
|
|
|
10
10
|
eventFamilies,
|
|
11
11
|
isPendingId,
|
|
12
12
|
matchProjectByCwd,
|
|
13
|
+
mayStillBeWorking,
|
|
13
14
|
normalizeProjectName,
|
|
14
15
|
pendingId,
|
|
15
16
|
repositoryCloneUrlIssue,
|
|
16
17
|
servicesHoldLine
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-5DORQXQT.js";
|
|
18
19
|
|
|
19
20
|
// src/dashboard.tsx
|
|
20
21
|
import { CliRenderEvents, createCliRenderer } from "@opentui/core";
|
|
@@ -2412,6 +2413,15 @@ var StatusLine = ({
|
|
|
2412
2413
|
return /* @__PURE__ */ jsx3("text", { height: 1, fg: INK_2, bg: "transparent", children: text });
|
|
2413
2414
|
};
|
|
2414
2415
|
var errorText = (error) => error instanceof Error ? error.message : String(error);
|
|
2416
|
+
var startedOrStarting = async (start, starting) => {
|
|
2417
|
+
try {
|
|
2418
|
+
return await start;
|
|
2419
|
+
} catch (error) {
|
|
2420
|
+
if (mayStillBeWorking(error)) return { ...starting, status: "starting" };
|
|
2421
|
+
throw error;
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2424
|
+
var startedLine = (session) => session.status === "starting" ? `still starting \xB7 ${sessionDisplayName(session)} \u2014 a attaches once the row reads running` : `started \xB7 ${sessionDisplayName(session)} \u2014 a attaches`;
|
|
2415
2425
|
var keepSpanVisible = (scroll, top, height, viewRows) => {
|
|
2416
2426
|
if (scroll === null || viewRows <= 0) return;
|
|
2417
2427
|
const viewH = Math.max(1, viewRows);
|
|
@@ -2597,7 +2607,7 @@ var App = ({ ctx, onQuit }) => {
|
|
|
2597
2607
|
`).join("");
|
|
2598
2608
|
process.stdout.write(
|
|
2599
2609
|
`
|
|
2600
|
-
|
|
2610
|
+
attaching \xB7 ${session.harness} \xB7 ${short} \xB7 detach: Ctrl+]
|
|
2601
2611
|
${tunneled}
|
|
2602
2612
|
`
|
|
2603
2613
|
);
|
|
@@ -2641,7 +2651,7 @@ ${tunneled}
|
|
|
2641
2651
|
lockRef.current = false;
|
|
2642
2652
|
}
|
|
2643
2653
|
say(
|
|
2644
|
-
outcome === "unavailable" ? "attach unavailable \u2014 could not connect" : outcome === "detached" || outcome === "interrupted" ? `detached \u2014 ${short} keeps running` : outcome === "dropped" ? `disconnected \xB7 ${short} \u2014 refreshing session status` : `terminal ended \xB7 ${short} \u2014 refreshing session status`
|
|
2654
|
+
outcome === "unavailable" ? "attach unavailable \u2014 could not connect" : outcome === "no-answer" ? `no answer \u2014 the server did not open ${short}'s terminal; it keeps running \xB7 a tries again` : outcome === "detached" || outcome === "interrupted" ? `detached \u2014 ${short} keeps running` : outcome === "dropped" ? `disconnected \xB7 ${short} \u2014 refreshing session status` : `terminal ended \xB7 ${short} \u2014 refreshing session status`
|
|
2645
2655
|
);
|
|
2646
2656
|
refetch();
|
|
2647
2657
|
};
|
|
@@ -2663,8 +2673,10 @@ ${tunneled}
|
|
|
2663
2673
|
name: vars.name,
|
|
2664
2674
|
base: vars.base
|
|
2665
2675
|
});
|
|
2666
|
-
|
|
2667
|
-
|
|
2676
|
+
return startedOrStarting(
|
|
2677
|
+
ctx.api("POST", `/sessions/${session.id}/launch`, { argv }),
|
|
2678
|
+
session
|
|
2679
|
+
);
|
|
2668
2680
|
},
|
|
2669
2681
|
onMutate: async (vars) => {
|
|
2670
2682
|
await queryClient.cancelQueries({ queryKey: WORKBENCH_KEY });
|
|
@@ -2700,7 +2712,7 @@ ${tunneled}
|
|
|
2700
2712
|
);
|
|
2701
2713
|
setSessionKey((current) => current === vars.pendingKey ? session.id : current);
|
|
2702
2714
|
setBusy(null);
|
|
2703
|
-
say(
|
|
2715
|
+
say(startedLine(session));
|
|
2704
2716
|
},
|
|
2705
2717
|
onSettled: (_data, _error, vars) => {
|
|
2706
2718
|
gate.release(vars.gateKey);
|
|
@@ -2708,9 +2720,12 @@ ${tunneled}
|
|
|
2708
2720
|
}
|
|
2709
2721
|
});
|
|
2710
2722
|
const resumeMutation = useMutation2({
|
|
2711
|
-
mutationFn: (vars) =>
|
|
2712
|
-
|
|
2713
|
-
|
|
2723
|
+
mutationFn: (vars) => startedOrStarting(
|
|
2724
|
+
ctx.api("POST", `/sessions/${vars.session.id}/resume`, {
|
|
2725
|
+
harness: vars.harness
|
|
2726
|
+
}),
|
|
2727
|
+
vars.session
|
|
2728
|
+
),
|
|
2714
2729
|
onMutate: async (vars) => {
|
|
2715
2730
|
await queryClient.cancelQueries({ queryKey: WORKBENCH_KEY });
|
|
2716
2731
|
patchWorkbench(
|
|
@@ -2735,7 +2750,9 @@ ${tunneled}
|
|
|
2735
2750
|
(current) => replaceSession(current, vars.projectId, vars.session.id, resumed)
|
|
2736
2751
|
);
|
|
2737
2752
|
setBusy(null);
|
|
2738
|
-
say(
|
|
2753
|
+
say(
|
|
2754
|
+
resumed.status === "starting" ? `still resuming \xB7 ${sessionDisplayName(resumed)} \u2014 a attaches once the row reads running` : `resumed \xB7 ${sessionDisplayName(resumed)} \u2014 a attaches`
|
|
2755
|
+
);
|
|
2739
2756
|
},
|
|
2740
2757
|
onSettled: (_data, _error, vars) => {
|
|
2741
2758
|
gate.release(vars.gateKey);
|
|
@@ -2846,8 +2863,10 @@ ${tunneled}
|
|
|
2846
2863
|
harness: vars.harness,
|
|
2847
2864
|
label: null
|
|
2848
2865
|
});
|
|
2849
|
-
|
|
2850
|
-
|
|
2866
|
+
return startedOrStarting(
|
|
2867
|
+
ctx.api("POST", `/sessions/${session.id}/launch`, { argv }),
|
|
2868
|
+
session
|
|
2869
|
+
);
|
|
2851
2870
|
},
|
|
2852
2871
|
onMutate: async (vars) => {
|
|
2853
2872
|
await queryClient.cancelQueries({ queryKey: WORKBENCH_KEY });
|
|
@@ -2880,7 +2899,7 @@ ${tunneled}
|
|
|
2880
2899
|
);
|
|
2881
2900
|
setSessionKey((current) => current === vars.pendingKey ? session.id : current);
|
|
2882
2901
|
setBusy(null);
|
|
2883
|
-
say(
|
|
2902
|
+
say(startedLine(session));
|
|
2884
2903
|
},
|
|
2885
2904
|
onSettled: (_data, _error, vars) => {
|
|
2886
2905
|
gate.release(vars.gateKey);
|