@alan-ai-hq/agent-manager-linux-x64 0.1.151 → 0.1.152
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/alan-agent.cjs +468 -920
- package/alan-holder.cjs +243 -744
- package/package.json +1 -1
package/alan-holder.cjs
CHANGED
|
@@ -22587,7 +22587,7 @@ function plan(command, args, options) {
|
|
|
22587
22587
|
function captureOutput(command, args, options) {
|
|
22588
22588
|
const launch = plan(command, args, options);
|
|
22589
22589
|
if (launch === void 0) return Promise.resolve(NEVER_STARTED);
|
|
22590
|
-
return new Promise((
|
|
22590
|
+
return new Promise((resolve8) => {
|
|
22591
22591
|
(0, import_child_process.execFile)(
|
|
22592
22592
|
launch.file,
|
|
22593
22593
|
[...launch.args],
|
|
@@ -22601,7 +22601,7 @@ function captureOutput(command, args, options) {
|
|
|
22601
22601
|
},
|
|
22602
22602
|
(error61, stdout, stderr) => {
|
|
22603
22603
|
const code = error61 && typeof error61.code === "number" ? error61.code : error61 ? void 0 : 0;
|
|
22604
|
-
|
|
22604
|
+
resolve8({ stdout, stderr, exitCode: code });
|
|
22605
22605
|
}
|
|
22606
22606
|
);
|
|
22607
22607
|
});
|
|
@@ -22643,18 +22643,18 @@ function decode3(bytes, start, end) {
|
|
|
22643
22643
|
}
|
|
22644
22644
|
async function linuxStartTicks(pid) {
|
|
22645
22645
|
try {
|
|
22646
|
-
const
|
|
22647
|
-
const fields =
|
|
22646
|
+
const stat15 = await (0, import_promises6.readFile)(`/proc/${pid}/stat`, "utf8");
|
|
22647
|
+
const fields = stat15.slice(stat15.lastIndexOf(")") + 2).split(" ");
|
|
22648
22648
|
return fields[19];
|
|
22649
22649
|
} catch {
|
|
22650
22650
|
return void 0;
|
|
22651
22651
|
}
|
|
22652
22652
|
}
|
|
22653
22653
|
function psStartTime(pid) {
|
|
22654
|
-
return new Promise((
|
|
22654
|
+
return new Promise((resolve8) => {
|
|
22655
22655
|
(0, import_child_process2.execFile)("ps", ["-o", "lstart=", "-p", String(pid)], { timeout: 2e3 }, (error61, stdout) => {
|
|
22656
22656
|
const text2 = stdout.trim();
|
|
22657
|
-
|
|
22657
|
+
resolve8(error61 || !text2 ? void 0 : text2);
|
|
22658
22658
|
});
|
|
22659
22659
|
});
|
|
22660
22660
|
}
|
|
@@ -22683,12 +22683,12 @@ function parseProcessList(text2) {
|
|
|
22683
22683
|
}
|
|
22684
22684
|
function listProcesses(platform = process.platform) {
|
|
22685
22685
|
if (platform === "win32") return Promise.resolve([]);
|
|
22686
|
-
return new Promise((
|
|
22686
|
+
return new Promise((resolve8) => {
|
|
22687
22687
|
(0, import_child_process3.execFile)(
|
|
22688
22688
|
"ps",
|
|
22689
22689
|
["-A", "-o", "pid=,ppid=,pgid=,lstart="],
|
|
22690
22690
|
{ timeout: 5e3, maxBuffer: 8 * 1024 * 1024 },
|
|
22691
|
-
(error61, stdout) =>
|
|
22691
|
+
(error61, stdout) => resolve8(error61 ? [] : parseProcessList(stdout))
|
|
22692
22692
|
);
|
|
22693
22693
|
});
|
|
22694
22694
|
}
|
|
@@ -22728,11 +22728,11 @@ async function taskkill(pid, options) {
|
|
|
22728
22728
|
stdio: "ignore",
|
|
22729
22729
|
windowsHide: true
|
|
22730
22730
|
});
|
|
22731
|
-
const exited = new Promise((
|
|
22732
|
-
killer.once("error", (error210) =>
|
|
22731
|
+
const exited = new Promise((resolve8) => {
|
|
22732
|
+
killer.once("error", (error210) => resolve8(error210));
|
|
22733
22733
|
killer.once(
|
|
22734
22734
|
"exit",
|
|
22735
|
-
(code, signal) =>
|
|
22735
|
+
(code, signal) => resolve8(code === 0 ? void 0 : new Error(`taskkill failed: exit ${code}, signal ${signal}`))
|
|
22736
22736
|
);
|
|
22737
22737
|
});
|
|
22738
22738
|
const timedOut = clock.sleep(options.timeoutMs ?? DEFAULT_TASKKILL_TIMEOUT_MS, timeout.signal).then(() => new Error("taskkill timed out")).catch(() => void 0);
|
|
@@ -22775,9 +22775,9 @@ function signalGroup(pgid, signal, onError) {
|
|
|
22775
22775
|
if (!isAlreadyDead(error61)) onError?.("group", error61);
|
|
22776
22776
|
}
|
|
22777
22777
|
}
|
|
22778
|
-
function liveEscapedGroups(
|
|
22779
|
-
const leaders = new Map(
|
|
22780
|
-
const groups = new Set(escapedGroups(
|
|
22778
|
+
function liveEscapedGroups(snapshot, rootPid, remembered) {
|
|
22779
|
+
const leaders = new Map(snapshot.map((entry) => [entry.pid, entry.startedAt]));
|
|
22780
|
+
const groups = new Set(escapedGroups(snapshot, rootPid).map((group) => group.pgid));
|
|
22781
22781
|
for (const [pgid, startedAt] of remembered) {
|
|
22782
22782
|
if (leaders.get(pgid) === startedAt) groups.add(pgid);
|
|
22783
22783
|
}
|
|
@@ -22988,10 +22988,10 @@ function spawnCli(options) {
|
|
|
22988
22988
|
function waitForSpawn(child, command) {
|
|
22989
22989
|
if (isWindowsJob(child)) return waitForWindowsJob(child, command);
|
|
22990
22990
|
if (child.pid !== void 0) return Promise.resolve();
|
|
22991
|
-
return new Promise((
|
|
22991
|
+
return new Promise((resolve8, reject) => {
|
|
22992
22992
|
const onSpawn = () => {
|
|
22993
22993
|
child.off("error", onError);
|
|
22994
|
-
|
|
22994
|
+
resolve8();
|
|
22995
22995
|
};
|
|
22996
22996
|
const onError = (error61) => {
|
|
22997
22997
|
child.off("spawn", onSpawn);
|
|
@@ -24903,8 +24903,8 @@ function readMediaFiles(candidates2, cwd, mimeByExt, maxBytes) {
|
|
|
24903
24903
|
seen.add(path);
|
|
24904
24904
|
const mimeType = mimeByExt[(0, import_path3.extname)(path).toLowerCase()];
|
|
24905
24905
|
if (!mimeType) continue;
|
|
24906
|
-
const
|
|
24907
|
-
if (!
|
|
24906
|
+
const stat15 = (0, import_fs4.statSync)(path);
|
|
24907
|
+
if (!stat15.isFile() || stat15.size <= 0 || stat15.size > maxBytes) continue;
|
|
24908
24908
|
files.push({ path, mimeType, buffer: (0, import_fs4.readFileSync)(path) });
|
|
24909
24909
|
}
|
|
24910
24910
|
return files;
|
|
@@ -24979,8 +24979,8 @@ function createJsonRpcPeer(writer, handlers) {
|
|
|
24979
24979
|
},
|
|
24980
24980
|
request: (method, params = {}) => {
|
|
24981
24981
|
const id = counter.next++;
|
|
24982
|
-
return new Promise((
|
|
24983
|
-
pending.set(id, { method, resolve:
|
|
24982
|
+
return new Promise((resolve8, reject) => {
|
|
24983
|
+
pending.set(id, { method, resolve: resolve8, reject });
|
|
24984
24984
|
writer.write({ id, method, params }).catch((error61) => {
|
|
24985
24985
|
pending.delete(id);
|
|
24986
24986
|
reject(error61 instanceof Error ? error61 : new Error(String(error61)));
|
|
@@ -25093,7 +25093,7 @@ function createNdjsonWriter(stream) {
|
|
|
25093
25093
|
get writable() {
|
|
25094
25094
|
return stream.writable && !stream.destroyed && failure5.error === void 0;
|
|
25095
25095
|
},
|
|
25096
|
-
write: (value) => new Promise((
|
|
25096
|
+
write: (value) => new Promise((resolve8, reject) => {
|
|
25097
25097
|
if (failure5.error) {
|
|
25098
25098
|
reject(failure5.error);
|
|
25099
25099
|
return;
|
|
@@ -25105,7 +25105,7 @@ function createNdjsonWriter(stream) {
|
|
|
25105
25105
|
stream.write(`${JSON.stringify(value)}
|
|
25106
25106
|
`, (error61) => {
|
|
25107
25107
|
if (error61) reject(error61);
|
|
25108
|
-
else
|
|
25108
|
+
else resolve8();
|
|
25109
25109
|
});
|
|
25110
25110
|
}),
|
|
25111
25111
|
end: () => {
|
|
@@ -25137,11 +25137,11 @@ function hostProcess(child, tree, options, handlers) {
|
|
|
25137
25137
|
});
|
|
25138
25138
|
child.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
25139
25139
|
child.stderr.once("end", () => stderr.flush());
|
|
25140
|
-
const processExit = new Promise((
|
|
25141
|
-
child.once("exit", (code, signal) =>
|
|
25140
|
+
const processExit = new Promise((resolve8) => {
|
|
25141
|
+
child.once("exit", (code, signal) => resolve8({ code, signal }));
|
|
25142
25142
|
});
|
|
25143
|
-
const outputEnded = new Promise((
|
|
25144
|
-
child.stdout.once("close", () =>
|
|
25143
|
+
const outputEnded = new Promise((resolve8) => {
|
|
25144
|
+
child.stdout.once("close", () => resolve8());
|
|
25145
25145
|
});
|
|
25146
25146
|
const watch = async () => {
|
|
25147
25147
|
const { clock, stdoutDrainMs, log, name } = options;
|
|
@@ -25438,13 +25438,13 @@ var init_chunk_A2TG6ROT = __esm({
|
|
|
25438
25438
|
const turnId = input2.turnId;
|
|
25439
25439
|
let finish = () => {
|
|
25440
25440
|
};
|
|
25441
|
-
const done = new Promise((
|
|
25441
|
+
const done = new Promise((resolve8) => {
|
|
25442
25442
|
finish = (outcome2) => {
|
|
25443
25443
|
if (this.#current?.id !== turnId) return;
|
|
25444
25444
|
this.#current = void 0;
|
|
25445
25445
|
if (this.#state === "busy") this.#state = "idle";
|
|
25446
25446
|
this.#emit({ type: "turn_ended", turnId, outcome: outcome2 });
|
|
25447
|
-
|
|
25447
|
+
resolve8({ turnId, outcome: outcome2, providerSessionId: this.#sessionId });
|
|
25448
25448
|
};
|
|
25449
25449
|
});
|
|
25450
25450
|
const pending = {
|
|
@@ -25742,18 +25742,18 @@ function environmentInstructions(environment, cwd) {
|
|
|
25742
25742
|
}
|
|
25743
25743
|
return lines;
|
|
25744
25744
|
}
|
|
25745
|
-
function instructionsFor(
|
|
25746
|
-
const cwd =
|
|
25745
|
+
function instructionsFor(snapshot) {
|
|
25746
|
+
const cwd = snapshot.workspace.cwd ?? snapshot.workspace.root ?? "the workspace";
|
|
25747
25747
|
return [
|
|
25748
|
-
...
|
|
25749
|
-
...
|
|
25748
|
+
...snapshot.session.trigger === "image_build" ? ["Alan sent this turn, not the user: it reports an image build result."] : [],
|
|
25749
|
+
...snapshot.environment ? environmentInstructions(snapshot.environment, cwd) : []
|
|
25750
25750
|
];
|
|
25751
25751
|
}
|
|
25752
|
-
function startingInstructions(
|
|
25753
|
-
const cwd =
|
|
25752
|
+
function startingInstructions(snapshot) {
|
|
25753
|
+
const cwd = snapshot.workspace.cwd ?? snapshot.workspace.root;
|
|
25754
25754
|
return [
|
|
25755
25755
|
...cwd ? [`Work from ${cwd}.`] : [],
|
|
25756
|
-
...
|
|
25756
|
+
...snapshot.workspace.repositories.flatMap(repositoryInstructions)
|
|
25757
25757
|
];
|
|
25758
25758
|
}
|
|
25759
25759
|
function sessionKind(input2, context) {
|
|
@@ -25776,17 +25776,17 @@ function environmentOf(input2, context) {
|
|
|
25776
25776
|
...start ? { start: start.state === "not_configured" ? start : { ...start, log: input2.startLogPath } } : {}
|
|
25777
25777
|
};
|
|
25778
25778
|
}
|
|
25779
|
-
function knownContext(
|
|
25780
|
-
const organizationId =
|
|
25781
|
-
if (!
|
|
25782
|
-
const environment =
|
|
25779
|
+
function knownContext(snapshot) {
|
|
25780
|
+
const organizationId = snapshot?.session.organizationId;
|
|
25781
|
+
if (!snapshot || !organizationId) return void 0;
|
|
25782
|
+
const environment = snapshot.environment;
|
|
25783
25783
|
return {
|
|
25784
|
-
kind:
|
|
25784
|
+
kind: snapshot.session.kind,
|
|
25785
25785
|
trigger: "user",
|
|
25786
25786
|
organizationId,
|
|
25787
|
-
...
|
|
25788
|
-
...
|
|
25789
|
-
repositories:
|
|
25787
|
+
...snapshot.task ? { taskWorkingBranch: snapshot.task.workingBranch } : {},
|
|
25788
|
+
...snapshot.pullRequest ? { pullRequest: snapshot.pullRequest } : {},
|
|
25789
|
+
repositories: snapshot.workspace.repositories.flatMap(
|
|
25790
25790
|
({ path, name, url: url2, branch, branchSource, base }) => name && url2 && branch && branchSource && base ? [{ path, name, url: url2, branch, branchSource, base }] : []
|
|
25791
25791
|
),
|
|
25792
25792
|
...environment ? {
|
|
@@ -25913,15 +25913,15 @@ function updateBody(previous, next) {
|
|
|
25913
25913
|
if (Object.keys(facts).length === 0) return void 0;
|
|
25914
25914
|
return next.session.trigger === "user" ? facts : { session: { trigger: next.session.trigger }, ...facts };
|
|
25915
25915
|
}
|
|
25916
|
-
function renderAgentContext(
|
|
25916
|
+
function renderAgentContext(snapshot, previous) {
|
|
25917
25917
|
const full = block("alan_agent_context", {
|
|
25918
|
-
...
|
|
25919
|
-
...
|
|
25920
|
-
instructions: [...startingInstructions(
|
|
25918
|
+
...snapshot,
|
|
25919
|
+
...snapshot.environment ? { environment: withCommandPreviews(snapshot.environment) } : {},
|
|
25920
|
+
instructions: [...startingInstructions(snapshot), ...snapshot.instructions]
|
|
25921
25921
|
});
|
|
25922
|
-
const update = previous ? updateBody(previous,
|
|
25922
|
+
const update = previous ? updateBody(previous, snapshot) : void 0;
|
|
25923
25923
|
return {
|
|
25924
|
-
snapshot
|
|
25924
|
+
snapshot,
|
|
25925
25925
|
full,
|
|
25926
25926
|
...update ? { update: block("alan_agent_context_update", update) } : {}
|
|
25927
25927
|
};
|
|
@@ -27341,18 +27341,24 @@ function realCwd(cwd) {
|
|
|
27341
27341
|
return cwd;
|
|
27342
27342
|
}
|
|
27343
27343
|
}
|
|
27344
|
+
function projectDirs(projectsRoot) {
|
|
27345
|
+
try {
|
|
27346
|
+
return (0, import_fs5.readdirSync)(projectsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
27347
|
+
} catch {
|
|
27348
|
+
return [];
|
|
27349
|
+
}
|
|
27350
|
+
}
|
|
27344
27351
|
function claudeSessionLogExists(query) {
|
|
27345
27352
|
if (!query.sessionId || !query.cwd) return false;
|
|
27346
|
-
|
|
27347
|
-
|
|
27348
|
-
|
|
27349
|
-
|
|
27350
|
-
|
|
27351
|
-
|
|
27352
|
-
|
|
27353
|
-
|
|
27354
|
-
|
|
27355
|
-
return false;
|
|
27353
|
+
const projectsRoot = (0, import_path5.join)(query.claudeHome, "projects");
|
|
27354
|
+
const fileName = `${query.sessionId}.jsonl`;
|
|
27355
|
+
const here = new Set([query.cwd, realCwd(query.cwd)].map(encodeProjectDir));
|
|
27356
|
+
for (const dir of here) {
|
|
27357
|
+
if ((0, import_fs5.existsSync)((0, import_path5.join)(projectsRoot, dir, fileName))) return true;
|
|
27358
|
+
}
|
|
27359
|
+
return projectDirs(projectsRoot).some(
|
|
27360
|
+
(dir) => !here.has(dir) && (0, import_fs5.existsSync)((0, import_path5.join)(projectsRoot, dir, fileName))
|
|
27361
|
+
);
|
|
27356
27362
|
}
|
|
27357
27363
|
function envDigest(env) {
|
|
27358
27364
|
const hash2 = (0, import_crypto7.createHash)("sha256");
|
|
@@ -28160,8 +28166,8 @@ var init_claude = __esm({
|
|
|
28160
28166
|
}
|
|
28161
28167
|
async #awaitTaskStop(requestId, taskId) {
|
|
28162
28168
|
const timer = new AbortController();
|
|
28163
|
-
const answered = new Promise((
|
|
28164
|
-
this.#taskStops.set(requestId,
|
|
28169
|
+
const answered = new Promise((resolve8) => {
|
|
28170
|
+
this.#taskStops.set(requestId, resolve8);
|
|
28165
28171
|
});
|
|
28166
28172
|
const timeoutMs = this.#options.stopTaskTimeoutMs;
|
|
28167
28173
|
const timedOut = this.#options.clock.sleep(timeoutMs, timer.signal).then(
|
|
@@ -28234,17 +28240,17 @@ var init_claude = __esm({
|
|
|
28234
28240
|
};
|
|
28235
28241
|
let markStarted = () => {
|
|
28236
28242
|
};
|
|
28237
|
-
const whenStarted = new Promise((
|
|
28238
|
-
markStarted =
|
|
28243
|
+
const whenStarted = new Promise((resolve8) => {
|
|
28244
|
+
markStarted = resolve8;
|
|
28239
28245
|
});
|
|
28240
|
-
const done = new Promise((
|
|
28246
|
+
const done = new Promise((resolve8) => {
|
|
28241
28247
|
finish = (outcome2) => {
|
|
28242
28248
|
if (this.#current?.id !== id) return;
|
|
28243
28249
|
this.#current = void 0;
|
|
28244
28250
|
this.#lastTurn = turn;
|
|
28245
28251
|
if (this.#state === "busy") this.#state = "idle";
|
|
28246
28252
|
this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
|
|
28247
|
-
|
|
28253
|
+
resolve8({ turnId: id, outcome: outcome2, providerSessionId: this.#providerSessionId });
|
|
28248
28254
|
};
|
|
28249
28255
|
});
|
|
28250
28256
|
const active = {
|
|
@@ -28362,8 +28368,8 @@ var init_claude = __esm({
|
|
|
28362
28368
|
void removeLaunchFiles(this.#launchFiles).catch((error61) => {
|
|
28363
28369
|
this.#options.log.warn("claude.launch_files_cleanup_failed", { error: error61 });
|
|
28364
28370
|
});
|
|
28365
|
-
for (const
|
|
28366
|
-
|
|
28371
|
+
for (const resolve8 of this.#taskStops.values()) {
|
|
28372
|
+
resolve8({ ok: false, reason: "runtime_unavailable", message: "Claude Code exited." });
|
|
28367
28373
|
}
|
|
28368
28374
|
const active = this.#current;
|
|
28369
28375
|
if (active) {
|
|
@@ -29860,7 +29866,7 @@ var init_codex = __esm({
|
|
|
29860
29866
|
const buckets = asRecord(response?.rateLimitsByLimitId);
|
|
29861
29867
|
if (buckets) {
|
|
29862
29868
|
return Object.entries(buckets).flatMap(
|
|
29863
|
-
([limitId,
|
|
29869
|
+
([limitId, snapshot]) => this.#update(snapshot, limitId)
|
|
29864
29870
|
);
|
|
29865
29871
|
}
|
|
29866
29872
|
return this.#update(response?.rateLimits);
|
|
@@ -29869,16 +29875,16 @@ var init_codex = __esm({
|
|
|
29869
29875
|
return this.#update(params.rateLimits);
|
|
29870
29876
|
}
|
|
29871
29877
|
#update(value, bucketId) {
|
|
29872
|
-
const
|
|
29873
|
-
if (!
|
|
29874
|
-
const primary = windowPatch(
|
|
29875
|
-
const secondary = windowPatch(
|
|
29876
|
-
const spend = spendPatch(
|
|
29877
|
-
const credits = creditsPatch(
|
|
29878
|
-
const planType =
|
|
29878
|
+
const snapshot = asRecord(value);
|
|
29879
|
+
if (!snapshot) return [];
|
|
29880
|
+
const primary = windowPatch(snapshot.primary);
|
|
29881
|
+
const secondary = windowPatch(snapshot.secondary);
|
|
29882
|
+
const spend = spendPatch(snapshot.individualLimit, snapshot.spendControlReached);
|
|
29883
|
+
const credits = creditsPatch(snapshot.credits);
|
|
29884
|
+
const planType = snapshot.planType === null ? null : asString(snapshot.planType) || void 0;
|
|
29879
29885
|
const parsed = runCodexRateLimitsUpdateSchema.safeParse({
|
|
29880
29886
|
sessionUpdate: "_alan/codex.rate_limits",
|
|
29881
|
-
limitId: bucketId ?? (asString(
|
|
29887
|
+
limitId: bucketId ?? (asString(snapshot.limitId) || "codex"),
|
|
29882
29888
|
...primary === void 0 ? {} : { primary },
|
|
29883
29889
|
...secondary === void 0 ? {} : { secondary },
|
|
29884
29890
|
...spend === void 0 ? {} : { spend },
|
|
@@ -30324,10 +30330,10 @@ var init_codex = __esm({
|
|
|
30324
30330
|
};
|
|
30325
30331
|
let identify = () => {
|
|
30326
30332
|
};
|
|
30327
|
-
const identified = new Promise((
|
|
30328
|
-
identify =
|
|
30333
|
+
const identified = new Promise((resolve8) => {
|
|
30334
|
+
identify = resolve8;
|
|
30329
30335
|
});
|
|
30330
|
-
const done = new Promise((
|
|
30336
|
+
const done = new Promise((resolve8) => {
|
|
30331
30337
|
finish = (outcome2) => {
|
|
30332
30338
|
if (this.#current?.id !== id) return;
|
|
30333
30339
|
this.#current = void 0;
|
|
@@ -30335,7 +30341,7 @@ var init_codex = __esm({
|
|
|
30335
30341
|
if (this.#state === "busy") this.#state = "idle";
|
|
30336
30342
|
this.#host.scanDescendants(true);
|
|
30337
30343
|
this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
|
|
30338
|
-
|
|
30344
|
+
resolve8({ turnId: id, outcome: outcome2, providerSessionId: this.#threadId });
|
|
30339
30345
|
};
|
|
30340
30346
|
});
|
|
30341
30347
|
const active = {
|
|
@@ -30826,7 +30832,7 @@ function alanCodeConfigContent(existing, input2) {
|
|
|
30826
30832
|
});
|
|
30827
30833
|
}
|
|
30828
30834
|
function readBody2(response) {
|
|
30829
|
-
return new Promise((
|
|
30835
|
+
return new Promise((resolve8, reject) => {
|
|
30830
30836
|
const chunks = [];
|
|
30831
30837
|
let size = 0;
|
|
30832
30838
|
response.on("data", (chunk) => {
|
|
@@ -30834,7 +30840,7 @@ function readBody2(response) {
|
|
|
30834
30840
|
if (size > MAX_CATALOG_BYTES) response.destroy(new Error("catalog too large"));
|
|
30835
30841
|
else chunks.push(chunk);
|
|
30836
30842
|
});
|
|
30837
|
-
response.on("end", () =>
|
|
30843
|
+
response.on("end", () => resolve8(Buffer.concat(chunks).toString("utf8")));
|
|
30838
30844
|
response.on("error", reject);
|
|
30839
30845
|
});
|
|
30840
30846
|
}
|
|
@@ -30850,13 +30856,13 @@ function parseResponseBody(text2, status) {
|
|
|
30850
30856
|
}
|
|
30851
30857
|
function getJson(url2, headers, timeout, signal) {
|
|
30852
30858
|
const request2 = url2.protocol === "https:" ? import_https.request : import_http3.request;
|
|
30853
|
-
return new Promise((
|
|
30859
|
+
return new Promise((resolve8, reject) => {
|
|
30854
30860
|
const outgoing = request2(url2, { method: "GET", headers, timeout, signal }, (response) => {
|
|
30855
30861
|
const status = response.statusCode ?? 0;
|
|
30856
30862
|
readBody2(response).then((text2) => {
|
|
30857
30863
|
const body = parseResponseBody(text2, status);
|
|
30858
30864
|
if (status < 200 || status >= 300) reject(new CatalogResponseError(status, body));
|
|
30859
|
-
else
|
|
30865
|
+
else resolve8(body);
|
|
30860
30866
|
}).catch(reject);
|
|
30861
30867
|
});
|
|
30862
30868
|
outgoing.on("timeout", () => outgoing.destroy(new Error("catalog timed out")));
|
|
@@ -39089,12 +39095,12 @@ function shellStart(update, sessionId) {
|
|
|
39089
39095
|
];
|
|
39090
39096
|
}
|
|
39091
39097
|
function shellEnd(update) {
|
|
39092
|
-
const
|
|
39093
|
-
const taskId = optional2(
|
|
39094
|
-
if (!
|
|
39095
|
-
const killed =
|
|
39096
|
-
const exitCode =
|
|
39097
|
-
const failed = typeof exitCode === "number" && exitCode !== 0 || optional2(
|
|
39098
|
+
const snapshot = asRecord(update.task_snapshot);
|
|
39099
|
+
const taskId = optional2(snapshot?.task_id);
|
|
39100
|
+
if (!snapshot || !taskId) return [];
|
|
39101
|
+
const killed = snapshot.explicitly_killed === true;
|
|
39102
|
+
const exitCode = snapshot.exit_code;
|
|
39103
|
+
const failed = typeof exitCode === "number" && exitCode !== 0 || optional2(snapshot.signal) !== void 0;
|
|
39098
39104
|
const ending = killed ? "stopped" : failed ? "failed" : "completed";
|
|
39099
39105
|
return [{ type: "end", taskId, ending }];
|
|
39100
39106
|
}
|
|
@@ -39766,7 +39772,7 @@ var init_acp3 = __esm({
|
|
|
39766
39772
|
const turn = new AcpTurn(`acp-${this.#turns}-${id}`, this.#profile);
|
|
39767
39773
|
let finish = () => {
|
|
39768
39774
|
};
|
|
39769
|
-
const done = new Promise((
|
|
39775
|
+
const done = new Promise((resolve8) => {
|
|
39770
39776
|
finish = (outcome2) => {
|
|
39771
39777
|
if (this.#current?.id !== id) return;
|
|
39772
39778
|
this.#current = void 0;
|
|
@@ -39774,7 +39780,7 @@ var init_acp3 = __esm({
|
|
|
39774
39780
|
if (this.#state === "busy") this.#state = "idle";
|
|
39775
39781
|
this.#host.scanDescendants(true);
|
|
39776
39782
|
this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
|
|
39777
|
-
|
|
39783
|
+
resolve8({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
|
|
39778
39784
|
};
|
|
39779
39785
|
});
|
|
39780
39786
|
const active = { id, turn, done, finish, cancelRequested: false };
|
|
@@ -40359,12 +40365,11 @@ function createPersistentDriver(provider4, options) {
|
|
|
40359
40365
|
log.warn("holder.history_rejected", { harness: provider4.harness });
|
|
40360
40366
|
await session.suspend();
|
|
40361
40367
|
};
|
|
40362
|
-
const respond = async (request2
|
|
40368
|
+
const respond = async (request2) => {
|
|
40363
40369
|
const turn = live.turn;
|
|
40364
40370
|
if (turn === void 0 || turn.runId !== request2.runId) return "unknown_run";
|
|
40365
40371
|
const isWaiting = () => live.turn === turn && turn.waiting.has(request2.toolCallId);
|
|
40366
40372
|
if (!isWaiting() || turn.session.respond === void 0) return "not_waiting";
|
|
40367
|
-
if (!await mayWrite() || !isWaiting()) return "not_waiting";
|
|
40368
40373
|
turn.waiting.delete(request2.toolCallId);
|
|
40369
40374
|
try {
|
|
40370
40375
|
await turn.session.respond(request2.toolCallId, request2.answer);
|
|
@@ -42590,8 +42595,8 @@ function createDroidPeer(writer, handlers) {
|
|
|
42590
42595
|
},
|
|
42591
42596
|
request: (method, params = {}) => {
|
|
42592
42597
|
const id = `alan-${counter.next++}`;
|
|
42593
|
-
return new Promise((
|
|
42594
|
-
pending.set(id, { method, resolve:
|
|
42598
|
+
return new Promise((resolve8, reject) => {
|
|
42599
|
+
pending.set(id, { method, resolve: resolve8, reject });
|
|
42595
42600
|
writer.write(envelope("request", { id, method, params })).catch((error61) => {
|
|
42596
42601
|
pending.delete(id);
|
|
42597
42602
|
reject(error61 instanceof Error ? error61 : new Error(String(error61)));
|
|
@@ -43219,14 +43224,14 @@ var init_droid = __esm({
|
|
|
43219
43224
|
const turn = new DroidTurn(sessionId, this.#memory);
|
|
43220
43225
|
let finish = () => {
|
|
43221
43226
|
};
|
|
43222
|
-
const done = new Promise((
|
|
43227
|
+
const done = new Promise((resolve8) => {
|
|
43223
43228
|
finish = (outcome2) => {
|
|
43224
43229
|
if (this.#current?.id !== id) return;
|
|
43225
43230
|
this.#current = void 0;
|
|
43226
43231
|
if (this.#state === "busy") this.#state = "idle";
|
|
43227
43232
|
this.#host.scanDescendants(true);
|
|
43228
43233
|
this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
|
|
43229
|
-
|
|
43234
|
+
resolve8({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
|
|
43230
43235
|
};
|
|
43231
43236
|
});
|
|
43232
43237
|
const active = { id, turn, done, finish, cancelRequested: false };
|
|
@@ -45551,46 +45556,6 @@ function openFileLog(path, level, clock) {
|
|
|
45551
45556
|
};
|
|
45552
45557
|
}
|
|
45553
45558
|
|
|
45554
|
-
// src/kernel/maintenance.ts
|
|
45555
|
-
function startMaintenance({ everyMs, jobs, clock, log }) {
|
|
45556
|
-
const controller = new AbortController();
|
|
45557
|
-
let running = Promise.resolve();
|
|
45558
|
-
const runJobs = async () => {
|
|
45559
|
-
for (const job of jobs) {
|
|
45560
|
-
if (controller.signal.aborted) return;
|
|
45561
|
-
try {
|
|
45562
|
-
await job.run(controller.signal);
|
|
45563
|
-
} catch (error61) {
|
|
45564
|
-
if (!controller.signal.aborted)
|
|
45565
|
-
log.warn("maintenance.job_failed", { job: job.name, error: error61 });
|
|
45566
|
-
}
|
|
45567
|
-
}
|
|
45568
|
-
};
|
|
45569
|
-
const tick = () => {
|
|
45570
|
-
running = running.then(runJobs);
|
|
45571
|
-
return running;
|
|
45572
|
-
};
|
|
45573
|
-
const loop = async () => {
|
|
45574
|
-
while (!controller.signal.aborted) {
|
|
45575
|
-
try {
|
|
45576
|
-
await clock.sleep(everyMs, controller.signal);
|
|
45577
|
-
} catch {
|
|
45578
|
-
return;
|
|
45579
|
-
}
|
|
45580
|
-
await tick();
|
|
45581
|
-
}
|
|
45582
|
-
};
|
|
45583
|
-
const looping = loop();
|
|
45584
|
-
return {
|
|
45585
|
-
runNow: tick,
|
|
45586
|
-
[Symbol.asyncDispose]: async () => {
|
|
45587
|
-
controller.abort();
|
|
45588
|
-
await looping;
|
|
45589
|
-
await running;
|
|
45590
|
-
}
|
|
45591
|
-
};
|
|
45592
|
-
}
|
|
45593
|
-
|
|
45594
45559
|
// src/api-client/http.ts
|
|
45595
45560
|
var import_node_http = require("http");
|
|
45596
45561
|
var import_node_https = require("https");
|
|
@@ -45618,7 +45583,7 @@ function transportFailure(request2, error61) {
|
|
|
45618
45583
|
});
|
|
45619
45584
|
}
|
|
45620
45585
|
function readBody(incoming, url2, maxBytes) {
|
|
45621
|
-
return new Promise((
|
|
45586
|
+
return new Promise((resolve8, reject) => {
|
|
45622
45587
|
const declared = Number(incoming.headers["content-length"] ?? "0");
|
|
45623
45588
|
if (maxBytes !== void 0 && declared > maxBytes) {
|
|
45624
45589
|
incoming.destroy();
|
|
@@ -45637,7 +45602,7 @@ function readBody(incoming, url2, maxBytes) {
|
|
|
45637
45602
|
chunks.push(chunk);
|
|
45638
45603
|
});
|
|
45639
45604
|
incoming.on("error", reject);
|
|
45640
|
-
incoming.on("end", () =>
|
|
45605
|
+
incoming.on("end", () => resolve8(Buffer.concat(chunks)));
|
|
45641
45606
|
});
|
|
45642
45607
|
}
|
|
45643
45608
|
function isConnectionReset(error61) {
|
|
@@ -45645,7 +45610,7 @@ function isConnectionReset(error61) {
|
|
|
45645
45610
|
}
|
|
45646
45611
|
function exchange(request2, agents, attempt = 0) {
|
|
45647
45612
|
const { signal, url: url2 } = request2;
|
|
45648
|
-
return new Promise((
|
|
45613
|
+
return new Promise((resolve8, reject) => {
|
|
45649
45614
|
if (signal.aborted) {
|
|
45650
45615
|
reject(signal.reason);
|
|
45651
45616
|
return;
|
|
@@ -45672,7 +45637,7 @@ function exchange(request2, agents, attempt = 0) {
|
|
|
45672
45637
|
const stale = outgoing.reusedSocket && !responded && isConnectionReset(error61);
|
|
45673
45638
|
if (stale && attempt < STALE_SOCKET_RETRIES && !signal.aborted) {
|
|
45674
45639
|
settle();
|
|
45675
|
-
|
|
45640
|
+
resolve8(exchange(request2, agents, attempt + 1));
|
|
45676
45641
|
return;
|
|
45677
45642
|
}
|
|
45678
45643
|
fail(error61);
|
|
@@ -45685,7 +45650,7 @@ function exchange(request2, agents, attempt = 0) {
|
|
|
45685
45650
|
readBody(incoming, url2, isRedirect(status) ? void 0 : request2.maxBodyBytes).then(
|
|
45686
45651
|
(body) => {
|
|
45687
45652
|
settle();
|
|
45688
|
-
|
|
45653
|
+
resolve8({ status, headers: incoming.headers, body });
|
|
45689
45654
|
},
|
|
45690
45655
|
fail
|
|
45691
45656
|
);
|
|
@@ -46004,7 +45969,7 @@ function createGitRunner(options) {
|
|
|
46004
45969
|
}
|
|
46005
45970
|
await killProcessTree(child.pid, { signal: "SIGKILL", child, platform });
|
|
46006
45971
|
};
|
|
46007
|
-
return new Promise((
|
|
45972
|
+
return new Promise((resolve8, reject) => {
|
|
46008
45973
|
let ending = null;
|
|
46009
45974
|
const stop = (next) => {
|
|
46010
45975
|
if (ending !== null) return;
|
|
@@ -46029,7 +45994,7 @@ function createGitRunner(options) {
|
|
|
46029
45994
|
signal.removeEventListener("abort", onAbort);
|
|
46030
45995
|
const final = ending ?? last;
|
|
46031
45996
|
if (final.kind === "exited") {
|
|
46032
|
-
|
|
45997
|
+
resolve8({ exitCode: final.exitCode, stdout: stdout.text(), stderr: stderr.text() });
|
|
46033
45998
|
} else {
|
|
46034
45999
|
reject(faultFor(final, command));
|
|
46035
46000
|
}
|
|
@@ -46351,9 +46316,9 @@ function isProcessAlive(pid) {
|
|
|
46351
46316
|
}
|
|
46352
46317
|
}
|
|
46353
46318
|
async function linuxStartTime(pid) {
|
|
46354
|
-
const
|
|
46355
|
-
if (
|
|
46356
|
-
const fields =
|
|
46319
|
+
const stat15 = await (0, import_promises10.readFile)(`/proc/${pid}/stat`, "utf8").catch(() => null);
|
|
46320
|
+
if (stat15 === null) return null;
|
|
46321
|
+
const fields = stat15.slice(stat15.lastIndexOf(")") + 2).split(" ");
|
|
46357
46322
|
return fields[19] ?? null;
|
|
46358
46323
|
}
|
|
46359
46324
|
async function linuxCommand(pid) {
|
|
@@ -46532,7 +46497,7 @@ function statusOf(error61) {
|
|
|
46532
46497
|
}
|
|
46533
46498
|
return 1;
|
|
46534
46499
|
}
|
|
46535
|
-
var systemExec = (request2) => new Promise((
|
|
46500
|
+
var systemExec = (request2) => new Promise((resolve8) => {
|
|
46536
46501
|
const child = (0, import_node_child_process5.execFile)(
|
|
46537
46502
|
request2.command,
|
|
46538
46503
|
[...request2.args],
|
|
@@ -46543,7 +46508,7 @@ var systemExec = (request2) => new Promise((resolve9) => {
|
|
|
46543
46508
|
windowsHide: true
|
|
46544
46509
|
},
|
|
46545
46510
|
(error61, stdout, stderr) => {
|
|
46546
|
-
|
|
46511
|
+
resolve8({ status: statusOf(error61), stdout, stderr });
|
|
46547
46512
|
}
|
|
46548
46513
|
);
|
|
46549
46514
|
child.stdin?.on("error", () => {
|
|
@@ -47507,7 +47472,7 @@ function openRepositoryLocks(options) {
|
|
|
47507
47472
|
|
|
47508
47473
|
// src/cli/config.ts
|
|
47509
47474
|
var import_node_os7 = require("os");
|
|
47510
|
-
var
|
|
47475
|
+
var import_node_path31 = require("path");
|
|
47511
47476
|
init_zod();
|
|
47512
47477
|
|
|
47513
47478
|
// src/client/locate.ts
|
|
@@ -47528,9 +47493,9 @@ function defaultInstallDir({ platform, home, env }) {
|
|
|
47528
47493
|
|
|
47529
47494
|
// src/sessions/index.ts
|
|
47530
47495
|
var import_node_crypto16 = require("crypto");
|
|
47531
|
-
var
|
|
47496
|
+
var import_promises39 = require("fs/promises");
|
|
47532
47497
|
var import_node_os6 = require("os");
|
|
47533
|
-
var
|
|
47498
|
+
var import_node_path30 = require("path");
|
|
47534
47499
|
|
|
47535
47500
|
// src/holder/control-client.ts
|
|
47536
47501
|
var import_node_crypto12 = require("crypto");
|
|
@@ -47585,9 +47550,9 @@ function selectDriver(persistent, fallback) {
|
|
|
47585
47550
|
suspend: async () => {
|
|
47586
47551
|
await Promise.all([...drivers].map((driver) => driver.suspend?.()));
|
|
47587
47552
|
},
|
|
47588
|
-
respond: async (request2
|
|
47553
|
+
respond: async (request2) => {
|
|
47589
47554
|
for (const driver of drivers) {
|
|
47590
|
-
const status = await driver.respond?.(request2
|
|
47555
|
+
const status = await driver.respond?.(request2);
|
|
47591
47556
|
if (status !== void 0 && status !== "unknown_run") return status;
|
|
47592
47557
|
}
|
|
47593
47558
|
return "unknown_run";
|
|
@@ -47627,9 +47592,9 @@ function createLazyDriver(load) {
|
|
|
47627
47592
|
suspend: async () => {
|
|
47628
47593
|
if (loaded.driver !== void 0) await (await loaded.driver).suspend?.();
|
|
47629
47594
|
},
|
|
47630
|
-
respond: async (request2
|
|
47595
|
+
respond: async (request2) => {
|
|
47631
47596
|
if (loaded.driver === void 0) return "unknown_run";
|
|
47632
|
-
return await (await loaded.driver).respond?.(request2
|
|
47597
|
+
return await (await loaded.driver).respond?.(request2) ?? "unknown_run";
|
|
47633
47598
|
},
|
|
47634
47599
|
stopTask: async (taskId) => {
|
|
47635
47600
|
if (loaded.driver === void 0) return TASK_NOT_FOUND;
|
|
@@ -47844,14 +47809,14 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
|
|
|
47844
47809
|
var import_node_crypto15 = require("crypto");
|
|
47845
47810
|
var import_node_fs11 = require("fs");
|
|
47846
47811
|
var import_node_net2 = require("net");
|
|
47847
|
-
var
|
|
47812
|
+
var import_node_path29 = require("path");
|
|
47848
47813
|
init_runtime_v2();
|
|
47849
47814
|
|
|
47850
47815
|
// src/holder/admission.ts
|
|
47851
47816
|
var import_node_fs9 = require("fs");
|
|
47852
|
-
var
|
|
47817
|
+
var import_promises35 = require("fs/promises");
|
|
47853
47818
|
var import_node_os5 = require("os");
|
|
47854
|
-
var
|
|
47819
|
+
var import_node_path25 = require("path");
|
|
47855
47820
|
init_constants();
|
|
47856
47821
|
|
|
47857
47822
|
// ../shared/dist/node/local-workspace.js
|
|
@@ -47862,88 +47827,16 @@ function resolveAlanDefaultWorkspacePath(homeDirectory = (0, import_node_os4.hom
|
|
|
47862
47827
|
return (0, import_node_path20.join)(homeDirectory, ".alan", "workspace");
|
|
47863
47828
|
}
|
|
47864
47829
|
|
|
47865
|
-
// src/holder/
|
|
47830
|
+
// src/holder/agent-context.ts
|
|
47866
47831
|
var import_promises32 = require("fs/promises");
|
|
47867
47832
|
var import_node_path21 = require("path");
|
|
47868
|
-
var MAX_RELOCATION_CANDIDATES = 200;
|
|
47869
|
-
var RELOCATION_BUDGET_MS = 2e4;
|
|
47870
|
-
function repositoryIdentity(url2) {
|
|
47871
|
-
const trimmed4 = url2.trim().replace(/\/+$/, "").replace(/\.git$/i, "");
|
|
47872
|
-
if (trimmed4.length === 0) return null;
|
|
47873
|
-
const scp = /^(?:[^@/]+@)?([^:/]+):(.+)$/.exec(trimmed4);
|
|
47874
|
-
if (scp !== null && !trimmed4.includes("://")) {
|
|
47875
|
-
return `${scp[1]}/${scp[2]}`.toLowerCase();
|
|
47876
|
-
}
|
|
47877
|
-
try {
|
|
47878
|
-
const parsed = new URL(trimmed4);
|
|
47879
|
-
return `${parsed.hostname}${parsed.pathname}`.replace(/\/+$/, "").toLowerCase();
|
|
47880
|
-
} catch {
|
|
47881
|
-
return null;
|
|
47882
|
-
}
|
|
47883
|
-
}
|
|
47884
|
-
function repositoryIdentities(urls) {
|
|
47885
|
-
return new Set(
|
|
47886
|
-
urls.map(repositoryIdentity).filter((identity) => identity !== null)
|
|
47887
|
-
);
|
|
47888
|
-
}
|
|
47889
|
-
async function originIdentity(git, path, signal) {
|
|
47890
|
-
try {
|
|
47891
|
-
const output2 = await git.run(
|
|
47892
|
-
{ cwd: path, args: ["config", "--get", "remote.origin.url"], readOnly: true },
|
|
47893
|
-
signal
|
|
47894
|
-
);
|
|
47895
|
-
return output2.exitCode === 0 ? repositoryIdentity(output2.stdout) : null;
|
|
47896
|
-
} catch {
|
|
47897
|
-
return null;
|
|
47898
|
-
}
|
|
47899
|
-
}
|
|
47900
|
-
async function childDirectories(parent, limit) {
|
|
47901
|
-
try {
|
|
47902
|
-
const entries = await (0, import_promises32.readdir)(parent, { withFileTypes: true });
|
|
47903
|
-
return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path21.join)(parent, entry.name));
|
|
47904
|
-
} catch {
|
|
47905
|
-
return [];
|
|
47906
|
-
}
|
|
47907
|
-
}
|
|
47908
|
-
async function candidateFolders(search) {
|
|
47909
|
-
const roots = /* @__PURE__ */ new Map();
|
|
47910
|
-
for (const path of [search.missingPath, ...search.approvedWorkspacePaths]) {
|
|
47911
|
-
const parent = (0, import_node_path21.dirname)((0, import_node_path21.resolve)(path));
|
|
47912
|
-
roots.set(comparablePath(parent, search.platform), parent);
|
|
47913
|
-
}
|
|
47914
|
-
const candidates2 = /* @__PURE__ */ new Map();
|
|
47915
|
-
for (const root of roots.values()) {
|
|
47916
|
-
const remaining = MAX_RELOCATION_CANDIDATES - candidates2.size;
|
|
47917
|
-
if (remaining <= 0) break;
|
|
47918
|
-
for (const child of await childDirectories(root, remaining)) {
|
|
47919
|
-
candidates2.set(comparablePath(child, search.platform), child);
|
|
47920
|
-
}
|
|
47921
|
-
}
|
|
47922
|
-
return [...candidates2.values()];
|
|
47923
|
-
}
|
|
47924
|
-
async function discoverRelocatedWorkspace(search) {
|
|
47925
|
-
if (search.expected.size === 0) return null;
|
|
47926
|
-
const signal = AbortSignal.any([search.signal, AbortSignal.timeout(RELOCATION_BUDGET_MS)]);
|
|
47927
|
-
const matches = [];
|
|
47928
|
-
for (const candidate of await candidateFolders(search)) {
|
|
47929
|
-
if (signal.aborted) return null;
|
|
47930
|
-
const identity = await originIdentity(search.git, candidate, signal);
|
|
47931
|
-
if (identity !== null && search.expected.has(identity)) matches.push(candidate);
|
|
47932
|
-
if (matches.length > 1) return null;
|
|
47933
|
-
}
|
|
47934
|
-
return matches[0] ?? null;
|
|
47935
|
-
}
|
|
47936
|
-
|
|
47937
|
-
// src/holder/agent-context.ts
|
|
47938
|
-
var import_promises33 = require("fs/promises");
|
|
47939
|
-
var import_node_path22 = require("path");
|
|
47940
47833
|
|
|
47941
47834
|
// ../agent-core/dist/prompt.js
|
|
47942
47835
|
init_chunk_GI3ZGXTY();
|
|
47943
47836
|
|
|
47944
47837
|
// src/holder/agent-context.ts
|
|
47945
47838
|
async function readText2(path) {
|
|
47946
|
-
return (0,
|
|
47839
|
+
return (0, import_promises32.readFile)(path, "utf8").then(
|
|
47947
47840
|
(text2) => text2.trim(),
|
|
47948
47841
|
() => null
|
|
47949
47842
|
);
|
|
@@ -47958,15 +47851,15 @@ async function startCommandState(statusPath) {
|
|
|
47958
47851
|
return code === 0 ? { state: "exited_ok" } : { state: "failed", exitCode: code };
|
|
47959
47852
|
}
|
|
47960
47853
|
function createAgentContext(deps) {
|
|
47961
|
-
const statusPath = (0,
|
|
47962
|
-
const logPath = (0,
|
|
47854
|
+
const statusPath = (0, import_node_path21.join)(deps.homeDir, ".alan", "start-commands.status");
|
|
47855
|
+
const logPath = (0, import_node_path21.join)(deps.homeDir, ".alan", "start-commands.log");
|
|
47963
47856
|
return async (spec, problems) => {
|
|
47964
|
-
const file2 = (0,
|
|
47857
|
+
const file2 = (0, import_node_path21.join)(deps.dir, `${spec.conversationId}.json`);
|
|
47965
47858
|
const saved = await readJsonFile(file2, agentContextSnapshotSchema);
|
|
47966
47859
|
const known = saved.kind === "ok" ? saved.value : void 0;
|
|
47967
47860
|
const hasEnvironment = (spec.agentContext ?? known)?.environment !== void 0;
|
|
47968
47861
|
const start = hasEnvironment ? await startCommandState(statusPath) : void 0;
|
|
47969
|
-
const
|
|
47862
|
+
const snapshot = agentContextSnapshot({
|
|
47970
47863
|
spec,
|
|
47971
47864
|
...spec.approvedWorkspacePaths?.[0] ? { workspaceRoot: spec.approvedWorkspacePaths[0] } : {},
|
|
47972
47865
|
problems,
|
|
@@ -47974,39 +47867,39 @@ function createAgentContext(deps) {
|
|
|
47974
47867
|
startLogPath: logPath,
|
|
47975
47868
|
...known ? { known } : {}
|
|
47976
47869
|
});
|
|
47977
|
-
if (
|
|
47978
|
-
const rendered = renderAgentContext(
|
|
47870
|
+
if (snapshot === null) return void 0;
|
|
47871
|
+
const rendered = renderAgentContext(snapshot, known);
|
|
47979
47872
|
return {
|
|
47980
47873
|
full: rendered.full,
|
|
47981
47874
|
...rendered.update ? { update: rendered.update } : {},
|
|
47982
|
-
save: () => writeJsonFileAtomic(file2,
|
|
47875
|
+
save: () => writeJsonFileAtomic(file2, snapshot)
|
|
47983
47876
|
};
|
|
47984
47877
|
};
|
|
47985
47878
|
}
|
|
47986
47879
|
|
|
47987
47880
|
// src/holder/checkout-refresh.ts
|
|
47988
|
-
var
|
|
47881
|
+
var import_node_path24 = require("path");
|
|
47989
47882
|
|
|
47990
47883
|
// src/holder/claim-once.ts
|
|
47991
47884
|
var import_node_crypto14 = require("crypto");
|
|
47992
|
-
var
|
|
47993
|
-
var
|
|
47885
|
+
var import_promises33 = require("fs/promises");
|
|
47886
|
+
var import_node_path22 = require("path");
|
|
47994
47887
|
async function claimOnce(dir, name) {
|
|
47995
47888
|
try {
|
|
47996
|
-
await (0,
|
|
47997
|
-
await (await (0,
|
|
47889
|
+
await (0, import_promises33.mkdir)(dir, { recursive: true, mode: 448 });
|
|
47890
|
+
await (await (0, import_promises33.open)((0, import_node_path22.join)(dir, name), "wx")).close();
|
|
47998
47891
|
return true;
|
|
47999
47892
|
} catch {
|
|
48000
47893
|
return false;
|
|
48001
47894
|
}
|
|
48002
47895
|
}
|
|
48003
47896
|
function claimFirstLease(freshnessDir, path) {
|
|
48004
|
-
return claimOnce((0,
|
|
47897
|
+
return claimOnce((0, import_node_path22.join)(freshnessDir, "leased"), (0, import_node_crypto14.createHash)("sha256").update(path).digest("hex"));
|
|
48005
47898
|
}
|
|
48006
47899
|
|
|
48007
47900
|
// src/holder/requested-checkout.ts
|
|
48008
|
-
var
|
|
48009
|
-
var
|
|
47901
|
+
var import_promises34 = require("fs/promises");
|
|
47902
|
+
var import_node_path23 = require("path");
|
|
48010
47903
|
var REMOTE2 = "origin";
|
|
48011
47904
|
var REASON_MAX_CHARS = 200;
|
|
48012
47905
|
function firstLine2(text2) {
|
|
@@ -48027,8 +47920,8 @@ function notSwitched(checkout, current, reason) {
|
|
|
48027
47920
|
);
|
|
48028
47921
|
}
|
|
48029
47922
|
async function clone2(checkout, deps, signal) {
|
|
48030
|
-
const parent = (0,
|
|
48031
|
-
await (0,
|
|
47923
|
+
const parent = (0, import_node_path23.dirname)(checkout.path);
|
|
47924
|
+
await (0, import_promises34.mkdir)(parent, { recursive: true });
|
|
48032
47925
|
await assertValidBranch(deps.git, parent, checkout.branch, signal);
|
|
48033
47926
|
const output2 = await deps.git.run(
|
|
48034
47927
|
{
|
|
@@ -48180,9 +48073,9 @@ async function applyRequestedCheckout(checkout, spec, deps, signal) {
|
|
|
48180
48073
|
function short(sha) {
|
|
48181
48074
|
return sha.slice(0, 12);
|
|
48182
48075
|
}
|
|
48183
|
-
function staleCheckout(path,
|
|
48184
|
-
const checkout =
|
|
48185
|
-
const base =
|
|
48076
|
+
function staleCheckout(path, snapshot, tip) {
|
|
48077
|
+
const checkout = snapshot === void 0 ? "is the environment snapshot's checkout" : `is the environment snapshot's checkout of ${snapshot.branch} (commit ${short(snapshot.head)})`;
|
|
48078
|
+
const base = snapshot === void 0 ? "its upstream" : `origin/${snapshot.base}`;
|
|
48186
48079
|
const remote = tip === void 0 ? "may be ahead" : `is ahead at ${short(tip)}`;
|
|
48187
48080
|
return {
|
|
48188
48081
|
path,
|
|
@@ -48193,18 +48086,18 @@ function staleCheckout(path, snapshot2, tip) {
|
|
|
48193
48086
|
async function fastForward(freshness, operationId, deps, signal) {
|
|
48194
48087
|
var _stack = [];
|
|
48195
48088
|
try {
|
|
48196
|
-
const { path: cwd, snapshot
|
|
48197
|
-
const attempt = await deps.locks.tryExclusive(
|
|
48089
|
+
const { path: cwd, snapshot, tip } = freshness;
|
|
48090
|
+
const attempt = await deps.locks.tryExclusive(snapshot.commonDir, operationId);
|
|
48198
48091
|
if (attempt.kind === "busy") return false;
|
|
48199
48092
|
const _lock = __using(_stack, attempt.lock, true);
|
|
48200
48093
|
const now = await readCheckoutStatus(deps.git, cwd, signal);
|
|
48201
|
-
if (now === null || now.dirty || now.head !==
|
|
48094
|
+
if (now === null || now.dirty || now.head !== snapshot.head || now.branch !== snapshot.branch) {
|
|
48202
48095
|
return false;
|
|
48203
48096
|
}
|
|
48204
48097
|
const git = (args) => deps.git.run({ cwd, args }, signal);
|
|
48205
48098
|
if ((await git(["switch", "--quiet", "--detach", tip])).exitCode !== 0) return false;
|
|
48206
|
-
const moved = await git(["update-ref", `refs/heads/${
|
|
48207
|
-
const back = await git(["switch", "--quiet",
|
|
48099
|
+
const moved = await git(["update-ref", `refs/heads/${snapshot.branch}`, tip, snapshot.head]);
|
|
48100
|
+
const back = await git(["switch", "--quiet", snapshot.branch]);
|
|
48208
48101
|
return moved.exitCode === 0 && back.exitCode === 0;
|
|
48209
48102
|
} catch (_) {
|
|
48210
48103
|
var _error = _, _hasError = true;
|
|
@@ -48236,9 +48129,8 @@ function problemFor(freshness) {
|
|
|
48236
48129
|
return staleCheckout(freshness.path, void 0);
|
|
48237
48130
|
}
|
|
48238
48131
|
}
|
|
48239
|
-
async function checkoutsOf(spec
|
|
48240
|
-
|
|
48241
|
-
return checkoutsUnder(spec.projectPath);
|
|
48132
|
+
async function checkoutsOf(spec) {
|
|
48133
|
+
return spec.projectPath === void 0 ? [] : checkoutsUnder(spec.projectPath);
|
|
48242
48134
|
}
|
|
48243
48135
|
function requestedCheckoutsOf(spec, log) {
|
|
48244
48136
|
const roots = spec.approvedWorkspacePaths ?? [];
|
|
@@ -48266,7 +48158,7 @@ async function applyRequestedCheckouts(spec, deps, signal) {
|
|
|
48266
48158
|
...outcome2.kind === "moved" ? { how: outcome2.how } : {}
|
|
48267
48159
|
});
|
|
48268
48160
|
if (outcome2.kind === "on_branch") continue;
|
|
48269
|
-
settled2.add((0,
|
|
48161
|
+
settled2.add((0, import_node_path24.resolve)(checkout.path));
|
|
48270
48162
|
if (outcome2.kind === "noted") {
|
|
48271
48163
|
problems.push({ path: checkout.path, problem: outcome2.problem, action: outcome2.action });
|
|
48272
48164
|
}
|
|
@@ -48276,7 +48168,7 @@ async function applyRequestedCheckouts(spec, deps, signal) {
|
|
|
48276
48168
|
async function refreshSnapshotCheckouts(spec, targets, settled2, deps, signal) {
|
|
48277
48169
|
const problems = [];
|
|
48278
48170
|
for (const target of targets) {
|
|
48279
|
-
if (settled2.has((0,
|
|
48171
|
+
if (settled2.has((0, import_node_path24.resolve)(target))) continue;
|
|
48280
48172
|
const freshness = await readCheckoutFreshness(deps.dir, target);
|
|
48281
48173
|
if (freshness === null) continue;
|
|
48282
48174
|
const outcome2 = await atFirstLease(freshness, spec, deps, signal).catch(
|
|
@@ -48293,11 +48185,11 @@ async function refreshSnapshotCheckouts(spec, targets, settled2, deps, signal) {
|
|
|
48293
48185
|
return problems;
|
|
48294
48186
|
}
|
|
48295
48187
|
function createCheckoutRefresh(deps) {
|
|
48296
|
-
return async (spec,
|
|
48188
|
+
return async (spec, signal) => {
|
|
48297
48189
|
if (spec.providerSessionId !== void 0) return [];
|
|
48298
|
-
if (!await claimOnce((0,
|
|
48190
|
+
if (!await claimOnce((0, import_node_path24.join)(deps.dir, "conversations"), spec.conversationId)) return [];
|
|
48299
48191
|
const requested = await applyRequestedCheckouts(spec, deps, signal);
|
|
48300
|
-
const targets = await checkoutsOf(spec
|
|
48192
|
+
const targets = await checkoutsOf(spec);
|
|
48301
48193
|
return [
|
|
48302
48194
|
...requested.problems,
|
|
48303
48195
|
...await refreshSnapshotCheckouts(spec, targets, requested.settled, deps, signal)
|
|
@@ -48305,207 +48197,6 @@ function createCheckoutRefresh(deps) {
|
|
|
48305
48197
|
};
|
|
48306
48198
|
}
|
|
48307
48199
|
|
|
48308
|
-
// src/holder/lease.ts
|
|
48309
|
-
var import_promises36 = require("fs/promises");
|
|
48310
|
-
var import_node_path26 = require("path");
|
|
48311
|
-
var LEASE_CHECK_EVERY_MS = 5e3;
|
|
48312
|
-
var MAX_TRANSIENT_FAILURES = 3;
|
|
48313
|
-
var BACKOFF_BASE_MS = 1e3;
|
|
48314
|
-
var BACKOFF_MAX_MS = 15e3;
|
|
48315
|
-
var MESSAGES = {
|
|
48316
|
-
workspace_lease_unavailable: "The workspace or Git checkout became unavailable while the run was active. Restore it and start a new run.",
|
|
48317
|
-
workspace_lease_path_changed: "The selected workspace folder changed while the run was active. The run stopped before continuing; choose the correct folder and start a new run.",
|
|
48318
|
-
workspace_lease_repository_changed: "The workspace now points to a different repository or worktree. The run stopped before continuing; restore the original checkout and start a new run."
|
|
48319
|
-
};
|
|
48320
|
-
function identityFailure(code, workspacePath) {
|
|
48321
|
-
return { code, problemCode: "app.workspace.missing", message: MESSAGES[code], workspacePath };
|
|
48322
|
-
}
|
|
48323
|
-
async function fileIdentity(path) {
|
|
48324
|
-
const canonical = await (0, import_promises36.realpath)(path);
|
|
48325
|
-
const info = await (0, import_promises36.stat)(canonical, { bigint: true });
|
|
48326
|
-
return `${canonical}:${info.dev}:${info.ino}`;
|
|
48327
|
-
}
|
|
48328
|
-
async function snapshot(git, path, signal) {
|
|
48329
|
-
try {
|
|
48330
|
-
const output2 = await git.run(
|
|
48331
|
-
{
|
|
48332
|
-
cwd: path,
|
|
48333
|
-
args: ["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"],
|
|
48334
|
-
readOnly: true
|
|
48335
|
-
},
|
|
48336
|
-
signal
|
|
48337
|
-
);
|
|
48338
|
-
const [gitDir, commonDir] = output2.stdout.trim().split("\n");
|
|
48339
|
-
if (output2.exitCode !== 0 || !gitDir || !commonDir) return null;
|
|
48340
|
-
return {
|
|
48341
|
-
workspace: await fileIdentity(path),
|
|
48342
|
-
repository: await fileIdentity(commonDir),
|
|
48343
|
-
worktree: await fileIdentity(gitDir),
|
|
48344
|
-
commonDir: await (0, import_promises36.realpath)(commonDir)
|
|
48345
|
-
};
|
|
48346
|
-
} catch {
|
|
48347
|
-
return null;
|
|
48348
|
-
}
|
|
48349
|
-
}
|
|
48350
|
-
async function gitValue(git, path, args, signal) {
|
|
48351
|
-
const output2 = await git.run({ cwd: path, args, readOnly: true }, signal).catch(() => null);
|
|
48352
|
-
const value = output2?.exitCode === 0 ? output2.stdout.trim() : "";
|
|
48353
|
-
return value.length > 0 ? value : null;
|
|
48354
|
-
}
|
|
48355
|
-
async function pathExists(path) {
|
|
48356
|
-
try {
|
|
48357
|
-
await (0, import_promises36.stat)(path);
|
|
48358
|
-
return true;
|
|
48359
|
-
} catch (error61) {
|
|
48360
|
-
return errnoCode(error61) !== "ENOENT" && errnoCode(error61) !== "ENOTDIR";
|
|
48361
|
-
}
|
|
48362
|
-
}
|
|
48363
|
-
async function hasGitMarker(path) {
|
|
48364
|
-
let directory;
|
|
48365
|
-
try {
|
|
48366
|
-
directory = await (0, import_promises36.realpath)(path);
|
|
48367
|
-
} catch {
|
|
48368
|
-
return true;
|
|
48369
|
-
}
|
|
48370
|
-
for (; ; ) {
|
|
48371
|
-
try {
|
|
48372
|
-
await (0, import_promises36.stat)((0, import_node_path26.join)(directory, ".git"));
|
|
48373
|
-
return true;
|
|
48374
|
-
} catch (error61) {
|
|
48375
|
-
const code = errnoCode(error61);
|
|
48376
|
-
if (code !== "ENOENT" && code !== "ENOTDIR") return true;
|
|
48377
|
-
}
|
|
48378
|
-
const parent = (0, import_node_path26.dirname)(directory);
|
|
48379
|
-
if (parent === directory) return false;
|
|
48380
|
-
directory = parent;
|
|
48381
|
-
}
|
|
48382
|
-
}
|
|
48383
|
-
async function probeCheckout(git, path, captured, signal) {
|
|
48384
|
-
const current = await snapshot(git, path, signal);
|
|
48385
|
-
if (current === null) {
|
|
48386
|
-
const failure5 = identityFailure("workspace_lease_unavailable", path);
|
|
48387
|
-
return await pathExists(path) ? { kind: "transient", failure: failure5 } : { kind: "failed", failure: failure5 };
|
|
48388
|
-
}
|
|
48389
|
-
if (current.workspace !== captured.workspace) {
|
|
48390
|
-
return { kind: "failed", failure: identityFailure("workspace_lease_path_changed", path) };
|
|
48391
|
-
}
|
|
48392
|
-
if (current.repository !== captured.repository || current.worktree !== captured.worktree) {
|
|
48393
|
-
return { kind: "failed", failure: identityFailure("workspace_lease_repository_changed", path) };
|
|
48394
|
-
}
|
|
48395
|
-
return { kind: "ok" };
|
|
48396
|
-
}
|
|
48397
|
-
async function releaseAll(locks) {
|
|
48398
|
-
for (const lock of locks) await lock[Symbol.asyncDispose]();
|
|
48399
|
-
}
|
|
48400
|
-
async function captureOne(git, path, signal) {
|
|
48401
|
-
const identity = await snapshot(git, path, signal);
|
|
48402
|
-
if (identity === null) return identityFailure("workspace_lease_unavailable", path);
|
|
48403
|
-
const branch = await gitValue(git, path, ["symbolic-ref", "-q", "--short", "HEAD"], signal);
|
|
48404
|
-
const head = await gitValue(git, path, ["rev-parse", "-q", "--verify", "HEAD"], signal);
|
|
48405
|
-
return { path, identity, checkout: { path, commonDir: identity.commonDir, branch, head } };
|
|
48406
|
-
}
|
|
48407
|
-
async function captureWorkspaceLease(runId, paths, deps, signal) {
|
|
48408
|
-
const captured = [];
|
|
48409
|
-
const locks = [];
|
|
48410
|
-
const locked = /* @__PURE__ */ new Set();
|
|
48411
|
-
for (const path of paths) {
|
|
48412
|
-
const one = await captureOne(deps.git, path, signal);
|
|
48413
|
-
if (!("identity" in one)) {
|
|
48414
|
-
await releaseAll(locks);
|
|
48415
|
-
return { kind: "failed", failure: one };
|
|
48416
|
-
}
|
|
48417
|
-
const key = comparablePath(one.identity.commonDir, deps.platform);
|
|
48418
|
-
if (!locked.has(key)) {
|
|
48419
|
-
const attempt = await deps.locks.tryShared(one.identity.commonDir, runId);
|
|
48420
|
-
if (attempt.kind === "busy") {
|
|
48421
|
-
await releaseAll(locks);
|
|
48422
|
-
return {
|
|
48423
|
-
kind: "failed",
|
|
48424
|
-
failure: {
|
|
48425
|
-
code: "workspace_busy",
|
|
48426
|
-
problemCode: null,
|
|
48427
|
-
message: "Alan is committing or pushing in this repository for a checkout switch. Try again when it finishes.",
|
|
48428
|
-
workspacePath: path
|
|
48429
|
-
}
|
|
48430
|
-
};
|
|
48431
|
-
}
|
|
48432
|
-
locked.add(key);
|
|
48433
|
-
locks.push(attempt.lock);
|
|
48434
|
-
}
|
|
48435
|
-
captured.push(one);
|
|
48436
|
-
}
|
|
48437
|
-
return { kind: "held", lease: holdLease(captured, locks, deps) };
|
|
48438
|
-
}
|
|
48439
|
-
function holdLease(captured, locks, deps) {
|
|
48440
|
-
const lifetime = new AbortController();
|
|
48441
|
-
const lost = new AbortController();
|
|
48442
|
-
const state = { failure: null, inFlight: null, transientStreak: 0, nextCheckAt: 0 };
|
|
48443
|
-
const probeOnce = async () => {
|
|
48444
|
-
for (const { path, identity } of captured) {
|
|
48445
|
-
const probe = await probeCheckout(deps.git, path, identity, lifetime.signal);
|
|
48446
|
-
if (probe.kind !== "ok") return probe;
|
|
48447
|
-
}
|
|
48448
|
-
return { kind: "ok" };
|
|
48449
|
-
};
|
|
48450
|
-
const lose = (failure5) => {
|
|
48451
|
-
if (state.failure !== null) return;
|
|
48452
|
-
state.failure = failure5;
|
|
48453
|
-
deps.log.warn("holder.workspace_lease_lost", {
|
|
48454
|
-
code: failure5.code,
|
|
48455
|
-
workspacePath: failure5.workspacePath
|
|
48456
|
-
});
|
|
48457
|
-
lost.abort(failure5);
|
|
48458
|
-
};
|
|
48459
|
-
const apply = (probe) => {
|
|
48460
|
-
if (probe.kind === "ok") {
|
|
48461
|
-
state.transientStreak = 0;
|
|
48462
|
-
state.nextCheckAt = 0;
|
|
48463
|
-
} else if (probe.kind === "failed") {
|
|
48464
|
-
lose(probe.failure);
|
|
48465
|
-
} else {
|
|
48466
|
-
state.transientStreak += 1;
|
|
48467
|
-
if (state.transientStreak >= MAX_TRANSIENT_FAILURES) lose(probe.failure);
|
|
48468
|
-
else {
|
|
48469
|
-
const backoff = BACKOFF_BASE_MS * 2 ** (state.transientStreak - 1);
|
|
48470
|
-
state.nextCheckAt = deps.clock.monotonic() + Math.min(backoff, BACKOFF_MAX_MS);
|
|
48471
|
-
}
|
|
48472
|
-
}
|
|
48473
|
-
return state.failure === null;
|
|
48474
|
-
};
|
|
48475
|
-
const check2 = () => {
|
|
48476
|
-
if (state.failure !== null) return Promise.resolve(false);
|
|
48477
|
-
state.inFlight ??= probeOnce().then((probe) => lifetime.signal.aborted ? state.failure === null : apply(probe)).finally(() => {
|
|
48478
|
-
state.inFlight = null;
|
|
48479
|
-
});
|
|
48480
|
-
return state.inFlight;
|
|
48481
|
-
};
|
|
48482
|
-
const monitor = captured.length === 0 ? null : startMaintenance({
|
|
48483
|
-
everyMs: deps.everyMs ?? LEASE_CHECK_EVERY_MS,
|
|
48484
|
-
jobs: [
|
|
48485
|
-
{
|
|
48486
|
-
name: "holder.workspace_lease",
|
|
48487
|
-
run: async () => {
|
|
48488
|
-
if (state.failure !== null || deps.clock.monotonic() < state.nextCheckAt) return;
|
|
48489
|
-
await check2();
|
|
48490
|
-
}
|
|
48491
|
-
}
|
|
48492
|
-
],
|
|
48493
|
-
clock: deps.clock,
|
|
48494
|
-
log: deps.log
|
|
48495
|
-
});
|
|
48496
|
-
return {
|
|
48497
|
-
checkouts: captured.map((entry) => entry.checkout),
|
|
48498
|
-
lost: lost.signal,
|
|
48499
|
-
failure: () => state.failure,
|
|
48500
|
-
verify: check2,
|
|
48501
|
-
[Symbol.asyncDispose]: async () => {
|
|
48502
|
-
lifetime.abort();
|
|
48503
|
-
await monitor?.[Symbol.asyncDispose]();
|
|
48504
|
-
await releaseAll(locks);
|
|
48505
|
-
}
|
|
48506
|
-
};
|
|
48507
|
-
}
|
|
48508
|
-
|
|
48509
48200
|
// src/holder/admission.ts
|
|
48510
48201
|
var VOLUME_ERRORS = /* @__PURE__ */ new Set([
|
|
48511
48202
|
"EIO",
|
|
@@ -48514,13 +48205,12 @@ var VOLUME_ERRORS = /* @__PURE__ */ new Set([
|
|
|
48514
48205
|
"ENXIO",
|
|
48515
48206
|
"ESTALE"
|
|
48516
48207
|
]);
|
|
48517
|
-
var
|
|
48208
|
+
var MESSAGES = {
|
|
48518
48209
|
missing: "This project folder was moved or removed. Locate it before starting the run.",
|
|
48519
48210
|
permission: "Alan needs permission to access this project folder.",
|
|
48520
48211
|
volume: "The drive containing this project is unavailable. Connect it and try again.",
|
|
48521
48212
|
pinnedMissing: "This run must use exactly this project folder, and it was moved or removed. Restore it or choose another folder.",
|
|
48522
|
-
notApproved: "This folder is not one of the workspaces approved on this computer."
|
|
48523
|
-
mismatch: "This folder belongs to a different repository. Choose the correct project folder and try again."
|
|
48213
|
+
notApproved: "This folder is not one of the workspaces approved on this computer."
|
|
48524
48214
|
};
|
|
48525
48215
|
function rejected(rejection, message) {
|
|
48526
48216
|
return { kind: "rejected", rejection, message };
|
|
@@ -48539,7 +48229,7 @@ function volumeRoot(path) {
|
|
|
48539
48229
|
}
|
|
48540
48230
|
async function exists(path) {
|
|
48541
48231
|
try {
|
|
48542
|
-
await (0,
|
|
48232
|
+
await (0, import_promises35.stat)(path);
|
|
48543
48233
|
return true;
|
|
48544
48234
|
} catch {
|
|
48545
48235
|
return false;
|
|
@@ -48547,30 +48237,23 @@ async function exists(path) {
|
|
|
48547
48237
|
}
|
|
48548
48238
|
async function inspectReadiness(path) {
|
|
48549
48239
|
try {
|
|
48550
|
-
if (!(await (0,
|
|
48551
|
-
return { ready: false, missing: true, message:
|
|
48240
|
+
if (!(await (0, import_promises35.stat)(path)).isDirectory()) {
|
|
48241
|
+
return { ready: false, missing: true, message: MESSAGES.missing };
|
|
48552
48242
|
}
|
|
48553
|
-
await (0,
|
|
48243
|
+
await (0, import_promises35.access)(path, import_node_fs9.constants.R_OK | import_node_fs9.constants.W_OK | import_node_fs9.constants.X_OK);
|
|
48554
48244
|
return { ready: true };
|
|
48555
48245
|
} catch (error61) {
|
|
48556
48246
|
const code = errnoCode(error61) ?? "";
|
|
48557
48247
|
if (code === "EACCES" || code === "EPERM") {
|
|
48558
|
-
return { ready: false, missing: false, message:
|
|
48248
|
+
return { ready: false, missing: false, message: MESSAGES.permission };
|
|
48559
48249
|
}
|
|
48560
48250
|
const root = volumeRoot(path);
|
|
48561
48251
|
if (VOLUME_ERRORS.has(code) || code === "ENOENT" && root !== null && !await exists(root)) {
|
|
48562
|
-
return { ready: false, missing: false, message:
|
|
48252
|
+
return { ready: false, missing: false, message: MESSAGES.volume };
|
|
48563
48253
|
}
|
|
48564
|
-
return { ready: false, missing: true, message:
|
|
48254
|
+
return { ready: false, missing: true, message: MESSAGES.missing };
|
|
48565
48255
|
}
|
|
48566
48256
|
}
|
|
48567
|
-
function expectedRepositoryUrls(spec, projectPath, platform) {
|
|
48568
|
-
const folder = comparablePath(projectPath, platform);
|
|
48569
|
-
return [
|
|
48570
|
-
...(spec.repoLocalPaths ?? []).filter((repo) => comparablePath(repo.localPath, platform) === folder).map((repo) => repo.repoUrl),
|
|
48571
|
-
...spec.localRepoUrls ?? []
|
|
48572
|
-
];
|
|
48573
|
-
}
|
|
48574
48257
|
function resolveSelectedSkills(spec, context) {
|
|
48575
48258
|
const invocations = spec.skillInvocations ?? [];
|
|
48576
48259
|
if (context.skills === void 0) {
|
|
@@ -48597,51 +48280,18 @@ async function checkProvider(spec, context) {
|
|
|
48597
48280
|
`The ${provider4.name} CLI (\`${provider4.command}\`) is not installed on this computer, or it is not on the PATH Alan uses. Install it and try again.`
|
|
48598
48281
|
);
|
|
48599
48282
|
}
|
|
48600
|
-
async function locateWorkspace(spec, projectPath, expected, context, signal) {
|
|
48601
|
-
const readiness = await inspectReadiness(projectPath);
|
|
48602
|
-
if (readiness.ready) return { cwd: projectPath, relocated: null };
|
|
48603
|
-
if (!readiness.missing) return rejected("workspace_unavailable", readiness.message);
|
|
48604
|
-
if (spec.workspacePathPinned === true) {
|
|
48605
|
-
return rejected("workspace_pinned_missing", MESSAGES2.pinnedMissing);
|
|
48606
|
-
}
|
|
48607
|
-
const found = await discoverRelocatedWorkspace({
|
|
48608
|
-
missingPath: projectPath,
|
|
48609
|
-
approvedWorkspacePaths: spec.approvedWorkspacePaths ?? [],
|
|
48610
|
-
expected,
|
|
48611
|
-
git: context.git,
|
|
48612
|
-
platform: context.platform,
|
|
48613
|
-
signal
|
|
48614
|
-
});
|
|
48615
|
-
if (found === null) return rejected("workspace_unavailable", readiness.message);
|
|
48616
|
-
const moved = await inspectReadiness(found);
|
|
48617
|
-
if (!moved.ready) return rejected("workspace_unavailable", moved.message);
|
|
48618
|
-
return {
|
|
48619
|
-
cwd: found,
|
|
48620
|
-
relocated: {
|
|
48621
|
-
sessionUpdate: "_alan/run.workspace_relocated",
|
|
48622
|
-
previousPath: projectPath,
|
|
48623
|
-
canonicalPath: found
|
|
48624
|
-
}
|
|
48625
|
-
};
|
|
48626
|
-
}
|
|
48627
48283
|
async function admitDefaultWorkspace(spec, context, skills) {
|
|
48628
48284
|
const { env } = context;
|
|
48629
48285
|
const path = resolveAlanDefaultWorkspacePath(env.HOME || env.USERPROFILE || (0, import_node_os5.homedir)());
|
|
48630
48286
|
try {
|
|
48631
|
-
await (0,
|
|
48632
|
-
await (0,
|
|
48633
|
-
return {
|
|
48634
|
-
kind: "admitted",
|
|
48635
|
-
spec: { ...spec, projectPath: path },
|
|
48636
|
-
relocated: null,
|
|
48637
|
-
leaseTargets: [],
|
|
48638
|
-
skills
|
|
48639
|
-
};
|
|
48287
|
+
await (0, import_promises35.mkdir)(path, { recursive: true, mode: 448 });
|
|
48288
|
+
await (0, import_promises35.access)(path, import_node_fs9.constants.R_OK | import_node_fs9.constants.W_OK | import_node_fs9.constants.X_OK);
|
|
48289
|
+
return { kind: "admitted", spec: { ...spec, projectPath: path }, skills };
|
|
48640
48290
|
} catch (error61) {
|
|
48641
48291
|
const code = errnoCode(error61);
|
|
48642
48292
|
return rejected(
|
|
48643
48293
|
"workspace_unavailable",
|
|
48644
|
-
code === "EACCES" || code === "EPERM" ?
|
|
48294
|
+
code === "EACCES" || code === "EPERM" ? MESSAGES.permission : MESSAGES.missing
|
|
48645
48295
|
);
|
|
48646
48296
|
}
|
|
48647
48297
|
}
|
|
@@ -48655,7 +48305,7 @@ async function withInstalledCloudSkills(spec, context) {
|
|
|
48655
48305
|
}
|
|
48656
48306
|
};
|
|
48657
48307
|
}
|
|
48658
|
-
async function admitRun(spec, context
|
|
48308
|
+
async function admitRun(spec, context) {
|
|
48659
48309
|
const provider4 = await checkProvider(spec, context);
|
|
48660
48310
|
if (provider4 !== null) return provider4;
|
|
48661
48311
|
const selected = await resolveSelectedSkills(spec, context);
|
|
@@ -48668,50 +48318,30 @@ async function admitRun(spec, context, signal) {
|
|
|
48668
48318
|
const skills = selected.skills;
|
|
48669
48319
|
spec = await withInstalledCloudSkills(spec, context);
|
|
48670
48320
|
const projectPath = spec.projectPath;
|
|
48671
|
-
if (projectPath === void 0) {
|
|
48672
|
-
return { kind: "admitted", spec, relocated: null, leaseTargets: [], skills };
|
|
48673
|
-
}
|
|
48321
|
+
if (projectPath === void 0) return { kind: "admitted", spec, skills };
|
|
48674
48322
|
if (isAlanDefaultWorkspace(projectPath)) return admitDefaultWorkspace(spec, context, skills);
|
|
48675
|
-
const
|
|
48676
|
-
|
|
48677
|
-
|
|
48678
|
-
|
|
48679
|
-
const { cwd, relocated } = located;
|
|
48323
|
+
const readiness = await inspectReadiness(projectPath);
|
|
48324
|
+
if (!readiness.ready) {
|
|
48325
|
+
return readiness.missing && spec.workspacePathPinned === true ? rejected("workspace_pinned_missing", MESSAGES.pinnedMissing) : rejected("workspace_unavailable", readiness.message);
|
|
48326
|
+
}
|
|
48680
48327
|
const roots = [
|
|
48681
48328
|
...await context.approvedRoots(),
|
|
48682
48329
|
projectPath,
|
|
48683
48330
|
...spec.approvedWorkspacePaths ?? [],
|
|
48684
|
-
...(spec.repoLocalPaths ?? []).map((repo) => repo.localPath)
|
|
48685
|
-
...relocated === null ? [] : [relocated.canonicalPath]
|
|
48331
|
+
...(spec.repoLocalPaths ?? []).map((repo) => repo.localPath)
|
|
48686
48332
|
];
|
|
48687
|
-
if (!await isApprovedPath(
|
|
48688
|
-
return rejected("workspace_unavailable",
|
|
48689
|
-
}
|
|
48690
|
-
if (expected.size > 0) {
|
|
48691
|
-
const identity = await originIdentity(context.git, cwd, signal);
|
|
48692
|
-
if (identity === null || !expected.has(identity)) {
|
|
48693
|
-
return rejected("workspace_repository_mismatch", MESSAGES2.mismatch);
|
|
48694
|
-
}
|
|
48333
|
+
if (!await isApprovedPath(projectPath, roots, context.platform)) {
|
|
48334
|
+
return rejected("workspace_unavailable", MESSAGES.notApproved);
|
|
48695
48335
|
}
|
|
48696
|
-
return {
|
|
48697
|
-
kind: "admitted",
|
|
48698
|
-
spec: relocated === null ? spec : { ...spec, projectPath: cwd },
|
|
48699
|
-
relocated,
|
|
48700
|
-
leaseTargets: await hasGitMarker(cwd) ? [cwd] : [],
|
|
48701
|
-
skills
|
|
48702
|
-
};
|
|
48336
|
+
return { kind: "admitted", spec, skills };
|
|
48703
48337
|
}
|
|
48704
|
-
var PROBE_TIMEOUT_MS2 = 5e3;
|
|
48705
48338
|
var CHECKOUT_LOCAL_TIMEOUT_MS = 6e4;
|
|
48706
48339
|
var CHECKOUT_NETWORK_TIMEOUT_MS = 12e4;
|
|
48707
48340
|
function createHolderWorkspace(machine, clock, log) {
|
|
48708
48341
|
const platform = machine.platform ?? process.platform;
|
|
48709
|
-
const git = createGitRunner({ env: machine.env, platform, localTimeoutMs: PROBE_TIMEOUT_MS2 });
|
|
48710
|
-
const locks = openRepositoryLocks({ dir: (0, import_node_path27.join)(machine.stateDir, "locks"), clock, platform });
|
|
48711
48342
|
return {
|
|
48712
48343
|
admission: {
|
|
48713
48344
|
env: machine.env,
|
|
48714
|
-
git,
|
|
48715
48345
|
platform,
|
|
48716
48346
|
skills: skillsLayout(
|
|
48717
48347
|
machine.stateDir,
|
|
@@ -48719,14 +48349,13 @@ function createHolderWorkspace(machine, clock, log) {
|
|
|
48719
48349
|
),
|
|
48720
48350
|
approvedRoots: async () => {
|
|
48721
48351
|
const approved = await openApprovedPaths({
|
|
48722
|
-
file: (0,
|
|
48352
|
+
file: (0, import_node_path25.join)(machine.stateDir, "workspaces.json"),
|
|
48723
48353
|
log,
|
|
48724
48354
|
platform
|
|
48725
48355
|
});
|
|
48726
48356
|
return approved.roots();
|
|
48727
48357
|
}
|
|
48728
48358
|
},
|
|
48729
|
-
lease: { git, locks, clock, log, platform },
|
|
48730
48359
|
...machine.refreshesFirstCheckout === true ? {
|
|
48731
48360
|
refreshFirstCheckout: createCheckoutRefresh({
|
|
48732
48361
|
git: createGitRunner({
|
|
@@ -48735,12 +48364,12 @@ function createHolderWorkspace(machine, clock, log) {
|
|
|
48735
48364
|
localTimeoutMs: CHECKOUT_LOCAL_TIMEOUT_MS,
|
|
48736
48365
|
networkTimeoutMs: CHECKOUT_NETWORK_TIMEOUT_MS
|
|
48737
48366
|
}),
|
|
48738
|
-
locks,
|
|
48367
|
+
locks: openRepositoryLocks({ dir: (0, import_node_path25.join)(machine.stateDir, "locks"), clock, platform }),
|
|
48739
48368
|
log,
|
|
48740
|
-
dir: (0,
|
|
48369
|
+
dir: (0, import_node_path25.join)(machine.stateDir, "checkout-freshness")
|
|
48741
48370
|
}),
|
|
48742
48371
|
prepareAgentContext: createAgentContext({
|
|
48743
|
-
dir: (0,
|
|
48372
|
+
dir: (0, import_node_path25.join)(machine.stateDir, "agent-context"),
|
|
48744
48373
|
homeDir: machine.env.HOME || (0, import_node_os5.homedir)()
|
|
48745
48374
|
})
|
|
48746
48375
|
} : {}
|
|
@@ -48748,28 +48377,14 @@ function createHolderWorkspace(machine, clock, log) {
|
|
|
48748
48377
|
}
|
|
48749
48378
|
|
|
48750
48379
|
// src/holder/respond.ts
|
|
48751
|
-
function
|
|
48752
|
-
const state = { lease: null };
|
|
48753
|
-
return {
|
|
48754
|
-
allows: () => state.lease?.verify() ?? Promise.resolve(true),
|
|
48755
|
-
guard: (lease) => {
|
|
48756
|
-
state.lease = lease;
|
|
48757
|
-
return {
|
|
48758
|
-
[Symbol.dispose]: () => {
|
|
48759
|
-
if (state.lease === lease) state.lease = null;
|
|
48760
|
-
}
|
|
48761
|
-
};
|
|
48762
|
-
}
|
|
48763
|
-
};
|
|
48764
|
-
}
|
|
48765
|
-
async function respondToTurn(runningRunId, gate, driver, request2) {
|
|
48380
|
+
async function respondToTurn(runningRunId, driver, request2) {
|
|
48766
48381
|
if (runningRunId !== request2.runId) return "unknown_run";
|
|
48767
48382
|
if (driver.respond === void 0) return "not_waiting";
|
|
48768
|
-
return driver.respond(request2
|
|
48383
|
+
return driver.respond(request2);
|
|
48769
48384
|
}
|
|
48770
48385
|
|
|
48771
48386
|
// src/holder/session-facts.ts
|
|
48772
|
-
var
|
|
48387
|
+
var import_promises36 = require("fs/promises");
|
|
48773
48388
|
var CLI_RSS_CACHE_MS = 1e4;
|
|
48774
48389
|
var LOGIN_PROBLEM_PREFIX = "cli.auth.";
|
|
48775
48390
|
function isLoginFailure(result) {
|
|
@@ -48795,8 +48410,8 @@ function createSessionFacts(options) {
|
|
|
48795
48410
|
const path = await resolveCommandOnPath(command, env, platform);
|
|
48796
48411
|
if (path === null) return null;
|
|
48797
48412
|
try {
|
|
48798
|
-
const real = await (0,
|
|
48799
|
-
const info = await (0,
|
|
48413
|
+
const real = await (0, import_promises36.realpath)(path);
|
|
48414
|
+
const info = await (0, import_promises36.stat)(real);
|
|
48800
48415
|
return { command, key: `${real}:${info.ino}:${info.size}:${info.mtimeMs}` };
|
|
48801
48416
|
} catch {
|
|
48802
48417
|
return null;
|
|
@@ -48883,8 +48498,8 @@ function createSessionFacts(options) {
|
|
|
48883
48498
|
init_acp2();
|
|
48884
48499
|
|
|
48885
48500
|
// src/run-log/directory.ts
|
|
48886
|
-
var
|
|
48887
|
-
var
|
|
48501
|
+
var import_promises37 = require("fs/promises");
|
|
48502
|
+
var import_node_path26 = require("path");
|
|
48888
48503
|
init_runtime_v2();
|
|
48889
48504
|
init_zod();
|
|
48890
48505
|
var runMetaSchema = external_exports.object({
|
|
@@ -48906,17 +48521,17 @@ var runMetaSchema = external_exports.object({
|
|
|
48906
48521
|
}).optional()
|
|
48907
48522
|
});
|
|
48908
48523
|
function runDirectory(runsDir, runId) {
|
|
48909
|
-
const dir = (0,
|
|
48524
|
+
const dir = (0, import_node_path26.join)(runsDir, runId);
|
|
48910
48525
|
return {
|
|
48911
48526
|
dir,
|
|
48912
|
-
log: (0,
|
|
48913
|
-
upload: (0,
|
|
48914
|
-
meta: (0,
|
|
48527
|
+
log: (0, import_node_path26.join)(dir, "log.jsonl"),
|
|
48528
|
+
upload: (0, import_node_path26.join)(dir, "upload.json"),
|
|
48529
|
+
meta: (0, import_node_path26.join)(dir, "run.json")
|
|
48915
48530
|
};
|
|
48916
48531
|
}
|
|
48917
48532
|
async function isRunClaimed(runsDir, runId) {
|
|
48918
48533
|
try {
|
|
48919
|
-
return (await (0,
|
|
48534
|
+
return (await (0, import_promises37.stat)(runDirectory(runsDir, runId).log)).size > 0;
|
|
48920
48535
|
} catch (error61) {
|
|
48921
48536
|
if (errnoCode(error61) === "ENOENT") return false;
|
|
48922
48537
|
throw error61;
|
|
@@ -48924,8 +48539,8 @@ async function isRunClaimed(runsDir, runId) {
|
|
|
48924
48539
|
}
|
|
48925
48540
|
|
|
48926
48541
|
// src/run-log/conversation-index.ts
|
|
48927
|
-
var
|
|
48928
|
-
var
|
|
48542
|
+
var import_promises38 = require("fs/promises");
|
|
48543
|
+
var import_node_path27 = require("path");
|
|
48929
48544
|
init_runtime_v2();
|
|
48930
48545
|
init_zod();
|
|
48931
48546
|
var ORDINALS_PER_SHARD = 1e3;
|
|
@@ -48941,13 +48556,13 @@ var coverageSchema = external_exports.object({
|
|
|
48941
48556
|
nextExpectedOrdinal: external_exports.number().int().positive()
|
|
48942
48557
|
});
|
|
48943
48558
|
function conversationsDirectory(runsDir) {
|
|
48944
|
-
return (0,
|
|
48559
|
+
return (0, import_node_path27.join)((0, import_node_path27.dirname)(runsDir), "conversations");
|
|
48945
48560
|
}
|
|
48946
48561
|
function indexDirectory(runsDir, conversationId) {
|
|
48947
|
-
return (0,
|
|
48562
|
+
return (0, import_node_path27.join)(conversationsDirectory(runsDir), conversationId, "turn-index");
|
|
48948
48563
|
}
|
|
48949
48564
|
function shardPath(runsDir, conversationId, ordinal) {
|
|
48950
|
-
return (0,
|
|
48565
|
+
return (0, import_node_path27.join)(
|
|
48951
48566
|
indexDirectory(runsDir, conversationId),
|
|
48952
48567
|
`${Math.floor(ordinal / ORDINALS_PER_SHARD)}.jsonl`
|
|
48953
48568
|
);
|
|
@@ -48956,10 +48571,10 @@ async function indexConversationRun(runsDir, conversationId, ordinal, assistantO
|
|
|
48956
48571
|
const nextOrdinal = assistantOrdinal + 1;
|
|
48957
48572
|
if (nextOrdinal <= ordinal) throw new Error("Assistant order must follow the prompt");
|
|
48958
48573
|
const path = shardPath(runsDir, conversationId, ordinal);
|
|
48959
|
-
await (0,
|
|
48960
|
-
await (0,
|
|
48574
|
+
await (0, import_promises38.mkdir)((0, import_node_path27.dirname)(path), { recursive: true, mode: 448 });
|
|
48575
|
+
await (0, import_promises38.appendFile)(path, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
|
|
48961
48576
|
`, { mode: 384 });
|
|
48962
|
-
const coveragePath = (0,
|
|
48577
|
+
const coveragePath = (0, import_node_path27.join)((0, import_node_path27.dirname)((0, import_node_path27.dirname)(path)), "coverage.json");
|
|
48963
48578
|
const coverage = await readJsonFile(coveragePath, coverageSchema);
|
|
48964
48579
|
const current = coverage.kind === "ok" ? coverage.value : null;
|
|
48965
48580
|
const next = nextCoverage(current, ordinal, nextOrdinal);
|
|
@@ -49003,7 +48618,7 @@ var decoder = new TextDecoder();
|
|
|
49003
48618
|
|
|
49004
48619
|
// src/run-log/writer.ts
|
|
49005
48620
|
var import_node_fs10 = require("fs");
|
|
49006
|
-
var
|
|
48621
|
+
var import_node_path28 = require("path");
|
|
49007
48622
|
init_runtime_v2();
|
|
49008
48623
|
function lastSeq(fd, size) {
|
|
49009
48624
|
for (const length of tailWindows(size)) {
|
|
@@ -49019,7 +48634,7 @@ function lastSeq(fd, size) {
|
|
|
49019
48634
|
throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
|
|
49020
48635
|
}
|
|
49021
48636
|
function openRunLog(path, clock) {
|
|
49022
|
-
(0, import_node_fs10.mkdirSync)((0,
|
|
48637
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path28.dirname)(path), { recursive: true, mode: 448 });
|
|
49023
48638
|
const fd = (0, import_node_fs10.openSync)(path, "a+", 384);
|
|
49024
48639
|
let size = (0, import_node_fs10.fstatSync)(fd).size;
|
|
49025
48640
|
let seq = lastSeq(fd, size);
|
|
@@ -49056,107 +48671,6 @@ function openRunLog(path, clock) {
|
|
|
49056
48671
|
};
|
|
49057
48672
|
}
|
|
49058
48673
|
|
|
49059
|
-
// src/holder/lease-gate.ts
|
|
49060
|
-
init_acp();
|
|
49061
|
-
var READ_ONLY_TOOL_KINDS = /* @__PURE__ */ new Set([
|
|
49062
|
-
"read",
|
|
49063
|
-
"search",
|
|
49064
|
-
"think",
|
|
49065
|
-
"fetch",
|
|
49066
|
-
"switch_mode"
|
|
49067
|
-
]);
|
|
49068
|
-
function gateWorkspaceWrites(sink, lease) {
|
|
49069
|
-
const kinds = /* @__PURE__ */ new Map();
|
|
49070
|
-
const state = { tail: Promise.resolve(), pending: 0, gate: null, blocked: 0 };
|
|
49071
|
-
const writesFiles = (update) => {
|
|
49072
|
-
if (!isUpdate(update, "tool_call_update")) return false;
|
|
49073
|
-
if (typeof update.kind === "string") kinds.set(update.toolCallId, update.kind);
|
|
49074
|
-
const kind = kinds.get(update.toolCallId);
|
|
49075
|
-
return kind === void 0 || !READ_ONLY_TOOL_KINDS.has(kind);
|
|
49076
|
-
};
|
|
49077
|
-
const deliver = (event) => {
|
|
49078
|
-
if (lease.failure() === null) {
|
|
49079
|
-
sink.onEvent(event);
|
|
49080
|
-
return;
|
|
49081
|
-
}
|
|
49082
|
-
if (event.update.sessionUpdate === "tool_call_update") state.blocked += 1;
|
|
49083
|
-
};
|
|
49084
|
-
const enqueue = (event, gate) => {
|
|
49085
|
-
state.pending += 1;
|
|
49086
|
-
state.tail = state.tail.then(async () => {
|
|
49087
|
-
if (gate === null || await gate) deliver(event);
|
|
49088
|
-
else if (event.update.sessionUpdate === "tool_call_update") state.blocked += 1;
|
|
49089
|
-
}).finally(() => {
|
|
49090
|
-
state.pending -= 1;
|
|
49091
|
-
if (state.pending === 0) state.gate = null;
|
|
49092
|
-
});
|
|
49093
|
-
};
|
|
49094
|
-
return {
|
|
49095
|
-
onSpawned: (pid) => sink.onSpawned(pid),
|
|
49096
|
-
onEvent: (event) => {
|
|
49097
|
-
const write = writesFiles(event.update);
|
|
49098
|
-
if (!write && state.pending === 0) {
|
|
49099
|
-
deliver(event);
|
|
49100
|
-
return;
|
|
49101
|
-
}
|
|
49102
|
-
if (write) state.gate ??= lease.verify();
|
|
49103
|
-
enqueue(event, state.gate);
|
|
49104
|
-
},
|
|
49105
|
-
drain: async () => {
|
|
49106
|
-
while (state.pending > 0) await state.tail;
|
|
49107
|
-
},
|
|
49108
|
-
blocked: () => state.blocked
|
|
49109
|
-
};
|
|
49110
|
-
}
|
|
49111
|
-
|
|
49112
|
-
// src/holder/lease-turn.ts
|
|
49113
|
-
function leaseNotice(failure5, blocked) {
|
|
49114
|
-
const withheld = blocked === 0 ? "" : ` ${blocked} tool ${blocked === 1 ? "update was" : "updates were"} withheld.`;
|
|
49115
|
-
return {
|
|
49116
|
-
sessionUpdate: "notice",
|
|
49117
|
-
severity: "error",
|
|
49118
|
-
title: "The workspace changed while the agent was working",
|
|
49119
|
-
description: `${failure5.message}${withheld}`,
|
|
49120
|
-
_meta: {
|
|
49121
|
-
"alan.dev/noticeKind": "workspace_lease_lost",
|
|
49122
|
-
...failure5.problemCode === null ? {} : { "alan.dev/problem": { domain: "application", code: failure5.problemCode } }
|
|
49123
|
-
}
|
|
49124
|
-
};
|
|
49125
|
-
}
|
|
49126
|
-
async function runLeased(spec, paths, turn, sink, signal, run) {
|
|
49127
|
-
var _stack = [];
|
|
49128
|
-
try {
|
|
49129
|
-
const capture = await captureWorkspaceLease(spec.runId, paths, turn.lease, signal);
|
|
49130
|
-
if (capture.kind === "failed") {
|
|
49131
|
-
turn.log.warn("holder.workspace_lease_refused", {
|
|
49132
|
-
runId: spec.runId,
|
|
49133
|
-
code: capture.failure.code
|
|
49134
|
-
});
|
|
49135
|
-
return { outcome: "failed", message: capture.failure.message };
|
|
49136
|
-
}
|
|
49137
|
-
const lease = __using(_stack, capture.lease, true);
|
|
49138
|
-
const _answers = __using(_stack, turn.answerGate?.guard(lease));
|
|
49139
|
-
turn.log.info("holder.workspace_leased", { runId: spec.runId, checkouts: lease.checkouts });
|
|
49140
|
-
const gated = gateWorkspaceWrites(sink, lease);
|
|
49141
|
-
const result = await run(gated, AbortSignal.any([signal, lease.lost]));
|
|
49142
|
-
await gated.drain();
|
|
49143
|
-
const failure5 = lease.failure();
|
|
49144
|
-
if (failure5 === null) return result;
|
|
49145
|
-
sink.onEvent({ seq: 0, at: turn.clock.now(), update: leaseNotice(failure5, gated.blocked()) });
|
|
49146
|
-
await turn.driver.suspend?.().catch((error61) => turn.log.warn("holder.driver_suspend_failed", { error: error61 }));
|
|
49147
|
-
return {
|
|
49148
|
-
outcome: "failed",
|
|
49149
|
-
message: failure5.message,
|
|
49150
|
-
...result.providerSessionId === void 0 ? {} : { providerSessionId: result.providerSessionId }
|
|
49151
|
-
};
|
|
49152
|
-
} catch (_) {
|
|
49153
|
-
var _error = _, _hasError = true;
|
|
49154
|
-
} finally {
|
|
49155
|
-
var _promise2 = __callDispose(_stack, _error, _hasError);
|
|
49156
|
-
_promise2 && await _promise2;
|
|
49157
|
-
}
|
|
49158
|
-
}
|
|
49159
|
-
|
|
49160
48674
|
// src/holder/record-fit.ts
|
|
49161
48675
|
init_acp2();
|
|
49162
48676
|
init_runtime_v2();
|
|
@@ -49194,11 +48708,11 @@ function fitForRunLog(update) {
|
|
|
49194
48708
|
}
|
|
49195
48709
|
|
|
49196
48710
|
// src/holder/turn.ts
|
|
49197
|
-
async function runWithInputs({ spec,
|
|
48711
|
+
async function runWithInputs({ spec, skills }, context, sink, signal) {
|
|
49198
48712
|
var _stack = [];
|
|
49199
48713
|
try {
|
|
49200
48714
|
const workspace = context.workspace;
|
|
49201
|
-
const sessionContext = (workspace?.refreshFirstCheckout?.(spec,
|
|
48715
|
+
const sessionContext = (workspace?.refreshFirstCheckout?.(spec, signal) ?? Promise.resolve([])).catch((error61) => {
|
|
49202
48716
|
context.log.warn("workspace.refresh_failed", { runId: spec.runId, error: error61 });
|
|
49203
48717
|
return [];
|
|
49204
48718
|
}).then((problems) => workspace?.prepareAgentContext?.(spec, problems)).catch((error61) => {
|
|
@@ -49217,35 +48731,24 @@ async function runWithInputs({ spec, leaseTargets, skills }, context, sink, sign
|
|
|
49217
48731
|
}
|
|
49218
48732
|
const agentContext = await sessionContext;
|
|
49219
48733
|
const prepared = __using(_stack, inputs, true);
|
|
49220
|
-
const
|
|
49221
|
-
const result = await context.driver.runTurn(
|
|
49222
|
-
spec,
|
|
49223
|
-
turnSink,
|
|
49224
|
-
turnSignal,
|
|
49225
|
-
agentContext === void 0 ? prepared : {
|
|
49226
|
-
...prepared,
|
|
49227
|
-
agentContext: {
|
|
49228
|
-
full: agentContext.full,
|
|
49229
|
-
...agentContext.update ? { update: agentContext.update } : {}
|
|
49230
|
-
}
|
|
49231
|
-
}
|
|
49232
|
-
);
|
|
49233
|
-
if (agentContext !== void 0 && result.outcome !== "rejected") {
|
|
49234
|
-
await agentContext.save().catch((error61) => {
|
|
49235
|
-
context.log.warn("holder.agent_context_save_failed", { runId: spec.runId, error: error61 });
|
|
49236
|
-
});
|
|
49237
|
-
}
|
|
49238
|
-
return result;
|
|
49239
|
-
};
|
|
49240
|
-
if (workspace === void 0) return await run(sink, signal);
|
|
49241
|
-
return await runLeased(
|
|
48734
|
+
const result = await context.driver.runTurn(
|
|
49242
48735
|
spec,
|
|
49243
|
-
leaseTargets,
|
|
49244
|
-
{ ...context, lease: workspace.lease },
|
|
49245
48736
|
sink,
|
|
49246
48737
|
signal,
|
|
49247
|
-
|
|
48738
|
+
agentContext === void 0 ? prepared : {
|
|
48739
|
+
...prepared,
|
|
48740
|
+
agentContext: {
|
|
48741
|
+
full: agentContext.full,
|
|
48742
|
+
...agentContext.update ? { update: agentContext.update } : {}
|
|
48743
|
+
}
|
|
48744
|
+
}
|
|
49248
48745
|
);
|
|
48746
|
+
if (agentContext !== void 0 && result.outcome !== "rejected") {
|
|
48747
|
+
await agentContext.save().catch((error61) => {
|
|
48748
|
+
context.log.warn("holder.agent_context_save_failed", { runId: spec.runId, error: error61 });
|
|
48749
|
+
});
|
|
48750
|
+
}
|
|
48751
|
+
return result;
|
|
49249
48752
|
} catch (_) {
|
|
49250
48753
|
var _error = _, _hasError = true;
|
|
49251
48754
|
} finally {
|
|
@@ -49253,7 +48756,7 @@ async function runWithInputs({ spec, leaseTargets, skills }, context, sink, sign
|
|
|
49253
48756
|
_promise2 && await _promise2;
|
|
49254
48757
|
}
|
|
49255
48758
|
}
|
|
49256
|
-
async function admitAndRun(spec, context,
|
|
48759
|
+
async function admitAndRun(spec, context, sink, signal) {
|
|
49257
48760
|
if (context.workspace === void 0) {
|
|
49258
48761
|
if (spec.skillInvocations?.length) {
|
|
49259
48762
|
return {
|
|
@@ -49262,14 +48765,13 @@ async function admitAndRun(spec, context, append, sink, signal) {
|
|
|
49262
48765
|
message: "Selected skills need this computer's skill sync, which this holder does not have."
|
|
49263
48766
|
};
|
|
49264
48767
|
}
|
|
49265
|
-
return runWithInputs({ spec,
|
|
48768
|
+
return runWithInputs({ spec, skills: [] }, context, sink, signal);
|
|
49266
48769
|
}
|
|
49267
|
-
const admission = await admitRun(spec, context.workspace.admission
|
|
48770
|
+
const admission = await admitRun(spec, context.workspace.admission);
|
|
49268
48771
|
if (admission.kind === "rejected") {
|
|
49269
48772
|
context.log.info("holder.run_rejected", { runId: spec.runId, rejection: admission.rejection });
|
|
49270
48773
|
return { outcome: "rejected", rejection: admission.rejection, message: admission.message };
|
|
49271
48774
|
}
|
|
49272
|
-
if (admission.relocated !== null) append(admission.relocated);
|
|
49273
48775
|
return runWithInputs(admission, context, sink, signal);
|
|
49274
48776
|
}
|
|
49275
48777
|
async function claimRun(spec, context) {
|
|
@@ -49316,7 +48818,6 @@ async function runClaimedTurn(spec, claimed, context, signal) {
|
|
|
49316
48818
|
result = await admitAndRun(
|
|
49317
48819
|
spec,
|
|
49318
48820
|
context,
|
|
49319
|
-
append,
|
|
49320
48821
|
{
|
|
49321
48822
|
onSpawned: (pid) => append(runStarted({ pid })),
|
|
49322
48823
|
// Base64 media in provider payloads and tool output never reaches the log (main 13590db369).
|
|
@@ -49379,12 +48880,11 @@ async function runHolder({
|
|
|
49379
48880
|
try {
|
|
49380
48881
|
const identity = await readProcessIdentity(process.pid);
|
|
49381
48882
|
if (identity === null) throw new RuntimeFault("internal", "Cannot read own process identity");
|
|
49382
|
-
const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0,
|
|
48883
|
+
const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path29.dirname)(launch.statusPath)), clock, log));
|
|
49383
48884
|
const holder = {
|
|
49384
48885
|
state: "idle",
|
|
49385
48886
|
runId: null,
|
|
49386
48887
|
turn: null,
|
|
49387
|
-
answerGate: createAnswerGate(),
|
|
49388
48888
|
clients: /* @__PURE__ */ new Set()
|
|
49389
48889
|
};
|
|
49390
48890
|
const exit = new AbortController();
|
|
@@ -49442,8 +48942,7 @@ async function runHolder({
|
|
|
49442
48942
|
log,
|
|
49443
48943
|
onAppended: (runId, offset) => broadcast({ type: "appended", runId, offset }),
|
|
49444
48944
|
...inputs === void 0 ? {} : { inputs },
|
|
49445
|
-
...workspace === void 0 ? {} : { workspace }
|
|
49446
|
-
answerGate: holder.answerGate
|
|
48945
|
+
...workspace === void 0 ? {} : { workspace }
|
|
49447
48946
|
};
|
|
49448
48947
|
claimRun(spec, context).then(
|
|
49449
48948
|
(claimed) => {
|
|
@@ -49475,7 +48974,7 @@ async function runHolder({
|
|
|
49475
48974
|
);
|
|
49476
48975
|
};
|
|
49477
48976
|
const respond = (request2, client) => {
|
|
49478
|
-
respondToTurn(holder.runId,
|
|
48977
|
+
respondToTurn(holder.runId, driver, request2).then((status) => {
|
|
49479
48978
|
log.info("holder.responded", { runId: request2.runId, status });
|
|
49480
48979
|
writeMessage(client, { type: "responded", id: request2.id, status });
|
|
49481
48980
|
}).catch((error61) => {
|
|
@@ -49521,12 +49020,12 @@ async function runHolder({
|
|
|
49521
49020
|
return;
|
|
49522
49021
|
case "status":
|
|
49523
49022
|
void facts.snapshot().then(
|
|
49524
|
-
(
|
|
49023
|
+
(snapshot) => writeMessage(client, {
|
|
49525
49024
|
type: "status",
|
|
49526
49025
|
id: request2.id,
|
|
49527
49026
|
state: holder.state,
|
|
49528
49027
|
runId: holder.runId,
|
|
49529
|
-
facts:
|
|
49028
|
+
facts: snapshot
|
|
49530
49029
|
})
|
|
49531
49030
|
);
|
|
49532
49031
|
return;
|
|
@@ -49575,16 +49074,16 @@ async function runHolder({
|
|
|
49575
49074
|
client.on("error", () => holder.clients.delete(client));
|
|
49576
49075
|
});
|
|
49577
49076
|
removeStaleEndpoint(launch.endpoint);
|
|
49578
|
-
await new Promise((
|
|
49077
|
+
await new Promise((resolve8, reject) => {
|
|
49579
49078
|
server.once("error", reject);
|
|
49580
|
-
server.listen(launch.endpoint, () =>
|
|
49079
|
+
server.listen(launch.endpoint, () => resolve8());
|
|
49581
49080
|
});
|
|
49582
49081
|
await writeStatus();
|
|
49583
49082
|
log.info("holder.ready", { conversationId: launch.conversationId, pid: identity.pid });
|
|
49584
|
-
await new Promise((
|
|
49083
|
+
await new Promise((resolve8) => exit.signal.addEventListener("abort", () => resolve8()));
|
|
49585
49084
|
await driver.suspend?.().catch((error61) => log.warn("holder.driver_suspend_failed", { error: error61 }));
|
|
49586
49085
|
for (const client of holder.clients) client.end();
|
|
49587
|
-
await new Promise((
|
|
49086
|
+
await new Promise((resolve8) => server.close(() => resolve8()));
|
|
49588
49087
|
(0, import_node_fs11.rmSync)(launch.statusPath, { force: true });
|
|
49589
49088
|
log.info("holder.suspended", { conversationId: launch.conversationId });
|
|
49590
49089
|
} catch (_) {
|
|
@@ -49724,7 +49223,7 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
|
|
|
49724
49223
|
providerProbes: ALAN_RUNTIME_PROVIDER_PROBES === "on",
|
|
49725
49224
|
providerToolchain: ALAN_RUNTIME_PROVIDER_NODE !== void 0 && ALAN_RUNTIME_PROVIDER_NPM_CLI !== void 0 ? { node: ALAN_RUNTIME_PROVIDER_NODE, npmCli: ALAN_RUNTIME_PROVIDER_NPM_CLI } : null,
|
|
49726
49225
|
home,
|
|
49727
|
-
configHome: XDG_CONFIG_HOME ?? (0,
|
|
49226
|
+
configHome: XDG_CONFIG_HOME ?? (0, import_node_path31.join)(home, ".config"),
|
|
49728
49227
|
codexHome: resolveCodexHome(CODEX_HOME, home),
|
|
49729
49228
|
...githubProxyConfig({ ALAN_RUNTIME_GITHUB_PROXY, XDG_CONFIG_HOME, GH_CONFIG_DIR }, home),
|
|
49730
49229
|
gitGatewayUrl: ALAN_RUNTIME_GIT_GATEWAY_URL ?? null,
|
|
@@ -49734,13 +49233,13 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
|
|
|
49734
49233
|
};
|
|
49735
49234
|
}
|
|
49736
49235
|
function resolveCodexHome(configuredHome, home) {
|
|
49737
|
-
return configuredHome ?? (0,
|
|
49236
|
+
return configuredHome ?? (0, import_node_path31.join)(home, ".codex");
|
|
49738
49237
|
}
|
|
49739
49238
|
function githubProxyConfig(env, home) {
|
|
49740
|
-
const configHome = env.XDG_CONFIG_HOME ?? (0,
|
|
49239
|
+
const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path31.join)(home, ".config");
|
|
49741
49240
|
return {
|
|
49742
49241
|
githubProxy: env.ALAN_RUNTIME_GITHUB_PROXY === "on",
|
|
49743
|
-
ghConfigDir: env.GH_CONFIG_DIR ?? (0,
|
|
49242
|
+
ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path31.join)(configHome, "gh")
|
|
49744
49243
|
};
|
|
49745
49244
|
}
|
|
49746
49245
|
function serviceEnvironment(env, profile) {
|
|
@@ -49839,7 +49338,7 @@ async function loadStoredAccess(paths, access3 = { exec: systemExec }) {
|
|
|
49839
49338
|
}
|
|
49840
49339
|
|
|
49841
49340
|
// src/cli/commands/hold.ts
|
|
49842
|
-
var
|
|
49341
|
+
var import_node_path32 = require("path");
|
|
49843
49342
|
init_agent2();
|
|
49844
49343
|
init_runtime_v2();
|
|
49845
49344
|
async function machineAccess(paths, log, conversationId, transport) {
|
|
@@ -49897,7 +49396,7 @@ async function runHold(argv) {
|
|
|
49897
49396
|
const config2 = loadRuntimeConfig();
|
|
49898
49397
|
const paths = runtimePaths(config2.stateDir);
|
|
49899
49398
|
const log = __using(_stack, openFileLog(
|
|
49900
|
-
(0,
|
|
49399
|
+
(0, import_node_path32.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
|
|
49901
49400
|
config2.logLevel,
|
|
49902
49401
|
systemClock
|
|
49903
49402
|
));
|
|
@@ -49908,7 +49407,7 @@ async function runHold(argv) {
|
|
|
49908
49407
|
);
|
|
49909
49408
|
const transport = __using(_stack, createHttpTransport());
|
|
49910
49409
|
const access3 = await machineAccess(paths, log, launch.value.conversationId, transport);
|
|
49911
|
-
const credentialPath = (0,
|
|
49410
|
+
const credentialPath = (0, import_node_path32.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
|
|
49912
49411
|
const managedMcp = __using(_stack, access3.managedMcp === void 0 ? void 0 : createHelperMcpAccess({
|
|
49913
49412
|
managedMcp: access3.managedMcp,
|
|
49914
49413
|
conversationId: launch.value.conversationId,
|