@monotykamary/localterm-server 2.2.3 → 2.4.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.
Files changed (39) hide show
  1. package/dist/caffeinate-battery.d.ts +10 -0
  2. package/dist/caffeinate-battery.d.ts.map +1 -0
  3. package/dist/caffeinate-battery.js +47 -0
  4. package/dist/caffeinate-battery.js.map +1 -0
  5. package/dist/caffeinate-manager.d.ts +17 -0
  6. package/dist/caffeinate-manager.d.ts.map +1 -1
  7. package/dist/caffeinate-manager.js +194 -4
  8. package/dist/caffeinate-manager.js.map +1 -1
  9. package/dist/caffeinate-preferences-store.d.ts +2 -0
  10. package/dist/caffeinate-preferences-store.d.ts.map +1 -1
  11. package/dist/caffeinate-preferences-store.js +31 -2
  12. package/dist/caffeinate-preferences-store.js.map +1 -1
  13. package/dist/constants.d.ts +8 -1
  14. package/dist/constants.d.ts.map +1 -1
  15. package/dist/constants.js +29 -1
  16. package/dist/constants.js.map +1 -1
  17. package/dist/git-worktrees.d.ts +9 -2
  18. package/dist/git-worktrees.d.ts.map +1 -1
  19. package/dist/git-worktrees.js +288 -53
  20. package/dist/git-worktrees.js.map +1 -1
  21. package/dist/index.d.ts +7 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +61 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/protocol.d.ts +3 -3
  26. package/dist/protocol.d.ts.map +1 -1
  27. package/dist/protocol.js +2 -2
  28. package/dist/protocol.js.map +1 -1
  29. package/dist/schemas.d.ts +34 -1
  30. package/dist/schemas.d.ts.map +1 -1
  31. package/dist/schemas.js +77 -3
  32. package/dist/schemas.js.map +1 -1
  33. package/dist/types.d.ts +4 -1
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/utils/worktree-names.d.ts +2 -0
  36. package/dist/utils/worktree-names.d.ts.map +1 -0
  37. package/dist/utils/worktree-names.js +155 -0
  38. package/dist/utils/worktree-names.js.map +1 -0
  39. package/package.json +1 -1
package/dist/constants.js CHANGED
@@ -20,7 +20,7 @@ export const CAFFEINATE_AUTO_DEFAULT_COMMANDS = [
20
20
  "opencode",
21
21
  "pi",
22
22
  ];
23
- export const CAFFEINATE_PREFERENCES_FILE_VERSION = 2;
23
+ export const CAFFEINATE_PREFERENCES_FILE_VERSION = 3;
24
24
  // Automatic detection is event-driven (no timer): a `ps` snapshot is taken only
25
25
  // in response to a foreground change or a session connect/disconnect. This
26
26
  // debounce window coalesces a burst of such events into a single snapshot; it
@@ -34,6 +34,34 @@ export const CAFFEINATE_AUTO_POKE_DEBOUNCE_MS = 150;
34
34
  export const CAFFEINATE_ACTIVITY_GATE_DEBOUNCE_MS = 5_000;
35
35
  export const MAX_CAFFEINATE_COMMANDS = 50;
36
36
  export const MAX_CAFFEINATE_COMMAND_LENGTH = 128;
37
+ // Battery floor for keep-awake: when the machine is on battery power and at or
38
+ // below this percent, the daemon refuses to hold the power assertion (it stops
39
+ // caffeinate without changing the selected mode). The default is on, so a
40
+ // machine left unplugged stops keeping itself awake before it dies. `null`
41
+ // (selectable in the menu as "Off") disables the guard entirely.
42
+ export const CAFFEINATE_BATTERY_LOW_WATER_PERCENT_DEFAULT = 20;
43
+ export const CAFFEINATE_BATTERY_LOW_WATER_MIN_PERCENT = 5;
44
+ export const CAFFEINATE_BATTERY_LOW_WATER_MAX_PERCENT = 50;
45
+ // The battery floor is enforced by reading `pmset -g batt` on an adaptive
46
+ // schedule rather than a fixed heartbeat. `pmset` reports the charge percent
47
+ // and an EWMA "time to empty" estimate; the next delay is 1/TIME_FRACTION of the
48
+ // interpolated time-to-threshold (estimate × charge fraction still above the
49
+ // floor), so polling tightens as the floor approaches and stays lax far from
50
+ // it. Halving (not subtracting a fixed margin) scales the buffer with the
51
+ // estimate: the EWMA lags real discharge and the active program drains faster
52
+ // than the idle minutes it averaged, so a 2× buffer absorbs a stale-high
53
+ // estimate without overshooting. Clamped to [MIN, MAX]: MIN keeps a
54
+ // near-threshold reading from busy-looping and drives fast recovery while
55
+ // suppressed; MAX bounds the far-from-threshold and on-AC cases. The floor is
56
+ // a courtesy guard — macOS still forces low-battery sleep at ~5% regardless of
57
+ // caffeinate — so a multi-minute MAX is an acceptable worst-case latency for
58
+ // noticing an unplug or a stalled estimate.
59
+ export const CAFFEINATE_BATTERY_POLL_MIN_INTERVAL_MS = 5_000;
60
+ export const CAFFEINATE_BATTERY_POLL_MAX_INTERVAL_MS = 15 * 60_000;
61
+ // Poll at 1/N of the interpolated time-to-threshold. N=2 gives a 2× buffer
62
+ // against the OS estimate being stale-high.
63
+ export const CAFFEINATE_BATTERY_POLL_TIME_FRACTION = 2;
64
+ export const CAFFEINATE_BATTERY_READ_TIMEOUT_MS = 2_000;
37
65
  export const TITLE_MAX_PATH_SEGMENTS = 1;
38
66
  /**
39
67
  * Strip terminal-emulator identity env vars inherited from the daemon's parent.
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,11 @@
1
1
  import type { GitWorktreeListResponse } from "./types.js";
2
- export declare const parseGitWorktreeList: (text: string) => GitWorktreeListResponse;
3
- export declare const getGitWorktrees: (cwd: string) => Promise<GitWorktreeListResponse>;
2
+ export declare class WorktreeError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare const listGitWorktrees: (cwd: string) => Promise<GitWorktreeListResponse>;
6
+ export declare const createGitWorktree: (cwd: string) => Promise<{
7
+ path: string;
8
+ branch: string;
9
+ }>;
10
+ export declare const removeGitWorktree: (cwd: string, targetPath: string) => Promise<void>;
4
11
  //# sourceMappingURL=git-worktrees.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-worktrees.d.ts","sourceRoot":"","sources":["../src/git-worktrees.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAMvE,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,uBA8CnD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,uBAAuB,CAIlF,CAAC"}
1
+ {"version":3,"file":"git-worktrees.d.ts","sourceRoot":"","sources":["../src/git-worktrees.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAMvE,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAsND,eAAO,MAAM,gBAAgB,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,uBAAuB,CAsBnF,CAAC;AAOF,eAAO,MAAM,iBAAiB,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAuB7F,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,KAAK,MAAM,EAAE,YAAY,MAAM,KAAG,OAAO,CAAC,IAAI,CAoBrF,CAAC"}
@@ -1,59 +1,294 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
1
5
  import { runGit } from "./utils/run-git.js";
2
- const stripRefsHeads = (ref) => ref.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref;
3
- export const parseGitWorktreeList = (text) => {
4
- const blocks = text
5
- .split(/\n{2,}/)
6
- .map((block) => block.trim())
7
- .filter(Boolean);
8
- const worktrees = [];
9
- for (const block of blocks) {
10
- const lines = block.split("\n");
11
- let path = "";
12
- let commit = "";
13
- let branch = null;
14
- let isDetached = false;
15
- let isBare = false;
16
- let isLocked = false;
17
- for (const line of lines) {
18
- if (line.startsWith("worktree ")) {
19
- path = line.slice("worktree ".length);
20
- }
21
- else if (line.startsWith("HEAD ")) {
22
- commit = line.slice("HEAD ".length);
23
- }
24
- else if (line.startsWith("branch ")) {
25
- branch = stripRefsHeads(line.slice("branch ".length));
26
- }
27
- else if (line === "detached") {
28
- isDetached = true;
29
- }
30
- else if (line === "bare") {
31
- isBare = true;
32
- }
33
- else if (line.startsWith("locked")) {
34
- isLocked = true;
6
+ import { generateWorktreeName } from "./utils/worktree-names.js";
7
+ // A user-facing git failure (path exists, branch checked out elsewhere, the
8
+ // main worktree can't be removed, …). The route catches this and surfaces
9
+ // `message` (git's own stderr) so the client can show something actionable
10
+ // instead of an opaque code.
11
+ export class WorktreeError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "WorktreeError";
15
+ }
16
+ }
17
+ const HOME = os.homedir();
18
+ const PATH_SEPARATOR = path.sep;
19
+ // Auto-created worktrees live under the localterm state dir (~/.localterm/),
20
+ // next to the daemon's other per-project state (automations.json, server.log).
21
+ const WORKTREES_PARENT_DIR = path.join(HOME, ".localterm", "worktrees");
22
+ // Marker file placed in each project folder so a second repo with the same
23
+ // project name (but a different main worktree path) gets its own folder instead
24
+ // of colliding with the first repo's worktrees.
25
+ const REPO_MARKER_FILENAME = ".localterm-repo-id";
26
+ const REPO_ID_HASH_LENGTH = 12;
27
+ const PROJECT_FOLDER_HASH_LENGTH = 6;
28
+ const MAX_PROJECT_FOLDER_ATTEMPTS = 100;
29
+ const MAX_WORKTREE_NAME_ATTEMPTS = 50;
30
+ // Tildify an absolute path against the daemon's home. The browser can't resolve
31
+ // the home dir itself, so the server does it for display strings (the absolute
32
+ // `path` is always sent back unchanged for actions like opening a shell).
33
+ const tildifyHome = (absolutePath) => {
34
+ const resolved = path.resolve(absolutePath);
35
+ if (resolved === HOME)
36
+ return "~";
37
+ if (resolved.startsWith(`${HOME}${PATH_SEPARATOR}`))
38
+ return `~${resolved.slice(HOME.length)}`;
39
+ return resolved;
40
+ };
41
+ // Stable per-repo identity: a short hash of the main worktree's absolute path.
42
+ // Two repos with the same project name but different paths get different ids, so
43
+ // their worktree folders don't collide.
44
+ const repoId = (mainRoot) => crypto.createHash("sha256").update(mainRoot).digest("hex").slice(0, REPO_ID_HASH_LENGTH);
45
+ const readRepoMarker = (dir) => {
46
+ try {
47
+ const content = fs.readFileSync(path.join(dir, REPO_MARKER_FILENAME), "utf8").trim();
48
+ return content || null;
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ };
54
+ const writeRepoMarker = (dir, id) => {
55
+ try {
56
+ fs.writeFileSync(path.join(dir, REPO_MARKER_FILENAME), id);
57
+ }
58
+ catch {
59
+ // A marker write failure isn't fatal — the folder still works; we just
60
+ // can't disambiguate a future same-named repo.
61
+ }
62
+ };
63
+ // Read-only resolution of the project folder NAME (for display). Mirrors
64
+ // ensureProjectFolder's logic without creating dirs or writing markers, so
65
+ // listGitWorktrees stays side-effect-free.
66
+ const resolveProjectFolderName = (projectName, id) => {
67
+ const preferred = path.join(WORKTREES_PARENT_DIR, projectName);
68
+ if (!fs.existsSync(preferred))
69
+ return projectName;
70
+ if (readRepoMarker(preferred) === id)
71
+ return projectName;
72
+ return `${projectName}-${id.slice(0, PROJECT_FOLDER_HASH_LENGTH)}`;
73
+ };
74
+ // Resolve + create the project folder, claiming it with the repo marker so a
75
+ // later same-named repo from a different path gets its own folder. Idempotent:
76
+ // re-uses an existing folder owned by this repo.
77
+ const ensureProjectFolder = (projectName, id) => {
78
+ const preferred = path.join(WORKTREES_PARENT_DIR, projectName);
79
+ if (!fs.existsSync(preferred)) {
80
+ fs.mkdirSync(preferred, { recursive: true });
81
+ writeRepoMarker(preferred, id);
82
+ return preferred;
83
+ }
84
+ if (readRepoMarker(preferred) === id) {
85
+ writeRepoMarker(preferred, id);
86
+ return preferred;
87
+ }
88
+ // Bare name is owned by a different repo. Fall back to a hashed name, then a
89
+ // counter if even that is taken by a third repo (near-impossible at 6 hex).
90
+ const hashedName = `${projectName}-${id.slice(0, PROJECT_FOLDER_HASH_LENGTH)}`;
91
+ let candidate = path.join(WORKTREES_PARENT_DIR, hashedName);
92
+ for (let attempt = 0; attempt < MAX_PROJECT_FOLDER_ATTEMPTS; attempt++) {
93
+ if (!fs.existsSync(candidate)) {
94
+ fs.mkdirSync(candidate, { recursive: true });
95
+ writeRepoMarker(candidate, id);
96
+ return candidate;
97
+ }
98
+ if (readRepoMarker(candidate) === id) {
99
+ writeRepoMarker(candidate, id);
100
+ return candidate;
101
+ }
102
+ candidate = path.join(WORKTREES_PARENT_DIR, `${hashedName}-${attempt + 2}`);
103
+ }
104
+ throw new WorktreeError("couldn't find a free project folder");
105
+ };
106
+ const isGitRepo = async (cwd) => {
107
+ const result = await runGit(cwd, ["rev-parse", "--is-inside-work-tree"]);
108
+ return result.exitCode === 0;
109
+ };
110
+ // The worktree the caller's cwd lives in (its toplevel root), so the matching
111
+ // entry can be flagged `isCurrent`. Cheaper than asking git to mark it: a single
112
+ // rev-parse vs a porcelain walk that already happened.
113
+ const currentWorktreeRoot = async (cwd) => {
114
+ const result = await runGit(cwd, ["rev-parse", "--show-toplevel"]);
115
+ if (result.exitCode !== 0)
116
+ return null;
117
+ const root = result.stdout.toString("utf8").trim();
118
+ return root || null;
119
+ };
120
+ // The main worktree's root — the parent of the shared common .git dir. Stable
121
+ // across linked worktrees (they all share it), so the derived project name and
122
+ // repo id don't depend on which worktree the caller's cwd happens to be in: a
123
+ // worktree created from inside a linked worktree still lands under the repo's
124
+ // own project folder. Resolved through realpath so it matches the paths git
125
+ // prints in `worktree list --porcelain` (git resolves symlinks; a naive
126
+ // path.resolve against a symlinked cwd would not).
127
+ const mainWorktreeRoot = async (cwd) => {
128
+ const result = await runGit(cwd, ["rev-parse", "--git-common-dir"]);
129
+ if (result.exitCode !== 0)
130
+ return null;
131
+ const commonDir = result.stdout.toString("utf8").trim();
132
+ if (!commonDir)
133
+ return null;
134
+ const root = path.dirname(path.resolve(cwd, commonDir));
135
+ try {
136
+ return fs.realpathSync(root);
137
+ }
138
+ catch {
139
+ return root;
140
+ }
141
+ };
142
+ // `git worktree list --porcelain` emits one block per worktree, fields on their
143
+ // own lines, blocks separated by a blank line:
144
+ //
145
+ // worktree /abs/path/to/main
146
+ // HEAD <sha>
147
+ // branch refs/heads/main
148
+ //
149
+ // worktree /abs/path/to/feature
150
+ // HEAD <sha>
151
+ // detached
152
+ // locked
153
+ // prunable
154
+ //
155
+ // The leading "worktree" line carries the path; HEAD/branch/detached/locked/
156
+ // prunable are optional flags. Parse defensively: unknown fields are ignored
157
+ // so future git output doesn't break the list.
158
+ const parseWorktreePorcelain = (raw) => {
159
+ const entries = [];
160
+ let current = null;
161
+ for (const line of raw.split("\n")) {
162
+ if (line === "") {
163
+ if (current) {
164
+ entries.push(current);
165
+ current = null;
35
166
  }
167
+ continue;
36
168
  }
37
- if (!path || !commit)
169
+ const spaceIndex = line.indexOf(" ");
170
+ const field = spaceIndex === -1 ? line : line.slice(0, spaceIndex);
171
+ const value = spaceIndex === -1 ? "" : line.slice(spaceIndex + 1);
172
+ if (field === "worktree") {
173
+ current = {
174
+ path: value,
175
+ head: null,
176
+ branch: null,
177
+ detached: false,
178
+ locked: false,
179
+ prunable: false,
180
+ };
38
181
  continue;
39
- worktrees.push({
40
- path,
41
- branch: isDetached || isBare ? null : branch,
42
- commit,
43
- isMain: false,
44
- isLocked,
45
- isBare,
46
- });
47
- }
48
- const repoRoot = worktrees[0]?.path ?? null;
49
- if (repoRoot)
50
- worktrees[0].isMain = true;
51
- return { isRepo: true, repoRoot, worktrees };
52
- };
53
- export const getGitWorktrees = async (cwd) => {
54
- const result = await runGit(cwd, ["worktree", "list", "--porcelain"]);
55
- if (result.exitCode !== 0)
56
- return { isRepo: false, repoRoot: null, worktrees: [] };
57
- return parseGitWorktreeList(result.stdout.toString("utf8"));
182
+ }
183
+ if (!current)
184
+ continue;
185
+ if (field === "HEAD") {
186
+ current.head = value || null;
187
+ }
188
+ else if (field === "branch") {
189
+ // refs/heads/<name> -> <name>. Keep the raw value if it isn't a ref
190
+ // (it never is in porcelain output, but be tolerant).
191
+ current.branch = value.startsWith("refs/heads/")
192
+ ? value.slice("refs/heads/".length)
193
+ : value || null;
194
+ }
195
+ else if (field === "detached") {
196
+ current.detached = true;
197
+ }
198
+ else if (field === "locked") {
199
+ current.locked = true;
200
+ }
201
+ else if (field === "prunable") {
202
+ current.prunable = true;
203
+ }
204
+ }
205
+ if (current)
206
+ entries.push(current);
207
+ return entries;
208
+ };
209
+ const toWorktree = (parsed, currentRoot, mainRoot) => ({
210
+ path: parsed.path,
211
+ displayPath: tildifyHome(parsed.path),
212
+ branch: parsed.detached ? null : parsed.branch,
213
+ head: parsed.head,
214
+ isCurrent: currentRoot !== null && path.resolve(parsed.path) === path.resolve(currentRoot),
215
+ isMain: mainRoot !== null && path.resolve(parsed.path) === path.resolve(mainRoot),
216
+ isLocked: parsed.locked,
217
+ isPrunable: parsed.prunable,
218
+ });
219
+ export const listGitWorktrees = async (cwd) => {
220
+ if (!(await isGitRepo(cwd)))
221
+ return { isRepo: false, worktrees: [], displayBaseDir: null };
222
+ const [listResult, currentRoot, mainRoot] = await Promise.all([
223
+ runGit(cwd, ["worktree", "list", "--porcelain"]),
224
+ currentWorktreeRoot(cwd),
225
+ mainWorktreeRoot(cwd),
226
+ ]);
227
+ if (listResult.exitCode !== 0) {
228
+ throw new WorktreeError(listResult.stderr.trim() || "git worktree list failed");
229
+ }
230
+ const parsed = parseWorktreePorcelain(listResult.stdout.toString("utf8"));
231
+ const worktrees = parsed.map((entry) => toWorktree(entry, currentRoot, mainRoot));
232
+ let displayBaseDir = null;
233
+ if (mainRoot) {
234
+ const projectName = path.basename(mainRoot);
235
+ if (projectName) {
236
+ displayBaseDir = tildifyHome(path.join(WORKTREES_PARENT_DIR, resolveProjectFolderName(projectName, repoId(mainRoot))));
237
+ }
238
+ }
239
+ return { isRepo: true, worktrees, displayBaseDir };
240
+ };
241
+ // Create a worktree under ~/.localterm/worktrees/<project>/ on a memorable
242
+ // auto-generated branch (adjective-noun) from HEAD. The branch and folder name
243
+ // match, so the folder is self-describing. A collision (branch or folder
244
+ // already exists) retries with a fresh phrase; any other git failure is
245
+ // surfaced immediately.
246
+ export const createGitWorktree = async (cwd) => {
247
+ const mainRoot = await mainWorktreeRoot(cwd);
248
+ if (!mainRoot)
249
+ throw new WorktreeError("couldn't resolve the repository's main worktree");
250
+ const projectName = path.basename(mainRoot);
251
+ if (!projectName)
252
+ throw new WorktreeError("couldn't resolve the repository's project name");
253
+ const projectDir = ensureProjectFolder(projectName, repoId(mainRoot));
254
+ let lastError = null;
255
+ const attempted = new Set();
256
+ for (let attempt = 0; attempt < MAX_WORKTREE_NAME_ATTEMPTS; attempt++) {
257
+ const name = generateWorktreeName(attempted);
258
+ attempted.add(name);
259
+ const targetPath = path.join(projectDir, name);
260
+ const result = await runGit(cwd, ["worktree", "add", "-b", name, targetPath]);
261
+ if (result.exitCode === 0)
262
+ return { path: targetPath, branch: name };
263
+ const stderr = result.stderr.trim();
264
+ if (/already exists/i.test(stderr)) {
265
+ lastError = new WorktreeError(stderr);
266
+ continue;
267
+ }
268
+ throw new WorktreeError(stderr || "git worktree add failed");
269
+ }
270
+ throw lastError ?? new WorktreeError("couldn't find a free worktree name");
271
+ };
272
+ export const removeGitWorktree = async (cwd, targetPath) => {
273
+ // The main worktree is never removable — not from itself, not from a linked
274
+ // worktree. Guard server-side so a crafted DELETE can't try it (git itself
275
+ // would also refuse, but this gives a clear message before spawning git).
276
+ const mainRoot = await mainWorktreeRoot(cwd);
277
+ if (mainRoot) {
278
+ let realTarget = targetPath;
279
+ try {
280
+ realTarget = fs.realpathSync(targetPath);
281
+ }
282
+ catch {
283
+ realTarget = path.resolve(targetPath);
284
+ }
285
+ if (realTarget === mainRoot) {
286
+ throw new WorktreeError("can't remove the main worktree");
287
+ }
288
+ }
289
+ const result = await runGit(cwd, ["worktree", "remove", targetPath]);
290
+ if (result.exitCode !== 0) {
291
+ throw new WorktreeError(result.stderr.trim() || "git worktree remove failed");
292
+ }
58
293
  };
59
294
  //# sourceMappingURL=git-worktrees.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-worktrees.js","sourceRoot":"","sources":["../src/git-worktrees.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,cAAc,GAAG,CAAC,GAAW,EAAU,EAAE,CAC7C,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAExE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAA2B,EAAE;IAC5E,MAAM,MAAM,GAAG,IAAI;SAChB,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,MAAM,SAAS,GAAkB,EAAE,CAAC;IAEpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAkB,IAAI,CAAC;QACjC,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBACjC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACxC,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACtC,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YACxD,CAAC;iBAAM,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC/B,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;iBAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC3B,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrC,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM;YAAE,SAAS;QAC/B,SAAS,CAAC,IAAI,CAAC;YACb,IAAI;YACJ,MAAM,EAAE,UAAU,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;YAC5C,MAAM;YACN,MAAM,EAAE,KAAK;YACb,QAAQ;YACR,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;IAC5C,IAAI,QAAQ;QAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,GAAW,EAAoC,EAAE;IACrF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IACtE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IACnF,OAAO,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC"}
1
+ {"version":3,"file":"git-worktrees.js","sourceRoot":"","sources":["../src/git-worktrees.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { BatteryProbe } from "./caffeinate-battery.js";
1
2
  import { CaffeinateController } from "./caffeinate-controller.js";
2
3
  import type { SnapshotProcesses } from "./caffeinate-process-match.js";
3
4
  import { SessionRegistry } from "./session-registry.js";
@@ -26,6 +27,12 @@ export interface ServerOptions {
26
27
  * deterministically without spawning processes.
27
28
  */
28
29
  caffeinateSnapshotProcesses?: SnapshotProcesses;
30
+ /**
31
+ * Override how keep-awake reads the machine's battery. Defaults to a real
32
+ * `pmset -g batt` read. Injectable so tests can drive the battery floor
33
+ * deterministically without shelling out.
34
+ */
35
+ caffeinateBatteryProbe?: BatteryProbe;
29
36
  }
30
37
  /** Opens and (optionally) closes the browser tab for an automation run. */
31
38
  export interface AutomationTabController {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAGlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AA2DvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkBxD,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,iBAAiB,CAAC;CACjD;AAED,2EAA2E;AAC3E,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,0EAA0E;IAC1E,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AA+DD,eAAO,MAAM,YAAY,GAAU,UAAS,aAAkB,KAAG,OAAO,CAAC,aAAa,CAq9BrF,CAAC;AAEF,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,YAAY,EACV,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAGlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AA4DvE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkBxD,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,iBAAiB,CAAC;IAChD;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,YAAY,CAAC;CACvC;AAED,2EAA2E;AAC3E,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,0EAA0E;IAC1E,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AA+DD,eAAO,MAAM,YAAY,GAAU,UAAS,aAAkB,KAAG,OAAO,CAAC,aAAa,CAshCrF,CAAC;AAEF,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,YAAY,EACV,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AACpC,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ import { getGitBranchInfo, getGitBranchPr, getGitDiff, getGitDiffFilePatch, getG
21
21
  import { GitDiffWatcher, GIT_DIFF_WATCHER_EVENT_NAMES, } from "./git-diff-watcher.js";
22
22
  import { HeartbeatStore } from "./heartbeat-store.js";
23
23
  import { parseCronExpression } from "./cron-expression.js";
24
+ import { createGitWorktree, listGitWorktrees, removeGitWorktree } from "./git-worktrees.js";
24
25
  import { clientToServerMessageSchema, createAutomationInputSchema, resetAutomationInputSchema, updateAutomationInputSchema, } from "./schemas.js";
25
26
  import { Session } from "./session.js";
26
27
  import { createNetworkPolicyMiddleware, isAllowedSourceIp, isLoopbackHost } from "./security.js";
@@ -137,6 +138,7 @@ export const createServer = async (options = {}) => {
137
138
  store: caffeinatePreferencesStore,
138
139
  listSessionPids: () => registry.pids(),
139
140
  snapshotProcesses: options.caffeinateSnapshotProcesses,
141
+ batteryProbe: options.caffeinateBatteryProbe,
140
142
  hasRecentOutput: (pids, withinMs) => registry.hasRecentOutput(pids, withinMs),
141
143
  });
142
144
  const clientSockets = new Set();
@@ -210,6 +212,7 @@ export const createServer = async (options = {}) => {
210
212
  active: caffeinateManager.active,
211
213
  mode: caffeinateManager.mode,
212
214
  activityGate: caffeinateManager.activityGate,
215
+ batteryThreshold: caffeinateManager.batteryThreshold,
213
216
  defaultCommands: [...caffeinateManager.defaultCommands],
214
217
  commands: caffeinateManager.commands,
215
218
  activeTrigger: caffeinateManager.activeTrigger,
@@ -422,6 +425,61 @@ export const createServer = async (options = {}) => {
422
425
  return undefined;
423
426
  }
424
427
  };
428
+ // Resolve a worktree path (create target / remove target). Relative paths are
429
+ // anchored to the caller's cwd so the client can pass a project-relative name;
430
+ // absolute paths pass through. No traversal/containment check — the daemon
431
+ // already hands out unrestricted shells, so creating a worktree elsewhere is
432
+ // not an escalation.
433
+ const resolveWorktreePath = (cwd, rawPath) => {
434
+ if (!rawPath)
435
+ return null;
436
+ const trimmed = rawPath.trim();
437
+ if (!trimmed)
438
+ return null;
439
+ return path.resolve(cwd, trimmed);
440
+ };
441
+ const worktreeErrorMessage = (error) => error instanceof Error ? error.message : "git operation failed";
442
+ // Every worktree sharing the caller's repo. `git worktree list` returns the
443
+ // whole linked set from any worktree, so this single read is the complete
444
+ // project view — no store, no per-worktree tracking.
445
+ api.get("/git/worktrees", async (context) => {
446
+ const cwd = resolveCwdQuery(context.req.query("cwd"));
447
+ if (!cwd)
448
+ return context.json({ error: "invalid_cwd" }, HTTP_STATUS_BAD_REQUEST);
449
+ try {
450
+ return context.json(await listGitWorktrees(cwd));
451
+ }
452
+ catch (error) {
453
+ return context.json({ error: "git_failed", message: worktreeErrorMessage(error) }, HTTP_STATUS_BAD_REQUEST);
454
+ }
455
+ });
456
+ api.post("/git/worktrees", async (context) => {
457
+ const cwd = resolveCwdQuery(context.req.query("cwd"));
458
+ if (!cwd)
459
+ return context.json({ error: "invalid_cwd" }, HTTP_STATUS_BAD_REQUEST);
460
+ try {
461
+ const result = await createGitWorktree(cwd);
462
+ return context.json(result, HTTP_STATUS_CREATED);
463
+ }
464
+ catch (error) {
465
+ return context.json({ error: "git_failed", message: worktreeErrorMessage(error) }, HTTP_STATUS_BAD_REQUEST);
466
+ }
467
+ });
468
+ api.delete("/git/worktrees", async (context) => {
469
+ const cwd = resolveCwdQuery(context.req.query("cwd"));
470
+ if (!cwd)
471
+ return context.json({ error: "invalid_cwd" }, HTTP_STATUS_BAD_REQUEST);
472
+ const targetPath = resolveWorktreePath(cwd, context.req.query("path"));
473
+ if (!targetPath)
474
+ return context.json({ error: "invalid_path" }, HTTP_STATUS_BAD_REQUEST);
475
+ try {
476
+ await removeGitWorktree(cwd, targetPath);
477
+ return context.json({ ok: true });
478
+ }
479
+ catch (error) {
480
+ return context.json({ error: "git_failed", message: worktreeErrorMessage(error) }, HTTP_STATUS_BAD_REQUEST);
481
+ }
482
+ });
425
483
  // A trigger is valid iff a schedule trigger compiles to ≥1 parseable cron;
426
484
  // watch and event triggers are always valid (their cwd is validated
427
485
  // separately).
@@ -833,6 +891,9 @@ export const createServer = async (options = {}) => {
833
891
  else if (parsed.data.type === "caffeinate-activity-gate") {
834
892
  caffeinateManager.setActivityGate(parsed.data.enabled);
835
893
  }
894
+ else if (parsed.data.type === "caffeinate-battery-threshold") {
895
+ caffeinateManager.setBatteryThreshold(parsed.data.percent);
896
+ }
836
897
  else {
837
898
  session.resize(parsed.data.cols, parsed.data.rows, parsed.data.pixelWidth, parsed.data.pixelHeight);
838
899
  }