crewly 1.20.301 → 1.20.302
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/config/skills/agent/core/receive-file/SKILL.md +4 -0
- package/config/skills/agent/core/request-file/SKILL.md +74 -0
- package/config/skills/agent/core/request-file/execute.sh +89 -0
- package/config/skills/agent/core/request-file/execute.test.sh +77 -0
- package/config/skills/agent/core/slack-file/SKILL.md +1 -1
- package/dist/backend/backend/src/constants.d.ts +13 -4
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +18 -6
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.controller.d.ts +9 -0
- package/dist/backend/backend/src/controllers/apps/apps.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.controller.js +21 -0
- package/dist/backend/backend/src/controllers/apps/apps.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.routes.d.ts +2 -0
- package/dist/backend/backend/src/controllers/apps/apps.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.routes.js +7 -1
- package/dist/backend/backend/src/controllers/apps/apps.routes.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/backend/backend/src/services/apps/apps.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/apps/apps.wiring.js +14 -0
- package/dist/backend/backend/src/services/apps/apps.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/apps/file-request-watch.service.d.ts +88 -0
- package/dist/backend/backend/src/services/apps/file-request-watch.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/apps/file-request-watch.service.js +170 -0
- package/dist/backend/backend/src/services/apps/file-request-watch.service.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +51 -33
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/types/slack.types.d.ts +8 -0
- package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/slack.types.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +13 -4
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +18 -6
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +51 -33
- package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/cli/backend/src/services/worktree/low-disk-guard.d.ts +109 -0
- package/dist/cli/backend/src/services/worktree/low-disk-guard.d.ts.map +1 -0
- package/dist/cli/backend/src/services/worktree/low-disk-guard.js +148 -0
- package/dist/cli/backend/src/services/worktree/low-disk-guard.js.map +1 -0
- package/dist/cli/backend/src/services/worktree/worktree-janitor.git.d.ts +224 -0
- package/dist/cli/backend/src/services/worktree/worktree-janitor.git.d.ts.map +1 -0
- package/dist/cli/backend/src/services/worktree/worktree-janitor.git.js +449 -0
- package/dist/cli/backend/src/services/worktree/worktree-janitor.git.js.map +1 -0
- package/dist/cli/backend/src/types/slack.types.d.ts +8 -0
- package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/slack.types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-disk guard — pure helpers for the disk janitor's free-space check.
|
|
3
|
+
*
|
|
4
|
+
* The janitor checks free space on the volume holding CREWLY_HOME every
|
|
5
|
+
* 10 minutes. Below 15 GB it cleans up at once with shorter idle thresholds;
|
|
6
|
+
* if space is still short it tells the owner (at most once per 24 h, or once
|
|
7
|
+
* per 6 h and marked urgent below 5 GB) what it could not remove and why.
|
|
8
|
+
* This file holds the decisions and the wording; the service does the I/O.
|
|
9
|
+
*
|
|
10
|
+
* @module services/worktree/low-disk-guard
|
|
11
|
+
*/
|
|
12
|
+
/** Subset of `fs.StatFs` the guard needs (numbers or bigints). */
|
|
13
|
+
export interface StatFsLike {
|
|
14
|
+
/** Free blocks available to unprivileged users */
|
|
15
|
+
bavail: number | bigint;
|
|
16
|
+
/** Block size in bytes */
|
|
17
|
+
bsize: number | bigint;
|
|
18
|
+
}
|
|
19
|
+
/** `fs.promises.statfs`-compatible probe. */
|
|
20
|
+
export type StatFsFn = (p: string) => Promise<StatFsLike>;
|
|
21
|
+
/** Disk level relative to the thresholds. */
|
|
22
|
+
export type DiskLevel = 'ok' | 'low' | 'critical';
|
|
23
|
+
/** When the owner was last told about low disk (persisted). */
|
|
24
|
+
export interface LowDiskNoticeState {
|
|
25
|
+
/** Last notice of any kind (ms epoch) */
|
|
26
|
+
lastNoticeAt?: number;
|
|
27
|
+
/** Last urgent notice (ms epoch) */
|
|
28
|
+
lastUrgentAt?: number;
|
|
29
|
+
}
|
|
30
|
+
/** Something the janitor looked at and left on disk. */
|
|
31
|
+
export interface KeptItem {
|
|
32
|
+
/** Absolute path */
|
|
33
|
+
path: string;
|
|
34
|
+
/** Size in bytes */
|
|
35
|
+
bytes: number;
|
|
36
|
+
/** Janitor reason code (`dirty`, `not-merged`, `unpushed`, …) */
|
|
37
|
+
reason: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Free bytes on the volume holding `p`.
|
|
41
|
+
*
|
|
42
|
+
* @param p - Any path on the volume
|
|
43
|
+
* @param statfs - Probe (default `fs.promises.statfs`)
|
|
44
|
+
* @returns Free bytes for unprivileged users, or null when the probe failed
|
|
45
|
+
*/
|
|
46
|
+
export declare function readFreeBytes(p: string, statfs?: StatFsFn): Promise<number | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Classify free space.
|
|
49
|
+
*
|
|
50
|
+
* @param freeBytes - Free bytes
|
|
51
|
+
* @returns `critical` below CRITICAL_DISK_BYTES, `low` below LOW_DISK_BYTES, else `ok`
|
|
52
|
+
*/
|
|
53
|
+
export declare function diskLevel(freeBytes: number): DiskLevel;
|
|
54
|
+
/**
|
|
55
|
+
* Idle threshold to use, shortened in low-disk mode.
|
|
56
|
+
*
|
|
57
|
+
* @param normalMs - Threshold in normal mode
|
|
58
|
+
* @param lowDisk - Whether free space is below LOW_DISK_BYTES
|
|
59
|
+
* @returns `normalMs`, or `normalMs / LOW_DISK_IDLE_DIVISOR` floored at LOW_DISK_MIN_IDLE_FLOOR_MS
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* idleThreshold(24 * HOUR, true); // 12 h
|
|
64
|
+
* idleThreshold(2 * HOUR, true); // 2 h (floor)
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function idleThreshold(normalMs: number, lowDisk: boolean): number;
|
|
68
|
+
/**
|
|
69
|
+
* Whether to tell the owner now, and how.
|
|
70
|
+
*
|
|
71
|
+
* @param level - Current disk level (after cleanup)
|
|
72
|
+
* @param state - When the owner was last told
|
|
73
|
+
* @param now - Current time (ms)
|
|
74
|
+
* @returns `urgent`, `normal`, or null (nothing to send)
|
|
75
|
+
*/
|
|
76
|
+
export declare function noticeToSend(level: DiskLevel, state: LowDiskNoticeState, now: number): 'urgent' | 'normal' | null;
|
|
77
|
+
/**
|
|
78
|
+
* The state after a notice went out.
|
|
79
|
+
*
|
|
80
|
+
* @param state - Previous state
|
|
81
|
+
* @param kind - What was sent
|
|
82
|
+
* @param now - Send time (ms)
|
|
83
|
+
* @returns New state
|
|
84
|
+
*/
|
|
85
|
+
export declare function recordNotice(state: LowDiskNoticeState, kind: 'urgent' | 'normal', now: number): LowDiskNoticeState;
|
|
86
|
+
/**
|
|
87
|
+
* Plain-English reason for a kept item.
|
|
88
|
+
*
|
|
89
|
+
* @param reason - Janitor reason code
|
|
90
|
+
* @returns Short phrase ("has changes that were never committed")
|
|
91
|
+
*/
|
|
92
|
+
export declare function describeReason(reason: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Owner notice for low disk: free space, what was freed, and the biggest
|
|
95
|
+
* items left with the reason, short enough for a phone.
|
|
96
|
+
*
|
|
97
|
+
* @param input - Free bytes, urgency, bytes freed this pass, kept items
|
|
98
|
+
* @returns Title and message
|
|
99
|
+
*/
|
|
100
|
+
export declare function buildLowDiskNotice(input: {
|
|
101
|
+
freeBytes: number;
|
|
102
|
+
urgent: boolean;
|
|
103
|
+
freedBytes: number;
|
|
104
|
+
items: KeptItem[];
|
|
105
|
+
}): {
|
|
106
|
+
title: string;
|
|
107
|
+
message: string;
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=low-disk-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"low-disk-guard.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/worktree/low-disk-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,kEAAkE;AAClE,MAAM,WAAW,UAAU;IAC1B,kDAAkD;IAClD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,6CAA6C;AAC7C,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAE1D,6CAA6C;AAC7C,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,UAAU,CAAC;AAElD,+DAA+D;AAC/D,MAAM,WAAW,kBAAkB;IAClC,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wDAAwD;AACxD,MAAM,WAAW,QAAQ;IACxB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,QAAwB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOvG;AAMD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAItD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAQjH;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAElH;AAqBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;CAClB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAkBrC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-disk guard — pure helpers for the disk janitor's free-space check.
|
|
3
|
+
*
|
|
4
|
+
* The janitor checks free space on the volume holding CREWLY_HOME every
|
|
5
|
+
* 10 minutes. Below 15 GB it cleans up at once with shorter idle thresholds;
|
|
6
|
+
* if space is still short it tells the owner (at most once per 24 h, or once
|
|
7
|
+
* per 6 h and marked urgent below 5 GB) what it could not remove and why.
|
|
8
|
+
* This file holds the decisions and the wording; the service does the I/O.
|
|
9
|
+
*
|
|
10
|
+
* @module services/worktree/low-disk-guard
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import { WORKTREE_JANITOR_CONSTANTS } from '../../constants.js';
|
|
14
|
+
import { formatBytes } from './worktree-janitor.git.js';
|
|
15
|
+
/**
|
|
16
|
+
* Free bytes on the volume holding `p`.
|
|
17
|
+
*
|
|
18
|
+
* @param p - Any path on the volume
|
|
19
|
+
* @param statfs - Probe (default `fs.promises.statfs`)
|
|
20
|
+
* @returns Free bytes for unprivileged users, or null when the probe failed
|
|
21
|
+
*/
|
|
22
|
+
export async function readFreeBytes(p, statfs = defaultStatFs) {
|
|
23
|
+
try {
|
|
24
|
+
const s = await statfs(p);
|
|
25
|
+
return Number(s.bavail) * Number(s.bsize);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function defaultStatFs(p) {
|
|
32
|
+
return fs.promises.statfs(p);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Classify free space.
|
|
36
|
+
*
|
|
37
|
+
* @param freeBytes - Free bytes
|
|
38
|
+
* @returns `critical` below CRITICAL_DISK_BYTES, `low` below LOW_DISK_BYTES, else `ok`
|
|
39
|
+
*/
|
|
40
|
+
export function diskLevel(freeBytes) {
|
|
41
|
+
if (freeBytes < WORKTREE_JANITOR_CONSTANTS.CRITICAL_DISK_BYTES)
|
|
42
|
+
return 'critical';
|
|
43
|
+
if (freeBytes < WORKTREE_JANITOR_CONSTANTS.LOW_DISK_BYTES)
|
|
44
|
+
return 'low';
|
|
45
|
+
return 'ok';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Idle threshold to use, shortened in low-disk mode.
|
|
49
|
+
*
|
|
50
|
+
* @param normalMs - Threshold in normal mode
|
|
51
|
+
* @param lowDisk - Whether free space is below LOW_DISK_BYTES
|
|
52
|
+
* @returns `normalMs`, or `normalMs / LOW_DISK_IDLE_DIVISOR` floored at LOW_DISK_MIN_IDLE_FLOOR_MS
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* idleThreshold(24 * HOUR, true); // 12 h
|
|
57
|
+
* idleThreshold(2 * HOUR, true); // 2 h (floor)
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function idleThreshold(normalMs, lowDisk) {
|
|
61
|
+
if (!lowDisk)
|
|
62
|
+
return normalMs;
|
|
63
|
+
const halved = normalMs / WORKTREE_JANITOR_CONSTANTS.LOW_DISK_IDLE_DIVISOR;
|
|
64
|
+
return Math.max(Math.min(normalMs, WORKTREE_JANITOR_CONSTANTS.LOW_DISK_MIN_IDLE_FLOOR_MS), halved);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Whether to tell the owner now, and how.
|
|
68
|
+
*
|
|
69
|
+
* @param level - Current disk level (after cleanup)
|
|
70
|
+
* @param state - When the owner was last told
|
|
71
|
+
* @param now - Current time (ms)
|
|
72
|
+
* @returns `urgent`, `normal`, or null (nothing to send)
|
|
73
|
+
*/
|
|
74
|
+
export function noticeToSend(level, state, now) {
|
|
75
|
+
if (level === 'ok')
|
|
76
|
+
return null;
|
|
77
|
+
if (level === 'critical') {
|
|
78
|
+
const last = state.lastUrgentAt;
|
|
79
|
+
return last === undefined || now - last >= WORKTREE_JANITOR_CONSTANTS.CRITICAL_DISK_NOTIFY_INTERVAL_MS ? 'urgent' : null;
|
|
80
|
+
}
|
|
81
|
+
const last = state.lastNoticeAt;
|
|
82
|
+
return last === undefined || now - last >= WORKTREE_JANITOR_CONSTANTS.LOW_DISK_NOTIFY_INTERVAL_MS ? 'normal' : null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The state after a notice went out.
|
|
86
|
+
*
|
|
87
|
+
* @param state - Previous state
|
|
88
|
+
* @param kind - What was sent
|
|
89
|
+
* @param now - Send time (ms)
|
|
90
|
+
* @returns New state
|
|
91
|
+
*/
|
|
92
|
+
export function recordNotice(state, kind, now) {
|
|
93
|
+
return { ...state, lastNoticeAt: now, ...(kind === 'urgent' ? { lastUrgentAt: now } : {}) };
|
|
94
|
+
}
|
|
95
|
+
const REASON_TEXT = {
|
|
96
|
+
dirty: 'has changes that were never committed',
|
|
97
|
+
'not-merged': 'has work that is not merged yet',
|
|
98
|
+
unpushed: 'has commits that were never pushed',
|
|
99
|
+
stash: 'has stashed changes',
|
|
100
|
+
'no-remote': 'is a git repo with no remote, so its history may exist nowhere else',
|
|
101
|
+
'has-external-worktrees': 'has a worktree somewhere else that depends on it',
|
|
102
|
+
'contains-worktree': 'holds a worktree that is still in use or not finished',
|
|
103
|
+
recent: 'was used recently',
|
|
104
|
+
locked: 'is locked by a running tool',
|
|
105
|
+
'process-inside': 'a program is still open in it',
|
|
106
|
+
'agent-session-inside': 'an agent is working in it',
|
|
107
|
+
'cwd-probe-failed': 'could not check whether a program is using it',
|
|
108
|
+
'managed-by-workitem-worktrees': 'belongs to an open task',
|
|
109
|
+
'status-failed': 'git could not read it',
|
|
110
|
+
'git-failed': 'git could not read it',
|
|
111
|
+
'remove-failed': 'deleting it failed',
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Plain-English reason for a kept item.
|
|
115
|
+
*
|
|
116
|
+
* @param reason - Janitor reason code
|
|
117
|
+
* @returns Short phrase ("has changes that were never committed")
|
|
118
|
+
*/
|
|
119
|
+
export function describeReason(reason) {
|
|
120
|
+
return REASON_TEXT[reason] ?? `kept (${reason})`;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Owner notice for low disk: free space, what was freed, and the biggest
|
|
124
|
+
* items left with the reason, short enough for a phone.
|
|
125
|
+
*
|
|
126
|
+
* @param input - Free bytes, urgency, bytes freed this pass, kept items
|
|
127
|
+
* @returns Title and message
|
|
128
|
+
*/
|
|
129
|
+
export function buildLowDiskNotice(input) {
|
|
130
|
+
const title = input.urgent ? 'URGENT: disk almost full' : 'Disk space is running low';
|
|
131
|
+
const lines = [];
|
|
132
|
+
lines.push(`Only ${formatBytes(input.freeBytes)} free on this machine.${input.urgent ? ' Crewly and the agents may stop working soon.' : ''}`);
|
|
133
|
+
lines.push(input.freedBytes > 0
|
|
134
|
+
? `I cleaned up ${formatBytes(input.freedBytes)} of finished work, but it is not enough.`
|
|
135
|
+
: 'I found nothing more that is safe to delete on my own.');
|
|
136
|
+
const top = [...input.items].sort((a, b) => b.bytes - a.bytes).slice(0, WORKTREE_JANITOR_CONSTANTS.LOW_DISK_REPORT_ITEMS);
|
|
137
|
+
if (top.length > 0) {
|
|
138
|
+
lines.push('', 'Biggest things I left alone:');
|
|
139
|
+
for (const it of top)
|
|
140
|
+
lines.push(`• ${it.path} (${formatBytes(it.bytes)}) — ${describeReason(it.reason)}`);
|
|
141
|
+
lines.push('', 'Tell me which ones can go, or free up space another way.');
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
lines.push('Please free up some space.');
|
|
145
|
+
}
|
|
146
|
+
return { title, message: lines.join('\n') };
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=low-disk-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"low-disk-guard.js","sourceRoot":"","sources":["../../../../../../backend/src/services/worktree/low-disk-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree janitor — low-level helpers.
|
|
3
|
+
*
|
|
4
|
+
* A command runner that never throws, a parser for `git worktree list
|
|
5
|
+
* --porcelain`, path helpers, and the process-cwd probe used to tell whether
|
|
6
|
+
* anything is still working inside a worktree. Kept apart from the service so
|
|
7
|
+
* each piece can be tested on its own.
|
|
8
|
+
*
|
|
9
|
+
* @module services/worktree/worktree-janitor.git
|
|
10
|
+
*/
|
|
11
|
+
/** Result of one external command. `code` is null when it could not start or timed out. */
|
|
12
|
+
export interface CommandResult {
|
|
13
|
+
/** Exit code, or null when the process did not exit normally */
|
|
14
|
+
code: number | null;
|
|
15
|
+
/** Captured stdout */
|
|
16
|
+
stdout: string;
|
|
17
|
+
/** Captured stderr (or the spawn error message) */
|
|
18
|
+
stderr: string;
|
|
19
|
+
}
|
|
20
|
+
/** Options for {@link runCommand}. */
|
|
21
|
+
export interface RunCommandOptions {
|
|
22
|
+
/** Working directory */
|
|
23
|
+
cwd?: string;
|
|
24
|
+
/** Timeout in ms (default: GIT_TIMEOUT_MS) */
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
/** Extra environment variables merged over process.env */
|
|
27
|
+
env?: Record<string, string>;
|
|
28
|
+
/** Text written to the command's stdin (then closed) */
|
|
29
|
+
input?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run a command without a shell and never throw.
|
|
33
|
+
*
|
|
34
|
+
* Git and gh are told never to prompt (no credential dialogs, no pager), so a
|
|
35
|
+
* periodic background job cannot hang on input, and git takes no optional
|
|
36
|
+
* locks (a status never rewrites the index).
|
|
37
|
+
*
|
|
38
|
+
* @param file - Executable (e.g. `git`, `gh`, or an absolute path)
|
|
39
|
+
* @param args - Arguments
|
|
40
|
+
* @param options - cwd / timeout / env
|
|
41
|
+
* @returns Exit code and output; `code` is null on spawn failure or timeout
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const r = await runCommand('git', ['-C', repo, 'status', '--porcelain']);
|
|
46
|
+
* if (r.code === 0 && r.stdout === '') console.log('clean');
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function runCommand(file: string, args: string[], options?: RunCommandOptions): Promise<CommandResult>;
|
|
50
|
+
/** One entry of `git worktree list --porcelain`. */
|
|
51
|
+
export interface PorcelainWorktree {
|
|
52
|
+
/** Absolute worktree path as git reports it */
|
|
53
|
+
path: string;
|
|
54
|
+
/** HEAD commit, or null (bare) */
|
|
55
|
+
head: string | null;
|
|
56
|
+
/** Short branch name (`refs/heads/` stripped), or null when detached */
|
|
57
|
+
branch: string | null;
|
|
58
|
+
/** True for the bare entry */
|
|
59
|
+
bare: boolean;
|
|
60
|
+
/** True when HEAD is detached */
|
|
61
|
+
detached: boolean;
|
|
62
|
+
/** True when the worktree is locked (`git worktree lock`) */
|
|
63
|
+
locked: boolean;
|
|
64
|
+
/** Lock reason, when given */
|
|
65
|
+
lockReason?: string;
|
|
66
|
+
/** True when git reports the directory as gone (`prunable`) */
|
|
67
|
+
prunable: boolean;
|
|
68
|
+
/** True for the first entry — the main worktree */
|
|
69
|
+
isMain: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Parse `git worktree list --porcelain` output.
|
|
73
|
+
*
|
|
74
|
+
* Entries are separated by blank lines; the first entry is the main worktree.
|
|
75
|
+
*
|
|
76
|
+
* @param output - Raw porcelain output
|
|
77
|
+
* @returns Parsed entries in git's order
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* parsePorcelainWorktrees('worktree /r\nHEAD abc\nbranch refs/heads/main\n');
|
|
82
|
+
* // [{ path: '/r', head: 'abc', branch: 'main', isMain: true, ... }]
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function parsePorcelainWorktrees(output: string): PorcelainWorktree[];
|
|
86
|
+
/**
|
|
87
|
+
* Real path of `p`, or its resolved form when it does not exist.
|
|
88
|
+
*
|
|
89
|
+
* @param p - Path
|
|
90
|
+
* @returns Canonical path for comparisons
|
|
91
|
+
*/
|
|
92
|
+
export declare function canonicalPath(p: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Whether `child` is `parent` or inside it (both canonicalised first).
|
|
95
|
+
*
|
|
96
|
+
* @param child - Candidate path
|
|
97
|
+
* @param parent - Directory
|
|
98
|
+
* @returns True when child === parent or child is under parent
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* isPathInside('/r/.claude/worktrees/a/src', '/r/.claude/worktrees/a'); // true
|
|
103
|
+
* isPathInside('/r/.claude/worktrees/ab', '/r/.claude/worktrees/a'); // false
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare function isPathInside(child: string, parent: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Latest modification time (ms) of a worktree: the directory itself plus its
|
|
109
|
+
* private git dir's `index`, `HEAD` and `logs/HEAD` — every commit, checkout,
|
|
110
|
+
* stage or reset touches one of those. Uncommitted edits are caught by the
|
|
111
|
+
* dirty check instead.
|
|
112
|
+
*
|
|
113
|
+
* @param worktreePath - Worktree root
|
|
114
|
+
* @param gitDir - Its private git dir (`.git/worktrees/<name>`), when known
|
|
115
|
+
* @returns Newest mtime in ms, or null when nothing could be stat'ed
|
|
116
|
+
*/
|
|
117
|
+
export declare function latestWorktreeMtimeMs(worktreePath: string, gitDir: string | null): number | null;
|
|
118
|
+
/**
|
|
119
|
+
* Current working directories of every process this user can see.
|
|
120
|
+
*
|
|
121
|
+
* macOS: `lsof -a -d cwd -u <uid> -Fn`. Linux: `/proc/<pid>/cwd`. Returns
|
|
122
|
+
* null when the probe cannot run, so the caller can treat "unknown" as busy.
|
|
123
|
+
*
|
|
124
|
+
* @returns Absolute cwd paths (deduplicated), or null when unavailable
|
|
125
|
+
*/
|
|
126
|
+
export declare function listProcessCwds(): Promise<string[] | null>;
|
|
127
|
+
/**
|
|
128
|
+
* Whether the kill switch disables the janitor.
|
|
129
|
+
*
|
|
130
|
+
* @param env - Environment (defaults to process.env)
|
|
131
|
+
* @returns True when `CREWLY_WORKTREE_JANITOR` is `0`/`off`/`false`/`no`
|
|
132
|
+
*/
|
|
133
|
+
export declare function isJanitorDisabled(env?: NodeJS.ProcessEnv): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Yield to the event loop every YIELD_EVERY_ENTRIES calls, so a long
|
|
136
|
+
* filesystem walk never holds up Slack, relay polls or PTY I/O.
|
|
137
|
+
*/
|
|
138
|
+
export declare class EventLoopYielder {
|
|
139
|
+
private count;
|
|
140
|
+
/**
|
|
141
|
+
* Count one unit of work; every YIELD_EVERY_ENTRIES units, wait one
|
|
142
|
+
* `setImmediate` turn.
|
|
143
|
+
*
|
|
144
|
+
* @returns Resolves when the caller may continue
|
|
145
|
+
*/
|
|
146
|
+
tick(): Promise<void>;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Git dir a `.git` file points to (`gitdir: <path>`), resolved against `dir`.
|
|
150
|
+
*
|
|
151
|
+
* @param dir - Directory holding the `.git` file
|
|
152
|
+
* @returns Absolute git dir, or null when there is no readable `.git` file
|
|
153
|
+
*/
|
|
154
|
+
export declare function readGitFilePointer(dir: string): Promise<string | null>;
|
|
155
|
+
/**
|
|
156
|
+
* Main worktree of the repo a linked worktree belongs to, read from the
|
|
157
|
+
* worktree's `.git` file (`gitdir: <main>/.git/worktrees/<name>`). Returns
|
|
158
|
+
* null for anything else: a `.git` directory (a normal clone), a submodule
|
|
159
|
+
* (`gitdir: …/.git/modules/…`), or an unreadable file.
|
|
160
|
+
*
|
|
161
|
+
* @param dir - Directory that may be a linked worktree
|
|
162
|
+
* @returns Absolute path of the main worktree, or null
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* // /tmp/visa-cm-wt/.git contains "gitdir: /src/ce-core/.git/worktrees/visa-cm-wt"
|
|
167
|
+
* await mainRepoOfLinkedWorktree('/tmp/visa-cm-wt'); // '/src/ce-core'
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export declare function mainRepoOfLinkedWorktree(dir: string): Promise<string | null>;
|
|
171
|
+
/** A git checkout found on disk. */
|
|
172
|
+
export interface FoundRepo {
|
|
173
|
+
/** Directory holding `.git` */
|
|
174
|
+
path: string;
|
|
175
|
+
/** `dir` for a `.git` directory (clone / main worktree), `file` for a `.git` file (linked worktree or submodule) */
|
|
176
|
+
kind: 'dir' | 'file';
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Find git checkouts under `root` without following symlinks. A directory
|
|
180
|
+
* with a `.git` directory or file is a checkout and is not descended into;
|
|
181
|
+
* `node_modules` and `.git` are never descended into. Fully async; yields to
|
|
182
|
+
* the event loop every few directories.
|
|
183
|
+
*
|
|
184
|
+
* @param root - Directory to search (itself included, at depth 0)
|
|
185
|
+
* @param maxDepth - Deepest level searched (root = 0)
|
|
186
|
+
* @param maxDirs - Stop after visiting this many directories
|
|
187
|
+
* @returns Checkouts found, in walk order
|
|
188
|
+
*/
|
|
189
|
+
export declare function findGitCheckouts(root: string, maxDepth: number, maxDirs?: number): Promise<FoundRepo[]>;
|
|
190
|
+
/**
|
|
191
|
+
* Main worktrees of every repo that owns a linked worktree somewhere under
|
|
192
|
+
* the given roots (e.g. `/tmp/claude-501/visa-cm-wt` → `~/src/ce-core`), so
|
|
193
|
+
* repos that are not registered projects still get their temp worktrees
|
|
194
|
+
* cleaned. Visits at most DISCOVERY_MAX_DIRS directories per root.
|
|
195
|
+
*
|
|
196
|
+
* @param roots - Temp roots to scan (missing roots are skipped)
|
|
197
|
+
* @returns De-duplicated main-worktree paths
|
|
198
|
+
*/
|
|
199
|
+
export declare function discoverLinkedWorktreeRepos(roots: readonly string[]): Promise<string[]>;
|
|
200
|
+
/**
|
|
201
|
+
* Newest mtime (ms) of `dir` and everything within `depth` levels below it,
|
|
202
|
+
* using lstat (symlinks are not followed). Async; yields every few entries.
|
|
203
|
+
*
|
|
204
|
+
* @param dir - Directory
|
|
205
|
+
* @param depth - Levels below `dir` to include (0 = only `dir`)
|
|
206
|
+
* @returns Newest mtime in ms, or null when `dir` cannot be stat'ed
|
|
207
|
+
*/
|
|
208
|
+
export declare function latestTreeMtimeMs(dir: string, depth: number): Promise<number | null>;
|
|
209
|
+
/**
|
|
210
|
+
* Disk usage of a path in bytes (`du -sk` in a child process, so the event
|
|
211
|
+
* loop is never blocked; `du` does not follow symlinks).
|
|
212
|
+
*
|
|
213
|
+
* @param p - File or directory
|
|
214
|
+
* @returns Bytes, or null when `du` failed or timed out
|
|
215
|
+
*/
|
|
216
|
+
export declare function diskUsageBytes(p: string): Promise<number | null>;
|
|
217
|
+
/**
|
|
218
|
+
* Human-readable size (`1.8 GB`, `512 MB`).
|
|
219
|
+
*
|
|
220
|
+
* @param bytes - Size in bytes
|
|
221
|
+
* @returns Short string with one decimal for GB
|
|
222
|
+
*/
|
|
223
|
+
export declare function formatBytes(bytes: number): string;
|
|
224
|
+
//# sourceMappingURL=worktree-janitor.git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-janitor.git.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/worktree/worktree-janitor.git.ts"],"names":[],"mappings":"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"}
|