@sealant/mend 0.29.2 → 0.30.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-BMFB2UN7.js} +410 -64
- package/dist/{dashboard-AREQGMNK.js → dashboard-OF5UXII2.js} +452 -228
- package/dist/main.js +1688 -825
- 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-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 +41 -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 +1 -1
- package/man/mend-ui.1 +8 -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 +14 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -137,6 +137,9 @@ mend resume [session-id] [--with h] rejoin a settled session (state restored;
|
|
|
137
137
|
mend rejoin [session-id] [--harness h] attach if live, otherwise resume; newest live wins
|
|
138
138
|
mend sessions [--all] [--project p] [--json]
|
|
139
139
|
mend status active sessions (alias of mend sessions)
|
|
140
|
+
mend land <session> [--branch b] [--no-pr] [--title t]
|
|
141
|
+
push the change to origin, open or update its pull request
|
|
142
|
+
mend pull <session> [--force] fetch the change into this clone as mend/<name>
|
|
140
143
|
mend pair [--url <base url>] pair a phone or a second machine: QR + code + URL
|
|
141
144
|
mend doctor read-only checklist of this machine's setup
|
|
142
145
|
mend skills [--project [p]] your skill library on the server (or a project's)
|
|
@@ -4,64 +4,6 @@ var __export = (target, all3) => {
|
|
|
4
4
|
__defProp(target, name, { get: all3[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// ../../packages/domain/src/workbench/connected-credential.ts
|
|
8
|
-
var CLAUDE_GRANT_SECTION = "claudeAiOauth";
|
|
9
|
-
var narrowCredential = (provider, secret) => {
|
|
10
|
-
if (provider !== "claude") return { kind: "unchanged", secret };
|
|
11
|
-
const parsed = parseDocument(secret);
|
|
12
|
-
if (parsed === null) return { kind: "unchanged", secret };
|
|
13
|
-
const grant = parsed[CLAUDE_GRANT_SECTION];
|
|
14
|
-
if (grant === void 0) return { kind: "unchanged", secret };
|
|
15
|
-
const dropped = Object.keys(parsed).filter((key) => key !== CLAUDE_GRANT_SECTION).toSorted();
|
|
16
|
-
return {
|
|
17
|
-
kind: "narrowed",
|
|
18
|
-
// Two spaces and a trailing newline: the shape Claude Code writes, so a round trip through
|
|
19
|
-
// Mend leaves a file a person can still read.
|
|
20
|
-
secret: `${JSON.stringify({ [CLAUDE_GRANT_SECTION]: grant }, null, 2)}
|
|
21
|
-
`,
|
|
22
|
-
dropped
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
var parseDocument = (secret) => {
|
|
26
|
-
const trimmed = secret.trim();
|
|
27
|
-
if (!trimmed.startsWith("{")) return null;
|
|
28
|
-
try {
|
|
29
|
-
const value3 = JSON.parse(trimmed);
|
|
30
|
-
return typeof value3 === "object" && value3 !== null && !Array.isArray(value3) ? value3 : null;
|
|
31
|
-
} catch {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
var claudeGrantFacts = (secret) => {
|
|
36
|
-
const parsed = parseDocument(secret);
|
|
37
|
-
const grant = parsed?.[CLAUDE_GRANT_SECTION];
|
|
38
|
-
if (typeof grant !== "object" || grant === null) return null;
|
|
39
|
-
const record3 = { ...grant };
|
|
40
|
-
const refreshToken = record3["refreshToken"];
|
|
41
|
-
return {
|
|
42
|
-
accessExpiresAt: asDate(record3["expiresAt"]),
|
|
43
|
-
refreshExpiresAt: asDate(record3["refreshTokenExpiresAt"]),
|
|
44
|
-
subscriptionType: typeof record3["subscriptionType"] === "string" ? record3["subscriptionType"] : null,
|
|
45
|
-
hasRefreshToken: typeof refreshToken === "string" && refreshToken !== ""
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
var asDate = (value3) => {
|
|
49
|
-
if (typeof value3 !== "number" || !Number.isFinite(value3) || value3 <= 0) return null;
|
|
50
|
-
const date2 = new Date(value3);
|
|
51
|
-
return Number.isNaN(date2.getTime()) ? null : date2;
|
|
52
|
-
};
|
|
53
|
-
var sameGrant = (left, right) => {
|
|
54
|
-
const token = (secret) => {
|
|
55
|
-
const grant = parseDocument(secret)?.[CLAUDE_GRANT_SECTION];
|
|
56
|
-
if (typeof grant !== "object" || grant === null) return null;
|
|
57
|
-
const value3 = grant["refreshToken"];
|
|
58
|
-
return typeof value3 === "string" && value3 !== "" ? value3 : null;
|
|
59
|
-
};
|
|
60
|
-
const a = token(left);
|
|
61
|
-
const b = token(right);
|
|
62
|
-
return a !== null && b !== null && a === b;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
7
|
// ../../node_modules/.pnpm/effect@4.0.0-beta.93/node_modules/effect/dist/Pipeable.js
|
|
66
8
|
var pipeArguments = (self, args2) => {
|
|
67
9
|
switch (args2.length) {
|
|
@@ -26499,10 +26441,12 @@ var InvitationId = Schema_exports.String.pipe(Schema_exports.brand("InvitationId
|
|
|
26499
26441
|
var FolderId = Schema_exports.String.pipe(Schema_exports.brand("FolderId"));
|
|
26500
26442
|
var AuditEventId = Schema_exports.String.pipe(Schema_exports.brand("AuditEventId"));
|
|
26501
26443
|
var SessionControlEventId = Schema_exports.String.pipe(Schema_exports.brand("SessionControlEventId"));
|
|
26444
|
+
var ChangeLandingId = Schema_exports.String.pipe(Schema_exports.brand("ChangeLandingId"));
|
|
26502
26445
|
|
|
26503
26446
|
// ../../packages/domain/src/settings.ts
|
|
26504
26447
|
var PrMode = Schema_exports.Literals(["draft-immediately", "pr-on-approval"]);
|
|
26505
26448
|
var onByDefault = Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(true)));
|
|
26449
|
+
var offByDefault = Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(false)));
|
|
26506
26450
|
var WorkspaceImageOs = Schema_exports.Literals(["fedora", "arch", "nix", "ubuntu"]);
|
|
26507
26451
|
var DEFAULT_WORKSPACE_PACKAGES = [
|
|
26508
26452
|
"pnpm",
|
|
@@ -26598,6 +26542,12 @@ var MendSettings = class extends Schema_exports.Class("MendSettings")({
|
|
|
26598
26542
|
autoSuggest: onByDefault,
|
|
26599
26543
|
/** Name the session from its first prompt — a label appears in lists while it still runs. */
|
|
26600
26544
|
autoName: onByDefault,
|
|
26545
|
+
/**
|
|
26546
|
+
* Land the change when a turn completes (docs/adr/0007-landing.md, "Automatic landing"): push
|
|
26547
|
+
* the branch and open or update its pull request. Off by default for sessions people run
|
|
26548
|
+
* themselves; Slack sessions follow the Slack app's own setting instead.
|
|
26549
|
+
*/
|
|
26550
|
+
autoLand: offByDefault,
|
|
26601
26551
|
/** Base operating system and additional tools baked into every new session workspace. */
|
|
26602
26552
|
workspaceImage: workspaceImageWithDefault,
|
|
26603
26553
|
/**
|
|
@@ -26615,6 +26565,7 @@ var defaultSettings = new MendSettings({
|
|
|
26615
26565
|
autoTour: true,
|
|
26616
26566
|
autoSuggest: true,
|
|
26617
26567
|
autoName: true,
|
|
26568
|
+
autoLand: false,
|
|
26618
26569
|
workspaceImage: defaultWorkspaceImage,
|
|
26619
26570
|
backgroundSessions: true
|
|
26620
26571
|
});
|
|
@@ -26726,6 +26677,13 @@ var Project = class extends Schema_exports.Class("Project")({
|
|
|
26726
26677
|
autoSuggest: AutomationChoice,
|
|
26727
26678
|
/** Override of the Settings default: name the session from its first prompt. */
|
|
26728
26679
|
autoName: AutomationChoice,
|
|
26680
|
+
/**
|
|
26681
|
+
* Override of the Settings default: land the change when a turn completes (docs/adr/0007). `off`
|
|
26682
|
+
* also stops sessions started from Slack.
|
|
26683
|
+
*/
|
|
26684
|
+
autoLand: AutomationChoice.pipe(
|
|
26685
|
+
Schema_exports.withDecodingDefaultKey(Effect_exports.succeed("inherit"))
|
|
26686
|
+
),
|
|
26729
26687
|
/**
|
|
26730
26688
|
* Override of the Settings default: sessions keep running when every client
|
|
26731
26689
|
* disconnects. Resolved by the launching CLI (flag → project → settings) —
|
|
@@ -26767,6 +26725,64 @@ var Project = class extends Schema_exports.Class("Project")({
|
|
|
26767
26725
|
}) {
|
|
26768
26726
|
};
|
|
26769
26727
|
|
|
26728
|
+
// ../../packages/domain/src/workbench/connected-credential.ts
|
|
26729
|
+
var CLAUDE_GRANT_SECTION = "claudeAiOauth";
|
|
26730
|
+
var narrowCredential = (provider, secret) => {
|
|
26731
|
+
if (provider !== "claude") return { kind: "unchanged", secret };
|
|
26732
|
+
const parsed = parseDocument(secret);
|
|
26733
|
+
if (parsed === null) return { kind: "unchanged", secret };
|
|
26734
|
+
const grant = parsed[CLAUDE_GRANT_SECTION];
|
|
26735
|
+
if (grant === void 0) return { kind: "unchanged", secret };
|
|
26736
|
+
const dropped = Object.keys(parsed).filter((key) => key !== CLAUDE_GRANT_SECTION).toSorted();
|
|
26737
|
+
return {
|
|
26738
|
+
kind: "narrowed",
|
|
26739
|
+
// Two spaces and a trailing newline: the shape Claude Code writes, so a round trip through
|
|
26740
|
+
// Mend leaves a file a person can still read.
|
|
26741
|
+
secret: `${JSON.stringify({ [CLAUDE_GRANT_SECTION]: grant }, null, 2)}
|
|
26742
|
+
`,
|
|
26743
|
+
dropped
|
|
26744
|
+
};
|
|
26745
|
+
};
|
|
26746
|
+
var parseDocument = (secret) => {
|
|
26747
|
+
const trimmed = secret.trim();
|
|
26748
|
+
if (!trimmed.startsWith("{")) return null;
|
|
26749
|
+
try {
|
|
26750
|
+
const value3 = JSON.parse(trimmed);
|
|
26751
|
+
return typeof value3 === "object" && value3 !== null && !Array.isArray(value3) ? value3 : null;
|
|
26752
|
+
} catch {
|
|
26753
|
+
return null;
|
|
26754
|
+
}
|
|
26755
|
+
};
|
|
26756
|
+
var claudeGrantFacts = (secret) => {
|
|
26757
|
+
const parsed = parseDocument(secret);
|
|
26758
|
+
const grant = parsed?.[CLAUDE_GRANT_SECTION];
|
|
26759
|
+
if (typeof grant !== "object" || grant === null) return null;
|
|
26760
|
+
const record3 = { ...grant };
|
|
26761
|
+
const refreshToken = record3["refreshToken"];
|
|
26762
|
+
return {
|
|
26763
|
+
accessExpiresAt: asDate(record3["expiresAt"]),
|
|
26764
|
+
refreshExpiresAt: asDate(record3["refreshTokenExpiresAt"]),
|
|
26765
|
+
subscriptionType: typeof record3["subscriptionType"] === "string" ? record3["subscriptionType"] : null,
|
|
26766
|
+
hasRefreshToken: typeof refreshToken === "string" && refreshToken !== ""
|
|
26767
|
+
};
|
|
26768
|
+
};
|
|
26769
|
+
var asDate = (value3) => {
|
|
26770
|
+
if (typeof value3 !== "number" || !Number.isFinite(value3) || value3 <= 0) return null;
|
|
26771
|
+
const date2 = new Date(value3);
|
|
26772
|
+
return Number.isNaN(date2.getTime()) ? null : date2;
|
|
26773
|
+
};
|
|
26774
|
+
var sameGrant = (left, right) => {
|
|
26775
|
+
const token = (secret) => {
|
|
26776
|
+
const grant = parseDocument(secret)?.[CLAUDE_GRANT_SECTION];
|
|
26777
|
+
if (typeof grant !== "object" || grant === null) return null;
|
|
26778
|
+
const value3 = grant["refreshToken"];
|
|
26779
|
+
return typeof value3 === "string" && value3 !== "" ? value3 : null;
|
|
26780
|
+
};
|
|
26781
|
+
const a = token(left);
|
|
26782
|
+
const b = token(right);
|
|
26783
|
+
return a !== null && b !== null && a === b;
|
|
26784
|
+
};
|
|
26785
|
+
|
|
26770
26786
|
// ../../packages/domain/src/workbench/audit.ts
|
|
26771
26787
|
var AuditAction = Schema_exports.Literals([
|
|
26772
26788
|
"invitation.created",
|
|
@@ -26786,7 +26802,22 @@ var AuditAction = Schema_exports.Literals([
|
|
|
26786
26802
|
"organization.created",
|
|
26787
26803
|
"organization.renamed",
|
|
26788
26804
|
"recovery.owner_granted",
|
|
26789
|
-
"recovery.password_reset_issued"
|
|
26805
|
+
"recovery.password_reset_issued",
|
|
26806
|
+
// docs/adr/0006-slack.md, "Audit".
|
|
26807
|
+
"slack.installed",
|
|
26808
|
+
"slack.replaced",
|
|
26809
|
+
"slack.removed",
|
|
26810
|
+
"slack.settings_changed",
|
|
26811
|
+
"slack.link_created",
|
|
26812
|
+
"slack.link_removed",
|
|
26813
|
+
"slack.session_started",
|
|
26814
|
+
"slack.channel_default_set",
|
|
26815
|
+
"slack.channel_default_cleared",
|
|
26816
|
+
// docs/adr/0007-landing.md, "What Mend records and shows": the owner's credentials pushed, and
|
|
26817
|
+
// `gh` spoke as them.
|
|
26818
|
+
"change.landed",
|
|
26819
|
+
"change.pull_request_refreshed",
|
|
26820
|
+
"change.bundle_downloaded"
|
|
26790
26821
|
]);
|
|
26791
26822
|
var AuditData = Schema_exports.Record(
|
|
26792
26823
|
Schema_exports.String,
|
|
@@ -26798,7 +26829,10 @@ var AuditEvent = class extends Schema_exports.Class("AuditEvent")({
|
|
|
26798
26829
|
/** The account that acted. */
|
|
26799
26830
|
actorUserId: Schema_exports.String,
|
|
26800
26831
|
action: AuditAction,
|
|
26801
|
-
/**
|
|
26832
|
+
/**
|
|
26833
|
+
* What the action touched: `member`, `invitation`, `project`, `session`, `folder`, `reference`,
|
|
26834
|
+
* `slack` (the organization's Slack app) or `change` (a landing).
|
|
26835
|
+
*/
|
|
26802
26836
|
subjectType: Schema_exports.String,
|
|
26803
26837
|
subjectId: Schema_exports.String,
|
|
26804
26838
|
data: AuditData,
|
|
@@ -26806,6 +26840,142 @@ var AuditEvent = class extends Schema_exports.Class("AuditEvent")({
|
|
|
26806
26840
|
}) {
|
|
26807
26841
|
};
|
|
26808
26842
|
|
|
26843
|
+
// ../../packages/domain/src/workbench/landing.ts
|
|
26844
|
+
var LandingTrigger = Schema_exports.Literals(["manual", "automatic"]);
|
|
26845
|
+
var LandingOutcome = Schema_exports.Literals(["pushed", "pull-request", "refused", "failed"]);
|
|
26846
|
+
var PullRequestState = Schema_exports.Literals(["open", "closed", "merged"]);
|
|
26847
|
+
var LandedPullRequest = Schema_exports.Struct({
|
|
26848
|
+
number: Schema_exports.Int,
|
|
26849
|
+
url: Schema_exports.String,
|
|
26850
|
+
state: PullRequestState,
|
|
26851
|
+
observedAt: Timestamp
|
|
26852
|
+
});
|
|
26853
|
+
var ChangeLanding = class extends Schema_exports.Class("ChangeLanding")({
|
|
26854
|
+
id: ChangeLandingId,
|
|
26855
|
+
changeId: ChangeId,
|
|
26856
|
+
/** The session that landed; null once that session is deleted. */
|
|
26857
|
+
sessionId: Schema_exports.NullOr(SessionId),
|
|
26858
|
+
projectId: ProjectId,
|
|
26859
|
+
/** The landed checkpoint; null when it was since removed, or never taken. */
|
|
26860
|
+
checkpointId: Schema_exports.NullOr(CheckpointId),
|
|
26861
|
+
checkpointRef: Schema_exports.NullOr(Schema_exports.String),
|
|
26862
|
+
checkpointSha: Schema_exports.NullOr(Sha),
|
|
26863
|
+
/** The commit Mend wrote for work the agent left uncommitted; null when it wrote none. */
|
|
26864
|
+
commitSha: Schema_exports.NullOr(Sha),
|
|
26865
|
+
/** The branch on origin, `mend/<name>` unless the owner named another. */
|
|
26866
|
+
remoteBranch: Schema_exports.String,
|
|
26867
|
+
/** What origin's branch was moved to; null when nothing was pushed. */
|
|
26868
|
+
pushedSha: Schema_exports.NullOr(Sha),
|
|
26869
|
+
trigger: LandingTrigger,
|
|
26870
|
+
pullRequest: Schema_exports.NullOr(LandedPullRequest),
|
|
26871
|
+
outcome: LandingOutcome,
|
|
26872
|
+
/** The remote's or `gh`'s own words for a refusal or a failure; null otherwise. */
|
|
26873
|
+
message: Schema_exports.NullOr(Schema_exports.String),
|
|
26874
|
+
/** The change's owner (`changeOwnerOf`), whose key pushed and who speaks on GitHub. */
|
|
26875
|
+
userId: Schema_exports.String,
|
|
26876
|
+
createdAt: Timestamp
|
|
26877
|
+
}) {
|
|
26878
|
+
};
|
|
26879
|
+
var RequestIntent = Schema_exports.Literals(["change", "question"]);
|
|
26880
|
+
var RequestIntentSource = Schema_exports.Literals(["read", "option", "unread"]);
|
|
26881
|
+
var RequestIntentReading = Schema_exports.Union([
|
|
26882
|
+
Schema_exports.Struct({ intent: RequestIntent, source: Schema_exports.Literals(["read", "option"]) }),
|
|
26883
|
+
Schema_exports.Struct({ intent: Schema_exports.Null, source: Schema_exports.Literals(["unread"]) })
|
|
26884
|
+
]);
|
|
26885
|
+
var LANDING_GUARD = [
|
|
26886
|
+
"--- How this work is published ---",
|
|
26887
|
+
"Mend publishes the changes this session makes: it pushes the branch and opens or updates the pull request.",
|
|
26888
|
+
"- If the request is a question, answer it and change no files.",
|
|
26889
|
+
"- Change code only when the request asks for a change.",
|
|
26890
|
+
"- Never push and never open a pull request. Committing is fine.",
|
|
26891
|
+
"--- End of how this work is published ---"
|
|
26892
|
+
].join("\n");
|
|
26893
|
+
var NotLandedReason = Schema_exports.Literals([
|
|
26894
|
+
/** The request read as a question. */
|
|
26895
|
+
"question",
|
|
26896
|
+
/** The request said `autopr=false`. */
|
|
26897
|
+
"option",
|
|
26898
|
+
/** Automatic landing is off for the session. */
|
|
26899
|
+
"off",
|
|
26900
|
+
/** Someone other than the owner sent the turn under shared control. */
|
|
26901
|
+
"not-owner"
|
|
26902
|
+
]);
|
|
26903
|
+
var TurnLanding = Schema_exports.Literals([
|
|
26904
|
+
"attempted",
|
|
26905
|
+
"question",
|
|
26906
|
+
"option",
|
|
26907
|
+
"off",
|
|
26908
|
+
"not-owner",
|
|
26909
|
+
"skipped"
|
|
26910
|
+
]);
|
|
26911
|
+
var LandingFact = Schema_exports.Union([
|
|
26912
|
+
/** A landing moved origin's branch to this sha. */
|
|
26913
|
+
Schema_exports.TaggedStruct("pushed", { branch: Schema_exports.String, sha: Sha }),
|
|
26914
|
+
/** The landing's pull request, as `gh` last reported it. */
|
|
26915
|
+
Schema_exports.TaggedStruct("pull-request", {
|
|
26916
|
+
number: Schema_exports.Int,
|
|
26917
|
+
state: PullRequestState,
|
|
26918
|
+
observedAt: Timestamp
|
|
26919
|
+
}),
|
|
26920
|
+
/** A fetch found commits on origin's branch that Mend's branch does not have. */
|
|
26921
|
+
Schema_exports.TaggedStruct("origin-moved", { branch: Schema_exports.String, commits: Schema_exports.Int }),
|
|
26922
|
+
/** The worktree moved past the landed checkpoint. */
|
|
26923
|
+
Schema_exports.TaggedStruct("changed-since-landing", { files: Schema_exports.Int }),
|
|
26924
|
+
/** The latest landing's push was refused, in the remote's words. */
|
|
26925
|
+
Schema_exports.TaggedStruct("refused", { branch: Schema_exports.String, message: Schema_exports.String }),
|
|
26926
|
+
/** The latest landing failed before it pushed. */
|
|
26927
|
+
Schema_exports.TaggedStruct("failed", { message: Schema_exports.String }),
|
|
26928
|
+
/** The latest landing pushed, and its pull request step failed. */
|
|
26929
|
+
Schema_exports.TaggedStruct("pull-request-failed", { message: Schema_exports.String }),
|
|
26930
|
+
/** A push the agent made itself, through the workspace's git transport. Not a landing. */
|
|
26931
|
+
Schema_exports.TaggedStruct("agent-push", { ref: Schema_exports.String, sha: Schema_exports.NullOr(Sha) }),
|
|
26932
|
+
/** A completed turn left changes that did not land. */
|
|
26933
|
+
Schema_exports.TaggedStruct("not-landed", { reason: NotLandedReason }),
|
|
26934
|
+
/** The request's intent could not be read, so it was treated as a change. */
|
|
26935
|
+
Schema_exports.TaggedStruct("intent-not-read", {})
|
|
26936
|
+
]);
|
|
26937
|
+
var decodeWireFacts = Schema_exports.decodeUnknownSync(Schema_exports.toCodecJson(Schema_exports.Array(LandingFact)));
|
|
26938
|
+
var landingFactsFromWire = (wire) => decodeWireFacts(wire);
|
|
26939
|
+
var shortSha = (sha) => sha.slice(0, 7);
|
|
26940
|
+
var plural = (count, one, many) => `${count} ${count === 1 ? one : many}`;
|
|
26941
|
+
var observedAgo = (at, now2) => {
|
|
26942
|
+
const seconds2 = Math.max(0, Math.floor((now2.getTime() - at.getTime()) / 1e3));
|
|
26943
|
+
if (seconds2 < 60) return `${seconds2} s ago`;
|
|
26944
|
+
if (seconds2 < 3600) return `${Math.floor(seconds2 / 60)} min ago`;
|
|
26945
|
+
if (seconds2 < 86400) return `${Math.floor(seconds2 / 3600)} h ago`;
|
|
26946
|
+
return `${Math.floor(seconds2 / 86400)} d ago`;
|
|
26947
|
+
};
|
|
26948
|
+
var NOT_LANDED = {
|
|
26949
|
+
question: "the request read as a question",
|
|
26950
|
+
option: "the request said autopr=false",
|
|
26951
|
+
off: "automatic landing is off",
|
|
26952
|
+
"not-owner": "the turn was not sent by the owner"
|
|
26953
|
+
};
|
|
26954
|
+
var landingFactLine = (fact, now2) => {
|
|
26955
|
+
switch (fact._tag) {
|
|
26956
|
+
case "pushed":
|
|
26957
|
+
return `pushed \xB7 ${fact.branch} \xB7 ${shortSha(fact.sha)} \xB7 observed`;
|
|
26958
|
+
case "pull-request":
|
|
26959
|
+
return `pull request #${fact.number} \xB7 ${fact.state} \xB7 observed ${observedAgo(fact.observedAt, now2)}`;
|
|
26960
|
+
case "origin-moved":
|
|
26961
|
+
return `origin has moved \xB7 ${fact.branch} has ${plural(fact.commits, "commit", "commits")} Mend has not seen`;
|
|
26962
|
+
case "changed-since-landing":
|
|
26963
|
+
return `changed since landing \xB7 ${plural(fact.files, "file", "files")}`;
|
|
26964
|
+
case "refused":
|
|
26965
|
+
return `push refused \xB7 ${fact.branch} \xB7 ${fact.message}`;
|
|
26966
|
+
case "failed":
|
|
26967
|
+
return `landing failed \xB7 ${fact.message}`;
|
|
26968
|
+
case "pull-request-failed":
|
|
26969
|
+
return `pull request step failed \xB7 ${fact.message}`;
|
|
26970
|
+
case "agent-push":
|
|
26971
|
+
return fact.sha === null ? `deleted by the agent \xB7 ${fact.ref}` : `pushed by the agent \xB7 ${fact.ref} \xB7 ${shortSha(fact.sha)}`;
|
|
26972
|
+
case "not-landed":
|
|
26973
|
+
return `changes not landed \xB7 ${NOT_LANDED[fact.reason]}`;
|
|
26974
|
+
case "intent-not-read":
|
|
26975
|
+
return "intent not read";
|
|
26976
|
+
}
|
|
26977
|
+
};
|
|
26978
|
+
|
|
26809
26979
|
// ../../packages/domain/src/workbench/agent-protocol.ts
|
|
26810
26980
|
var AgentLaunchMode = Schema_exports.Literals(["pty", "protocol"]);
|
|
26811
26981
|
var AgentTurnStatus = Schema_exports.Literals([
|
|
@@ -26836,6 +27006,23 @@ var AgentTurn = class extends Schema_exports.Class("AgentTurn")({
|
|
|
26836
27006
|
providerTurnId: Schema_exports.NullOr(Schema_exports.String),
|
|
26837
27007
|
error: Schema_exports.NullOr(Schema_exports.String),
|
|
26838
27008
|
usage: Schema_exports.NullOr(AgentTurnUsage),
|
|
27009
|
+
/**
|
|
27010
|
+
* What the request asked for (docs/adr/0007-landing.md, "Questions do not open pull requests"):
|
|
27011
|
+
* null until Mend reads it, and null with source `unread` when it could not.
|
|
27012
|
+
*/
|
|
27013
|
+
intent: Schema_exports.NullOr(RequestIntent).pipe(Schema_exports.withConstructorDefault(Effect_exports.succeed(null))),
|
|
27014
|
+
intentSource: Schema_exports.NullOr(RequestIntentSource).pipe(
|
|
27015
|
+
Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
|
|
27016
|
+
),
|
|
27017
|
+
/**
|
|
27018
|
+
* What Mend decided about landing once the turn ended ("When a completed turn lands"): null
|
|
27019
|
+
* until it decides, or for a turn that ended before automatic landing existed.
|
|
27020
|
+
*/
|
|
27021
|
+
landing: Schema_exports.NullOr(TurnLanding).pipe(Schema_exports.withConstructorDefault(Effect_exports.succeed(null))),
|
|
27022
|
+
/** The automatic landing this turn started, when it `attempted` one and the row remains. */
|
|
27023
|
+
landingId: Schema_exports.NullOr(ChangeLandingId).pipe(
|
|
27024
|
+
Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
|
|
27025
|
+
),
|
|
26839
27026
|
createdAt: Timestamp,
|
|
26840
27027
|
startedAt: Schema_exports.NullOr(Timestamp),
|
|
26841
27028
|
endedAt: Schema_exports.NullOr(Timestamp)
|
|
@@ -27186,6 +27373,10 @@ var SessionReferenceMount = class extends Schema_exports.Class(
|
|
|
27186
27373
|
};
|
|
27187
27374
|
|
|
27188
27375
|
// ../../packages/domain/src/workbench/session.ts
|
|
27376
|
+
var SessionDotfilesNotApplied = Schema_exports.Struct({
|
|
27377
|
+
source: Schema_exports.Literals(["repository", "snapshot"]),
|
|
27378
|
+
reason: Schema_exports.String
|
|
27379
|
+
});
|
|
27189
27380
|
var SessionDotfiles = Schema_exports.Struct({
|
|
27190
27381
|
repository: Schema_exports.NullOr(
|
|
27191
27382
|
Schema_exports.Struct({
|
|
@@ -27193,7 +27384,11 @@ var SessionDotfiles = Schema_exports.Struct({
|
|
|
27193
27384
|
ref: Schema_exports.NullOr(Schema_exports.String)
|
|
27194
27385
|
})
|
|
27195
27386
|
),
|
|
27196
|
-
snapshotSha: Schema_exports.NullOr(Schema_exports.String)
|
|
27387
|
+
snapshotSha: Schema_exports.NullOr(Schema_exports.String),
|
|
27388
|
+
/** Rows stamped before this field decode as nothing left out. */
|
|
27389
|
+
notApplied: Schema_exports.Array(SessionDotfilesNotApplied).pipe(
|
|
27390
|
+
Schema_exports.withDecodingDefaultKey(Effect_exports.succeed([]))
|
|
27391
|
+
)
|
|
27197
27392
|
});
|
|
27198
27393
|
var SessionStatus = Schema_exports.Literals([
|
|
27199
27394
|
"starting",
|
|
@@ -27204,6 +27399,7 @@ var SessionStatus = Schema_exports.Literals([
|
|
|
27204
27399
|
"failed",
|
|
27205
27400
|
"stopped"
|
|
27206
27401
|
]);
|
|
27402
|
+
var SessionOrigin = Schema_exports.Literals(["mend", "slack"]);
|
|
27207
27403
|
var NativeIngestCursor = Schema_exports.Struct({
|
|
27208
27404
|
providerSessionId: Schema_exports.String,
|
|
27209
27405
|
lastEntryUuid: Schema_exports.NullOr(Schema_exports.String),
|
|
@@ -27256,6 +27452,14 @@ var Session = class extends Schema_exports.Class("Session")({
|
|
|
27256
27452
|
dotfiles: Schema_exports.NullOr(SessionDotfiles),
|
|
27257
27453
|
/** Who provisioned the session — whose dotfiles apply. Null for pre-column rows. */
|
|
27258
27454
|
ownerUserId: Schema_exports.NullOr(Schema_exports.String),
|
|
27455
|
+
/** Where it was started from (docs/adr/0006-slack.md). */
|
|
27456
|
+
origin: SessionOrigin.pipe(Schema_exports.withConstructorDefault(Effect_exports.succeed("mend"))),
|
|
27457
|
+
/**
|
|
27458
|
+
* The session's own automatic-landing override (docs/adr/0007-landing.md), set at start: the
|
|
27459
|
+
* composer's or `mend`'s `--land` / `--no-land`, or a Slack request's `autopr=`. Null follows the
|
|
27460
|
+
* project and Settings.
|
|
27461
|
+
*/
|
|
27462
|
+
autoLand: Schema_exports.NullOr(Schema_exports.Boolean).pipe(Schema_exports.withConstructorDefault(Effect_exports.succeed(null))),
|
|
27259
27463
|
/**
|
|
27260
27464
|
* Shared control (docs/adr/0003-organizations-and-tenancy.md): when set, anyone who can see the
|
|
27261
27465
|
* session may steer it, still on the owner's credentials. Who turned it on, and when.
|
|
@@ -27825,6 +28029,73 @@ var SkillWithFiles = class extends Schema_exports.Class("SkillWithFiles")({
|
|
|
27825
28029
|
var SKILL_MAX_FILE_BYTES = 512 * 1024;
|
|
27826
28030
|
var SKILL_MAX_BYTES = 2 * 1024 * 1024;
|
|
27827
28031
|
|
|
28032
|
+
// ../../packages/domain/src/workbench/slack.ts
|
|
28033
|
+
var SlackInstallSettings = Schema_exports.Struct({
|
|
28034
|
+
defaultHarness: Schema_exports.String,
|
|
28035
|
+
/** The plan, closing messages and questions, as well as status, reactions and links. */
|
|
28036
|
+
showAgentMessages: Schema_exports.Boolean,
|
|
28037
|
+
/** The diff of each changed file, as well as the file list and line counts. */
|
|
28038
|
+
showDiffs: Schema_exports.Boolean,
|
|
28039
|
+
/** Whether the two settings above also apply in Slack Connect channels. */
|
|
28040
|
+
externalChannels: Schema_exports.Boolean,
|
|
28041
|
+
/**
|
|
28042
|
+
* "Land automatically" (docs/adr/0007-landing.md): a session started from Slack pushes its
|
|
28043
|
+
* branch and opens its pull request when a turn completes. On unless an owner turned it off;
|
|
28044
|
+
* a request's `autopr=` and the project's own `off` win over it.
|
|
28045
|
+
*/
|
|
28046
|
+
landAutomatically: Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(true)))
|
|
28047
|
+
});
|
|
28048
|
+
var SlackProjectSource = Schema_exports.Literals([
|
|
28049
|
+
"message",
|
|
28050
|
+
"thread-session",
|
|
28051
|
+
"thread-link",
|
|
28052
|
+
"thread-inference",
|
|
28053
|
+
"channel-default",
|
|
28054
|
+
"personal-default",
|
|
28055
|
+
"picked"
|
|
28056
|
+
]);
|
|
28057
|
+
var SlackSessionState = Schema_exports.Literals([
|
|
28058
|
+
"starting",
|
|
28059
|
+
"running",
|
|
28060
|
+
"waiting",
|
|
28061
|
+
"completed",
|
|
28062
|
+
"failed",
|
|
28063
|
+
"stopped"
|
|
28064
|
+
]);
|
|
28065
|
+
var SlackPendingFile = Schema_exports.Struct({
|
|
28066
|
+
id: Schema_exports.String,
|
|
28067
|
+
name: Schema_exports.NullOr(Schema_exports.String),
|
|
28068
|
+
mimetype: Schema_exports.NullOr(Schema_exports.String),
|
|
28069
|
+
urlPrivate: Schema_exports.NullOr(Schema_exports.String),
|
|
28070
|
+
size: Schema_exports.NullOr(Schema_exports.Number)
|
|
28071
|
+
});
|
|
28072
|
+
var SlackPendingMention = Schema_exports.Struct({
|
|
28073
|
+
channelId: Schema_exports.String,
|
|
28074
|
+
/** The mention itself: the message Mend reacts to. */
|
|
28075
|
+
messageTs: Schema_exports.String,
|
|
28076
|
+
/** The thread it was written in; null when the mention is the thread's first message. */
|
|
28077
|
+
threadTs: Schema_exports.NullOr(Schema_exports.String),
|
|
28078
|
+
text: Schema_exports.String,
|
|
28079
|
+
/**
|
|
28080
|
+
* Whether the channel is a Slack Connect channel, as the event said. Absent on codes minted
|
|
28081
|
+
* before Mend recorded it, which the reporter treats as external.
|
|
28082
|
+
*/
|
|
28083
|
+
external: Schema_exports.optional(Schema_exports.Boolean),
|
|
28084
|
+
/** The files on the mention itself. Absent on codes minted before Mend recorded them. */
|
|
28085
|
+
files: Schema_exports.optional(Schema_exports.Array(SlackPendingFile))
|
|
28086
|
+
});
|
|
28087
|
+
var SlackLinkedMentionJob = Schema_exports.Struct({
|
|
28088
|
+
organizationId: OrganizationId,
|
|
28089
|
+
teamId: Schema_exports.String,
|
|
28090
|
+
/** The mention's author in Slack. */
|
|
28091
|
+
slackUserId: Schema_exports.String,
|
|
28092
|
+
/** The Mend account they linked, the session's owner. */
|
|
28093
|
+
userId: Schema_exports.String,
|
|
28094
|
+
request: SlackPendingMention,
|
|
28095
|
+
/** ISO time of the link, so the runner can leave a stale request alone. */
|
|
28096
|
+
linkedAt: Schema_exports.String
|
|
28097
|
+
});
|
|
28098
|
+
|
|
27828
28099
|
// ../../packages/domain/src/workbench/tour.ts
|
|
27829
28100
|
var TourStop = class extends Schema_exports.Class("TourStop")({
|
|
27830
28101
|
title: Schema_exports.String,
|
|
@@ -27907,6 +28178,8 @@ var LAUNCH_ERROR = {
|
|
|
27907
28178
|
fast: false,
|
|
27908
28179
|
detach: false,
|
|
27909
28180
|
foreground: false,
|
|
28181
|
+
noTunnel: false,
|
|
28182
|
+
autoLand: null,
|
|
27910
28183
|
custom: []
|
|
27911
28184
|
};
|
|
27912
28185
|
var parseLaunchArgs = (args2) => {
|
|
@@ -27924,6 +28197,9 @@ var parseLaunchArgs = (args2) => {
|
|
|
27924
28197
|
let fast = false;
|
|
27925
28198
|
let detach = false;
|
|
27926
28199
|
let foreground = false;
|
|
28200
|
+
let noTunnel = false;
|
|
28201
|
+
let land = false;
|
|
28202
|
+
let noLand = false;
|
|
27927
28203
|
for (let index2 = 0; index2 < flagArgs.length; index2 += 1) {
|
|
27928
28204
|
const arg = flagArgs[index2] ?? "";
|
|
27929
28205
|
if (arg === "--ask") {
|
|
@@ -27942,6 +28218,18 @@ var parseLaunchArgs = (args2) => {
|
|
|
27942
28218
|
foreground = true;
|
|
27943
28219
|
continue;
|
|
27944
28220
|
}
|
|
28221
|
+
if (arg === "--no-tunnel") {
|
|
28222
|
+
noTunnel = true;
|
|
28223
|
+
continue;
|
|
28224
|
+
}
|
|
28225
|
+
if (arg === "--land") {
|
|
28226
|
+
land = true;
|
|
28227
|
+
continue;
|
|
28228
|
+
}
|
|
28229
|
+
if (arg === "--no-land") {
|
|
28230
|
+
noLand = true;
|
|
28231
|
+
continue;
|
|
28232
|
+
}
|
|
27945
28233
|
if (arg === "--project" || arg === "--model" || arg === "--effort" || arg === "--base" || arg === "--name" || arg === "--worktree") {
|
|
27946
28234
|
const value3 = flagArgs[index2 + 1];
|
|
27947
28235
|
if (value3 === void 0) return { ...LAUNCH_ERROR, error: `${arg} needs a value` };
|
|
@@ -27974,6 +28262,9 @@ var parseLaunchArgs = (args2) => {
|
|
|
27974
28262
|
if (detach && foreground) {
|
|
27975
28263
|
return { ...LAUNCH_ERROR, error: "--detach and --foreground contradict \u2014 pick one" };
|
|
27976
28264
|
}
|
|
28265
|
+
if (land && noLand) {
|
|
28266
|
+
return { ...LAUNCH_ERROR, error: "--land and --no-land contradict \u2014 pick one" };
|
|
28267
|
+
}
|
|
27977
28268
|
if (workName !== null && joinWorktree !== null) {
|
|
27978
28269
|
return {
|
|
27979
28270
|
...LAUNCH_ERROR,
|
|
@@ -27992,6 +28283,8 @@ var parseLaunchArgs = (args2) => {
|
|
|
27992
28283
|
fast,
|
|
27993
28284
|
detach,
|
|
27994
28285
|
foreground,
|
|
28286
|
+
noTunnel,
|
|
28287
|
+
autoLand: land ? true : noLand ? false : null,
|
|
27995
28288
|
custom,
|
|
27996
28289
|
error: null
|
|
27997
28290
|
};
|
|
@@ -28105,12 +28398,62 @@ var trackBracketedPaste = (output, current) => {
|
|
|
28105
28398
|
};
|
|
28106
28399
|
var pasteBytes = (text, bracketed) => Buffer.from(bracketed ? `\x1B[200~${text}\x1B[201~` : text, "utf8");
|
|
28107
28400
|
|
|
28401
|
+
// src/workbench-events.ts
|
|
28402
|
+
var createSseParser = () => {
|
|
28403
|
+
let buffer = "";
|
|
28404
|
+
return {
|
|
28405
|
+
push: (chunk) => {
|
|
28406
|
+
buffer += chunk;
|
|
28407
|
+
const payloads = [];
|
|
28408
|
+
for (; ; ) {
|
|
28409
|
+
const boundary = buffer.indexOf("\n\n");
|
|
28410
|
+
if (boundary === -1) break;
|
|
28411
|
+
const frame = buffer.slice(0, boundary);
|
|
28412
|
+
buffer = buffer.slice(boundary + 2);
|
|
28413
|
+
const data = frame.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice("data:".length).replace(/^ /, "")).join("\n");
|
|
28414
|
+
if (data !== "") payloads.push(data);
|
|
28415
|
+
}
|
|
28416
|
+
return payloads;
|
|
28417
|
+
}
|
|
28418
|
+
};
|
|
28419
|
+
};
|
|
28420
|
+
var eventFamilies = (payload) => {
|
|
28421
|
+
let parsed;
|
|
28422
|
+
try {
|
|
28423
|
+
parsed = JSON.parse(payload);
|
|
28424
|
+
} catch {
|
|
28425
|
+
return [];
|
|
28426
|
+
}
|
|
28427
|
+
if (typeof parsed !== "object" || parsed === null || !("type" in parsed)) return [];
|
|
28428
|
+
switch (parsed.type) {
|
|
28429
|
+
case "project":
|
|
28430
|
+
case "worktree":
|
|
28431
|
+
case "session-process":
|
|
28432
|
+
return ["workbench"];
|
|
28433
|
+
// Settlement refreshes the final transcript immediately. Conversation
|
|
28434
|
+
// items can arrive many times per second; the live preview's bounded
|
|
28435
|
+
// polling reads those instead of repeatedly fetching the whole record.
|
|
28436
|
+
case "session":
|
|
28437
|
+
return ["workbench", "review", "transcript"];
|
|
28438
|
+
case "agent-conversation":
|
|
28439
|
+
return ["workbench", "review"];
|
|
28440
|
+
// A comment moves the review AND the dashboard's open-comment counts.
|
|
28441
|
+
case "session-change":
|
|
28442
|
+
case "review-comment":
|
|
28443
|
+
return ["workbench", "review"];
|
|
28444
|
+
default:
|
|
28445
|
+
return [];
|
|
28446
|
+
}
|
|
28447
|
+
};
|
|
28448
|
+
|
|
28108
28449
|
export {
|
|
28450
|
+
repositoryCloneUrlIssue,
|
|
28451
|
+
RepositoryCloneUrl,
|
|
28452
|
+
landingFactsFromWire,
|
|
28453
|
+
landingFactLine,
|
|
28109
28454
|
narrowCredential,
|
|
28110
28455
|
claudeGrantFacts,
|
|
28111
28456
|
sameGrant,
|
|
28112
|
-
repositoryCloneUrlIssue,
|
|
28113
|
-
RepositoryCloneUrl,
|
|
28114
28457
|
HARNESS_COMMANDS,
|
|
28115
28458
|
pendingId,
|
|
28116
28459
|
isPendingId,
|
|
@@ -28120,6 +28463,7 @@ export {
|
|
|
28120
28463
|
LIVE_STATUSES,
|
|
28121
28464
|
agentIsLive,
|
|
28122
28465
|
agentOutcome,
|
|
28466
|
+
normalizeRemoteUrl,
|
|
28123
28467
|
matchProjectByCwd,
|
|
28124
28468
|
cwdFacts,
|
|
28125
28469
|
gitCurrentBranch,
|
|
@@ -28128,5 +28472,7 @@ export {
|
|
|
28128
28472
|
normalizeProjectName,
|
|
28129
28473
|
isPasteChunk,
|
|
28130
28474
|
trackBracketedPaste,
|
|
28131
|
-
pasteBytes
|
|
28475
|
+
pasteBytes,
|
|
28476
|
+
createSseParser,
|
|
28477
|
+
eventFamilies
|
|
28132
28478
|
};
|