@sealant/mend 0.35.1 → 0.36.0-next.602

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.
Files changed (89) hide show
  1. package/dist/{chunk-SMH65F6Z.js → chunk-5MPE4D2O.js} +559 -4
  2. package/dist/{dashboard-MGR4YUFD.js → dashboard-AVABQC2T.js} +225 -98
  3. package/dist/main.js +2495 -490
  4. package/man/mend-accounts.1 +1 -1
  5. package/man/mend-adopt.1 +1 -1
  6. package/man/mend-attach.1 +1 -1
  7. package/man/mend-codex.1 +7 -7
  8. package/man/mend-completions.1 +1 -1
  9. package/man/mend-connect-pi.1 +28 -0
  10. package/man/mend-connect.1 +4 -2
  11. package/man/mend-continue.1 +1 -1
  12. package/man/mend-doctor.1 +1 -1
  13. package/man/mend-dotfiles-repo.1 +1 -1
  14. package/man/mend-dotfiles-sync.1 +1 -1
  15. package/man/mend-dotfiles.1 +1 -1
  16. package/man/mend-env-cluster.1 +1 -1
  17. package/man/mend-env-load.1 +1 -1
  18. package/man/mend-env-show.1 +1 -1
  19. package/man/mend-folder-create.1 +1 -1
  20. package/man/mend-folder-list.1 +1 -1
  21. package/man/mend-folder-push.1 +1 -1
  22. package/man/mend-folder-rm.1 +1 -1
  23. package/man/mend-git-author.1 +1 -1
  24. package/man/mend-help.1 +1 -1
  25. package/man/mend-invite.1 +1 -1
  26. package/man/mend-keys-init.1 +1 -1
  27. package/man/mend-keys-mode.1 +1 -1
  28. package/man/mend-keys-share.1 +1 -1
  29. package/man/mend-keys-show.1 +1 -1
  30. package/man/mend-land.1 +1 -1
  31. package/man/mend-login.1 +1 -1
  32. package/man/mend-logout.1 +1 -1
  33. package/man/mend-man.1 +1 -1
  34. package/man/mend-members.1 +1 -1
  35. package/man/mend-memory-import.1 +23 -0
  36. package/man/mend-memory-rm.1 +15 -0
  37. package/man/mend-memory-show.1 +15 -0
  38. package/man/mend-memory.1 +32 -0
  39. package/man/mend-models.1 +22 -0
  40. package/man/mend-operator-exposure.1 +1 -1
  41. package/man/mend-operator-gate.1 +1 -1
  42. package/man/mend-operator-grant-owner.1 +1 -1
  43. package/man/mend-operator-org-create.1 +1 -1
  44. package/man/mend-operator-org-invite-owner.1 +1 -1
  45. package/man/mend-operator-org-list.1 +1 -1
  46. package/man/mend-operator-org-rename.1 +1 -1
  47. package/man/mend-operator-reset-link.1 +1 -1
  48. package/man/mend-pair.1 +1 -1
  49. package/man/mend-projects.1 +1 -1
  50. package/man/mend-pull.1 +1 -1
  51. package/man/mend-refresh.1 +1 -1
  52. package/man/mend-rejoin.1 +1 -1
  53. package/man/mend-resume.1 +1 -1
  54. package/man/mend-run.1 +1 -1
  55. package/man/mend-secrets-add.1 +24 -0
  56. package/man/mend-secrets-rm.1 +14 -0
  57. package/man/mend-secrets.1 +18 -0
  58. package/man/mend-server-logs.1 +1 -1
  59. package/man/mend-server-restart.1 +1 -1
  60. package/man/mend-server-setup.1 +27 -3
  61. package/man/mend-server-start.1 +1 -1
  62. package/man/mend-server-status.1 +5 -3
  63. package/man/mend-server-stop.1 +3 -3
  64. package/man/mend-server-upgrade.1 +7 -2
  65. package/man/mend-server.1 +1 -1
  66. package/man/mend-service-add.1 +1 -1
  67. package/man/mend-service-connect.1 +1 -1
  68. package/man/mend-service-init.1 +1 -1
  69. package/man/mend-service-list.1 +1 -1
  70. package/man/mend-service-logs.1 +1 -1
  71. package/man/mend-service-restart.1 +1 -1
  72. package/man/mend-service-run.1 +1 -1
  73. package/man/mend-service-stop.1 +1 -1
  74. package/man/mend-session-share.1 +2 -2
  75. package/man/mend-sessions.1 +1 -1
  76. package/man/mend-shell.1 +1 -1
  77. package/man/mend-skills-push.1 +1 -1
  78. package/man/mend-skills.1 +1 -1
  79. package/man/mend-snake.1 +1 -1
  80. package/man/mend-ssh-setup.1 +1 -1
  81. package/man/mend-ssh.1 +1 -1
  82. package/man/mend-stop.1 +1 -1
  83. package/man/mend-ui.1 +1 -1
  84. package/man/mend-uninstall.1 +1 -1
  85. package/man/mend-version.1 +1 -1
  86. package/man/mend-worktrees-rm.1 +29 -0
  87. package/man/mend-worktrees.1 +2 -2
  88. package/man/mend.1 +35 -5
  89. package/package.json +19 -38
@@ -5,7 +5,7 @@ var __export = (target, all3) => {
5
5
  };
6
6
 
7
7
  // ../../packages/domain/src/workbench/harness-launch.ts
8
- var EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
8
+ var EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max", "ultra"];
9
9
  var PERMISSION_MODES = ["bypass", "ask"];
10
10
 
11
11
  // ../../packages/domain/src/workbench/agent-start.ts
@@ -26442,6 +26442,7 @@ var FollowUpId = Schema_exports.String.pipe(Schema_exports.brand("FollowUpId"));
26442
26442
  var ReferenceId = Schema_exports.String.pipe(Schema_exports.brand("ReferenceId"));
26443
26443
  var ProjectMountId = Schema_exports.String.pipe(Schema_exports.brand("ProjectMountId"));
26444
26444
  var ProjectLinkId = Schema_exports.String.pipe(Schema_exports.brand("ProjectLinkId"));
26445
+ var SessionRepositoryId = Schema_exports.String.pipe(Schema_exports.brand("SessionRepositoryId"));
26445
26446
  var SkillId = Schema_exports.String.pipe(Schema_exports.brand("SkillId"));
26446
26447
  var SessionProcessId = Schema_exports.String.pipe(Schema_exports.brand("SessionProcessId"));
26447
26448
  var AgentTurnId = Schema_exports.String.pipe(Schema_exports.brand("AgentTurnId"));
@@ -26456,6 +26457,7 @@ var ProjectEnvironmentVariableId = Schema_exports.String.pipe(
26456
26457
  );
26457
26458
  var ProjectSecretId = Schema_exports.String.pipe(Schema_exports.brand("ProjectSecretId"));
26458
26459
  var ProjectClusterBindingId = Schema_exports.String.pipe(Schema_exports.brand("ProjectClusterBindingId"));
26460
+ var SecretFileId = Schema_exports.String.pipe(Schema_exports.brand("SecretFileId"));
26459
26461
  var OrganizationId = Schema_exports.String.pipe(Schema_exports.brand("OrganizationId"));
26460
26462
  var InvitationId = Schema_exports.String.pipe(Schema_exports.brand("InvitationId"));
26461
26463
  var FolderId = Schema_exports.String.pipe(Schema_exports.brand("FolderId"));
@@ -26771,11 +26773,135 @@ var Project = class extends Schema_exports.Class("Project")({
26771
26773
  installCommand: Schema_exports.NullOr(Schema_exports.String).pipe(
26772
26774
  Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null))
26773
26775
  ),
26776
+ /**
26777
+ * "Automatic install": whether Mend runs the install command above (or the detected one) at
26778
+ * all. Off, neither a session's launch nor the install job runs one; restoring a dependency
26779
+ * tree from saved state or the shared cache is unaffected. Older values decode to on.
26780
+ */
26781
+ installEnabled: Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(true))),
26774
26782
  createdAt: Timestamp,
26775
26783
  updatedAt: Timestamp
26776
26784
  }) {
26777
26785
  };
26778
26786
 
26787
+ // ../../packages/domain/src/workbench/agent-memory.ts
26788
+ var AGENT_MEMORY_ROOTS = [
26789
+ { harness: "claude", root: ".claude/projects/-workspace-repo/memory" },
26790
+ { harness: "codex", root: ".codex/memories" },
26791
+ // Mend's own: the first line of each conversation Codex summarised on another machine
26792
+ // (`mend memory import`), so a session can list that conversation for Codex again.
26793
+ { harness: "codex", root: ".mend/codex-threads" }
26794
+ ];
26795
+ var AGENT_MEMORY_FILES = [{ harness: "codex", path: ".codex/memories_1.sqlite" }];
26796
+ var CODEX_MEMORY_DATABASE = ".codex/memories_1.sqlite";
26797
+ var AGENT_MEMORY_MAX_FILE_BYTES = 1024 * 1024;
26798
+ var AGENT_MEMORY_MAX_DATABASE_BYTES = 16 * 1024 * 1024;
26799
+ var AGENT_MEMORY_MAX_BYTES = 32 * 1024 * 1024;
26800
+ var AgentMemoryFile = class extends Schema_exports.Class("AgentMemoryFile")({
26801
+ path: Schema_exports.String,
26802
+ encoding: Schema_exports.Literals(["utf8", "base64"]),
26803
+ contents: Schema_exports.String
26804
+ }) {
26805
+ };
26806
+ var AgentMemoryEntry = class extends Schema_exports.Class("AgentMemoryEntry")({
26807
+ path: Schema_exports.String,
26808
+ /** Which harness keeps it. */
26809
+ harness: Schema_exports.String,
26810
+ /** Its path under that harness's memory root: what a person calls it. */
26811
+ name: Schema_exports.String,
26812
+ bytes: Schema_exports.Int,
26813
+ digest: Schema_exports.String,
26814
+ updatedAt: Timestamp,
26815
+ /** The session whose agent last wrote it, or null for an import. */
26816
+ updatedBySession: Schema_exports.NullOr(Schema_exports.String)
26817
+ }) {
26818
+ };
26819
+ var AgentMemoryView = class extends Schema_exports.Class("AgentMemoryView")({
26820
+ files: Schema_exports.Array(AgentMemoryEntry)
26821
+ }) {
26822
+ };
26823
+ var AgentMemoryFileView = class extends Schema_exports.Class("AgentMemoryFileView")({
26824
+ entry: AgentMemoryEntry,
26825
+ encoding: Schema_exports.Literals(["utf8", "base64"]),
26826
+ contents: Schema_exports.String
26827
+ }) {
26828
+ };
26829
+ var AgentMemoryImportSource = class extends Schema_exports.Class(
26830
+ "AgentMemoryImportSource"
26831
+ )({
26832
+ /** Stable for that checkout on that machine: the CLI's machine id and the checkout's path. */
26833
+ id: Schema_exports.String.check(Schema_exports.isMinLength(1), Schema_exports.isMaxLength(1024)),
26834
+ /** What a merge calls the machine where it has to say so: its host name. */
26835
+ label: Schema_exports.String.check(Schema_exports.isMinLength(1), Schema_exports.isMaxLength(64))
26836
+ }) {
26837
+ };
26838
+ var AgentMemoryImport = class extends Schema_exports.Class("AgentMemoryImport")({
26839
+ files: Schema_exports.Array(AgentMemoryFile),
26840
+ /** Absent from an older CLI: nothing is recorded then, and no merge has a shared version. */
26841
+ source: Schema_exports.optional(AgentMemoryImportSource)
26842
+ }) {
26843
+ };
26844
+ var AgentMemoryImportMerge = class extends Schema_exports.Class(
26845
+ "AgentMemoryImportMerge"
26846
+ )({
26847
+ path: Schema_exports.String,
26848
+ /**
26849
+ * - `last-import`: text, three-way against what this machine sent the last time;
26850
+ * - `no-shared-version`: text, both sides' lines with no version to diff against;
26851
+ * - `summaries`: Codex's summary database, each conversation's newer summary from either.
26852
+ */
26853
+ against: Schema_exports.Literals(["last-import", "no-shared-version", "summaries"]),
26854
+ /**
26855
+ * How many of this machine's lines the result does not hold (a line Mend removed since the last
26856
+ * import is not counted). When any, this machine's file is kept whole as a version, and the next
26857
+ * import from there merges it again.
26858
+ */
26859
+ missingLines: Schema_exports.Int,
26860
+ /**
26861
+ * How many of Mend's lines the result does not hold (a line this machine removed since its last
26862
+ * import is not counted). Mend's file is always kept as a version, pinned when it is the only
26863
+ * copy of a line.
26864
+ */
26865
+ storeMissingLines: Schema_exports.Int
26866
+ }) {
26867
+ };
26868
+ var AgentMemoryImported = class extends Schema_exports.Class("AgentMemoryImported")({
26869
+ /** Not in Mend: stored as this machine has it. */
26870
+ added: Schema_exports.Array(Schema_exports.String),
26871
+ /** The same on both sides. */
26872
+ unchanged: Schema_exports.Array(Schema_exports.String),
26873
+ /** Unchanged in Mend since this machine's last import: replaced by this machine's. */
26874
+ updated: Schema_exports.Array(Schema_exports.String),
26875
+ /** Changed on both sides: merged, keeping both sides' lines. */
26876
+ merged: Schema_exports.Array(AgentMemoryImportMerge),
26877
+ /** Unchanged on this machine since its last import and changed in Mend: Mend's stays. */
26878
+ keptStored: Schema_exports.Array(Schema_exports.String),
26879
+ /** Removed in Mend since this machine's last import, unchanged here: not added again. */
26880
+ removedInMend: Schema_exports.Array(Schema_exports.String),
26881
+ /**
26882
+ * Changed on both sides and not mergeable: not text, frontmatter that differs outside the subset
26883
+ * merged by key, too different to align with no earlier import, or merged over the size limit.
26884
+ * Mend's stays, this machine's is kept as a version, and the next import reports it again.
26885
+ */
26886
+ conflicting: Schema_exports.Array(Schema_exports.String),
26887
+ /** Outside the limits (path, size or count): not stored. */
26888
+ skipped: Schema_exports.Array(Schema_exports.String)
26889
+ }) {
26890
+ };
26891
+ var AgentMemoryRemoved = class extends Schema_exports.Class("AgentMemoryRemoved")({
26892
+ removed: Schema_exports.Boolean
26893
+ }) {
26894
+ };
26895
+ var agentMemoryNameOf = (filePath) => {
26896
+ for (const { harness, root } of AGENT_MEMORY_ROOTS) {
26897
+ if (filePath.startsWith(`${root}/`)) return { harness, name: filePath.slice(root.length + 1) };
26898
+ }
26899
+ for (const { harness, path: file } of AGENT_MEMORY_FILES) {
26900
+ if (filePath === file) return { harness, name: file.slice(file.lastIndexOf("/") + 1) };
26901
+ }
26902
+ return null;
26903
+ };
26904
+
26779
26905
  // ../../packages/domain/src/workbench/connected-credential.ts
26780
26906
  var CLAUDE_GRANT_SECTION = "claudeAiOauth";
26781
26907
  var narrowCredential = (provider, secret) => {
@@ -26834,6 +26960,155 @@ var sameGrant = (left, right) => {
26834
26960
  return a !== null && b !== null && a === b;
26835
26961
  };
26836
26962
 
26963
+ // ../../packages/domain/src/workbench/launch-phase.ts
26964
+ var LAUNCH_WAITING_PREFIX = "waiting \xB7 the previous session in this worktree";
26965
+ var LAUNCH_WAITING_SAVING = `${LAUNCH_WAITING_PREFIX} is saving`;
26966
+ var LAUNCH_BOOTING = "booting";
26967
+ var LAUNCH_PREPARING = "preparing the workspace \xB7 no runtime yet \xB7 after an update, building the image takes about 8 minutes";
26968
+ var LAUNCH_BUILDING_IMAGE_LEGACY = "building the workspace image (first launch after an update, ~8 min)";
26969
+ var LAUNCH_PHASE_PREFIXES = [
26970
+ LAUNCH_WAITING_PREFIX,
26971
+ LAUNCH_BOOTING,
26972
+ LAUNCH_PREPARING,
26973
+ LAUNCH_BUILDING_IMAGE_LEGACY
26974
+ ];
26975
+ var phaseWordsOf = (summary) => {
26976
+ for (const prefix of LAUNCH_PHASE_PREFIXES) {
26977
+ if (summary.startsWith(prefix)) return { at: 0, words: summary };
26978
+ const at = summary.indexOf(` \xB7 ${prefix}`);
26979
+ if (at >= 0) return { at, words: summary.slice(at + 3) };
26980
+ }
26981
+ return null;
26982
+ };
26983
+ var withoutLaunchPhase = (summary) => {
26984
+ if (summary === null) return null;
26985
+ const phase = phaseWordsOf(summary);
26986
+ if (phase === null) return summary;
26987
+ return phase.at === 0 ? null : summary.slice(0, phase.at);
26988
+ };
26989
+ var launchPhaseOf = (summary) => {
26990
+ if (summary === null) return null;
26991
+ const phase = phaseWordsOf(summary);
26992
+ if (phase === null) return null;
26993
+ if (phase.words.startsWith(LAUNCH_WAITING_PREFIX)) {
26994
+ return { kind: "waiting-previous", words: phase.words };
26995
+ }
26996
+ if (phase.words.startsWith(LAUNCH_BOOTING)) return { kind: "booting", words: phase.words };
26997
+ return { kind: "preparing", words: phase.words };
26998
+ };
26999
+
27000
+ // ../../packages/domain/src/workbench/pi-profile.ts
27001
+ var PI_PROFILE_AGENT_PATH = "mend/profile";
27002
+ var PI_PROFILE_LOCAL_PACKAGES = "packages";
27003
+ var PI_PROFILE_DIRECTORIES = ["extensions", "themes", "prompts", "packages"];
27004
+ var PI_PROFILE_FILES = [
27005
+ "settings.json",
27006
+ "package.json",
27007
+ "package-lock.json",
27008
+ "root/mcp.json",
27009
+ "root/keybindings.json"
27010
+ ];
27011
+ var PI_PROFILE_MAX_FILES = 4e3;
27012
+ var PI_PROFILE_MAX_FILE_BYTES = 8 * 1024 * 1024;
27013
+ var PI_PROFILE_MAX_BYTES = 16 * 1024 * 1024;
27014
+ var PI_PROFILE_MAX_PATH_LENGTH = 512;
27015
+ var PiProfileFile = class extends Schema_exports.Class("PiProfileFile")({
27016
+ /** Profile-relative POSIX path; validated by `validatePiProfileFilePath`. */
27017
+ path: Schema_exports.String,
27018
+ encoding: Schema_exports.Literals(["utf8", "base64"]),
27019
+ contents: Schema_exports.String
27020
+ }) {
27021
+ };
27022
+ var PiProfile = class extends Schema_exports.Class("PiProfile")({
27023
+ fileCount: Schema_exports.Int,
27024
+ bytes: Schema_exports.Int,
27025
+ /** The profile's top-level extensions: each file or directory under `extensions/`. */
27026
+ extensions: Schema_exports.Array(Schema_exports.String),
27027
+ /** The packages its `settings.json` declares, each as its source. */
27028
+ packages: Schema_exports.Array(Schema_exports.String),
27029
+ /** Changes whenever the files do: the tree digest a session compares against. */
27030
+ digest: Schema_exports.String,
27031
+ revision: Schema_exports.Int,
27032
+ updatedAt: Timestamp
27033
+ }) {
27034
+ };
27035
+ var PiProfileView = class extends Schema_exports.Class("PiProfileView")({
27036
+ profile: Schema_exports.NullOr(PiProfile)
27037
+ }) {
27038
+ };
27039
+ var PiProfileUpload = class extends Schema_exports.Class("PiProfileUpload")({
27040
+ files: Schema_exports.Array(PiProfileFile)
27041
+ }) {
27042
+ };
27043
+ var PiProfileSaved = class extends Schema_exports.Class("PiProfileSaved")({
27044
+ profile: PiProfile,
27045
+ changed: Schema_exports.Boolean
27046
+ }) {
27047
+ };
27048
+ var PiProfileRemoved = class extends Schema_exports.Class("PiProfileRemoved")({
27049
+ removed: Schema_exports.Boolean
27050
+ }) {
27051
+ };
27052
+ var piProfileFileBytes = (file) => {
27053
+ if (file.encoding === "utf8") return new TextEncoder().encode(file.contents);
27054
+ if (!/^[A-Za-z0-9+/]*={0,2}$/.test(file.contents) || file.contents.length % 4 !== 0) return null;
27055
+ try {
27056
+ return Uint8Array.from(atob(file.contents), (char) => char.charCodeAt(0));
27057
+ } catch {
27058
+ return null;
27059
+ }
27060
+ };
27061
+ var validatePiProfileFilePath = (filePath) => {
27062
+ if (filePath.length === 0) return "a file path is required";
27063
+ if (filePath.length > PI_PROFILE_MAX_PATH_LENGTH) {
27064
+ return `${filePath} is longer than ${PI_PROFILE_MAX_PATH_LENGTH} characters`;
27065
+ }
27066
+ if (filePath.startsWith("/") || filePath.includes("\\") || filePath.includes("\0")) {
27067
+ return `${filePath} is not a relative POSIX path`;
27068
+ }
27069
+ const segments = filePath.split("/");
27070
+ if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
27071
+ return `${filePath} must not contain empty, "." or ".." segments`;
27072
+ }
27073
+ if (PI_PROFILE_FILES.some((file) => file === filePath)) return null;
27074
+ const top = segments[0] ?? "";
27075
+ if (segments.length > 1 && PI_PROFILE_DIRECTORIES.some((directory) => directory === top)) {
27076
+ return null;
27077
+ }
27078
+ return `${filePath} is not part of a pi profile`;
27079
+ };
27080
+ var validatePiProfile = (files) => {
27081
+ if (files.length === 0) return "a pi profile needs at least one file";
27082
+ if (files.length > PI_PROFILE_MAX_FILES) {
27083
+ return `a pi profile is capped at ${PI_PROFILE_MAX_FILES} files`;
27084
+ }
27085
+ const seen = /* @__PURE__ */ new Set();
27086
+ let total = 0;
27087
+ for (const file of files) {
27088
+ const pathIssue = validatePiProfileFilePath(file.path);
27089
+ if (pathIssue !== null) return pathIssue;
27090
+ if (seen.has(file.path)) return `${file.path} appears twice`;
27091
+ seen.add(file.path);
27092
+ const bytes = piProfileFileBytes(file);
27093
+ if (bytes === null) return `${file.path} is not valid base64`;
27094
+ if (bytes.byteLength > PI_PROFILE_MAX_FILE_BYTES) {
27095
+ return `${file.path} is over ${PI_PROFILE_MAX_FILE_BYTES / (1024 * 1024)} MB`;
27096
+ }
27097
+ total += bytes.byteLength;
27098
+ }
27099
+ for (const filePath of seen) {
27100
+ const segments = filePath.split("/");
27101
+ for (let depth = 1; depth < segments.length; depth += 1) {
27102
+ const parent = segments.slice(0, depth).join("/");
27103
+ if (seen.has(parent)) return `${parent} is both a file and a directory`;
27104
+ }
27105
+ }
27106
+ if (total > PI_PROFILE_MAX_BYTES) {
27107
+ return `a pi profile is capped at ${PI_PROFILE_MAX_BYTES / (1024 * 1024)} MB in total`;
27108
+ }
27109
+ return null;
27110
+ };
27111
+
26837
27112
  // ../../packages/domain/src/workbench/audit.ts
26838
27113
  var AuditAction = Schema_exports.Literals([
26839
27114
  "invitation.created",
@@ -26912,8 +27187,14 @@ var LandedPullRequest = Schema_exports.Struct({
26912
27187
  number: Schema_exports.Int,
26913
27188
  url: Schema_exports.String,
26914
27189
  state: PullRequestState,
27190
+ /** Its title as `gh` last reported it; null when recorded before Mend kept it. */
27191
+ title: Schema_exports.NullOr(Schema_exports.String).pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null))),
26915
27192
  observedAt: Timestamp
26916
27193
  });
27194
+ var ChangePullRequest = Schema_exports.Struct({
27195
+ ...LandedPullRequest.fields,
27196
+ adopted: Schema_exports.Boolean
27197
+ });
26917
27198
  var ChangeLanding = class extends Schema_exports.Class("ChangeLanding")({
26918
27199
  id: ChangeLandingId,
26919
27200
  changeId: ChangeId,
@@ -27102,6 +27383,7 @@ var AgentTurnUsage = Schema_exports.Struct({
27102
27383
  totalTokens: Schema_exports.NullOr(Schema_exports.Int),
27103
27384
  contextWindow: Schema_exports.NullOr(Schema_exports.Int)
27104
27385
  });
27386
+ var AgentTurnOrigin = Schema_exports.Literals(["request", "harness"]);
27105
27387
  var AgentTurn = class extends Schema_exports.Class("AgentTurn")({
27106
27388
  id: AgentTurnId,
27107
27389
  sessionId: SessionId,
@@ -27110,6 +27392,10 @@ var AgentTurn = class extends Schema_exports.Class("AgentTurn")({
27110
27392
  ordinal: Schema_exports.Int,
27111
27393
  /** Mend user id, or null for a system-authored follow-up. */
27112
27394
  author: Schema_exports.NullOr(Schema_exports.String),
27395
+ /** What opened the turn. A `harness` turn's input is what the agent was answering. */
27396
+ origin: AgentTurnOrigin.pipe(
27397
+ Schema_exports.withConstructorDefault(Effect_exports.succeed("request"))
27398
+ ),
27113
27399
  input: Schema_exports.String,
27114
27400
  status: AgentTurnStatus,
27115
27401
  providerTurnId: Schema_exports.NullOr(Schema_exports.String),
@@ -27132,6 +27418,24 @@ var AgentTurn = class extends Schema_exports.Class("AgentTurn")({
27132
27418
  landingId: Schema_exports.NullOr(ChangeLandingId).pipe(
27133
27419
  Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27134
27420
  ),
27421
+ /**
27422
+ * Whose login the turn ran on (`TurnPayer`), recorded when Mend sent it or the harness opened
27423
+ * it. Null on a turn never sent, one recorded before payers were, and where Mend cannot say.
27424
+ */
27425
+ billedUserId: Schema_exports.NullOr(Schema_exports.String).pipe(
27426
+ Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)),
27427
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27428
+ ),
27429
+ /** The connected account's id as Core reported it; null until Core reports one. */
27430
+ billedAccountId: Schema_exports.NullOr(Schema_exports.String).pipe(
27431
+ Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)),
27432
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27433
+ ),
27434
+ /** The connected account's name when the turn ran (`default`, `work`). */
27435
+ billedAccountName: Schema_exports.NullOr(Schema_exports.String).pipe(
27436
+ Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)),
27437
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27438
+ ),
27135
27439
  createdAt: Timestamp,
27136
27440
  startedAt: Schema_exports.NullOr(Timestamp),
27137
27441
  endedAt: Schema_exports.NullOr(Timestamp)
@@ -27146,6 +27450,8 @@ var AgentItemKind = Schema_exports.Literals([
27146
27450
  "file-change",
27147
27451
  "tool-call",
27148
27452
  "web-search",
27453
+ /** A background task the agent started: a workflow, a background agent or command. */
27454
+ "task",
27149
27455
  "error",
27150
27456
  "other"
27151
27457
  ]);
@@ -27218,6 +27524,43 @@ var AgentRequest = class extends Schema_exports.Class("AgentRequest")({
27218
27524
  decidedAt: Schema_exports.NullOr(Timestamp)
27219
27525
  }) {
27220
27526
  };
27527
+ var AgentTaskStatus = Schema_exports.Literals([
27528
+ "running",
27529
+ "completed",
27530
+ "failed",
27531
+ "stopped",
27532
+ "paused"
27533
+ ]);
27534
+ var AgentTaskAgent = Schema_exports.Struct({
27535
+ index: Schema_exports.Int,
27536
+ label: Schema_exports.String,
27537
+ phaseIndex: Schema_exports.NullOr(Schema_exports.Int),
27538
+ state: Schema_exports.String,
27539
+ model: Schema_exports.NullOr(Schema_exports.String),
27540
+ tokens: Schema_exports.NullOr(Schema_exports.Int),
27541
+ toolCalls: Schema_exports.NullOr(Schema_exports.Int),
27542
+ durationMs: Schema_exports.NullOr(Schema_exports.Int),
27543
+ lastTool: Schema_exports.NullOr(Schema_exports.String),
27544
+ /** The start of the agent's result, or of its error. */
27545
+ preview: Schema_exports.NullOr(Schema_exports.String)
27546
+ });
27547
+ var AgentTaskData = Schema_exports.Struct({
27548
+ taskId: Schema_exports.String,
27549
+ /** The harness's task type: `local_workflow`, `local_agent`, `local_bash`, … */
27550
+ taskType: Schema_exports.String,
27551
+ /** The workflow's name, when the task is one. */
27552
+ workflow: Schema_exports.NullOr(Schema_exports.String),
27553
+ description: Schema_exports.String,
27554
+ status: AgentTaskStatus,
27555
+ /** The harness's closing line, once the task ended. */
27556
+ summary: Schema_exports.NullOr(Schema_exports.String),
27557
+ error: Schema_exports.NullOr(Schema_exports.String),
27558
+ phases: Schema_exports.Array(Schema_exports.Struct({ index: Schema_exports.Int, title: Schema_exports.String })),
27559
+ agents: Schema_exports.Array(AgentTaskAgent),
27560
+ totalTokens: Schema_exports.NullOr(Schema_exports.Int),
27561
+ toolUses: Schema_exports.NullOr(Schema_exports.Int),
27562
+ durationMs: Schema_exports.NullOr(Schema_exports.Int)
27563
+ });
27221
27564
  var AgentEventItem = Schema_exports.Struct({
27222
27565
  providerItemId: Schema_exports.String,
27223
27566
  providerTurnId: Schema_exports.String,
@@ -27243,6 +27586,11 @@ var AgentEvent = Schema_exports.Union([
27243
27586
  Schema_exports.TaggedStruct("turn.started", {
27244
27587
  providerTurnId: Schema_exports.String
27245
27588
  }),
27589
+ /** The agent started a turn nobody sent; `reason` is what it is answering, when known. */
27590
+ Schema_exports.TaggedStruct("harness-turn.started", {
27591
+ providerTurnId: Schema_exports.String,
27592
+ reason: Schema_exports.String
27593
+ }),
27246
27594
  Schema_exports.TaggedStruct("turn.completed", {
27247
27595
  providerTurnId: Schema_exports.String,
27248
27596
  status: Schema_exports.Literals(["completed", "interrupted", "failed", "cancelled"]),
@@ -27371,8 +27719,9 @@ var captureStatusLine = (facts) => {
27371
27719
  ...facts.captureIncompleteReason === CAPTURE_EXECUTOR_RETAINED ? [] : ["workspace kept"]
27372
27720
  ].join(" \xB7 ");
27373
27721
  }
27722
+ const noneQueued = facts.capturePendingBytes === 0 || facts.capturePendingBytes === null && facts.capturePending === 0;
27374
27723
  return [
27375
- left === null ? "saving" : `saving \xB7 ${left} left`,
27724
+ noneQueued ? "saving \xB7 no uploads pending" : left === null ? "saving" : `saving \xB7 ${left} left`,
27376
27725
  ...overdue === null ? [] : [overdue]
27377
27726
  ].join(" \xB7 ");
27378
27727
  }
@@ -27682,6 +28031,21 @@ var Session = class extends Schema_exports.Class("Session")({
27682
28031
  worktreeId: WorktreeId,
27683
28032
  /** The adapter that launched it: `codex` · `claude` · `opencode` · `custom`. */
27684
28033
  harness: Schema_exports.String,
28034
+ /**
28035
+ * The model the session was started with, as the server resolved it (docs/models-audit.md): the
28036
+ * one the request named, else the harness's catalog default. Null for a harness with no catalog,
28037
+ * before launch, and on rows from before the column. A resume keeps it: the harness continues
28038
+ * the conversation on its own model.
28039
+ */
28040
+ model: Schema_exports.NullOr(Schema_exports.String).pipe(
28041
+ Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)),
28042
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
28043
+ ),
28044
+ /** The effort the session was started with; null is the harness's own default. */
28045
+ effort: Schema_exports.NullOr(Schema_exports.Literals(EFFORT_LEVELS)).pipe(
28046
+ Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(null)),
28047
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
28048
+ ),
27685
28049
  /** Provider-native session/thread id when the adapter can extract one. */
27686
28050
  providerSessionId: Schema_exports.NullOr(Schema_exports.String),
27687
28051
  /** Optional human label ("reaper retry storm"); sessions have no issue titles. */
@@ -27926,6 +28290,32 @@ var HotWorkspace = class extends Schema_exports.Class("HotWorkspace")({
27926
28290
  }) {
27927
28291
  };
27928
28292
 
28293
+ // ../../packages/domain/src/workbench/model-catalog.ts
28294
+ var HarnessModel = class extends Schema_exports.Class("HarnessModel")({
28295
+ id: Schema_exports.String,
28296
+ label: Schema_exports.String,
28297
+ /** The model a launch runs when the request names none; one per harness. */
28298
+ isDefault: Schema_exports.Boolean,
28299
+ /** The efforts this model takes when fewer than its harness's; null means the harness's. */
28300
+ efforts: Schema_exports.NullOr(Schema_exports.Array(Schema_exports.Literals(EFFORT_LEVELS)))
28301
+ }) {
28302
+ };
28303
+ var HarnessModelCatalog = class extends Schema_exports.Class("HarnessModelCatalog")({
28304
+ harness: Schema_exports.String,
28305
+ /** In the order the picker shows them; empty when the harness takes no model flag Mend knows. */
28306
+ models: Schema_exports.Array(HarnessModel),
28307
+ /**
28308
+ * The model a launch runs when none is named; null when the list is empty, or when the harness
28309
+ * chooses its own and no row is flagged (`HARNESSES_CHOOSING_THEIR_OWN_MODEL`).
28310
+ */
28311
+ defaultModel: Schema_exports.NullOr(Schema_exports.String),
28312
+ /** What the harness CLI accepts at all; a model may take fewer. */
28313
+ efforts: Schema_exports.Array(Schema_exports.Literals(EFFORT_LEVELS)),
28314
+ /** Whether a launch may ask for priority processing. */
28315
+ fastCapable: Schema_exports.Boolean
28316
+ }) {
28317
+ };
28318
+
27929
28319
  // ../../packages/domain/src/workbench/notifications.ts
27930
28320
  var NotificationKind = Schema_exports.Literals(["finished", "needs-input", "failed"]);
27931
28321
  var NotificationSettings = class extends Schema_exports.Class(
@@ -27950,6 +28340,26 @@ var DEFAULT_NOTIFICATION_SETTINGS = new NotificationSettings({
27950
28340
  });
27951
28341
  var SlackThreadReach = Schema_exports.Literals(["replies", "status", "none"]);
27952
28342
 
28343
+ // ../../packages/domain/src/workbench/host-user-namespaces.ts
28344
+ var HOST_USER_NAMESPACE_FILES = [
28345
+ "/proc/sys/kernel/apparmor_restrict_unprivileged_userns",
28346
+ "/sys/module/apparmor/parameters/enabled",
28347
+ "/proc/sys/kernel/unprivileged_userns_clone"
28348
+ ];
28349
+ var HOST_USER_NAMESPACE_SYSCTL_FILE = "/etc/sysctl.d/60-mend-rootless-docker.conf";
28350
+ var hostUserNamespacesOf = (readings) => {
28351
+ const restrict = readings.apparmorRestrictUnprivilegedUserns?.trim();
28352
+ const apparmorOff = readings.apparmorEnabled?.trim() === "N";
28353
+ if (restrict === "1" && !apparmorOff) {
28354
+ return { allowed: false, setting: "kernel.apparmor_restrict_unprivileged_userns = 0" };
28355
+ }
28356
+ if (readings.unprivilegedUsernsClone?.trim() === "0") {
28357
+ return { allowed: false, setting: "kernel.unprivileged_userns_clone = 1" };
28358
+ }
28359
+ return { allowed: true };
28360
+ };
28361
+ var hostUserNamespacesFix = (setting) => `echo '${setting}' | sudo tee ${HOST_USER_NAMESPACE_SYSCTL_FILE} && sudo sysctl --system`;
28362
+
27953
28363
  // ../../packages/domain/src/workbench/link.ts
27954
28364
  var ProjectLink = class extends Schema_exports.Class("ProjectLink")({
27955
28365
  id: ProjectLinkId,
@@ -28004,7 +28414,7 @@ var ProjectClusterBindingsSnapshot = class extends Schema_exports.Class(
28004
28414
  }) {
28005
28415
  };
28006
28416
 
28007
- // ../../node_modules/.pnpm/@sealant+api-contracts@0.38.1_effect@4.0.0-beta.93/node_modules/@sealant/api-contracts/dist/workspace-environment.js
28417
+ // ../../node_modules/.pnpm/@sealant+api-contracts-next@0.39.0-next.683_effect@4.0.0-beta.93/node_modules/@sealant/api-contracts-next/dist/workspace-environment.js
28008
28418
  var RESERVED_NAMES = new Map([
28009
28419
  // Identity/process roots the daemon and shells own.
28010
28420
  ...[
@@ -28186,6 +28596,38 @@ var servicesHoldLine = (input) => {
28186
28596
  return input.agentOutcome === null ? hold : `agent ${input.agentOutcome} \xB7 ${hold}`;
28187
28597
  };
28188
28598
 
28599
+ // ../../packages/domain/src/workbench/repository.ts
28600
+ var SessionRepositoryState = Schema_exports.Literals(["adding", "ready", "failed", "missing"]);
28601
+ var SessionRepositoryCapture = Schema_exports.Literals(["nested", "own"]);
28602
+ var SessionRepositorySource = Schema_exports.Literals(["origin", "store"]);
28603
+ var SessionRepository = class extends Schema_exports.Class("SessionRepository")({
28604
+ id: SessionRepositoryId,
28605
+ sessionId: SessionId,
28606
+ /** The repository's project, never the session's own. */
28607
+ projectId: ProjectId,
28608
+ /** The worktree of that project this session works in. */
28609
+ worktreeId: WorktreeId,
28610
+ /** The directory name under `/workspace/repos/`. */
28611
+ name: Schema_exports.String,
28612
+ /** `repositoryPath(name)`, recorded so the record reads without computing. */
28613
+ path: Schema_exports.String,
28614
+ /** Mirrors of the worktree row, as the session's own `branch` and `baseSha` are. */
28615
+ branch: Schema_exports.String,
28616
+ baseSha: Sha,
28617
+ baseRef: Schema_exports.NullOr(Schema_exports.String),
28618
+ state: SessionRepositoryState,
28619
+ /** Why it `failed` or went `missing`, in the words the person reads. */
28620
+ error: Schema_exports.NullOr(Schema_exports.String),
28621
+ capture: SessionRepositoryCapture,
28622
+ source: SessionRepositorySource,
28623
+ /** The account that asked for it: the session's owner. */
28624
+ addedByUserId: Schema_exports.NullOr(Schema_exports.String),
28625
+ createdAt: Timestamp,
28626
+ updatedAt: Timestamp,
28627
+ readyAt: Schema_exports.NullOr(Timestamp)
28628
+ }) {
28629
+ };
28630
+
28189
28631
  // ../../packages/domain/src/workbench/review-comment.ts
28190
28632
  var CommentAuthor = Schema_exports.Literals(["reviewer", "mend"]);
28191
28633
  var CommentState = Schema_exports.Literals(["draft", "open", "addressed", "dismissed"]);
@@ -28244,6 +28686,83 @@ var ReviewComment = class extends Schema_exports.Class("ReviewComment")({
28244
28686
  }) {
28245
28687
  };
28246
28688
 
28689
+ // ../../packages/domain/src/workbench/secret-file.ts
28690
+ var SECRET_FILE_MAX_BYTES = 256 * 1024;
28691
+ var SECRET_FILES_MAX_TOTAL_BYTES = 1024 * 1024;
28692
+ var SECRET_FILE_MAX_PATH_LENGTH = 512;
28693
+ var SECRET_FILE_RESERVED_PATHS = [
28694
+ ".claude",
28695
+ ".claude.json",
28696
+ ".codex",
28697
+ ".pi",
28698
+ ".local/share/opencode",
28699
+ ".local/state/opencode",
28700
+ ".mend"
28701
+ ];
28702
+ var SecretFile = class extends Schema_exports.Class("SecretFile")({
28703
+ id: SecretFileId,
28704
+ /** Home-relative POSIX path, as `validateSecretFilePath` accepts it. */
28705
+ path: Schema_exports.String,
28706
+ /** The last segment of `path`: what a list shows first. */
28707
+ name: Schema_exports.String,
28708
+ bytes: Schema_exports.Int,
28709
+ /** Grows with every replace; the content itself never appears. */
28710
+ revision: Schema_exports.Int,
28711
+ createdAt: Timestamp,
28712
+ updatedAt: Timestamp
28713
+ }) {
28714
+ };
28715
+ var SecretFilesView = class extends Schema_exports.Class("SecretFilesView")({
28716
+ files: Schema_exports.Array(SecretFile)
28717
+ }) {
28718
+ };
28719
+ var SecretFileUpload = class extends Schema_exports.Class("SecretFileUpload")({
28720
+ path: Schema_exports.String,
28721
+ encoding: Schema_exports.Literals(["utf8", "base64"]),
28722
+ contents: Schema_exports.String
28723
+ }) {
28724
+ };
28725
+ var SecretFileSaved = class extends Schema_exports.Class("SecretFileSaved")({
28726
+ file: SecretFile,
28727
+ action: Schema_exports.Literals(["created", "replaced"])
28728
+ }) {
28729
+ };
28730
+ var SecretFileRemoved = class extends Schema_exports.Class("SecretFileRemoved")({
28731
+ removed: Schema_exports.Boolean
28732
+ }) {
28733
+ };
28734
+ var validateSecretFilePath = (filePath) => {
28735
+ const syntax = validateSecretFilePathSyntax(filePath);
28736
+ if (syntax !== null) return syntax;
28737
+ const reserved = reservedSecretFileRoot(filePath);
28738
+ if (reserved !== null) {
28739
+ return `${filePath} is under ${reserved}, which sessions capture`;
28740
+ }
28741
+ return null;
28742
+ };
28743
+ var reservedSecretFileRoot = (filePath) => SECRET_FILE_RESERVED_PATHS.find(
28744
+ (prefix) => filePath === prefix || filePath.startsWith(`${prefix}/`)
28745
+ ) ?? null;
28746
+ var validateSecretFilePathSyntax = (filePath) => {
28747
+ if (filePath.length === 0) return "a path under the home directory is required";
28748
+ if (filePath.length > SECRET_FILE_MAX_PATH_LENGTH) {
28749
+ return `${filePath} is longer than ${SECRET_FILE_MAX_PATH_LENGTH} characters`;
28750
+ }
28751
+ if (filePath.startsWith("/") || filePath.startsWith("~")) {
28752
+ return `${filePath} must be relative to the home directory, as .aws/credentials is`;
28753
+ }
28754
+ const control = [...filePath].some((char) => {
28755
+ const code = char.codePointAt(0) ?? 0;
28756
+ return code < 32 || code === 127;
28757
+ });
28758
+ if (filePath.includes("\\") || control) return `${filePath} is not a POSIX path`;
28759
+ const segments = filePath.split("/");
28760
+ if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
28761
+ return `${filePath} must not contain empty, "." or ".." segments`;
28762
+ }
28763
+ return null;
28764
+ };
28765
+
28247
28766
  // ../../packages/domain/src/workbench/service-recipe.ts
28248
28767
  var ServiceRecipe = class extends Schema_exports.Class("ServiceRecipe")({
28249
28768
  name: Schema_exports.String,
@@ -28359,6 +28878,7 @@ var ServiceView = class extends Schema_exports.Class("ServiceView")({
28359
28878
  var SessionControlKind = Schema_exports.Literals([
28360
28879
  "interrupt",
28361
28880
  "terminal-attach",
28881
+ "terminal-watch",
28362
28882
  "shell-open",
28363
28883
  "stop",
28364
28884
  "services-stop",
@@ -28377,6 +28897,7 @@ var SessionControlEvent = class extends Schema_exports.Class("SessionControlEven
28377
28897
  createdAt: Timestamp
28378
28898
  }) {
28379
28899
  };
28900
+ var terminalReadOnlyLine = (ownerName) => `This session runs in a terminal. Only ${ownerName} types here; they can continue it as a conversation.`;
28380
28901
 
28381
28902
  // ../../packages/domain/src/workbench/session-run.ts
28382
28903
  var SessionRun = class extends Schema_exports.Class("SessionRun")({
@@ -28577,6 +29098,9 @@ var Worktree = class extends Schema_exports.Class("Worktree")({
28577
29098
  }) {
28578
29099
  };
28579
29100
 
29101
+ // ../../packages/domain/src/workbench/worktree-removal.ts
29102
+ var WORKTREE_REMOVAL_FORCE_HINT = "or pass force=true to remove it anyway";
29103
+
28580
29104
  // src/shared.ts
28581
29105
  import { spawnSync } from "node:child_process";
28582
29106
  import * as path from "node:path";
@@ -28584,10 +29108,18 @@ var HARNESS_COMMANDS = {
28584
29108
  codex: ["codex"],
28585
29109
  claude: ["claude"],
28586
29110
  opencode: ["opencode"],
29111
+ pi: ["pi"],
28587
29112
  // Not a coding agent: a plain bash session in its own recorded worktree.
28588
29113
  shell: ["bash"]
28589
29114
  };
28590
- var EFFORT_LEVELS2 = ["low", "medium", "high", "xhigh", "max"];
29115
+ var EFFORT_LEVELS2 = [
29116
+ "low",
29117
+ "medium",
29118
+ "high",
29119
+ "xhigh",
29120
+ "max",
29121
+ "ultra"
29122
+ ];
28591
29123
  var PENDING_ID_PREFIX = "pending:";
28592
29124
  var pendingId = () => `${PENDING_ID_PREFIX}${crypto.randomUUID()}`;
28593
29125
  var isPendingId = (id2) => id2.startsWith(PENDING_ID_PREFIX);
@@ -28847,6 +29379,9 @@ var trackBracketedPaste = (output, current) => {
28847
29379
  return on > off;
28848
29380
  };
28849
29381
  var pasteBytes = (text, bracketed) => Buffer.from(bracketed ? `\x1B[200~${text}\x1B[201~` : text, "utf8");
29382
+ var firstPositional = (args2, valued) => args2.find(
29383
+ (argument, index2) => !argument.startsWith("--") && (index2 === 0 || !valued.includes(args2[index2 - 1] ?? ""))
29384
+ );
28850
29385
 
28851
29386
  // src/server-request.ts
28852
29387
  var MendRequestError = class extends Error {
@@ -28970,12 +29505,30 @@ export {
28970
29505
  RepositoryCloneUrl,
28971
29506
  landingFactsFromWire,
28972
29507
  landingFactLine,
29508
+ AGENT_MEMORY_ROOTS,
29509
+ AGENT_MEMORY_FILES,
29510
+ CODEX_MEMORY_DATABASE,
29511
+ AGENT_MEMORY_MAX_FILE_BYTES,
29512
+ AGENT_MEMORY_MAX_DATABASE_BYTES,
29513
+ agentMemoryNameOf,
28973
29514
  narrowCredential,
28974
29515
  claudeGrantFacts,
28975
29516
  sameGrant,
28976
29517
  normalizeGitAuthor,
28977
29518
  gitAuthorIssue,
29519
+ withoutLaunchPhase,
29520
+ launchPhaseOf,
29521
+ HOST_USER_NAMESPACE_FILES,
29522
+ hostUserNamespacesOf,
29523
+ hostUserNamespacesFix,
29524
+ PI_PROFILE_AGENT_PATH,
29525
+ PI_PROFILE_LOCAL_PACKAGES,
29526
+ PI_PROFILE_MAX_FILE_BYTES,
29527
+ validatePiProfile,
28978
29528
  servicesHoldLine,
29529
+ validateSecretFilePath,
29530
+ terminalReadOnlyLine,
29531
+ WORKTREE_REMOVAL_FORCE_HINT,
28979
29532
  HARNESS_COMMANDS,
28980
29533
  pendingId,
28981
29534
  isPendingId,
@@ -28994,9 +29547,11 @@ export {
28994
29547
  gitOriginUrl,
28995
29548
  gitTopLevel,
28996
29549
  normalizeProjectName,
29550
+ csiUKeysOf,
28997
29551
  isPasteChunk,
28998
29552
  trackBracketedPaste,
28999
29553
  pasteBytes,
29554
+ firstPositional,
29000
29555
  MendRequestError,
29001
29556
  spoken,
29002
29557
  noAnswerError,