@sealant/mend 0.30.0 → 0.32.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/dist/{chunk-BMFB2UN7.js → chunk-J3TR4UAG.js} +81 -7
- package/dist/{dashboard-OF5UXII2.js → dashboard-3HNFSQZD.js} +60 -7
- package/dist/main.js +1821 -871
- 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 +28 -3
- 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 +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 +9 -2
- 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 +8 -1
- package/man/mend-ui.1 +2 -2
- 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 +6 -3
- package/package.json +3 -3
|
@@ -26817,7 +26817,9 @@ var AuditAction = Schema_exports.Literals([
|
|
|
26817
26817
|
// `gh` spoke as them.
|
|
26818
26818
|
"change.landed",
|
|
26819
26819
|
"change.pull_request_refreshed",
|
|
26820
|
-
"change.bundle_downloaded"
|
|
26820
|
+
"change.bundle_downloaded",
|
|
26821
|
+
// A pull request opened outside Mend was read with the owner's `gh` and recorded.
|
|
26822
|
+
"change.pull_request_adopted"
|
|
26821
26823
|
]);
|
|
26822
26824
|
var AuditData = Schema_exports.Record(
|
|
26823
26825
|
Schema_exports.String,
|
|
@@ -26841,8 +26843,14 @@ var AuditEvent = class extends Schema_exports.Class("AuditEvent")({
|
|
|
26841
26843
|
};
|
|
26842
26844
|
|
|
26843
26845
|
// ../../packages/domain/src/workbench/landing.ts
|
|
26844
|
-
var LandingTrigger = Schema_exports.Literals(["manual", "automatic"]);
|
|
26845
|
-
var LandingOutcome = Schema_exports.Literals([
|
|
26846
|
+
var LandingTrigger = Schema_exports.Literals(["manual", "automatic", "adopted"]);
|
|
26847
|
+
var LandingOutcome = Schema_exports.Literals([
|
|
26848
|
+
"pushed",
|
|
26849
|
+
"pull-request",
|
|
26850
|
+
"refused",
|
|
26851
|
+
"failed",
|
|
26852
|
+
"adopted"
|
|
26853
|
+
]);
|
|
26846
26854
|
var PullRequestState = Schema_exports.Literals(["open", "closed", "merged"]);
|
|
26847
26855
|
var LandedPullRequest = Schema_exports.Struct({
|
|
26848
26856
|
number: Schema_exports.Int,
|
|
@@ -26868,6 +26876,19 @@ var ChangeLanding = class extends Schema_exports.Class("ChangeLanding")({
|
|
|
26868
26876
|
pushedSha: Schema_exports.NullOr(Sha),
|
|
26869
26877
|
trigger: LandingTrigger,
|
|
26870
26878
|
pullRequest: Schema_exports.NullOr(LandedPullRequest),
|
|
26879
|
+
/**
|
|
26880
|
+
* The pull request's head is in another repository (a fork): Mend pushes to origin only, so it
|
|
26881
|
+
* never updates such a pull request. Older servers omit it.
|
|
26882
|
+
*/
|
|
26883
|
+
pullRequestCrossRepository: Schema_exports.Boolean.pipe(
|
|
26884
|
+
Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(false)),
|
|
26885
|
+
Schema_exports.withConstructorDefault(Effect_exports.succeed(false))
|
|
26886
|
+
),
|
|
26887
|
+
/** Who owns the repository the pull request's head is in, as `gh` reported it; null unknown. */
|
|
26888
|
+
pullRequestHeadOwner: Schema_exports.NullOr(Schema_exports.String).pipe(
|
|
26889
|
+
Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)),
|
|
26890
|
+
Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
|
|
26891
|
+
),
|
|
26871
26892
|
outcome: LandingOutcome,
|
|
26872
26893
|
/** The remote's or `gh`'s own words for a refusal or a failure; null otherwise. */
|
|
26873
26894
|
message: Schema_exports.NullOr(Schema_exports.String),
|
|
@@ -26915,7 +26936,11 @@ var LandingFact = Schema_exports.Union([
|
|
|
26915
26936
|
Schema_exports.TaggedStruct("pull-request", {
|
|
26916
26937
|
number: Schema_exports.Int,
|
|
26917
26938
|
state: PullRequestState,
|
|
26918
|
-
observedAt: Timestamp
|
|
26939
|
+
observedAt: Timestamp,
|
|
26940
|
+
/** Opened outside Mend and adopted. Older servers omit it. */
|
|
26941
|
+
outside: Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(false))),
|
|
26942
|
+
/** The fork's owner when its head is in another repository; null for origin's own. */
|
|
26943
|
+
fork: Schema_exports.NullOr(Schema_exports.String).pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)))
|
|
26919
26944
|
}),
|
|
26920
26945
|
/** A fetch found commits on origin's branch that Mend's branch does not have. */
|
|
26921
26946
|
Schema_exports.TaggedStruct("origin-moved", { branch: Schema_exports.String, commits: Schema_exports.Int }),
|
|
@@ -26956,7 +26981,7 @@ var landingFactLine = (fact, now2) => {
|
|
|
26956
26981
|
case "pushed":
|
|
26957
26982
|
return `pushed \xB7 ${fact.branch} \xB7 ${shortSha(fact.sha)} \xB7 observed`;
|
|
26958
26983
|
case "pull-request":
|
|
26959
|
-
return `pull request #${fact.number} \xB7 ${fact.state} \xB7 observed ${observedAgo(fact.observedAt, now2)}
|
|
26984
|
+
return `pull request #${fact.number} \xB7 ${fact.state} \xB7 observed ${observedAgo(fact.observedAt, now2)}` + (fact.outside ? " \xB7 opened outside Mend" : "") + (fact.fork === null ? "" : ` \xB7 from ${fact.fork === "" ? "a fork" : `${fact.fork}'s fork`}`);
|
|
26960
26985
|
case "origin-moved":
|
|
26961
26986
|
return `origin has moved \xB7 ${fact.branch} has ${plural(fact.commits, "commit", "commits")} Mend has not seen`;
|
|
26962
26987
|
case "changed-since-landing":
|
|
@@ -27258,6 +27283,37 @@ var FolderFile = class extends Schema_exports.Class("FolderFile")({
|
|
|
27258
27283
|
var FOLDER_MAX_FILE_BYTES = 1024 * 1024;
|
|
27259
27284
|
var FOLDER_MAX_REQUEST_BYTES = 4 * 1024 * 1024;
|
|
27260
27285
|
|
|
27286
|
+
// ../../packages/domain/src/workbench/git-author.ts
|
|
27287
|
+
var GitAuthorSource = Schema_exports.Literals(["setting", "account"]);
|
|
27288
|
+
var GitAuthor = class extends Schema_exports.Class("GitAuthor")({
|
|
27289
|
+
name: Schema_exports.String,
|
|
27290
|
+
email: Schema_exports.String
|
|
27291
|
+
}) {
|
|
27292
|
+
};
|
|
27293
|
+
var ResolvedGitAuthor = class extends Schema_exports.Class("ResolvedGitAuthor")({
|
|
27294
|
+
name: Schema_exports.String,
|
|
27295
|
+
email: Schema_exports.String,
|
|
27296
|
+
source: GitAuthorSource
|
|
27297
|
+
}) {
|
|
27298
|
+
};
|
|
27299
|
+
var GIT_AUTHOR_MAX_LENGTH = 200;
|
|
27300
|
+
var normalizeGitAuthor = (author) => new GitAuthor({ name: author.name.trim(), email: author.email.trim() });
|
|
27301
|
+
var gitAuthorIssue = (author) => {
|
|
27302
|
+
const { name, email } = normalizeGitAuthor(author);
|
|
27303
|
+
if (name === "") return "the name is empty";
|
|
27304
|
+
if (email === "") return "the email is empty";
|
|
27305
|
+
if (name.length > GIT_AUTHOR_MAX_LENGTH) {
|
|
27306
|
+
return `the name is longer than ${GIT_AUTHOR_MAX_LENGTH} characters`;
|
|
27307
|
+
}
|
|
27308
|
+
if (email.length > GIT_AUTHOR_MAX_LENGTH) {
|
|
27309
|
+
return `the email is longer than ${GIT_AUTHOR_MAX_LENGTH} characters`;
|
|
27310
|
+
}
|
|
27311
|
+
if (/[<>\r\n]/.test(name)) return "the name contains <, > or a line break";
|
|
27312
|
+
if (!/^[^\s<>@]+@[^\s<>@]+$/.test(email))
|
|
27313
|
+
return "the email is not an address like you@example.com";
|
|
27314
|
+
return null;
|
|
27315
|
+
};
|
|
27316
|
+
|
|
27261
27317
|
// ../../packages/domain/src/workbench/review-slice.ts
|
|
27262
27318
|
var DiffDigest = Schema_exports.String.pipe(
|
|
27263
27319
|
Schema_exports.check(Schema_exports.isPattern(/^[0-9a-f]{64}$/)),
|
|
@@ -27563,13 +27619,14 @@ var ProjectLink = class extends Schema_exports.Class("ProjectLink")({
|
|
|
27563
27619
|
|
|
27564
27620
|
// ../../packages/domain/src/workbench/pass.ts
|
|
27565
27621
|
var PassKind = Schema_exports.Literals(["tour", "read", "suggest"]);
|
|
27566
|
-
var PassStatus = Schema_exports.Literals(["running", "completed", "failed"]);
|
|
27622
|
+
var PassStatus = Schema_exports.Literals(["queued", "running", "completed", "failed"]);
|
|
27567
27623
|
var ChangePass = class extends Schema_exports.Class("ChangePass")({
|
|
27568
27624
|
changeId: ChangeId,
|
|
27569
27625
|
kind: PassKind,
|
|
27570
27626
|
status: PassStatus,
|
|
27571
27627
|
detail: Schema_exports.NullOr(Schema_exports.String),
|
|
27572
27628
|
findings: Schema_exports.NullOr(Schema_exports.Int),
|
|
27629
|
+
/** When it began running; for a `queued` row, when it was queued. */
|
|
27573
27630
|
startedAt: Timestamp,
|
|
27574
27631
|
finishedAt: Schema_exports.NullOr(Timestamp)
|
|
27575
27632
|
}) {
|
|
@@ -27599,7 +27656,7 @@ var ProjectClusterBindingsSnapshot = class extends Schema_exports.Class(
|
|
|
27599
27656
|
}) {
|
|
27600
27657
|
};
|
|
27601
27658
|
|
|
27602
|
-
// ../../node_modules/.pnpm/@sealant+api-contracts@0.37.
|
|
27659
|
+
// ../../node_modules/.pnpm/@sealant+api-contracts@0.37.1_effect@4.0.0-beta.93/node_modules/@sealant/api-contracts/dist/workspace-environment.js
|
|
27603
27660
|
var RESERVED_NAMES = new Map([
|
|
27604
27661
|
// Identity/process roots the daemon and shells own.
|
|
27605
27662
|
...[
|
|
@@ -27934,12 +27991,20 @@ var ServiceView = class extends Schema_exports.Class("ServiceView")({
|
|
|
27934
27991
|
}) {
|
|
27935
27992
|
};
|
|
27936
27993
|
|
|
27994
|
+
// ../../packages/domain/src/workbench/session-fold.ts
|
|
27995
|
+
var servicesHoldLine = (input) => {
|
|
27996
|
+
if (input.agentLive || input.liveServices <= 0) return null;
|
|
27997
|
+
const hold = input.liveServices === 1 ? "1 service keeps the workspace up" : `${input.liveServices} services keep the workspace up`;
|
|
27998
|
+
return input.agentOutcome === null ? hold : `agent ${input.agentOutcome} \xB7 ${hold}`;
|
|
27999
|
+
};
|
|
28000
|
+
|
|
27937
28001
|
// ../../packages/domain/src/workbench/session-control.ts
|
|
27938
28002
|
var SessionControlKind = Schema_exports.Literals([
|
|
27939
28003
|
"interrupt",
|
|
27940
28004
|
"terminal-attach",
|
|
27941
28005
|
"shell-open",
|
|
27942
28006
|
"stop",
|
|
28007
|
+
"services-stop",
|
|
27943
28008
|
"shared-control-on",
|
|
27944
28009
|
"shared-control-off"
|
|
27945
28010
|
]);
|
|
@@ -28315,6 +28380,11 @@ var agentOutcome = (currentAgent) => {
|
|
|
28315
28380
|
if (currentAgent.harness === "shell") return "completed";
|
|
28316
28381
|
return currentAgent.exitCode === null || currentAgent.exitCode === 0 ? "completed" : "failed";
|
|
28317
28382
|
};
|
|
28383
|
+
var servicesHoldOf = (session, currentAgent, liveServices) => servicesHoldLine({
|
|
28384
|
+
agentLive: agentIsLive(session, currentAgent),
|
|
28385
|
+
agentOutcome: agentOutcome(currentAgent),
|
|
28386
|
+
liveServices
|
|
28387
|
+
});
|
|
28318
28388
|
var normalizeRemoteUrl = (raw) => {
|
|
28319
28389
|
if (raw === null) return null;
|
|
28320
28390
|
const trimmed = raw.trim();
|
|
@@ -28454,6 +28524,9 @@ export {
|
|
|
28454
28524
|
narrowCredential,
|
|
28455
28525
|
claudeGrantFacts,
|
|
28456
28526
|
sameGrant,
|
|
28527
|
+
normalizeGitAuthor,
|
|
28528
|
+
gitAuthorIssue,
|
|
28529
|
+
servicesHoldLine,
|
|
28457
28530
|
HARNESS_COMMANDS,
|
|
28458
28531
|
pendingId,
|
|
28459
28532
|
isPendingId,
|
|
@@ -28463,6 +28536,7 @@ export {
|
|
|
28463
28536
|
LIVE_STATUSES,
|
|
28464
28537
|
agentIsLive,
|
|
28465
28538
|
agentOutcome,
|
|
28539
|
+
servicesHoldOf,
|
|
28466
28540
|
normalizeRemoteUrl,
|
|
28467
28541
|
matchProjectByCwd,
|
|
28468
28542
|
cwdFacts,
|
|
@@ -2,6 +2,8 @@ import {
|
|
|
2
2
|
HARNESS_COMMANDS,
|
|
3
3
|
LIVE_STATUSES,
|
|
4
4
|
RepositoryCloneUrl,
|
|
5
|
+
agentIsLive,
|
|
6
|
+
agentOutcome,
|
|
5
7
|
createSseParser,
|
|
6
8
|
cwdFacts,
|
|
7
9
|
eventFamilies,
|
|
@@ -9,8 +11,9 @@ import {
|
|
|
9
11
|
matchProjectByCwd,
|
|
10
12
|
normalizeProjectName,
|
|
11
13
|
pendingId,
|
|
12
|
-
repositoryCloneUrlIssue
|
|
13
|
-
|
|
14
|
+
repositoryCloneUrlIssue,
|
|
15
|
+
servicesHoldLine
|
|
16
|
+
} from "./chunk-J3TR4UAG.js";
|
|
14
17
|
|
|
15
18
|
// src/dashboard.tsx
|
|
16
19
|
import { CliRenderEvents, createCliRenderer } from "@opentui/core";
|
|
@@ -267,17 +270,31 @@ var createLaunchGate = () => {
|
|
|
267
270
|
var markSessionStopped = (data, sessionId) => {
|
|
268
271
|
const processesBySession = new Map(data.processesBySession);
|
|
269
272
|
processesBySession.delete(sessionId);
|
|
270
|
-
const servicesBySession = new Map(data.servicesBySession);
|
|
271
|
-
servicesBySession.delete(sessionId);
|
|
272
273
|
return {
|
|
273
274
|
...mapWorkbenchSessions(
|
|
274
275
|
data,
|
|
275
276
|
(session) => session.id === sessionId ? { ...session, status: "stopped" } : session
|
|
276
277
|
),
|
|
277
|
-
processesBySession
|
|
278
|
-
servicesBySession
|
|
278
|
+
processesBySession
|
|
279
279
|
};
|
|
280
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
|
+
};
|
|
281
298
|
var removeWorktreeGroup = (data, projectId, group) => {
|
|
282
299
|
const memberIds = new Set(group.sessions.map((item) => item.session.id));
|
|
283
300
|
const detail = data.details.get(projectId);
|
|
@@ -995,6 +1012,7 @@ var stateColor = (state) => state === "draft" || state === "open" ? INK : state
|
|
|
995
1012
|
var anchorOf = (comment) => comment.file === null ? "change" : `${comment.file}${comment.line === null ? "" : `:${comment.line}${comment.endLine === null || comment.endLine === comment.line ? "" : `-${comment.endLine}`}`}`;
|
|
996
1013
|
var passFact = (pass) => {
|
|
997
1014
|
const label = pass.kind === "suggest" ? "suggestions" : pass.kind;
|
|
1015
|
+
if (pass.status === "queued") return { text: `${label} queued`, color: MUTED };
|
|
998
1016
|
if (pass.status === "running") return { text: `${label} running`, color: INK_2 };
|
|
999
1017
|
if (pass.status === "failed") return { text: `${label} failed`, color: ERROR };
|
|
1000
1018
|
return {
|
|
@@ -2257,13 +2275,15 @@ var SessionRow = ({
|
|
|
2257
2275
|
const shells = processes.filter((process2) => process2.kind === "shell").length;
|
|
2258
2276
|
const nameWidth = Math.max(6, width - 5 - status.length);
|
|
2259
2277
|
const factWidth = Math.max(8, width - 3);
|
|
2278
|
+
const hold = sessionHold(item);
|
|
2260
2279
|
const facts = fitHints(
|
|
2261
2280
|
[
|
|
2281
|
+
...hold === null ? [] : [hold],
|
|
2262
2282
|
session.harness,
|
|
2263
2283
|
shortAge(session.createdAt),
|
|
2264
2284
|
...shells > 0 ? [`${shells} shell`] : [],
|
|
2265
2285
|
...agents > 0 ? [`${agents} agent`] : [],
|
|
2266
|
-
...services.length > 0 ? [`${services.length} service`] : []
|
|
2286
|
+
...hold === null && services.length > 0 ? [`${services.length} service`] : []
|
|
2267
2287
|
],
|
|
2268
2288
|
factWidth
|
|
2269
2289
|
);
|
|
@@ -2315,6 +2335,7 @@ var SessionFacts = ({
|
|
|
2315
2335
|
}) => {
|
|
2316
2336
|
const { session, annotation, services } = item;
|
|
2317
2337
|
const color = STATUS_COLOR[session.status] ?? MUTED;
|
|
2338
|
+
const hold = sessionHold(item);
|
|
2318
2339
|
const summary = session.summary?.split("\n")[0] ?? null;
|
|
2319
2340
|
const change = annotation ?? group?.annotation;
|
|
2320
2341
|
const lines = [
|
|
@@ -2326,6 +2347,10 @@ var SessionFacts = ({
|
|
|
2326
2347
|
/* @__PURE__ */ jsxs3("text", { height: 1, bg: "transparent", children: [
|
|
2327
2348
|
/* @__PURE__ */ jsx3("span", { children: " " }),
|
|
2328
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
|
+
] }),
|
|
2329
2354
|
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: " \xB7 " }),
|
|
2330
2355
|
/* @__PURE__ */ jsx3("span", { fg: MUTED, children: session.branch }),
|
|
2331
2356
|
/* @__PURE__ */ jsx3("span", { fg: FAINT, children: session.baseSha === "" ? "" : ` vs ${session.baseRef ?? session.baseSha.slice(0, 12)}` })
|
|
@@ -2779,6 +2804,23 @@ ${tunneled}
|
|
|
2779
2804
|
},
|
|
2780
2805
|
onSettled: settleRefetch
|
|
2781
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
|
+
});
|
|
2782
2824
|
const stopMutation = useMutation2({
|
|
2783
2825
|
mutationFn: (session) => ctx.api("POST", `/sessions/${session.id}/stop`),
|
|
2784
2826
|
onMutate: async (session) => {
|
|
@@ -2943,6 +2985,17 @@ ${tunneled}
|
|
|
2943
2985
|
}
|
|
2944
2986
|
const session = selectedSession;
|
|
2945
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
|
+
}
|
|
2946
2999
|
if (!LIVE_STATUSES.has(session.status)) {
|
|
2947
3000
|
say("nothing to stop \u2014 the session is settled");
|
|
2948
3001
|
return;
|