@wjarka/cezarion 0.14.2 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/dist/contract/delegation.d.ts +9 -0
- package/dist/contract/index.js +4 -2
- package/dist/contract/runs.d.ts +18 -0
- package/dist/core/cursor-acp-runner.js +13 -0
- package/dist/core/cursor-acp-runner.js.map +1 -1
- package/dist/runs/agent-tmpdir.d.ts +44 -4
- package/dist/runs/agent-tmpdir.js +209 -31
- package/dist/runs/agent-tmpdir.js.map +1 -1
- package/dist/server/server.d.ts +63 -58
- package/dist/workflows/run.d.ts +4 -0
- package/dist/workflows/run.js +8 -1
- package/dist/workflows/run.js.map +1 -1
- package/package.json +3 -3
- package/scripts/mock-cursor-acp.mjs +15 -3
- package/web/dist/assets/agent-accounts-BxBsIXGa.js +1 -0
- package/web/dist/assets/alert-dialog-BOp2HnnL.js +43 -0
- package/web/dist/assets/{collapsible-D7QXWXZq.js → collapsible-bb0csfMs.js} +1 -1
- package/web/dist/assets/{commit-list-AwLNQE91.js → commit-list-CEVhJoCF.js} +1 -1
- package/web/dist/assets/{compare-variants-CBggabVc.js → compare-variants-CZqdiqvW.js} +1 -1
- package/web/dist/assets/{diff-C4aSZfrQ2.js → diff-BjLZHKfD2.js} +2 -2
- package/web/dist/assets/{diff-controls-74Z0C3ay.js → diff-controls-DaO836o4.js} +1 -1
- package/web/dist/assets/{diff-stat-B7f-F8cC.js → diff-stat-DpHwISUB.js} +1 -1
- package/web/dist/assets/{diff-view-BPKHTL85.js → diff-view-BaYxuP8L.js} +1 -1
- package/web/dist/assets/dropdown-menu-DAmCVaLJ.js +1 -0
- package/web/dist/assets/{git-toolbar-Dntzprrr.js → git-toolbar-rk3doc2w.js} +1 -1
- package/web/dist/assets/github-BPfdr6aa.js +1 -0
- package/web/dist/assets/{image-preview-BhuwWeyP.js → image-preview-CFHgISfb.js} +1 -1
- package/web/dist/assets/index-C4iEPAUV.js +7 -0
- package/web/dist/assets/index-DPOGn7D5.css +1 -0
- package/web/dist/assets/{markdown-BssEOroY.js → markdown-Ir62-VMS.js} +1 -1
- package/web/dist/assets/pill-Dvvq0Otw.js +1 -0
- package/web/dist/assets/{project-router-a1gx3dfP.js → project-router-CvFAMDcP.js} +1 -1
- package/web/dist/assets/{prompt-templates-B4eJ8kQZ.js → prompt-templates-BGGpAIzb.js} +1 -1
- package/web/dist/assets/repo-git-C1Qv1JmM.js +1 -0
- package/web/dist/assets/{run-diff-CHDwMBEQ.js → run-diff-DrQsmf3-.js} +1 -1
- package/web/dist/assets/run-header-C9Aeh27u.js +1 -0
- package/web/dist/assets/skills-_ZVZxmKz.js +1 -0
- package/web/dist/assets/{tab-link-DRP4FV8D.js → tab-link-CkIV8ixq.js} +1 -1
- package/web/dist/assets/task-changes-BU9upwUw.js +1 -0
- package/web/dist/assets/{task-commits-DTdRtZur.js → task-commits-CbJutMBx.js} +1 -1
- package/web/dist/assets/{task-files-Cr2qKUk2.js → task-files-_hQyxAc7.js} +2 -2
- package/web/dist/assets/task-thread-Yo52ML6l.js +9 -0
- package/web/dist/assets/{textarea-DAHMUyAp.js → textarea-DfvlPIgO.js} +1 -1
- package/web/dist/assets/thread-loading-B9uTF0dX.js +1 -0
- package/web/dist/assets/{token-metrics-Q0paVq5n.js → token-metrics-BLzFUb8F.js} +1 -1
- package/web/dist/assets/{utils-CG8vWc5K.js → utils-GZNjgma4.js} +1 -1
- package/web/dist/assets/workflows-B6Er16t0.js +11 -0
- package/web/dist/assets/{zoomable-image-BXioMWqb.js → zoomable-image-COhBxkky.js} +1 -1
- package/web/dist/index.html +14 -14
- package/web/dist/assets/agent-accounts-BP0XBzQP.js +0 -1
- package/web/dist/assets/alert-dialog-Bv9zV9w1.js +0 -43
- package/web/dist/assets/dropdown-menu-DkzcT6aO.js +0 -1
- package/web/dist/assets/github-CBYawanT.js +0 -1
- package/web/dist/assets/index-BpI26cbM.js +0 -7
- package/web/dist/assets/index-CG0CPeOx.css +0 -1
- package/web/dist/assets/pill-C7gWe96Z.js +0 -1
- package/web/dist/assets/repo-git-D8GN9ork.js +0 -1
- package/web/dist/assets/run-header-BlqnTQeP.js +0 -1
- package/web/dist/assets/skills-CkWBfIfQ.js +0 -1
- package/web/dist/assets/task-changes-CEyHhiK1.js +0 -1
- package/web/dist/assets/task-thread-C8XeQXO4.js +0 -9
- package/web/dist/assets/thread-loading-OtvWGq9Y.js +0 -1
- package/web/dist/assets/workflows-uDL1z3Qp.js +0 -11
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Task-scoped temp directory for spawned agents (#785).
|
|
2
|
+
* Task-scoped temp directory for spawned agents (#785, length-capped by #387).
|
|
3
3
|
*
|
|
4
4
|
* Every agent used to inherit the host's `TMPDIR`/`TEMP`/`TMP` verbatim — they
|
|
5
5
|
* ride in on `buildChildEnv`'s base allowlist — so every run on the machine
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* the agent reads back an empty result with a bogus exit status. Nothing in the
|
|
13
13
|
* cockpit says anything is wrong.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* Three properties fix that, and this module owns all of them:
|
|
16
16
|
*
|
|
17
17
|
* 1. **Isolation** — each run gets `<dataDir>/tmp/<runId>`, on the same disk
|
|
18
18
|
* as the run's own state rather than a shared tmpfs, reaped when the run
|
|
@@ -21,15 +21,28 @@
|
|
|
21
21
|
* 2. **Fail loud** — the directory is write-probed before the backend spawns.
|
|
22
22
|
* A run that cannot get a working temp directory fails immediately with a
|
|
23
23
|
* named, actionable error instead of spawning an agent that will run blind.
|
|
24
|
+
* 3. **Short enough to bind** (#387) — tools bind *named* unix sockets under
|
|
25
|
+
* `TMPDIR` (tsx's IPC server lays down `<tmpdir>/tsx-<uid>/<pid>.pipe`,
|
|
26
|
+
* Chrome a `SingletonSocket`), and the kernel caps a socket path at
|
|
27
|
+
* `sun_path` — 108 bytes on Linux, 104 on macOS, NUL included. A checkout
|
|
28
|
+
* deep enough (Cezar's own nested task worktrees land past 100 chars)
|
|
29
|
+
* pushed every such bind past the cap and broke `npm install` and
|
|
30
|
+
* typechecking inside the run. A directory that would land too deep
|
|
31
|
+
* resolves instead to a short digest-named directory under the OS temp
|
|
32
|
+
* root — still per-run, still probed, still reaped. A repo whose own path
|
|
33
|
+
* already fits keeps today's directory, byte for byte.
|
|
24
34
|
*
|
|
25
|
-
* `CEZ_AGENT_TMPDIR=0` opts out of
|
|
26
|
-
* directory entirely and the pre-#785 behaviour is back, byte for byte.
|
|
27
|
-
* deliberate: an escape hatch that still imposed the preflight would be
|
|
28
|
-
* you cannot actually escape through, and this repo's
|
|
29
|
-
* says a new check must never become the only way to
|
|
35
|
+
* `CEZ_AGENT_TMPDIR=0` opts out of ALL THREE — cezar keeps its hands off the
|
|
36
|
+
* temp directory entirely and the pre-#785 behaviour is back, byte for byte.
|
|
37
|
+
* That is deliberate: an escape hatch that still imposed the preflight would be
|
|
38
|
+
* a hatch you cannot actually escape through, and this repo's
|
|
39
|
+
* graceful-degradation rule says a new check must never become the only way to
|
|
40
|
+
* run.
|
|
30
41
|
*/
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
42
|
+
import { createHash } from 'node:crypto';
|
|
43
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
44
|
+
import { tmpdir } from 'node:os';
|
|
45
|
+
import { basename, join } from 'node:path';
|
|
33
46
|
/** Run ids are uuids; anything else must never reach a recursive `rmSync`.
|
|
34
47
|
*
|
|
35
48
|
* `.` and `..` are excluded explicitly, not as pedantry: they match the
|
|
@@ -48,6 +61,103 @@ export function agentTmpDir(dataDir, runId) {
|
|
|
48
61
|
function agentTmpRoot(dataDir) {
|
|
49
62
|
return join(dataDir, 'tmp');
|
|
50
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* The longest a per-run temp directory may be so that tools binding named
|
|
66
|
+
* unix sockets under it still work (#387), measured in UTF-8 bytes — the
|
|
67
|
+
* kernel bounds the encoded path, not the JavaScript character count.
|
|
68
|
+
* `sockaddr_un.sun_path` holds 108 bytes on Linux and 104 on macOS, NUL
|
|
69
|
+
* included; the longest name a known tool lays down under TMPDIR is tsx's IPC
|
|
70
|
+
* socket, `<tmpdir>/tsx-<uid>/<pid>.pipe`, ~22 bytes (Chrome's
|
|
71
|
+
* `SingletonSocket` is 16). A 78-byte ceiling leaves ≥25 bytes of headroom on
|
|
72
|
+
* the tighter platform — past anything these tools generate — while keeping
|
|
73
|
+
* ordinary checkouts on their repo-local scratch: only a genuinely deep path,
|
|
74
|
+
* like the 100-character directories #387 reports, moves to the fallback.
|
|
75
|
+
*/
|
|
76
|
+
export const MAX_SOCKET_SAFE_DIR_LENGTH = 78;
|
|
77
|
+
/** The OS temp root, symlink-resolved: `bind(2)` bounds the path the kernel
|
|
78
|
+
* walks, so the check must measure what the path resolves to, not what it
|
|
79
|
+
* says (macOS hands out `/var/folders/...` through a `/private/var` symlink). */
|
|
80
|
+
function osTempRoot() {
|
|
81
|
+
try {
|
|
82
|
+
return realpathSync(tmpdir());
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return tmpdir();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const FALLBACK_PREFIX = 'cez-agent-';
|
|
89
|
+
const FALLBACK_NAME_LENGTH = 12;
|
|
90
|
+
/** The marker file inside a fallback directory naming the dataDir that minted
|
|
91
|
+
* it. The directory name digests `dataDir:runId` and is not reversible, so
|
|
92
|
+
* without this marker a sweep could not tell its own stale directories from
|
|
93
|
+
* another project's live ones in the shared root — and would delete them. */
|
|
94
|
+
const OWNER_FILE = '.cez-owner';
|
|
95
|
+
function dataDirOwner(dataDir) {
|
|
96
|
+
return createHash('sha256').update(`cez-agent-owner:${dataDir}`).digest('hex').slice(0, 16);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Write the ownership marker. `'wx'` never follows an existing name: an agent
|
|
100
|
+
* that replaced a previous marker with a symlink must not turn this rewrite
|
|
101
|
+
* into an arbitrary-file write. An existing marker is verified by content —
|
|
102
|
+
* a mismatch means the directory's ownership is no longer what the digest
|
|
103
|
+
* name promises, and the spawn refuses rather than guess.
|
|
104
|
+
*/
|
|
105
|
+
function writeOwnerMarker(dir, dataDir) {
|
|
106
|
+
const marker = join(dir, OWNER_FILE);
|
|
107
|
+
const expected = dataDirOwner(dataDir);
|
|
108
|
+
try {
|
|
109
|
+
writeFileSync(marker, expected, { encoding: 'utf8', flag: 'wx' });
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
if (err.code !== 'EEXIST')
|
|
113
|
+
throw err;
|
|
114
|
+
let actual = '';
|
|
115
|
+
try {
|
|
116
|
+
actual = readFileSync(marker, 'utf8').trim();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// unreadable marker (symlink to nowhere, wrong type): verify below.
|
|
120
|
+
}
|
|
121
|
+
if (actual !== expected) {
|
|
122
|
+
throw new AgentTempDirError(dir, new Error('ownership marker was replaced — remove the directory to re-mint it'));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Where the fallback lives for this dataDir+run pair. The name digests the
|
|
128
|
+
* dataDir in, because the OS temp root is SHARED: a name derived from the run
|
|
129
|
+
* id alone would let one repo's reap delete another repo's live scratch when
|
|
130
|
+
* two run ids happen to share their leading characters. The name alone cannot
|
|
131
|
+
* make the sweep safe — a digest is not reversible, so a sweep could not tell
|
|
132
|
+
* its own stale directories from another project's live ones — which is why
|
|
133
|
+
* every fallback directory also carries the `.cez-owner` marker.
|
|
134
|
+
*/
|
|
135
|
+
function fallbackTmpDir(dataDir, runId) {
|
|
136
|
+
const digest = createHash('sha256').update(`${dataDir}:${runId}`).digest('hex');
|
|
137
|
+
return join(osTempRoot(), FALLBACK_PREFIX + digest.slice(0, FALLBACK_NAME_LENGTH));
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The temp directory this run should use: the repo-local per-run directory
|
|
141
|
+
* when it is short enough for unix-socket paths, and a short directory under
|
|
142
|
+
* the OS temp root when it is not (#387). Pure resolution — nothing is
|
|
143
|
+
* created, nothing is probed; `agentTmpEnv` owns the side effects.
|
|
144
|
+
*/
|
|
145
|
+
export function resolveAgentTmpDir(dataDir, runId) {
|
|
146
|
+
const local = agentTmpDir(dataDir, runId);
|
|
147
|
+
if (Buffer.byteLength(local, 'utf8') <= MAX_SOCKET_SAFE_DIR_LENGTH)
|
|
148
|
+
return local;
|
|
149
|
+
const fallback = fallbackTmpDir(dataDir, runId);
|
|
150
|
+
if (Buffer.byteLength(fallback, 'utf8') <= MAX_SOCKET_SAFE_DIR_LENGTH)
|
|
151
|
+
return fallback;
|
|
152
|
+
// Nothing fits — a host TMPDIR so long that even the OS-root candidate
|
|
153
|
+
// crosses the cap. Minting either would hand the agent a temp directory
|
|
154
|
+
// that cannot serve unix sockets: the silent failure #387 is about. Fail
|
|
155
|
+
// the spawn with the named error instead; the remedy names the escape.
|
|
156
|
+
throw new AgentTempDirError(Buffer.byteLength(fallback) < Buffer.byteLength(local) ? fallback : local, new Error(`no socket-safe temp directory exists — repo-local path is `
|
|
157
|
+
+ `${Buffer.byteLength(local)} bytes and the OS temp root candidate is `
|
|
158
|
+
+ `${Buffer.byteLength(fallback)} bytes, both past the `
|
|
159
|
+
+ `${MAX_SOCKET_SAFE_DIR_LENGTH}-byte unix socket budget`));
|
|
160
|
+
}
|
|
51
161
|
/** `errno` → the phrasing a human recognises from their shell. */
|
|
52
162
|
const REASONS = {
|
|
53
163
|
EDQUOT: 'Disk quota exceeded',
|
|
@@ -110,20 +220,33 @@ function probeWritable(dir) {
|
|
|
110
220
|
* directory actually accepts writes. Throws `AgentTempDirError` when it does
|
|
111
221
|
* not — callers turn that into the run's error rather than spawning.
|
|
112
222
|
*
|
|
223
|
+
* The directory is `resolveAgentTmpDir`'s call: repo-local when that path is
|
|
224
|
+
* short enough for unix-socket paths, a digest-named directory under the OS
|
|
225
|
+
* temp root when the checkout is too deep for one (#387). In the shared OS
|
|
226
|
+
* root the directory is created private to this user (0700); repo-local
|
|
227
|
+
* scratch already sits inside the user's own tree and keeps the default mode
|
|
228
|
+
* it always had.
|
|
229
|
+
*
|
|
113
230
|
* All three spellings are set, on every platform: a tool that reads `TMP` (or
|
|
114
231
|
* `TEMP`) would otherwise keep following the host value straight back to the
|
|
115
232
|
* exhausted directory this exists to escape.
|
|
116
233
|
*
|
|
117
|
-
* Returns `{}` under the opt-out, without probing anything: the hatch turns
|
|
118
|
-
* whole feature off, preflight included, so it stays an escape someone can
|
|
234
|
+
* Returns `{}` under the opt-out, without probing anything: the hatch turns
|
|
235
|
+
* the whole feature off, preflight included, so it stays an escape someone can
|
|
119
236
|
* actually take.
|
|
120
237
|
*/
|
|
121
238
|
export function agentTmpEnv(dataDir, runId, env = process.env) {
|
|
122
239
|
if (!agentTmpDirEnabled(env))
|
|
123
240
|
return {};
|
|
124
|
-
const
|
|
241
|
+
const local = agentTmpDir(dataDir, runId);
|
|
242
|
+
const dir = resolveAgentTmpDir(dataDir, runId);
|
|
125
243
|
try {
|
|
126
|
-
mkdirSync(dir, { recursive: true });
|
|
244
|
+
mkdirSync(dir, dir === local ? { recursive: true } : { recursive: true, mode: 0o700 });
|
|
245
|
+
// In the shared OS root the directory carries its ownership marker, so a
|
|
246
|
+
// startup sweep from another project can tell it apart from stale
|
|
247
|
+
// scratch (the sweep skips anything whose marker is missing or foreign).
|
|
248
|
+
if (dir !== local)
|
|
249
|
+
writeOwnerMarker(dir, dataDir);
|
|
127
250
|
}
|
|
128
251
|
catch (err) {
|
|
129
252
|
throw new AgentTempDirError(dir, err);
|
|
@@ -135,44 +258,99 @@ export function agentTmpEnv(dataDir, runId, env = process.env) {
|
|
|
135
258
|
* Reap one run's directory. Scratch, not an artifact: nothing reads it once the
|
|
136
259
|
* agent is gone, and a Continue re-creates it through `agentTmpEnv`. Never
|
|
137
260
|
* throws — reaping must not break a terminal transition.
|
|
261
|
+
*
|
|
262
|
+
* Both locations are tried because the resolution depends on the length of
|
|
263
|
+
* `dataDir`, which a Continue or a re-base can change between mint and reap;
|
|
264
|
+
* removing a name that was never minted is a no-op, so trying both is pure
|
|
265
|
+
* safety.
|
|
138
266
|
*/
|
|
139
267
|
export function removeAgentTmpDir(dataDir, runId) {
|
|
140
268
|
if (!safeRunId(runId))
|
|
141
269
|
return;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
270
|
+
for (const dir of [agentTmpDir(dataDir, runId), fallbackTmpDir(dataDir, runId)]) {
|
|
271
|
+
try {
|
|
272
|
+
rmSync(dir, { recursive: true, force: true });
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
// best-effort; the startup sweep picks up whatever survives.
|
|
276
|
+
}
|
|
147
277
|
}
|
|
148
278
|
}
|
|
149
279
|
/**
|
|
150
280
|
* Remove every per-run directory that is not in `keepRunIds` — the startup
|
|
151
281
|
* sweep, so a crash (which never reaches the terminal-transition reap) cannot
|
|
152
|
-
* accumulate them forever.
|
|
153
|
-
*
|
|
282
|
+
* accumulate them forever. Two confined roots are swept and nothing else:
|
|
283
|
+
*
|
|
284
|
+
* - `<dataDir>/tmp`, where entries ARE the run ids (reports the ids reaped);
|
|
285
|
+
* - the OS temp root's `cez-agent-<12 hex>` directories (#387), where the
|
|
286
|
+
* name digests the dataDir and is not reversible to a run id (reports the
|
|
287
|
+
* directory names reaped). The pattern is exact — prefix, lowercase hex,
|
|
288
|
+
* fixed length, directories only — and a directory is removed only when
|
|
289
|
+
* its `.cez-owner` marker names THIS dataDir and none of this dataDir's
|
|
290
|
+
* kept runs claims it, so another project's scratch in the shared root is
|
|
291
|
+
* never touched.
|
|
154
292
|
*/
|
|
155
293
|
export function sweepAgentTmpDirs(dataDir, keepRunIds) {
|
|
156
|
-
const root = agentTmpRoot(dataDir);
|
|
157
|
-
if (!existsSync(root))
|
|
158
|
-
return [];
|
|
159
294
|
const keep = new Set(keepRunIds);
|
|
160
295
|
const reaped = [];
|
|
161
296
|
let entries;
|
|
297
|
+
const root = agentTmpRoot(dataDir);
|
|
298
|
+
if (existsSync(root)) {
|
|
299
|
+
try {
|
|
300
|
+
entries = readdirSync(root, { withFileTypes: true })
|
|
301
|
+
.filter((e) => e.isDirectory())
|
|
302
|
+
.map((e) => e.name);
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
entries = [];
|
|
306
|
+
}
|
|
307
|
+
for (const name of entries) {
|
|
308
|
+
if (keep.has(name) || !safeRunId(name))
|
|
309
|
+
continue;
|
|
310
|
+
try {
|
|
311
|
+
rmSync(join(root, name), { recursive: true, force: true });
|
|
312
|
+
reaped.push(name);
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
// best-effort: a locked directory is retried on the next boot.
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// The #387 fallback location, in the shared OS temp root. Kept narrow on
|
|
320
|
+
// purpose: exact prefix, 12 lowercase-hex name, directories only, and
|
|
321
|
+
// ownership — a directory is removed only when its `.cez-owner` marker
|
|
322
|
+
// names THIS dataDir (a marker that is missing or foreign is another
|
|
323
|
+
// project's, or unknown, and is never ours to remove) and none of this
|
|
324
|
+
// dataDir's kept runs claims it.
|
|
325
|
+
const owner = dataDirOwner(dataDir);
|
|
326
|
+
const claimed = new Set([...keep].filter(safeRunId).map((id) => basename(fallbackTmpDir(dataDir, id))));
|
|
327
|
+
const osRoot = osTempRoot();
|
|
328
|
+
let fallbackEntries;
|
|
162
329
|
try {
|
|
163
|
-
|
|
164
|
-
.filter((e) => e.isDirectory())
|
|
165
|
-
.map((e) => e.name);
|
|
330
|
+
fallbackEntries = readdirSync(osRoot, { withFileTypes: true });
|
|
166
331
|
}
|
|
167
332
|
catch {
|
|
168
|
-
return
|
|
333
|
+
return reaped;
|
|
169
334
|
}
|
|
170
|
-
for (const
|
|
171
|
-
if (
|
|
335
|
+
for (const entry of fallbackEntries) {
|
|
336
|
+
if (!entry.isDirectory() || !entry.name.startsWith(FALLBACK_PREFIX))
|
|
337
|
+
continue;
|
|
338
|
+
if (!/^[0-9a-f]{12}$/.test(entry.name.slice(FALLBACK_PREFIX.length)))
|
|
339
|
+
continue;
|
|
340
|
+
let entryOwner;
|
|
341
|
+
try {
|
|
342
|
+
entryOwner = readFileSync(join(osRoot, entry.name, OWNER_FILE), 'utf8').trim();
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
continue; // no readable marker: unknown ownership is never ours to remove.
|
|
346
|
+
}
|
|
347
|
+
if (entryOwner !== owner)
|
|
348
|
+
continue;
|
|
349
|
+
if (claimed.has(entry.name))
|
|
172
350
|
continue;
|
|
173
351
|
try {
|
|
174
|
-
rmSync(join(
|
|
175
|
-
reaped.push(name);
|
|
352
|
+
rmSync(join(osRoot, entry.name), { recursive: true, force: true });
|
|
353
|
+
reaped.push(entry.name);
|
|
176
354
|
}
|
|
177
355
|
catch {
|
|
178
356
|
// best-effort: a locked directory is retried on the next boot.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-tmpdir.js","sourceRoot":"","sources":["../../src/runs/agent-tmpdir.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agent-tmpdir.js","sourceRoot":"","sources":["../../src/runs/agent-tmpdir.ts"],"names":[],"mappings":"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"}
|
package/dist/server/server.d.ts
CHANGED
|
@@ -406,10 +406,15 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
406
406
|
} | {
|
|
407
407
|
role: "root";
|
|
408
408
|
wait?: {
|
|
409
|
+
requestIds?: string[] | undefined;
|
|
409
410
|
phase: "parked" | "registered" | "wake-pending";
|
|
410
411
|
} | undefined;
|
|
411
412
|
} | {
|
|
412
413
|
role: "worker";
|
|
414
|
+
wait?: {
|
|
415
|
+
requestIds?: string[] | undefined;
|
|
416
|
+
phase: "parked" | "registered" | "wake-pending";
|
|
417
|
+
} | undefined;
|
|
413
418
|
} | undefined;
|
|
414
419
|
createdAt: string;
|
|
415
420
|
finishedAt?: string | undefined;
|
|
@@ -3957,19 +3962,6 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
3957
3962
|
} & {
|
|
3958
3963
|
"/repo/commit/:sha": {
|
|
3959
3964
|
$get: {
|
|
3960
|
-
output: string;
|
|
3961
|
-
outputFormat: "text";
|
|
3962
|
-
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
3963
|
-
input: {
|
|
3964
|
-
query: {
|
|
3965
|
-
structured?: string | undefined;
|
|
3966
|
-
};
|
|
3967
|
-
} & {
|
|
3968
|
-
param: {
|
|
3969
|
-
sha: string;
|
|
3970
|
-
};
|
|
3971
|
-
};
|
|
3972
|
-
} | {
|
|
3973
3965
|
output: {
|
|
3974
3966
|
error: string;
|
|
3975
3967
|
code?: "invalid_input" | undefined;
|
|
@@ -4033,6 +4025,19 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
4033
4025
|
sha: string;
|
|
4034
4026
|
};
|
|
4035
4027
|
};
|
|
4028
|
+
} | {
|
|
4029
|
+
output: string;
|
|
4030
|
+
outputFormat: "text";
|
|
4031
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
4032
|
+
input: {
|
|
4033
|
+
query: {
|
|
4034
|
+
structured?: string | undefined;
|
|
4035
|
+
};
|
|
4036
|
+
} & {
|
|
4037
|
+
param: {
|
|
4038
|
+
sha: string;
|
|
4039
|
+
};
|
|
4040
|
+
};
|
|
4036
4041
|
};
|
|
4037
4042
|
};
|
|
4038
4043
|
} & {
|
|
@@ -10093,20 +10098,20 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
10093
10098
|
} & {
|
|
10094
10099
|
"/runs/:id/handoff": {
|
|
10095
10100
|
$get: {
|
|
10096
|
-
output:
|
|
10097
|
-
|
|
10098
|
-
|
|
10101
|
+
output: {
|
|
10102
|
+
error: string;
|
|
10103
|
+
};
|
|
10104
|
+
outputFormat: "json";
|
|
10105
|
+
status: 404;
|
|
10099
10106
|
input: {
|
|
10100
10107
|
param: {
|
|
10101
10108
|
id: string;
|
|
10102
10109
|
};
|
|
10103
10110
|
};
|
|
10104
10111
|
} | {
|
|
10105
|
-
output:
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
outputFormat: "json";
|
|
10109
|
-
status: 404;
|
|
10112
|
+
output: string;
|
|
10113
|
+
outputFormat: "text";
|
|
10114
|
+
status: 200;
|
|
10110
10115
|
input: {
|
|
10111
10116
|
param: {
|
|
10112
10117
|
id: string;
|
|
@@ -10144,20 +10149,20 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
10144
10149
|
} & {
|
|
10145
10150
|
"/runs/:id/diff": {
|
|
10146
10151
|
$get: {
|
|
10147
|
-
output:
|
|
10148
|
-
|
|
10149
|
-
|
|
10152
|
+
output: {
|
|
10153
|
+
error: string;
|
|
10154
|
+
};
|
|
10155
|
+
outputFormat: "json";
|
|
10156
|
+
status: 404;
|
|
10150
10157
|
input: {
|
|
10151
10158
|
param: {
|
|
10152
10159
|
id: string;
|
|
10153
10160
|
};
|
|
10154
10161
|
};
|
|
10155
10162
|
} | {
|
|
10156
|
-
output:
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
outputFormat: "json";
|
|
10160
|
-
status: 404;
|
|
10163
|
+
output: string;
|
|
10164
|
+
outputFormat: "text";
|
|
10165
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
10161
10166
|
input: {
|
|
10162
10167
|
param: {
|
|
10163
10168
|
id: string;
|
|
@@ -12534,19 +12539,6 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
12534
12539
|
} & {
|
|
12535
12540
|
"/repo/commit/:sha": {
|
|
12536
12541
|
$get: {
|
|
12537
|
-
output: string;
|
|
12538
|
-
outputFormat: "text";
|
|
12539
|
-
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
12540
|
-
input: {
|
|
12541
|
-
query: {
|
|
12542
|
-
structured?: string | undefined;
|
|
12543
|
-
};
|
|
12544
|
-
} & {
|
|
12545
|
-
param: {
|
|
12546
|
-
sha: string;
|
|
12547
|
-
};
|
|
12548
|
-
};
|
|
12549
|
-
} | {
|
|
12550
12542
|
output: {
|
|
12551
12543
|
error: string;
|
|
12552
12544
|
code?: "invalid_input" | undefined;
|
|
@@ -12610,6 +12602,19 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
12610
12602
|
sha: string;
|
|
12611
12603
|
};
|
|
12612
12604
|
};
|
|
12605
|
+
} | {
|
|
12606
|
+
output: string;
|
|
12607
|
+
outputFormat: "text";
|
|
12608
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
12609
|
+
input: {
|
|
12610
|
+
query: {
|
|
12611
|
+
structured?: string | undefined;
|
|
12612
|
+
};
|
|
12613
|
+
} & {
|
|
12614
|
+
param: {
|
|
12615
|
+
sha: string;
|
|
12616
|
+
};
|
|
12617
|
+
};
|
|
12613
12618
|
};
|
|
12614
12619
|
};
|
|
12615
12620
|
} & {
|
|
@@ -18670,20 +18675,20 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
18670
18675
|
} & {
|
|
18671
18676
|
"/runs/:id/handoff": {
|
|
18672
18677
|
$get: {
|
|
18673
|
-
output:
|
|
18674
|
-
|
|
18675
|
-
|
|
18678
|
+
output: {
|
|
18679
|
+
error: string;
|
|
18680
|
+
};
|
|
18681
|
+
outputFormat: "json";
|
|
18682
|
+
status: 404;
|
|
18676
18683
|
input: {
|
|
18677
18684
|
param: {
|
|
18678
18685
|
id: string;
|
|
18679
18686
|
};
|
|
18680
18687
|
};
|
|
18681
18688
|
} | {
|
|
18682
|
-
output:
|
|
18683
|
-
|
|
18684
|
-
|
|
18685
|
-
outputFormat: "json";
|
|
18686
|
-
status: 404;
|
|
18689
|
+
output: string;
|
|
18690
|
+
outputFormat: "text";
|
|
18691
|
+
status: 200;
|
|
18687
18692
|
input: {
|
|
18688
18693
|
param: {
|
|
18689
18694
|
id: string;
|
|
@@ -18721,20 +18726,20 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
18721
18726
|
} & {
|
|
18722
18727
|
"/runs/:id/diff": {
|
|
18723
18728
|
$get: {
|
|
18724
|
-
output:
|
|
18725
|
-
|
|
18726
|
-
|
|
18729
|
+
output: {
|
|
18730
|
+
error: string;
|
|
18731
|
+
};
|
|
18732
|
+
outputFormat: "json";
|
|
18733
|
+
status: 404;
|
|
18727
18734
|
input: {
|
|
18728
18735
|
param: {
|
|
18729
18736
|
id: string;
|
|
18730
18737
|
};
|
|
18731
18738
|
};
|
|
18732
18739
|
} | {
|
|
18733
|
-
output:
|
|
18734
|
-
|
|
18735
|
-
|
|
18736
|
-
outputFormat: "json";
|
|
18737
|
-
status: 404;
|
|
18740
|
+
output: string;
|
|
18741
|
+
outputFormat: "text";
|
|
18742
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
18738
18743
|
input: {
|
|
18739
18744
|
param: {
|
|
18740
18745
|
id: string;
|
package/dist/workflows/run.d.ts
CHANGED
|
@@ -282,6 +282,10 @@ export declare class RunManager {
|
|
|
282
282
|
* `active`, which is why the timer cannot live on an `ActiveRun` like the monitoring one. */
|
|
283
283
|
private readonly autoResumeTimers;
|
|
284
284
|
private pumping;
|
|
285
|
+
/** The scheduler only needs repo presence, stable for this manager's lifetime.
|
|
286
|
+
* Cache the promise (including null) so every sweep doesn't spawn Git (#364).
|
|
287
|
+
* execute() still reads fresh branch/remote metadata for each run. */
|
|
288
|
+
private pumpRepoInfo?;
|
|
285
289
|
/** A pump that arrived while one was in flight — replayed by `pump()`'s own
|
|
286
290
|
* loop so a slot freed mid-sweep is never a lost wakeup. */
|
|
287
291
|
private pumpAgain;
|
package/dist/workflows/run.js
CHANGED
|
@@ -606,6 +606,10 @@ export class RunManager {
|
|
|
606
606
|
* `active`, which is why the timer cannot live on an `ActiveRun` like the monitoring one. */
|
|
607
607
|
autoResumeTimers = new Map();
|
|
608
608
|
pumping = false;
|
|
609
|
+
/** The scheduler only needs repo presence, stable for this manager's lifetime.
|
|
610
|
+
* Cache the promise (including null) so every sweep doesn't spawn Git (#364).
|
|
611
|
+
* execute() still reads fresh branch/remote metadata for each run. */
|
|
612
|
+
pumpRepoInfo;
|
|
609
613
|
/** A pump that arrived while one was in flight — replayed by `pump()`'s own
|
|
610
614
|
* loop so a slot freed mid-sweep is never a lost wakeup. */
|
|
611
615
|
pumpAgain = false;
|
|
@@ -1077,7 +1081,7 @@ export class RunManager {
|
|
|
1077
1081
|
try {
|
|
1078
1082
|
do {
|
|
1079
1083
|
this.pumpAgain = false;
|
|
1080
|
-
const repo = await getRepoInfo(this.repoRoot);
|
|
1084
|
+
const repo = await (this.pumpRepoInfo ??= getRepoInfo(this.repoRoot));
|
|
1081
1085
|
const maxParallel = this.semaphore.maxParallel();
|
|
1082
1086
|
// Per-project ceiling (spec 2026-07-22-per-project-concurrency): this
|
|
1083
1087
|
// project never runs more than its own configured `maxParallel`; absent
|
|
@@ -3461,6 +3465,9 @@ export class RunManager {
|
|
|
3461
3465
|
finishedAt: undefined,
|
|
3462
3466
|
currentStepId: undefined,
|
|
3463
3467
|
});
|
|
3468
|
+
// Enqueueing must wake the scheduler even if the previous execution's
|
|
3469
|
+
// slot-release sweep has already finished (#364).
|
|
3470
|
+
void this.pump();
|
|
3464
3471
|
return { ok: true };
|
|
3465
3472
|
}
|
|
3466
3473
|
this.starting.add(runId);
|