@ordewell/core 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +498 -310
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +473 -286
- package/dist/index.mjs.map +1 -1
- package/dist/plan-utils.d.mts +1 -1
- package/dist/plan-utils.d.ts +1 -1
- package/dist/{runSettingsText-tnmvdSfS.d.mts → runSettingsText-BuLVBlXS.d.mts} +3 -0
- package/dist/{runSettingsText-CYMhTWfw.d.ts → runSettingsText-DVOd7vKC.d.ts} +3 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -472,6 +472,7 @@ __export(index_exports, {
|
|
|
472
472
|
repoBaseLine: () => repoBaseLine,
|
|
473
473
|
repoResultLines: () => repoResultLines,
|
|
474
474
|
reposWithWork: () => reposWithWork,
|
|
475
|
+
repositoryRunnerConfigPaths: () => repositoryRunnerConfigPaths,
|
|
475
476
|
researchShellWarning: () => researchShellWarning,
|
|
476
477
|
researchToolsPath: () => researchToolsPath,
|
|
477
478
|
resetInstalledPlanner: () => resetInstalledPlanner,
|
|
@@ -662,18 +663,18 @@ function dependencyTargetErrors(tasks, taskId, dependencies) {
|
|
|
662
663
|
}
|
|
663
664
|
function findDependencyCycle(tasks) {
|
|
664
665
|
const byId = new Map([...walkPlan(tasks)].map(({ task: task2 }) => [task2.id, task2]));
|
|
665
|
-
const
|
|
666
|
+
const path50 = [];
|
|
666
667
|
const done = /* @__PURE__ */ new Set();
|
|
667
668
|
const visit = (id2) => {
|
|
668
669
|
if (done.has(id2)) return null;
|
|
669
|
-
const at =
|
|
670
|
-
if (at >= 0) return
|
|
671
|
-
|
|
670
|
+
const at = path50.indexOf(id2);
|
|
671
|
+
if (at >= 0) return path50.slice(at);
|
|
672
|
+
path50.push(id2);
|
|
672
673
|
for (const dep of byId.get(id2)?.dependencies ?? []) {
|
|
673
674
|
const hit = visit(dep);
|
|
674
675
|
if (hit) return hit;
|
|
675
676
|
}
|
|
676
|
-
|
|
677
|
+
path50.pop();
|
|
677
678
|
done.add(id2);
|
|
678
679
|
return null;
|
|
679
680
|
};
|
|
@@ -1738,7 +1739,7 @@ function lastServedModel(events) {
|
|
|
1738
1739
|
return void 0;
|
|
1739
1740
|
}
|
|
1740
1741
|
function taskLogForSurface(events) {
|
|
1741
|
-
return events.map((event) => event.type === "task_skills" ? { type: "task_skills", skills: event.skills.map(({ name, source, path:
|
|
1742
|
+
return events.map((event) => event.type === "task_skills" ? { type: "task_skills", skills: event.skills.map(({ name, source, path: path50 }) => ({ name, source, path: path50 })) } : event);
|
|
1742
1743
|
}
|
|
1743
1744
|
function coalesceTaskLog(events) {
|
|
1744
1745
|
const out = [];
|
|
@@ -6220,7 +6221,7 @@ function pathRefs(command, opts = {}) {
|
|
|
6220
6221
|
return lexAll(command.trim(), dialect, opts.cdpathSet).segments.flatMap((seg) => {
|
|
6221
6222
|
const patterns = patternArgs(seg);
|
|
6222
6223
|
const cwd = seg.cwd ?? [];
|
|
6223
|
-
return [...seg.args.filter((_, i) => !patterns.has(i)), ...seg.inputs].flatMap(pathIn).map((
|
|
6224
|
+
return [...seg.args.filter((_, i) => !patterns.has(i)), ...seg.inputs].flatMap(pathIn).map((path50) => ({ path: path50, cwd }));
|
|
6224
6225
|
});
|
|
6225
6226
|
}
|
|
6226
6227
|
function excludedBy(command, allow, opts = {}) {
|
|
@@ -6764,10 +6765,10 @@ function summarizeToolCall(tool2, argsJson, toolLabel) {
|
|
|
6764
6765
|
const scope = args.include ? ` in ${args.include}` : "";
|
|
6765
6766
|
return `grep ${ellipsize(String(args.pattern), 40)}${scope}${mode}`;
|
|
6766
6767
|
}
|
|
6767
|
-
const
|
|
6768
|
-
if (
|
|
6769
|
-
const
|
|
6770
|
-
return `${display} ${
|
|
6768
|
+
const path50 = args.filePath || args.file_path || args.path;
|
|
6769
|
+
if (path50) {
|
|
6770
|
+
const basename7 = String(path50).split("/").pop() || String(path50);
|
|
6771
|
+
return `${display} ${basename7}`;
|
|
6771
6772
|
}
|
|
6772
6773
|
if (args.pattern) {
|
|
6773
6774
|
return `${display} ${args.pattern}`;
|
|
@@ -8382,7 +8383,7 @@ ${outcome.output}${outcome.success ? "" : `
|
|
|
8382
8383
|
}
|
|
8383
8384
|
let shell;
|
|
8384
8385
|
try {
|
|
8385
|
-
const sealed2 = site.task?.gitBefore ? { ...site.sealed, gitEntries: site.task.gitBefore.entries.map(({ path:
|
|
8386
|
+
const sealed2 = site.task?.gitBefore ? { ...site.sealed, gitEntries: site.task.gitBefore.entries.map(({ path: path50, directory }) => ({ path: path50, directory })) } : site.sealed;
|
|
8386
8387
|
shell = await site.sandbox.launchSealed(this.researchShell, sealed2);
|
|
8387
8388
|
} catch (err) {
|
|
8388
8389
|
return { refused: refusal(`Command not run: its sealed sandbox could not be prepared (${err instanceof Error ? err.message : String(err)}).`) };
|
|
@@ -9931,8 +9932,8 @@ function firstLineOf(command) {
|
|
|
9931
9932
|
function text(value) {
|
|
9932
9933
|
return typeof value === "string" ? value : "";
|
|
9933
9934
|
}
|
|
9934
|
-
function searchArg(pattern,
|
|
9935
|
-
return `${pattern}${
|
|
9935
|
+
function searchArg(pattern, path50, include = "") {
|
|
9936
|
+
return `${pattern}${path50 ? ` in ${path50}` : ""}${include ? ` (${include})` : ""}`;
|
|
9936
9937
|
}
|
|
9937
9938
|
function hintArg(args) {
|
|
9938
9939
|
for (const field of HINT_FIELDS) {
|
|
@@ -10037,8 +10038,8 @@ function userMessage(id2, text6, skills, { turnId, forced } = {}) {
|
|
|
10037
10038
|
...forced ? { forced: true } : {}
|
|
10038
10039
|
};
|
|
10039
10040
|
}
|
|
10040
|
-
function skillLoadNotice({ invokedBy, name, source, path:
|
|
10041
|
-
return { invokedBy, name, source, path:
|
|
10041
|
+
function skillLoadNotice({ invokedBy, name, source, path: path50, attaches }) {
|
|
10042
|
+
return { invokedBy, name, source, path: path50, ...attaches ? { attaches } : {} };
|
|
10042
10043
|
}
|
|
10043
10044
|
var LOAD_SKILL_TOOL = /(?:^|_)load_skill$/;
|
|
10044
10045
|
function surfaceStep(step) {
|
|
@@ -10055,8 +10056,8 @@ function loadedSkillName(args) {
|
|
|
10055
10056
|
return void 0;
|
|
10056
10057
|
}
|
|
10057
10058
|
}
|
|
10058
|
-
function skillLoadBlock(id2, { invokedBy, name, source, path:
|
|
10059
|
-
return { type: "skill_load", id: id2, invokedBy, name, source, path:
|
|
10059
|
+
function skillLoadBlock(id2, { invokedBy, name, source, path: path50, attaches }, turnId) {
|
|
10060
|
+
return { type: "skill_load", id: id2, invokedBy, name, source, path: path50, ...attaches ? { attaches } : {}, ...turnId ? { turnId } : {} };
|
|
10060
10061
|
}
|
|
10061
10062
|
function subagentBlock(id2, { toolCallId, model, usage, turnId, ...fields }) {
|
|
10062
10063
|
return {
|
|
@@ -10934,9 +10935,9 @@ function claudeManagedSettingsDir(platform = process.platform) {
|
|
|
10934
10935
|
}
|
|
10935
10936
|
function readClaudeSettingsModels(files, platform = process.platform) {
|
|
10936
10937
|
const managed = claudeManagedSettingsDir(platform);
|
|
10937
|
-
const
|
|
10938
|
-
const dropIns = files.list(
|
|
10939
|
-
const ranked = [...dropIns.reverse(),
|
|
10938
|
+
const join46 = platform === "win32" ? path13.win32.join : path13.posix.join;
|
|
10939
|
+
const dropIns = files.list(join46(managed, "managed-settings.d")).filter((name) => name.endsWith(".json") && !name.startsWith(".")).sort().map((name) => join46(managed, "managed-settings.d", name));
|
|
10940
|
+
const ranked = [...dropIns.reverse(), join46(managed, "managed-settings.json"), join46(claudeConfigDir(files.env), "settings.json")];
|
|
10940
10941
|
for (const file of ranked) {
|
|
10941
10942
|
const content = files.read(file);
|
|
10942
10943
|
const lineup = content === null ? null : parseClaudeSettingsModels(content);
|
|
@@ -12048,12 +12049,12 @@ function checkpointReply(answer2) {
|
|
|
12048
12049
|
return { text: `The checkpoint was withdrawn: ${answer2.why}`, isError: true };
|
|
12049
12050
|
}
|
|
12050
12051
|
}
|
|
12051
|
-
function fieldPath(
|
|
12052
|
-
return
|
|
12052
|
+
function fieldPath(path50) {
|
|
12053
|
+
return path50.reduce((text6, part) => typeof part === "number" ? `${text6}[${part}]` : text6 ? `${text6}.${String(part)}` : String(part), "");
|
|
12053
12054
|
}
|
|
12054
|
-
function valueAt(value,
|
|
12055
|
+
function valueAt(value, path50) {
|
|
12055
12056
|
let current = value;
|
|
12056
|
-
for (const part of
|
|
12057
|
+
for (const part of path50) {
|
|
12057
12058
|
if (typeof part === "number") {
|
|
12058
12059
|
if (!Array.isArray(current)) return void 0;
|
|
12059
12060
|
current = current[part];
|
|
@@ -12075,7 +12076,7 @@ function boundedRefusal(issue, args) {
|
|
|
12075
12076
|
var LEAKED_PARAMETER = /<\/parameter>|<parameter\s+name\s*=\s*"([^"]*)">/g;
|
|
12076
12077
|
function leakedMarkupIn(value) {
|
|
12077
12078
|
const found = [];
|
|
12078
|
-
const walk = (node,
|
|
12079
|
+
const walk = (node, path50) => {
|
|
12079
12080
|
if (typeof node === "string") {
|
|
12080
12081
|
const names = [];
|
|
12081
12082
|
let closing = false;
|
|
@@ -12083,25 +12084,25 @@ function leakedMarkupIn(value) {
|
|
|
12083
12084
|
if (match[1] !== void 0) names.push(match[1]);
|
|
12084
12085
|
else closing = true;
|
|
12085
12086
|
}
|
|
12086
|
-
if (names.length > 0 || closing) found.push({ path:
|
|
12087
|
+
if (names.length > 0 || closing) found.push({ path: path50, names: [...new Set(names)], closing });
|
|
12087
12088
|
return;
|
|
12088
12089
|
}
|
|
12089
12090
|
if (Array.isArray(node)) {
|
|
12090
|
-
node.forEach((item, i) => walk(item, `${
|
|
12091
|
+
node.forEach((item, i) => walk(item, `${path50}[${i}]`));
|
|
12091
12092
|
return;
|
|
12092
12093
|
}
|
|
12093
12094
|
if (node !== null && typeof node === "object") {
|
|
12094
|
-
for (const [key, item] of Object.entries(node)) walk(item,
|
|
12095
|
+
for (const [key, item] of Object.entries(node)) walk(item, path50 ? `${path50}.${key}` : key);
|
|
12095
12096
|
}
|
|
12096
12097
|
};
|
|
12097
12098
|
walk(value, "");
|
|
12098
12099
|
return found;
|
|
12099
12100
|
}
|
|
12100
12101
|
function markupRefusal(leaks) {
|
|
12101
|
-
return leaks.map(({ path:
|
|
12102
|
+
return leaks.map(({ path: path50, names, closing }) => {
|
|
12102
12103
|
const tags = [...names.map((n) => `<parameter name="${n}">`), ...closing ? ["</parameter>"] : []];
|
|
12103
|
-
const guide = names.length > 0 ? ` The parameters ${names.map((n) => JSON.stringify(n)).join(", ")} are inside it; pass them as separate arguments, not inside ${
|
|
12104
|
-
return `${
|
|
12104
|
+
const guide = names.length > 0 ? ` The parameters ${names.map((n) => JSON.stringify(n)).join(", ")} are inside it; pass them as separate arguments, not inside ${path50}.` : " Pass each argument separately, not inside one string.";
|
|
12105
|
+
return `${path50} contains leaked tool-call markup: ${tags.join(", ")}.${guide}`;
|
|
12105
12106
|
}).join("\n");
|
|
12106
12107
|
}
|
|
12107
12108
|
function invalidArguments(name, error, args) {
|
|
@@ -12566,9 +12567,9 @@ function mcpClientConfig(credential) {
|
|
|
12566
12567
|
}
|
|
12567
12568
|
function ownerOnlyConfigFile(fileName, contents) {
|
|
12568
12569
|
const dir = (0, import_fs5.mkdtempSync)((0, import_path4.join)((0, import_os.tmpdir)(), "ordewell-mcp-"));
|
|
12569
|
-
const
|
|
12570
|
-
(0, import_fs5.writeFileSync)(
|
|
12571
|
-
return { path:
|
|
12570
|
+
const path50 = (0, import_path4.join)(dir, fileName);
|
|
12571
|
+
(0, import_fs5.writeFileSync)(path50, contents, { mode: 384 });
|
|
12572
|
+
return { path: path50, remove: () => (0, import_fs5.rmSync)(dir, { recursive: true, force: true }) };
|
|
12572
12573
|
}
|
|
12573
12574
|
|
|
12574
12575
|
// src/services/harness/repoConfig.ts
|
|
@@ -12697,33 +12698,33 @@ var TomlReader = class {
|
|
|
12697
12698
|
if (this.i >= this.src.length) return root;
|
|
12698
12699
|
if (this.src.startsWith("[[", this.i)) {
|
|
12699
12700
|
this.i += 2;
|
|
12700
|
-
const
|
|
12701
|
+
const path50 = this.key();
|
|
12701
12702
|
this.expect("]]");
|
|
12702
|
-
const parent = this.tableAt(root,
|
|
12703
|
-
const last =
|
|
12703
|
+
const parent = this.tableAt(root, path50.slice(0, -1));
|
|
12704
|
+
const last = path50[path50.length - 1];
|
|
12704
12705
|
const list = Object.hasOwn(parent, last) ? parent[last] : parent[last] = [];
|
|
12705
|
-
if (!Array.isArray(list)) throw this.fail(`${
|
|
12706
|
+
if (!Array.isArray(list)) throw this.fail(`${path50.join(".")} is not an array of tables`);
|
|
12706
12707
|
table = newTable();
|
|
12707
12708
|
list.push(table);
|
|
12708
12709
|
} else if (this.src[this.i] === "[") {
|
|
12709
12710
|
this.i += 1;
|
|
12710
|
-
const
|
|
12711
|
+
const path50 = this.key();
|
|
12711
12712
|
this.expect("]");
|
|
12712
|
-
table = this.tableAt(root,
|
|
12713
|
+
table = this.tableAt(root, path50);
|
|
12713
12714
|
} else {
|
|
12714
|
-
const
|
|
12715
|
+
const path50 = this.key();
|
|
12715
12716
|
this.skipBlank(false);
|
|
12716
12717
|
this.expect("=");
|
|
12717
12718
|
this.skipBlank(false);
|
|
12718
|
-
const owner = this.tableAt(table,
|
|
12719
|
-
owner[
|
|
12719
|
+
const owner = this.tableAt(table, path50.slice(0, -1));
|
|
12720
|
+
owner[path50[path50.length - 1]] = this.value();
|
|
12720
12721
|
}
|
|
12721
12722
|
this.endOfLine();
|
|
12722
12723
|
}
|
|
12723
12724
|
}
|
|
12724
|
-
tableAt(from,
|
|
12725
|
+
tableAt(from, path50) {
|
|
12725
12726
|
let table = from;
|
|
12726
|
-
for (const part of
|
|
12727
|
+
for (const part of path50) {
|
|
12727
12728
|
const next = Object.hasOwn(table, part) ? table[part] : void 0;
|
|
12728
12729
|
if (next === void 0) table = table[part] = newTable();
|
|
12729
12730
|
else if (isRecord2(next)) table = next;
|
|
@@ -12792,10 +12793,10 @@ var TomlReader = class {
|
|
|
12792
12793
|
this.i++;
|
|
12793
12794
|
return table;
|
|
12794
12795
|
}
|
|
12795
|
-
const
|
|
12796
|
+
const path50 = this.key();
|
|
12796
12797
|
this.expect("=");
|
|
12797
12798
|
this.skipBlank(false);
|
|
12798
|
-
this.tableAt(table,
|
|
12799
|
+
this.tableAt(table, path50.slice(0, -1))[path50[path50.length - 1]] = this.value();
|
|
12799
12800
|
this.skipBlank(true);
|
|
12800
12801
|
if (this.src[this.i] === ",") this.i++;
|
|
12801
12802
|
else if (this.src[this.i] !== "}") throw this.fail("expected , or } in an inline table");
|
|
@@ -13170,7 +13171,7 @@ var LineBuffer = class {
|
|
|
13170
13171
|
// src/services/harness/ClaudeCodeAdapter.ts
|
|
13171
13172
|
var import_crypto6 = require("crypto");
|
|
13172
13173
|
var import_fs11 = require("fs");
|
|
13173
|
-
var
|
|
13174
|
+
var path23 = __toESM(require("path"));
|
|
13174
13175
|
|
|
13175
13176
|
// src/plugins/resolveArgs.ts
|
|
13176
13177
|
function claudeThinkingArgs(effort) {
|
|
@@ -13253,28 +13254,28 @@ function posixBinDirs() {
|
|
|
13253
13254
|
];
|
|
13254
13255
|
}
|
|
13255
13256
|
function windowsBinDirs(env, home) {
|
|
13256
|
-
const
|
|
13257
|
-
const under = (base, ...parts) => base ? [
|
|
13257
|
+
const join46 = (...parts) => path15.win32.join(...parts);
|
|
13258
|
+
const under = (base, ...parts) => base ? [join46(base, ...parts)] : [];
|
|
13258
13259
|
const appData = env.APPDATA;
|
|
13259
13260
|
const localAppData = env.LOCALAPPDATA;
|
|
13260
13261
|
const programData = env.ProgramData;
|
|
13261
13262
|
return [
|
|
13262
13263
|
// Native per-user installers, PowerShell-driven and otherwise.
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
|
|
13264
|
+
join46(home, ".local", "bin"),
|
|
13265
|
+
join46(home, ".opencode", "bin"),
|
|
13266
|
+
join46(home, ".claude", "bin"),
|
|
13267
|
+
join46(home, ".codex", "bin"),
|
|
13267
13268
|
...under(localAppData, "Programs", "claude"),
|
|
13268
13269
|
// Node package managers. npm's global prefix is `%APPDATA%\npm`; the
|
|
13269
13270
|
// literal spelling is kept as a fallback for a host that does not export
|
|
13270
13271
|
// APPDATA (a service account, a stripped CI container).
|
|
13271
13272
|
...under(appData, "npm"),
|
|
13272
|
-
|
|
13273
|
+
join46(home, "AppData", "Roaming", "npm"),
|
|
13273
13274
|
...under(localAppData, "pnpm"),
|
|
13274
13275
|
...under(localAppData, "Yarn", "bin"),
|
|
13275
|
-
|
|
13276
|
+
join46(home, ".bun", "bin"),
|
|
13276
13277
|
// Windows package managers.
|
|
13277
|
-
|
|
13278
|
+
join46(home, "scoop", "shims"),
|
|
13278
13279
|
...under(env.SCOOP, "shims"),
|
|
13279
13280
|
...under(env.SCOOP_GLOBAL ?? programData, "scoop", "shims"),
|
|
13280
13281
|
...under(programData, "chocolatey", "bin"),
|
|
@@ -13284,7 +13285,7 @@ function windowsBinDirs(env, home) {
|
|
|
13284
13285
|
...under(localAppData, "Microsoft", "WindowsApps"),
|
|
13285
13286
|
// Version managers. Volta's Windows home is not the POSIX `~/.volta`.
|
|
13286
13287
|
...under(localAppData, "Volta", "bin"),
|
|
13287
|
-
|
|
13288
|
+
join46(home, ".volta", "bin")
|
|
13288
13289
|
];
|
|
13289
13290
|
}
|
|
13290
13291
|
function wellKnownBinDirs(deps = {}) {
|
|
@@ -14532,7 +14533,7 @@ function readOnlySessionRules(site) {
|
|
|
14532
14533
|
real = import_fs8.realpathSync.native(root);
|
|
14533
14534
|
} catch {
|
|
14534
14535
|
}
|
|
14535
|
-
for (const
|
|
14536
|
+
for (const path50 of /* @__PURE__ */ new Set([root, real])) rules.push({ action: "external_directory", resource: `${path50.replace(/[\\/]$/, "")}/*`, effect: "allow" });
|
|
14536
14537
|
}
|
|
14537
14538
|
return rules;
|
|
14538
14539
|
}
|
|
@@ -15254,6 +15255,20 @@ ${lines2.map((line) => `${line}
|
|
|
15254
15255
|
}
|
|
15255
15256
|
|
|
15256
15257
|
// src/services/harness/claudeOrdewell.ts
|
|
15258
|
+
var path21 = __toESM(require("path"));
|
|
15259
|
+
function assertNoClaudeTaskCollision(cwd) {
|
|
15260
|
+
const text6 = readText(path21.join(cwd, ".mcp.json"));
|
|
15261
|
+
if (text6 === void 0) return;
|
|
15262
|
+
let parsed;
|
|
15263
|
+
try {
|
|
15264
|
+
parsed = JSON.parse(text6);
|
|
15265
|
+
} catch {
|
|
15266
|
+
return;
|
|
15267
|
+
}
|
|
15268
|
+
if (isRecord2(parsed) && isRecord2(parsed.mcpServers) && Object.hasOwn(parsed.mcpServers, ORDEWELL_MCP_SERVER_NAME)) {
|
|
15269
|
+
throw new Error(".mcp.json declares an MCP server named ordewell; rename or remove the ordewell server before starting this task.");
|
|
15270
|
+
}
|
|
15271
|
+
}
|
|
15257
15272
|
var CLAUDE_ORDEWELL = {
|
|
15258
15273
|
toolName: MCP_CLIENT_TOOL_NAMES.toolName,
|
|
15259
15274
|
toolNames: MCP_CLIENT_TOOL_NAMES.toolNames,
|
|
@@ -15401,8 +15416,8 @@ var ReplyRuns = class {
|
|
|
15401
15416
|
};
|
|
15402
15417
|
|
|
15403
15418
|
// src/services/harness/claudeRepoConfig.ts
|
|
15404
|
-
var
|
|
15405
|
-
var MEMORY_FILES = ["CLAUDE.md",
|
|
15419
|
+
var path22 = __toESM(require("path"));
|
|
15420
|
+
var MEMORY_FILES = ["CLAUDE.md", path22.join(".claude", "CLAUDE.md"), "CLAUDE.local.md"];
|
|
15406
15421
|
var MAX_IMPORT_DEPTH = 5;
|
|
15407
15422
|
function importsOf(text6) {
|
|
15408
15423
|
const prose = text6.replace(/```[\s\S]*?```/g, "").replace(/`[^`\n]*`/g, "");
|
|
@@ -15413,11 +15428,11 @@ function withImports(workspace, file, depth, seen, into) {
|
|
|
15413
15428
|
seen.add(file);
|
|
15414
15429
|
const text6 = readText(file);
|
|
15415
15430
|
if (text6 === void 0) return;
|
|
15416
|
-
into.push({ path:
|
|
15431
|
+
into.push({ path: path22.relative(workspace, file), text: text6 });
|
|
15417
15432
|
if (depth >= MAX_IMPORT_DEPTH) return;
|
|
15418
15433
|
for (const target of importsOf(text6)) {
|
|
15419
15434
|
if (target.startsWith("~")) continue;
|
|
15420
|
-
const abs =
|
|
15435
|
+
const abs = path22.resolve(path22.dirname(file), target);
|
|
15421
15436
|
if (insideOnDisk(workspace, abs)) withImports(workspace, abs, depth + 1, seen, into);
|
|
15422
15437
|
}
|
|
15423
15438
|
}
|
|
@@ -15438,12 +15453,12 @@ var CLAUDE_REPO_CONFIG = {
|
|
|
15438
15453
|
instructions(workspace) {
|
|
15439
15454
|
const files = [];
|
|
15440
15455
|
const seen = /* @__PURE__ */ new Set();
|
|
15441
|
-
for (const name of MEMORY_FILES) withImports(workspace,
|
|
15456
|
+
for (const name of MEMORY_FILES) withImports(workspace, path22.join(workspace, name), 0, seen, files);
|
|
15442
15457
|
return files;
|
|
15443
15458
|
},
|
|
15444
15459
|
projectServers(workspace) {
|
|
15445
15460
|
const source = ".mcp.json";
|
|
15446
|
-
const text6 = readText(
|
|
15461
|
+
const text6 = readText(path22.join(workspace, source));
|
|
15447
15462
|
if (text6 === void 0) return NO_SERVERS;
|
|
15448
15463
|
let parsed;
|
|
15449
15464
|
try {
|
|
@@ -15463,12 +15478,12 @@ var CLAUDE_REPO_CONFIG = {
|
|
|
15463
15478
|
};
|
|
15464
15479
|
function claudeLocalServers(env, workspace) {
|
|
15465
15480
|
const configDir2 = env.CLAUDE_CONFIG_DIR?.trim();
|
|
15466
|
-
const file = expandRunnerHome(configDir2 ?
|
|
15481
|
+
const file = expandRunnerHome(configDir2 ? path22.join(configDir2, ".claude.json") : "~/.claude.json", env);
|
|
15467
15482
|
const text6 = file === null ? void 0 : readText(file);
|
|
15468
15483
|
if (text6 === void 0) return {};
|
|
15469
15484
|
try {
|
|
15470
15485
|
const parsed = JSON.parse(text6);
|
|
15471
|
-
const project = isRecord2(parsed) && isRecord2(parsed.projects) ? parsed.projects[
|
|
15486
|
+
const project = isRecord2(parsed) && isRecord2(parsed.projects) ? parsed.projects[path22.resolve(workspace)] : void 0;
|
|
15472
15487
|
return isRecord2(project) && isRecord2(project.mcpServers) ? project.mcpServers : {};
|
|
15473
15488
|
} catch {
|
|
15474
15489
|
return {};
|
|
@@ -15723,13 +15738,13 @@ var NO_AUTO_MEMORY = { CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1" };
|
|
|
15723
15738
|
function inSavedOutput(abs, configDir2, sessionId) {
|
|
15724
15739
|
let projects;
|
|
15725
15740
|
try {
|
|
15726
|
-
projects = import_fs11.realpathSync.native(
|
|
15741
|
+
projects = import_fs11.realpathSync.native(path23.join(configDir2, "projects"));
|
|
15727
15742
|
} catch {
|
|
15728
15743
|
return false;
|
|
15729
15744
|
}
|
|
15730
|
-
const rel =
|
|
15731
|
-
if (rel.startsWith("..") ||
|
|
15732
|
-
const [project, session, folder] = rel.split(
|
|
15745
|
+
const rel = path23.relative(projects, abs);
|
|
15746
|
+
if (rel.startsWith("..") || path23.isAbsolute(rel)) return false;
|
|
15747
|
+
const [project, session, folder] = rel.split(path23.sep);
|
|
15733
15748
|
return Boolean(project) && session === sessionId && folder === "tool-results";
|
|
15734
15749
|
}
|
|
15735
15750
|
var PATH_TOOLS = {
|
|
@@ -16020,6 +16035,7 @@ var ClaudeCodeAdapter = class extends StdioAgentAdapter {
|
|
|
16020
16035
|
*/
|
|
16021
16036
|
taskSpawnSpec(opts) {
|
|
16022
16037
|
const readOnly = readOnlyTask(opts);
|
|
16038
|
+
if (!readOnly) assertNoClaudeTaskCollision(opts.cwd);
|
|
16023
16039
|
this.readOnlySite = readOnly ? opts : null;
|
|
16024
16040
|
this.requestedMode = readOnly ? PLANNER_PERMISSION_MODE : opts.flags.permissionMode;
|
|
16025
16041
|
this.followedModel = opts.model;
|
|
@@ -16815,8 +16831,8 @@ function runProbe(deps, cwd, env, flags) {
|
|
|
16815
16831
|
}
|
|
16816
16832
|
|
|
16817
16833
|
// src/services/harness/codexRepoConfig.ts
|
|
16818
|
-
var
|
|
16819
|
-
var CONFIG_FILE =
|
|
16834
|
+
var path24 = __toESM(require("path"));
|
|
16835
|
+
var CONFIG_FILE = path24.join(".codex", "config.toml");
|
|
16820
16836
|
function stringsOf(value) {
|
|
16821
16837
|
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
16822
16838
|
}
|
|
@@ -16842,9 +16858,9 @@ var CODEX_REPO_CONFIG = {
|
|
|
16842
16858
|
const files = [];
|
|
16843
16859
|
for (const dir of repoLevels(workspace)) {
|
|
16844
16860
|
for (const name of ["AGENTS.override.md", "AGENTS.md"]) {
|
|
16845
|
-
const text6 = readText(
|
|
16861
|
+
const text6 = readText(path24.join(dir, name));
|
|
16846
16862
|
if (text6 === void 0) continue;
|
|
16847
|
-
files.push({ path:
|
|
16863
|
+
files.push({ path: path24.relative(workspace, path24.join(dir, name)) || name, text: text6 });
|
|
16848
16864
|
break;
|
|
16849
16865
|
}
|
|
16850
16866
|
}
|
|
@@ -16855,10 +16871,10 @@ var CODEX_REPO_CONFIG = {
|
|
|
16855
16871
|
const byName = /* @__PURE__ */ new Map();
|
|
16856
16872
|
const unreadable = [];
|
|
16857
16873
|
for (const dir of repoLevels(workspace)) {
|
|
16858
|
-
const file =
|
|
16874
|
+
const file = path24.join(dir, CONFIG_FILE);
|
|
16859
16875
|
const text6 = readText(file);
|
|
16860
16876
|
if (text6 === void 0) continue;
|
|
16861
|
-
const source =
|
|
16877
|
+
const source = path24.relative(workspace, file);
|
|
16862
16878
|
let parsed;
|
|
16863
16879
|
try {
|
|
16864
16880
|
parsed = parseToml(text6);
|
|
@@ -16878,9 +16894,9 @@ var CODEX_REPO_CONFIG = {
|
|
|
16878
16894
|
};
|
|
16879
16895
|
function untrustedProjects(workspace) {
|
|
16880
16896
|
const projects = {};
|
|
16881
|
-
for (let dir =
|
|
16897
|
+
for (let dir = path24.resolve(workspace); ; dir = path24.dirname(dir)) {
|
|
16882
16898
|
projects[dir] = { trust_level: "untrusted" };
|
|
16883
|
-
if (
|
|
16899
|
+
if (path24.dirname(dir) === dir) return projects;
|
|
16884
16900
|
}
|
|
16885
16901
|
}
|
|
16886
16902
|
|
|
@@ -18001,7 +18017,7 @@ ${this.exitMessage()}`);
|
|
|
18001
18017
|
case "webSearch":
|
|
18002
18018
|
return;
|
|
18003
18019
|
case "fileChange": {
|
|
18004
|
-
const paths = (item.changes ?? []).map((change) => change.path).filter((
|
|
18020
|
+
const paths = (item.changes ?? []).map((change) => change.path).filter((path50) => !!path50);
|
|
18005
18021
|
this.fileChangePaths.set(item.id, paths);
|
|
18006
18022
|
if (this.startOpts?.kind === "task") {
|
|
18007
18023
|
for (const change of item.changes ?? []) this.announceFileChange(item.id, change, emit, subagentId);
|
|
@@ -18104,20 +18120,20 @@ ${this.exitMessage()}`);
|
|
|
18104
18120
|
announceFileChange(itemId, change, emit, subagentId) {
|
|
18105
18121
|
const rows = this.fileChangeRows.get(itemId) ?? /* @__PURE__ */ new Map();
|
|
18106
18122
|
this.fileChangeRows.set(itemId, rows);
|
|
18107
|
-
const
|
|
18108
|
-
const known = rows.get(
|
|
18123
|
+
const path50 = this.shownChangePath(change);
|
|
18124
|
+
const known = rows.get(path50);
|
|
18109
18125
|
if (known) return known;
|
|
18110
|
-
const row = rows.size === 0 ? itemId : `${itemId}:${
|
|
18111
|
-
rows.set(
|
|
18112
|
-
emit({ type: "tool_call", id: row, name: changeName(change), args: { path:
|
|
18126
|
+
const row = rows.size === 0 ? itemId : `${itemId}:${path50}`;
|
|
18127
|
+
rows.set(path50, row);
|
|
18128
|
+
emit({ type: "tool_call", id: row, name: changeName(change), args: { path: path50 }, ...subagentId ? { subagentId } : {} });
|
|
18113
18129
|
return row;
|
|
18114
18130
|
}
|
|
18115
18131
|
/** Relative to the task's worktree, where every path but a stray one lies; a move names both ends. */
|
|
18116
18132
|
shownChangePath(change) {
|
|
18117
|
-
const shown = (
|
|
18133
|
+
const shown = (path50) => {
|
|
18118
18134
|
const cwd = this.startOpts?.cwd;
|
|
18119
|
-
const rel = cwd ? (0, import_path6.relative)(cwd,
|
|
18120
|
-
return rel && rel !== ".." && !rel.startsWith(`..${import_path6.sep}`) && !(0, import_path6.isAbsolute)(rel) ? rel :
|
|
18135
|
+
const rel = cwd ? (0, import_path6.relative)(cwd, path50) : path50;
|
|
18136
|
+
return rel && rel !== ".." && !rel.startsWith(`..${import_path6.sep}`) && !(0, import_path6.isAbsolute)(rel) ? rel : path50;
|
|
18121
18137
|
};
|
|
18122
18138
|
const from = shown(change.path ?? "");
|
|
18123
18139
|
return change.kind?.move_path ? `${from} \u2192 ${shown(change.kind.move_path)}` : from;
|
|
@@ -18168,7 +18184,7 @@ var import_fs12 = require("fs");
|
|
|
18168
18184
|
|
|
18169
18185
|
// src/services/harness/projectServers.ts
|
|
18170
18186
|
var import_crypto8 = require("crypto");
|
|
18171
|
-
var
|
|
18187
|
+
var path25 = __toESM(require("path"));
|
|
18172
18188
|
function canonical2(value) {
|
|
18173
18189
|
if (Array.isArray(value)) return value.map(canonical2);
|
|
18174
18190
|
if (!isRecord2(value)) return value;
|
|
@@ -18179,7 +18195,7 @@ function projectServerScope(server4) {
|
|
|
18179
18195
|
return `mcp-server:${server4.name}@${hash}`;
|
|
18180
18196
|
}
|
|
18181
18197
|
var scopeName = (scope) => scope.slice(0, scope.lastIndexOf("@"));
|
|
18182
|
-
function fileProjectServerApprovals(file =
|
|
18198
|
+
function fileProjectServerApprovals(file = path25.join(globalDataDir(), "project-mcp-servers.json")) {
|
|
18183
18199
|
const load = () => {
|
|
18184
18200
|
const text6 = readText(file);
|
|
18185
18201
|
if (text6 === void 0) return {};
|
|
@@ -19342,8 +19358,8 @@ var OpenCodeAdapter = class extends ProcessLifecycle {
|
|
|
19342
19358
|
this.v2 = new OpenCodeV2({
|
|
19343
19359
|
version,
|
|
19344
19360
|
nativeShell: this.nativeShell?.prefix ?? null,
|
|
19345
|
-
request: (method,
|
|
19346
|
-
json: (method,
|
|
19361
|
+
request: (method, path50, body, signal, timeoutMs) => this.request(method, path50, body, signal, timeoutMs),
|
|
19362
|
+
json: (method, path50, body, signal, timeoutMs) => this.json(method, path50, body, signal, timeoutMs),
|
|
19347
19363
|
openEvents: (signal) => this.deps.fetch(`${this.baseUrl}/api/event`, { signal, headers: this.headers() }),
|
|
19348
19364
|
processEnded: this.processEnded,
|
|
19349
19365
|
isExited: () => this.exited,
|
|
@@ -19980,15 +19996,15 @@ var OpenCodeAdapter = class extends ProcessLifecycle {
|
|
|
19980
19996
|
onActivity
|
|
19981
19997
|
);
|
|
19982
19998
|
}
|
|
19983
|
-
async json(method,
|
|
19984
|
-
const response = await this.request(method,
|
|
19985
|
-
if (!response.ok) throw new OpenCodeHttpError(`${method} ${
|
|
19999
|
+
async json(method, path50, body, signal, timeoutMs) {
|
|
20000
|
+
const response = await this.request(method, path50, body, signal, timeoutMs);
|
|
20001
|
+
if (!response.ok) throw new OpenCodeHttpError(`${method} ${path50} failed: ${response.status} ${response.statusText}`);
|
|
19986
20002
|
return await response.json().catch(() => null);
|
|
19987
20003
|
}
|
|
19988
20004
|
/** `timeoutMs` null is for a turn's own POST, which the server answers when the turn is done. */
|
|
19989
|
-
request(method,
|
|
20005
|
+
request(method, path50, body, signal, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
19990
20006
|
const deadline = withDeadline(signal, timeoutMs);
|
|
19991
|
-
return this.deps.fetch(`${this.baseUrl}${
|
|
20007
|
+
return this.deps.fetch(`${this.baseUrl}${path50}`, {
|
|
19992
20008
|
method,
|
|
19993
20009
|
headers: this.headers({ "content-type": "application/json" }),
|
|
19994
20010
|
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
@@ -20049,8 +20065,8 @@ var OpenCodeAdapter = class extends ProcessLifecycle {
|
|
|
20049
20065
|
};
|
|
20050
20066
|
|
|
20051
20067
|
// src/services/harness/openCodeRepoConfig.ts
|
|
20052
|
-
var
|
|
20053
|
-
var CONFIG_FILES = ["opencode.json", "opencode.jsonc",
|
|
20068
|
+
var path26 = __toESM(require("path"));
|
|
20069
|
+
var CONFIG_FILES = ["opencode.json", "opencode.jsonc", path26.join(".opencode", "opencode.json"), path26.join(".opencode", "opencode.jsonc")];
|
|
20054
20070
|
var INSTRUCTION_NAMES = ["AGENTS.md", "CLAUDE.md", "CONTEXT.md"];
|
|
20055
20071
|
function server3(name, entry, source) {
|
|
20056
20072
|
if (!isRecord2(entry)) return "not an object";
|
|
@@ -20069,8 +20085,8 @@ var OPENCODE_REPO_CONFIG = {
|
|
|
20069
20085
|
const levels = repoLevels(workspace);
|
|
20070
20086
|
for (const name of INSTRUCTION_NAMES) {
|
|
20071
20087
|
const files = levels.flatMap((dir) => {
|
|
20072
|
-
const text6 = readText(
|
|
20073
|
-
return text6 === void 0 ? [] : [{ path:
|
|
20088
|
+
const text6 = readText(path26.join(dir, name));
|
|
20089
|
+
return text6 === void 0 ? [] : [{ path: path26.relative(workspace, path26.join(dir, name)) || name, text: text6 }];
|
|
20074
20090
|
});
|
|
20075
20091
|
if (files.length > 0) return files;
|
|
20076
20092
|
}
|
|
@@ -20082,10 +20098,10 @@ var OPENCODE_REPO_CONFIG = {
|
|
|
20082
20098
|
const unreadable = [];
|
|
20083
20099
|
for (const dir of repoLevels(workspace)) {
|
|
20084
20100
|
for (const name of CONFIG_FILES) {
|
|
20085
|
-
const file =
|
|
20101
|
+
const file = path26.join(dir, name);
|
|
20086
20102
|
const text6 = readText(file);
|
|
20087
20103
|
if (text6 === void 0) continue;
|
|
20088
|
-
const source =
|
|
20104
|
+
const source = path26.relative(workspace, file);
|
|
20089
20105
|
let parsed;
|
|
20090
20106
|
try {
|
|
20091
20107
|
parsed = parseJsonc(text6);
|
|
@@ -20274,7 +20290,7 @@ function knownModelId(value, optionIds, shortcuts) {
|
|
|
20274
20290
|
|
|
20275
20291
|
// src/services/ModelCatalog.ts
|
|
20276
20292
|
var fs6 = __toESM(require("fs"));
|
|
20277
|
-
var
|
|
20293
|
+
var path27 = __toESM(require("path"));
|
|
20278
20294
|
var CACHE_KEY = "model-catalog";
|
|
20279
20295
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
20280
20296
|
function storageKey(baseUrl) {
|
|
@@ -20327,7 +20343,7 @@ var ModelCatalog = class {
|
|
|
20327
20343
|
const url = (baseUrl || "https://openrouter.ai/api/v1").replace(/\/+$/, "");
|
|
20328
20344
|
const key = storageKey(url);
|
|
20329
20345
|
const cacheDir = globalCacheDir();
|
|
20330
|
-
const cacheFile =
|
|
20346
|
+
const cacheFile = path27.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
20331
20347
|
if (fs6.existsSync(cacheFile)) fs6.rmSync(cacheFile);
|
|
20332
20348
|
} catch {
|
|
20333
20349
|
}
|
|
@@ -20335,7 +20351,7 @@ var ModelCatalog = class {
|
|
|
20335
20351
|
static readCache(key) {
|
|
20336
20352
|
try {
|
|
20337
20353
|
const cacheDir = globalCacheDir();
|
|
20338
|
-
const cacheFile =
|
|
20354
|
+
const cacheFile = path27.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
20339
20355
|
if (!fs6.existsSync(cacheFile)) return null;
|
|
20340
20356
|
const raw = fs6.readFileSync(cacheFile, "utf8");
|
|
20341
20357
|
const data = JSON.parse(raw);
|
|
@@ -20349,7 +20365,7 @@ var ModelCatalog = class {
|
|
|
20349
20365
|
try {
|
|
20350
20366
|
const cacheDir = globalCacheDir();
|
|
20351
20367
|
fs6.mkdirSync(cacheDir, { recursive: true });
|
|
20352
|
-
const cacheFile =
|
|
20368
|
+
const cacheFile = path27.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
20353
20369
|
fs6.writeFileSync(
|
|
20354
20370
|
cacheFile,
|
|
20355
20371
|
JSON.stringify({ models, cachedAt: Date.now() }, null, 2)
|
|
@@ -20360,7 +20376,7 @@ var ModelCatalog = class {
|
|
|
20360
20376
|
};
|
|
20361
20377
|
|
|
20362
20378
|
// src/services/ModelDiscovery.ts
|
|
20363
|
-
var
|
|
20379
|
+
var path28 = __toESM(require("path"));
|
|
20364
20380
|
var import_child_process6 = require("child_process");
|
|
20365
20381
|
var import_util2 = require("util");
|
|
20366
20382
|
var fsSync5 = __toESM(require("fs"));
|
|
@@ -20506,7 +20522,7 @@ function geminiDiscoveryCacheKey(apiKey) {
|
|
|
20506
20522
|
return {
|
|
20507
20523
|
key: `gemini-models:${hash}`,
|
|
20508
20524
|
dir,
|
|
20509
|
-
file:
|
|
20525
|
+
file: path28.join(dir, `gemini_models_${hash}.json`)
|
|
20510
20526
|
};
|
|
20511
20527
|
}
|
|
20512
20528
|
function readGeminiCache(apiKey) {
|
|
@@ -21014,7 +21030,7 @@ function parseMaxParallel(value) {
|
|
|
21014
21030
|
|
|
21015
21031
|
// src/services/SettingsService.ts
|
|
21016
21032
|
var fs12 = __toESM(require("fs"));
|
|
21017
|
-
var
|
|
21033
|
+
var path35 = __toESM(require("path"));
|
|
21018
21034
|
|
|
21019
21035
|
// src/utils/fileLock.ts
|
|
21020
21036
|
var fs7 = __toESM(require("fs"));
|
|
@@ -23066,33 +23082,33 @@ ${skillBlock(entry.skill)}`, timestamp: entry.timestamp });
|
|
|
23066
23082
|
}
|
|
23067
23083
|
|
|
23068
23084
|
// src/services/taskSkills.ts
|
|
23069
|
-
var
|
|
23085
|
+
var path34 = __toESM(require("path"));
|
|
23070
23086
|
|
|
23071
23087
|
// src/services/SkillsService.ts
|
|
23072
23088
|
var import_crypto12 = require("crypto");
|
|
23073
23089
|
var fs11 = __toESM(require("fs"));
|
|
23074
|
-
var
|
|
23090
|
+
var path33 = __toESM(require("path"));
|
|
23075
23091
|
|
|
23076
23092
|
// src/services/builtinSkills.ts
|
|
23077
|
-
var
|
|
23093
|
+
var path29 = __toESM(require("path"));
|
|
23078
23094
|
var import_url = require("url");
|
|
23079
23095
|
function builtinSkillsDir() {
|
|
23080
|
-
const dir = typeof __dirname !== "undefined" && __dirname ? __dirname :
|
|
23096
|
+
const dir = typeof __dirname !== "undefined" && __dirname ? __dirname : path29.dirname((0, import_url.fileURLToPath)(
|
|
23081
23097
|
// @ts-expect-error - import.meta is only valid under an ESM module setting
|
|
23082
23098
|
__filename
|
|
23083
23099
|
));
|
|
23084
|
-
return
|
|
23100
|
+
return path29.join(dir, "..", "skills");
|
|
23085
23101
|
}
|
|
23086
23102
|
|
|
23087
23103
|
// src/services/repoGroup.ts
|
|
23088
23104
|
var fs10 = __toESM(require("fs"));
|
|
23089
|
-
var
|
|
23105
|
+
var path32 = __toESM(require("path"));
|
|
23090
23106
|
|
|
23091
23107
|
// src/services/worktreeBootstrap.ts
|
|
23092
23108
|
var import_child_process8 = require("child_process");
|
|
23093
23109
|
var import_util4 = require("util");
|
|
23094
23110
|
var fs9 = __toESM(require("fs"));
|
|
23095
|
-
var
|
|
23111
|
+
var path31 = __toESM(require("path"));
|
|
23096
23112
|
|
|
23097
23113
|
// src/services/gitExec.ts
|
|
23098
23114
|
var import_child_process7 = require("child_process");
|
|
@@ -23174,7 +23190,7 @@ function subcommandOf2(args) {
|
|
|
23174
23190
|
|
|
23175
23191
|
// src/services/worktreeLink.ts
|
|
23176
23192
|
var fs8 = __toESM(require("fs"));
|
|
23177
|
-
var
|
|
23193
|
+
var path30 = __toESM(require("path"));
|
|
23178
23194
|
function linkPath(source, target, platform, hardLink = fs8.linkSync) {
|
|
23179
23195
|
const isDir = fs8.statSync(source).isDirectory();
|
|
23180
23196
|
if (platform !== "win32") {
|
|
@@ -23199,8 +23215,8 @@ function mirrorDir(source, target, opts) {
|
|
|
23199
23215
|
const mirror = (from, to, prefix, top) => {
|
|
23200
23216
|
fs8.mkdirSync(to, { recursive: true });
|
|
23201
23217
|
for (const entry of fs8.readdirSync(from, { withFileTypes: true })) {
|
|
23202
|
-
const name =
|
|
23203
|
-
const at = { from:
|
|
23218
|
+
const name = path30.join(prefix, entry.name);
|
|
23219
|
+
const at = { from: path30.join(from, entry.name), to: path30.join(to, entry.name), name };
|
|
23204
23220
|
if (entry.isSymbolicLink()) links.push(at);
|
|
23205
23221
|
else if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin")) mirror(at.from, at.to, name, false);
|
|
23206
23222
|
else if (linkPath(at.from, at.to, opts.platform, opts.hardLink) === "copy") copied.push(name);
|
|
@@ -23220,16 +23236,16 @@ function mirrorDir(source, target, opts) {
|
|
|
23220
23236
|
}
|
|
23221
23237
|
function relink(from, to, opts) {
|
|
23222
23238
|
const text6 = fs8.readlinkSync(from);
|
|
23223
|
-
const pointee =
|
|
23239
|
+
const pointee = path30.isAbsolute(text6) ? rebased(text6, opts) : text6;
|
|
23224
23240
|
if (opts.platform !== "win32") {
|
|
23225
|
-
if (!fs8.existsSync(
|
|
23226
|
-
fs8.symlinkSync(rebased(
|
|
23241
|
+
if (!fs8.existsSync(path30.resolve(path30.dirname(to), pointee)) && fs8.existsSync(path30.resolve(path30.dirname(from), pointee))) {
|
|
23242
|
+
fs8.symlinkSync(rebased(path30.resolve(path30.dirname(from), pointee), opts), to);
|
|
23227
23243
|
return "symlink";
|
|
23228
23244
|
}
|
|
23229
23245
|
fs8.symlinkSync(pointee, to);
|
|
23230
23246
|
return "symlink";
|
|
23231
23247
|
}
|
|
23232
|
-
const resolved = fs8.existsSync(
|
|
23248
|
+
const resolved = fs8.existsSync(path30.resolve(path30.dirname(to), pointee)) ? path30.resolve(path30.dirname(to), pointee) : rebased(path30.resolve(path30.dirname(from), pointee), opts);
|
|
23233
23249
|
try {
|
|
23234
23250
|
fs8.statSync(resolved);
|
|
23235
23251
|
} catch {
|
|
@@ -23238,9 +23254,9 @@ function relink(from, to, opts) {
|
|
|
23238
23254
|
return linkPath(resolved, to, opts.platform, opts.hardLink);
|
|
23239
23255
|
}
|
|
23240
23256
|
function rebased(pointee, opts) {
|
|
23241
|
-
const rel =
|
|
23242
|
-
const inside2 = rel !== "" && !rel.startsWith("..") && !
|
|
23243
|
-
return inside2 && !rel.split(/[\\/]/).includes("node_modules") ?
|
|
23257
|
+
const rel = path30.relative(opts.from, pointee);
|
|
23258
|
+
const inside2 = rel !== "" && !rel.startsWith("..") && !path30.isAbsolute(rel);
|
|
23259
|
+
return inside2 && !rel.split(/[\\/]/).includes("node_modules") ? path30.join(opts.to, rel) : pointee;
|
|
23244
23260
|
}
|
|
23245
23261
|
|
|
23246
23262
|
// src/services/worktreeBootstrap.ts
|
|
@@ -23277,18 +23293,18 @@ function matchLinks(root, patterns) {
|
|
|
23277
23293
|
}
|
|
23278
23294
|
function segmentMatches(root, base, segment) {
|
|
23279
23295
|
const under = (name) => base ? `${base}/${name}` : name;
|
|
23280
|
-
if (!/[*?]/.test(segment)) return lexists(
|
|
23296
|
+
if (!/[*?]/.test(segment)) return lexists(path31.join(root, base, segment)) ? [under(segment)] : [];
|
|
23281
23297
|
const pattern = new RegExp(`^${segment.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
|
|
23282
|
-
return listDir2(
|
|
23298
|
+
return listDir2(path31.join(root, base)).filter((name) => !NEVER_SCANNED.has(name) && pattern.test(name)).map(under);
|
|
23283
23299
|
}
|
|
23284
23300
|
function installDirs(root) {
|
|
23285
23301
|
const packages = matchLinks(root, workspaceGlobs(root)).map((pkg) => `${pkg}/node_modules`);
|
|
23286
|
-
return ["node_modules", ...packages].filter((dir) => lexists(
|
|
23302
|
+
return ["node_modules", ...packages].filter((dir) => lexists(path31.join(root, dir)));
|
|
23287
23303
|
}
|
|
23288
23304
|
function workspaceGlobs(root) {
|
|
23289
23305
|
let manifest;
|
|
23290
23306
|
try {
|
|
23291
|
-
manifest = JSON.parse(fs9.readFileSync(
|
|
23307
|
+
manifest = JSON.parse(fs9.readFileSync(path31.join(root, "package.json"), "utf8"));
|
|
23292
23308
|
} catch {
|
|
23293
23309
|
return [];
|
|
23294
23310
|
}
|
|
@@ -23303,19 +23319,19 @@ async function bootstrap(repo, cwd, opts) {
|
|
|
23303
23319
|
const linked = [];
|
|
23304
23320
|
const copied = [];
|
|
23305
23321
|
const link = (name) => {
|
|
23306
|
-
const target =
|
|
23322
|
+
const target = path31.join(cwd, name);
|
|
23307
23323
|
if (lexists(target)) return;
|
|
23308
|
-
fs9.mkdirSync(
|
|
23309
|
-
if (linkPath(
|
|
23324
|
+
fs9.mkdirSync(path31.dirname(target), { recursive: true });
|
|
23325
|
+
if (linkPath(path31.join(repo.root, name), target, opts.platform) === "copy") copied.push(name);
|
|
23310
23326
|
linked.push(name);
|
|
23311
23327
|
};
|
|
23312
23328
|
const mirror = (name) => {
|
|
23313
|
-
const target =
|
|
23314
|
-
if (lexists(target) || !fs9.existsSync(
|
|
23315
|
-
const source =
|
|
23329
|
+
const target = path31.join(cwd, name);
|
|
23330
|
+
if (lexists(target) || !fs9.existsSync(path31.dirname(target))) return;
|
|
23331
|
+
const source = path31.join(repo.root, name);
|
|
23316
23332
|
if (!fs9.lstatSync(source).isDirectory()) return link(name);
|
|
23317
23333
|
const mirrored = mirrorDir(source, target, { platform: opts.platform, from: repo.root, to: cwd });
|
|
23318
|
-
copied.push(...mirrored.map((entry) =>
|
|
23334
|
+
copied.push(...mirrored.map((entry) => path31.join(name, entry)));
|
|
23319
23335
|
linked.push(name);
|
|
23320
23336
|
};
|
|
23321
23337
|
if (!setup) {
|
|
@@ -23350,12 +23366,12 @@ async function runSetup(command, repo, cwd, resolvePath) {
|
|
|
23350
23366
|
|
|
23351
23367
|
// src/services/repoGroup.ts
|
|
23352
23368
|
function hasGitEntry(dir) {
|
|
23353
|
-
return fs10.existsSync(
|
|
23369
|
+
return fs10.existsSync(path32.join(dir, ".git"));
|
|
23354
23370
|
}
|
|
23355
23371
|
function groupPathOf(listed3) {
|
|
23356
23372
|
const slashed = listed3.trim().replace(/\\/g, "/");
|
|
23357
|
-
if (
|
|
23358
|
-
const rel =
|
|
23373
|
+
if (path32.posix.isAbsolute(slashed) || path32.win32.isAbsolute(slashed)) return null;
|
|
23374
|
+
const rel = path32.posix.normalize(slashed).replace(/\/+$/, "");
|
|
23359
23375
|
return rel === "" || rel === "." || rel === ".." || rel.startsWith("../") ? null : rel;
|
|
23360
23376
|
}
|
|
23361
23377
|
function childDirs(dir) {
|
|
@@ -23366,14 +23382,14 @@ function childDirs(dir) {
|
|
|
23366
23382
|
}
|
|
23367
23383
|
}
|
|
23368
23384
|
function groupPaths(workspaceRoot, listed3) {
|
|
23369
|
-
if (listed3.length === 0) return childDirs(workspaceRoot).filter((name) => hasGitEntry(
|
|
23370
|
-
const paths = listed3.map(groupPathOf).filter((rel) => rel !== null && hasGitEntry(
|
|
23385
|
+
if (listed3.length === 0) return childDirs(workspaceRoot).filter((name) => hasGitEntry(path32.join(workspaceRoot, name)));
|
|
23386
|
+
const paths = listed3.map(groupPathOf).filter((rel) => rel !== null && hasGitEntry(path32.join(workspaceRoot, rel)));
|
|
23371
23387
|
return [...new Set(paths)].sort();
|
|
23372
23388
|
}
|
|
23373
23389
|
function workspaceRepoGroup(workspaceRoot, listed3) {
|
|
23374
|
-
for (let dir =
|
|
23390
|
+
for (let dir = path32.resolve(workspaceRoot); ; dir = path32.dirname(dir)) {
|
|
23375
23391
|
if (hasGitEntry(dir)) return [SELF_REPO];
|
|
23376
|
-
if (
|
|
23392
|
+
if (path32.dirname(dir) === dir) break;
|
|
23377
23393
|
}
|
|
23378
23394
|
return groupPaths(workspaceRoot, listed3);
|
|
23379
23395
|
}
|
|
@@ -23454,8 +23470,8 @@ function copyDirSync(src, dest) {
|
|
|
23454
23470
|
fs11.mkdirSync(dest, { recursive: true });
|
|
23455
23471
|
const entries = fs11.readdirSync(src, { withFileTypes: true });
|
|
23456
23472
|
for (const entry of entries) {
|
|
23457
|
-
const srcPath =
|
|
23458
|
-
const destPath =
|
|
23473
|
+
const srcPath = path33.join(src, entry.name);
|
|
23474
|
+
const destPath = path33.join(dest, entry.name);
|
|
23459
23475
|
if (entry.isDirectory()) copyDirSync(srcPath, destPath);
|
|
23460
23476
|
else fs11.copyFileSync(srcPath, destPath);
|
|
23461
23477
|
}
|
|
@@ -23479,7 +23495,7 @@ function readDir(dir, source) {
|
|
|
23479
23495
|
if (!fs11.existsSync(dir)) return { skills, invalid };
|
|
23480
23496
|
for (const entry of fs11.readdirSync(dir, { withFileTypes: true })) {
|
|
23481
23497
|
if (!entry.isDirectory()) continue;
|
|
23482
|
-
const skillFile =
|
|
23498
|
+
const skillFile = path33.join(dir, entry.name, "SKILL.md");
|
|
23483
23499
|
if (!fs11.existsSync(skillFile)) continue;
|
|
23484
23500
|
if (!isSkillName(entry.name)) {
|
|
23485
23501
|
invalid.push({ name: entry.name, path: skillFile, source, reason: INVALID_SKILL_NAME_REASON });
|
|
@@ -23498,15 +23514,15 @@ function skillFileIn(dir, name) {
|
|
|
23498
23514
|
return void 0;
|
|
23499
23515
|
}
|
|
23500
23516
|
if (!entries.some((entry) => entry.isDirectory() && entry.name === name)) return void 0;
|
|
23501
|
-
const skillFile =
|
|
23517
|
+
const skillFile = path33.join(dir, name, "SKILL.md");
|
|
23502
23518
|
return fs11.existsSync(skillFile) ? skillFile : void 0;
|
|
23503
23519
|
}
|
|
23504
23520
|
function skillsDirOf(root) {
|
|
23505
|
-
return
|
|
23521
|
+
return path33.join(root, STATE_DIR, "skills");
|
|
23506
23522
|
}
|
|
23507
23523
|
function workspaceSkillRoots(workspaceRoot, repos, checkout = workspaceRoot) {
|
|
23508
23524
|
if (repos.length === 0 || repos.includes(SELF_REPO)) return [checkout];
|
|
23509
|
-
return [workspaceRoot, ...repos.map((repo) =>
|
|
23525
|
+
return [workspaceRoot, ...repos.map((repo) => path33.join(checkout, repo))];
|
|
23510
23526
|
}
|
|
23511
23527
|
var SkillsService = class _SkillsService {
|
|
23512
23528
|
workspaceRoots;
|
|
@@ -23529,11 +23545,11 @@ var SkillsService = class _SkillsService {
|
|
|
23529
23545
|
return this.workspaceRoots.map(skillsDirOf);
|
|
23530
23546
|
}
|
|
23531
23547
|
globalDir() {
|
|
23532
|
-
return
|
|
23548
|
+
return path33.join(globalDataDir(), "skills");
|
|
23533
23549
|
}
|
|
23534
23550
|
readSeedManifest() {
|
|
23535
23551
|
try {
|
|
23536
|
-
const parsed = JSON.parse(fs11.readFileSync(
|
|
23552
|
+
const parsed = JSON.parse(fs11.readFileSync(path33.join(this.globalDir(), SEED_MANIFEST), "utf8"));
|
|
23537
23553
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
23538
23554
|
return Object.fromEntries(
|
|
23539
23555
|
Object.entries(parsed).filter((entry) => typeof entry[1] === "string")
|
|
@@ -23549,7 +23565,7 @@ var SkillsService = class _SkillsService {
|
|
|
23549
23565
|
manifest[name] = hash;
|
|
23550
23566
|
try {
|
|
23551
23567
|
fs11.mkdirSync(this.globalDir(), { recursive: true });
|
|
23552
|
-
fs11.writeFileSync(
|
|
23568
|
+
fs11.writeFileSync(path33.join(this.globalDir(), SEED_MANIFEST), JSON.stringify(manifest, null, 2));
|
|
23553
23569
|
} catch (err) {
|
|
23554
23570
|
console.warn(`Could not record seeded skill ${name}: ${String(err)}`);
|
|
23555
23571
|
}
|
|
@@ -23560,11 +23576,11 @@ var SkillsService = class _SkillsService {
|
|
|
23560
23576
|
return this.readSeedManifest()[name] === currentHash || (PRIOR_BUILTIN_HASHES[name] ?? []).includes(currentHash);
|
|
23561
23577
|
}
|
|
23562
23578
|
seed(name) {
|
|
23563
|
-
const dest =
|
|
23579
|
+
const dest = path33.join(this.globalDir(), name);
|
|
23564
23580
|
const exists = fs11.existsSync(dest);
|
|
23565
23581
|
let srcDir;
|
|
23566
23582
|
try {
|
|
23567
|
-
srcDir =
|
|
23583
|
+
srcDir = path33.join(builtinSkillsDir(), name);
|
|
23568
23584
|
} catch (err) {
|
|
23569
23585
|
if (!exists) console.warn(`Could not locate built-in skills dir: ${String(err)}`);
|
|
23570
23586
|
return false;
|
|
@@ -23573,9 +23589,9 @@ var SkillsService = class _SkillsService {
|
|
|
23573
23589
|
if (!exists) console.warn(`Built-in skill not found in package: ${name}`);
|
|
23574
23590
|
return false;
|
|
23575
23591
|
}
|
|
23576
|
-
const srcHash = fileHash(
|
|
23592
|
+
const srcHash = fileHash(path33.join(srcDir, "SKILL.md"));
|
|
23577
23593
|
if (exists) {
|
|
23578
|
-
const currentHash = fileHash(
|
|
23594
|
+
const currentHash = fileHash(path33.join(dest, "SKILL.md"));
|
|
23579
23595
|
if (currentHash !== void 0 && currentHash === srcHash) {
|
|
23580
23596
|
this.recordSeed(name, currentHash);
|
|
23581
23597
|
return false;
|
|
@@ -23619,7 +23635,7 @@ var SkillsService = class _SkillsService {
|
|
|
23619
23635
|
if (entries.length !== 1 || entries[0].name !== "SKILL.md" || !entries[0].isFile()) return false;
|
|
23620
23636
|
let raw;
|
|
23621
23637
|
try {
|
|
23622
|
-
raw = readSkillText(
|
|
23638
|
+
raw = readSkillText(path33.join(dir, "SKILL.md"));
|
|
23623
23639
|
} catch {
|
|
23624
23640
|
return false;
|
|
23625
23641
|
}
|
|
@@ -23627,7 +23643,7 @@ var SkillsService = class _SkillsService {
|
|
|
23627
23643
|
}
|
|
23628
23644
|
pruneRetired() {
|
|
23629
23645
|
for (const name of RETIRED_BUILTIN_SKILL_NAMES) {
|
|
23630
|
-
const dest =
|
|
23646
|
+
const dest = path33.join(this.globalDir(), name);
|
|
23631
23647
|
if (!fs11.existsSync(dest)) continue;
|
|
23632
23648
|
if (!this.isUnmodifiedRetiredSeed(dest, name)) continue;
|
|
23633
23649
|
try {
|
|
@@ -23765,12 +23781,12 @@ var runGit = execFileWithTimeout(1e4);
|
|
|
23765
23781
|
async function committedInHead(files) {
|
|
23766
23782
|
const byDir = /* @__PURE__ */ new Map();
|
|
23767
23783
|
for (const file of new Set(files)) {
|
|
23768
|
-
const dir =
|
|
23784
|
+
const dir = path34.dirname(path34.dirname(file));
|
|
23769
23785
|
byDir.set(dir, [...byDir.get(dir) ?? [], file]);
|
|
23770
23786
|
}
|
|
23771
23787
|
const result = /* @__PURE__ */ new Map();
|
|
23772
23788
|
await Promise.all([...byDir].map(async ([dir, inDir]) => {
|
|
23773
|
-
const relative17 = (file) =>
|
|
23789
|
+
const relative17 = (file) => path34.relative(dir, file).split(path34.sep).join("/");
|
|
23774
23790
|
try {
|
|
23775
23791
|
const { stdout } = await runGit("git", ["ls-tree", "--name-only", "HEAD", "--", ...inDir.map(relative17)], { cwd: dir, env: cleanEnv() });
|
|
23776
23792
|
const listed3 = new Set(stdout.split("\n").map((line) => line.trim()).filter(Boolean));
|
|
@@ -23790,9 +23806,9 @@ function plannedSkillLookup(skillsAt, workspaceRoot, layout) {
|
|
|
23790
23806
|
searchedDirs: () => lookup2.searchedDirs(),
|
|
23791
23807
|
listSkills: () => lookup2.listSkills(),
|
|
23792
23808
|
uncommitted: async (skills) => {
|
|
23793
|
-
const checked = skills.filter((skill) => skill.source === "workspace" && !(readInPlace &&
|
|
23809
|
+
const checked = skills.filter((skill) => skill.source === "workspace" && !(readInPlace && path34.dirname(path34.dirname(skill.path)) === readInPlace));
|
|
23794
23810
|
const committed = await committedInHead(checked.map((skill) => skill.path));
|
|
23795
|
-
return new Map(checked.filter((skill) => committed.get(skill.path) === false).map((skill) => [skill.path,
|
|
23811
|
+
return new Map(checked.filter((skill) => committed.get(skill.path) === false).map((skill) => [skill.path, path34.relative(workspaceRoot, path34.dirname(skill.path)).split(path34.sep).join("/")]));
|
|
23796
23812
|
}
|
|
23797
23813
|
};
|
|
23798
23814
|
}
|
|
@@ -23805,13 +23821,13 @@ function checkPlanSkills(tasks, lookup2) {
|
|
|
23805
23821
|
function checkTaskSkillsEdit(task2, skills, lookup2) {
|
|
23806
23822
|
return check([{ taskId: task2.id, owner: `Task "${task2.title}"`, ...attached(skills) }], lookup2);
|
|
23807
23823
|
}
|
|
23808
|
-
function subtaskEntries(op, spec,
|
|
23824
|
+
function subtaskEntries(op, spec, path50 = []) {
|
|
23809
23825
|
const subtasks = spec?.subtasks;
|
|
23810
23826
|
if (!Array.isArray(subtasks)) return [];
|
|
23811
23827
|
return subtasks.flatMap((sub, i) => {
|
|
23812
23828
|
if (typeof sub !== "object" || sub === null) return [];
|
|
23813
23829
|
const child = sub;
|
|
23814
|
-
const at = [...
|
|
23830
|
+
const at = [...path50, typeof child.title === "string" && child.title.trim() ? `"${child.title}"` : `#${i + 1}`];
|
|
23815
23831
|
return [{ op, owner: `subtask ${at.join(" > ")}`, ...attached(child.skills) }, ...subtaskEntries(op, child, at)];
|
|
23816
23832
|
});
|
|
23817
23833
|
}
|
|
@@ -27681,7 +27697,7 @@ var RUN_SETTING_KEYS = Object.keys(RUN_SETTING_CHECKS);
|
|
|
27681
27697
|
function getSettingsPath() {
|
|
27682
27698
|
const override = process.env.ORDEWELL_SETTINGS_PATH;
|
|
27683
27699
|
if (override && override.trim()) return override.trim();
|
|
27684
|
-
return
|
|
27700
|
+
return path35.join(globalDataDir(), "settings.json");
|
|
27685
27701
|
}
|
|
27686
27702
|
function readPlannerModels(raw) {
|
|
27687
27703
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
@@ -27761,8 +27777,8 @@ var SettingsService = class {
|
|
|
27761
27777
|
* a watch on the old one pointing at nothing.
|
|
27762
27778
|
*/
|
|
27763
27779
|
watch(listener) {
|
|
27764
|
-
const dir =
|
|
27765
|
-
const name =
|
|
27780
|
+
const dir = path35.dirname(this.filePath);
|
|
27781
|
+
const name = path35.basename(this.filePath);
|
|
27766
27782
|
let seen = this.fileStamp();
|
|
27767
27783
|
let timer;
|
|
27768
27784
|
let dead = false;
|
|
@@ -27771,7 +27787,7 @@ var SettingsService = class {
|
|
|
27771
27787
|
fs12.mkdirSync(dir, { recursive: true });
|
|
27772
27788
|
watcher = fs12.watch(dir, (_event, changed) => {
|
|
27773
27789
|
if (dead) return;
|
|
27774
|
-
if (changed && changed !== name && changed !==
|
|
27790
|
+
if (changed && changed !== name && changed !== path35.basename(dir)) return;
|
|
27775
27791
|
clearTimeout(timer);
|
|
27776
27792
|
timer = setTimeout(() => {
|
|
27777
27793
|
const stamp2 = this.fileStamp();
|
|
@@ -28004,7 +28020,7 @@ var SettingsService = class {
|
|
|
28004
28020
|
if (this.unreadable) {
|
|
28005
28021
|
throw new Error(`Cannot save settings: ${this.filePath} could not be read, so it will not be overwritten. Fix or remove it and try again.`);
|
|
28006
28022
|
}
|
|
28007
|
-
const dir =
|
|
28023
|
+
const dir = path35.dirname(this.filePath);
|
|
28008
28024
|
if (!fs12.existsSync(dir)) {
|
|
28009
28025
|
fs12.mkdirSync(dir, { recursive: true });
|
|
28010
28026
|
}
|
|
@@ -28606,11 +28622,11 @@ function mergeOutcome(result, branch, group, repaired = []) {
|
|
|
28606
28622
|
// src/services/taskDiffRead.ts
|
|
28607
28623
|
var import_crypto13 = require("crypto");
|
|
28608
28624
|
var fs13 = __toESM(require("fs"));
|
|
28609
|
-
var
|
|
28625
|
+
var path36 = __toESM(require("path"));
|
|
28610
28626
|
var import_os3 = require("os");
|
|
28611
28627
|
var TASK_DIFF_UNAVAILABLE = "Task diff is not available for this run: no task-specific changes were recorded (shared runs cannot attribute workspace changes to one task).";
|
|
28612
28628
|
function allowedPath(file) {
|
|
28613
|
-
return file.length > 0 && !
|
|
28629
|
+
return file.length > 0 && !path36.isAbsolute(file) && !/^[A-Za-z]:/.test(file) && !file.split(/[\\/]/).some((part) => part === ".." || part === ".git" || part === ".ordewell");
|
|
28614
28630
|
}
|
|
28615
28631
|
function stats(raw) {
|
|
28616
28632
|
return raw.split("\0").flatMap((row) => {
|
|
@@ -28619,8 +28635,8 @@ function stats(raw) {
|
|
|
28619
28635
|
});
|
|
28620
28636
|
}
|
|
28621
28637
|
function inside(root, target) {
|
|
28622
|
-
const rel =
|
|
28623
|
-
return rel === "" || !rel.startsWith(`..${
|
|
28638
|
+
const rel = path36.relative(root, target);
|
|
28639
|
+
return rel === "" || !rel.startsWith(`..${path36.sep}`) && rel !== ".." && !path36.isAbsolute(rel);
|
|
28624
28640
|
}
|
|
28625
28641
|
function unquoted(quoted4) {
|
|
28626
28642
|
const bytes = [];
|
|
@@ -28668,10 +28684,10 @@ function patchFiles(patch) {
|
|
|
28668
28684
|
const sections = patch.toString("utf8").split(/(?<![^\n])(?=diff --git )/).filter((section) => section.startsWith("diff --git "));
|
|
28669
28685
|
const files = /* @__PURE__ */ new Map();
|
|
28670
28686
|
for (const section of sections) {
|
|
28671
|
-
const
|
|
28687
|
+
const path50 = sectionPath(section);
|
|
28672
28688
|
const counts = sectionStats(section);
|
|
28673
|
-
const earlier = files.get(
|
|
28674
|
-
files.set(
|
|
28689
|
+
const earlier = files.get(path50);
|
|
28690
|
+
files.set(path50, earlier ? { path: path50, section: earlier.section + section, added: summed(earlier.added, counts.added), removed: summed(earlier.removed, counts.removed) } : { path: path50, section, ...counts });
|
|
28675
28691
|
}
|
|
28676
28692
|
return [...files.values()];
|
|
28677
28693
|
}
|
|
@@ -28741,11 +28757,11 @@ async function readTaskDiff(invoker, run, taskId, options) {
|
|
|
28741
28757
|
files.push({ ...file, repo: repo.path, patch: () => git(reader, cwd, [...diffArgs, "--", `:(top,literal)${prefix}${file.path}`]) });
|
|
28742
28758
|
}
|
|
28743
28759
|
if (live3) {
|
|
28744
|
-
const workspace =
|
|
28760
|
+
const workspace = path36.join(entry.worktree, prefix);
|
|
28745
28761
|
const others = await git(reader, workspace, [...common, "ls-files", "--others", "--exclude-standard", "-z", "--", "."]);
|
|
28746
28762
|
for (const file of others.split("\0").filter((f) => allowed(f))) {
|
|
28747
|
-
const full =
|
|
28748
|
-
if (!inside(fs13.realpathSync(workspace), fs13.realpathSync(
|
|
28763
|
+
const full = path36.join(workspace, file);
|
|
28764
|
+
if (!inside(fs13.realpathSync(workspace), fs13.realpathSync(path36.dirname(full)))) continue;
|
|
28749
28765
|
const untracked = async (numstat) => {
|
|
28750
28766
|
const result = await tryGit(reader, workspace, [...common, "diff", "--no-index", "--no-renames", "--no-ext-diff", "--no-textconv", ...numstat ? ["--numstat", "-z"] : [], "--", import_os3.devNull, file]);
|
|
28751
28767
|
if (!result.ok && result.code !== 1) throw new Error(result.stderr.trim() || "Could not read an untracked file diff.");
|
|
@@ -28775,11 +28791,11 @@ ${await file.patch()}`);
|
|
|
28775
28791
|
var import_crypto14 = require("crypto");
|
|
28776
28792
|
var import_child_process9 = require("child_process");
|
|
28777
28793
|
var fs15 = __toESM(require("fs"));
|
|
28778
|
-
var
|
|
28794
|
+
var path38 = __toESM(require("path"));
|
|
28779
28795
|
|
|
28780
28796
|
// src/utils/prdStore.ts
|
|
28781
28797
|
var fs14 = __toESM(require("fs"));
|
|
28782
|
-
var
|
|
28798
|
+
var path37 = __toESM(require("path"));
|
|
28783
28799
|
var PRD_BLOCK_RE = /<!--\s*ORDEWELL_PRD_START\s+slug="([^"]+)"\s*-->\s*([\s\S]*?)\s*<!--\s*ORDEWELL_PRD_END\s*-->/;
|
|
28784
28800
|
function extractPrdBlock(text6) {
|
|
28785
28801
|
const match = PRD_BLOCK_RE.exec(text6);
|
|
@@ -28793,9 +28809,9 @@ function sanitizeSlug(raw) {
|
|
|
28793
28809
|
return raw.toLowerCase().replace(/[^a-z0-9-_]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
28794
28810
|
}
|
|
28795
28811
|
function savePrdMarkdown(workspace, slug, markdown) {
|
|
28796
|
-
const dir =
|
|
28812
|
+
const dir = path37.join(workspace, ".scratch", sanitizeSlug(slug));
|
|
28797
28813
|
fs14.mkdirSync(dir, { recursive: true });
|
|
28798
|
-
const file =
|
|
28814
|
+
const file = path37.join(dir, "PRD.md");
|
|
28799
28815
|
fs14.writeFileSync(file, markdown.endsWith("\n") ? markdown : markdown + "\n", "utf8");
|
|
28800
28816
|
return file;
|
|
28801
28817
|
}
|
|
@@ -28827,12 +28843,12 @@ var NESTED_REPO_DEPTH = 2;
|
|
|
28827
28843
|
var GITLINK_MODE = "160000";
|
|
28828
28844
|
var READ_ONLY = ["--no-optional-locks", "-c", "core.fsmonitor=false"];
|
|
28829
28845
|
function isInside(parent, child) {
|
|
28830
|
-
const rel =
|
|
28831
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
28846
|
+
const rel = path38.relative(parent, child);
|
|
28847
|
+
return rel !== "" && !rel.startsWith("..") && !path38.isAbsolute(rel);
|
|
28832
28848
|
}
|
|
28833
28849
|
function resolvesAsNamed(base, p) {
|
|
28834
28850
|
try {
|
|
28835
|
-
return fs15.realpathSync(p) ===
|
|
28851
|
+
return fs15.realpathSync(p) === path38.join(fs15.realpathSync(base), path38.relative(base, p));
|
|
28836
28852
|
} catch {
|
|
28837
28853
|
return false;
|
|
28838
28854
|
}
|
|
@@ -28887,7 +28903,7 @@ function sameDir(a, b) {
|
|
|
28887
28903
|
try {
|
|
28888
28904
|
return fs15.realpathSync.native(p);
|
|
28889
28905
|
} catch {
|
|
28890
|
-
return
|
|
28906
|
+
return path38.resolve(p);
|
|
28891
28907
|
}
|
|
28892
28908
|
};
|
|
28893
28909
|
return real(a) === real(b);
|
|
@@ -28909,7 +28925,7 @@ function clearImmutableFlags(platform, dir) {
|
|
|
28909
28925
|
(0, import_child_process9.spawnSync)("/usr/bin/chflags", ["-R", "nouchg", dir], { stdio: "ignore" });
|
|
28910
28926
|
}
|
|
28911
28927
|
function leftoverLinks(dir) {
|
|
28912
|
-
const named3 = listDir2(dir).filter((name) => LINKED_ARTIFACTS.has(name) || isEnvFile(name) || isLink(
|
|
28928
|
+
const named3 = listDir2(dir).filter((name) => LINKED_ARTIFACTS.has(name) || isEnvFile(name) || isLink(path38.join(dir, name)));
|
|
28913
28929
|
return [.../* @__PURE__ */ new Set([...named3, ...installDirs(dir)])];
|
|
28914
28930
|
}
|
|
28915
28931
|
function isLink(target) {
|
|
@@ -28982,7 +28998,7 @@ var GitWorktreeIsolation = class {
|
|
|
28982
28998
|
const head = await this.headOf(root);
|
|
28983
28999
|
const repo = { path: repoPath, head };
|
|
28984
29000
|
if (scan.toplevel !== void 0) {
|
|
28985
|
-
const top =
|
|
29001
|
+
const top = path38.relative(workspaceRoot, scan.toplevel).split(path38.sep).join("/");
|
|
28986
29002
|
if (top !== "") repo.top = top;
|
|
28987
29003
|
}
|
|
28988
29004
|
if (enabled && (head.kind === "branch" || head.kind === "detached")) {
|
|
@@ -29039,9 +29055,9 @@ var GitWorktreeIsolation = class {
|
|
|
29039
29055
|
async nestedRepos(workspaceRoot, toplevel) {
|
|
29040
29056
|
const found = [];
|
|
29041
29057
|
const walk = (rel, depth) => {
|
|
29042
|
-
for (const name of childDirs(
|
|
29058
|
+
for (const name of childDirs(path38.join(workspaceRoot, rel))) {
|
|
29043
29059
|
const child = rel ? `${rel}/${name}` : name;
|
|
29044
|
-
if (hasGitEntry(
|
|
29060
|
+
if (hasGitEntry(path38.join(workspaceRoot, child))) found.push(child);
|
|
29045
29061
|
else if (depth < NESTED_REPO_DEPTH) walk(child, depth + 1);
|
|
29046
29062
|
}
|
|
29047
29063
|
};
|
|
@@ -29059,7 +29075,7 @@ var GitWorktreeIsolation = class {
|
|
|
29059
29075
|
const [meta, file] = entry.split(" ");
|
|
29060
29076
|
if (file !== void 0 && meta.startsWith(`${GITLINK_MODE} `)) paths.add(file);
|
|
29061
29077
|
}
|
|
29062
|
-
const declared = await this.tryGit(workspaceRoot, ["config", "-z", "-f",
|
|
29078
|
+
const declared = await this.tryGit(workspaceRoot, ["config", "-z", "-f", path38.join(toplevel, ".gitmodules"), "--get-regexp", "^submodule\\..*\\.path$"]);
|
|
29063
29079
|
for (const entry of declared.stdout.split("\0")) {
|
|
29064
29080
|
const value = entry.split("\n")[1];
|
|
29065
29081
|
if (value) paths.add(value.replace(/\/+$/, ""));
|
|
@@ -29117,7 +29133,7 @@ var GitWorktreeIsolation = class {
|
|
|
29117
29133
|
async acceptsWorktree(run, repo) {
|
|
29118
29134
|
const dir = this.integrationDir(run, repo);
|
|
29119
29135
|
ensureStateDirIgnored(run.workspaceRoot);
|
|
29120
|
-
fs15.mkdirSync(
|
|
29136
|
+
fs15.mkdirSync(path38.dirname(dir), { recursive: true });
|
|
29121
29137
|
const added = await this.tryGit(repo.root, ["worktree", "add", "-q", "--no-checkout", dir, repo.integrationBranch]);
|
|
29122
29138
|
await this.removeWorktreeDir(run, repo, dir, []);
|
|
29123
29139
|
return added.ok;
|
|
@@ -29132,12 +29148,12 @@ var GitWorktreeIsolation = class {
|
|
|
29132
29148
|
if (isolated.includes(SELF_REPO)) return [];
|
|
29133
29149
|
const shared2 = [];
|
|
29134
29150
|
const walk = (rel) => {
|
|
29135
|
-
for (const name of listDir2(
|
|
29151
|
+
for (const name of listDir2(path38.join(workspaceRoot, rel))) {
|
|
29136
29152
|
if (!rel && (name === STATE_DIR || name === ".git")) continue;
|
|
29137
29153
|
const child = rel ? `${rel}/${name}` : name;
|
|
29138
29154
|
if (isolated.includes(child)) continue;
|
|
29139
29155
|
if (isolated.some((p) => p.startsWith(`${child}/`))) walk(child);
|
|
29140
|
-
else if (resolves(
|
|
29156
|
+
else if (resolves(path38.join(workspaceRoot, child))) shared2.push(child);
|
|
29141
29157
|
}
|
|
29142
29158
|
};
|
|
29143
29159
|
walk("");
|
|
@@ -29177,9 +29193,9 @@ var GitWorktreeIsolation = class {
|
|
|
29177
29193
|
try {
|
|
29178
29194
|
ensureStateDirIgnored(run.workspaceRoot);
|
|
29179
29195
|
for (const repo of run.repos) {
|
|
29180
|
-
const worktree =
|
|
29196
|
+
const worktree = path38.join(dir, repo.path);
|
|
29181
29197
|
const tip = (await this.git(repo.root, ["rev-parse", repo.integrationBranch])).trim();
|
|
29182
|
-
fs15.mkdirSync(
|
|
29198
|
+
fs15.mkdirSync(path38.dirname(worktree), { recursive: true });
|
|
29183
29199
|
await this.git(repo.root, ["worktree", "add", "-q", "-B", branch, worktree, tip]);
|
|
29184
29200
|
record.repos[repo.path] = { worktree, linked: [], baseRef: tip };
|
|
29185
29201
|
}
|
|
@@ -29204,13 +29220,13 @@ var GitWorktreeIsolation = class {
|
|
|
29204
29220
|
setupFailed.push({ repo: repo.path, detail: err.detail });
|
|
29205
29221
|
}
|
|
29206
29222
|
entry.linked = boot.linked;
|
|
29207
|
-
copied.push(...boot.copied.map((name) =>
|
|
29223
|
+
copied.push(...boot.copied.map((name) => path38.posix.join(repo.path, name)));
|
|
29208
29224
|
}
|
|
29209
29225
|
for (const rel of run.shared) {
|
|
29210
|
-
const source =
|
|
29211
|
-
const target =
|
|
29226
|
+
const source = path38.join(run.workspaceRoot, rel);
|
|
29227
|
+
const target = path38.join(cwd, rel);
|
|
29212
29228
|
if (!resolves(source) || lexists(target)) continue;
|
|
29213
|
-
fs15.mkdirSync(
|
|
29229
|
+
fs15.mkdirSync(path38.dirname(target), { recursive: true });
|
|
29214
29230
|
if (linkPath(source, target, this.platform) === "copy") copied.push(rel);
|
|
29215
29231
|
const entry = self ? record.repos[SELF_REPO] : void 0;
|
|
29216
29232
|
if (entry) entry.linked.push(rel);
|
|
@@ -29242,7 +29258,7 @@ var GitWorktreeIsolation = class {
|
|
|
29242
29258
|
*/
|
|
29243
29259
|
async clearLeftovers(run, task2, names) {
|
|
29244
29260
|
const removal = noRemoval();
|
|
29245
|
-
const holder = Object.values(run.tasks).find((r) => r.taskId !== task2.id && (r.branch === names.branch ||
|
|
29261
|
+
const holder = Object.values(run.tasks).find((r) => r.taskId !== task2.id && (r.branch === names.branch || path38.resolve(r.workspace) === path38.resolve(names.dir) || isInside(r.workspace, names.dir)));
|
|
29246
29262
|
if (holder) throw new Error(`Its worktree path or branch is held by the record of task ${holder.order} (${holder.title}); Ordewell will not remove it`);
|
|
29247
29263
|
const found = [];
|
|
29248
29264
|
for (const repo of run.repos) {
|
|
@@ -29252,14 +29268,14 @@ var GitWorktreeIsolation = class {
|
|
|
29252
29268
|
worktree: /^worktree (.+)$/m.exec(block)?.[1],
|
|
29253
29269
|
branch: /^branch refs\/heads\/(.+)$/m.exec(block)?.[1]
|
|
29254
29270
|
}));
|
|
29255
|
-
const at = /* @__PURE__ */ new Set([
|
|
29271
|
+
const at = /* @__PURE__ */ new Set([path38.join(names.dir, repo.path)]);
|
|
29256
29272
|
for (const entry of registered) {
|
|
29257
|
-
if (entry.worktree && entry.branch === names.branch && isInside(this.runRoot(run),
|
|
29273
|
+
if (entry.worktree && entry.branch === names.branch && isInside(this.runRoot(run), path38.resolve(entry.worktree))) at.add(entry.worktree);
|
|
29258
29274
|
}
|
|
29259
|
-
const base = { branch: names.branch, name:
|
|
29275
|
+
const base = { branch: names.branch, name: path38.basename(names.dir), title: task2.title };
|
|
29260
29276
|
for (const worktree of at) {
|
|
29261
29277
|
if (!fs15.existsSync(worktree)) continue;
|
|
29262
|
-
const linked = leftoverLinks(
|
|
29278
|
+
const linked = leftoverLinks(path38.join(worktree, await this.prefixOf(repo)));
|
|
29263
29279
|
found.push({ repo, worktree, target: { ...base, worktree, linked } });
|
|
29264
29280
|
}
|
|
29265
29281
|
found.push({ repo, worktree: names.dir, target: { ...base, linked: [] } });
|
|
@@ -29352,7 +29368,7 @@ var GitWorktreeIsolation = class {
|
|
|
29352
29368
|
*/
|
|
29353
29369
|
async inWorkspacePlace(repo, worktree) {
|
|
29354
29370
|
const prefix = await this.prefixOf(repo);
|
|
29355
|
-
return prefix ?
|
|
29371
|
+
return prefix ? path38.join(worktree, prefix) : worktree;
|
|
29356
29372
|
}
|
|
29357
29373
|
async prefixOf(repo) {
|
|
29358
29374
|
return (await this.git(repo.root, ["rev-parse", "--show-prefix"])).trim();
|
|
@@ -29882,15 +29898,15 @@ var GitWorktreeIsolation = class {
|
|
|
29882
29898
|
return landingMessage(kind, from, this.deps.plannedWith?.() ?? false);
|
|
29883
29899
|
}
|
|
29884
29900
|
integrationDir(run, repo) {
|
|
29885
|
-
return
|
|
29901
|
+
return path38.join(this.runRoot(run), INTEGRATION_DIR, repo.path);
|
|
29886
29902
|
}
|
|
29887
29903
|
async ensureIntegrationWorktree(run, repo) {
|
|
29888
29904
|
return this.admin(run.workspaceRoot, async () => {
|
|
29889
29905
|
const dir = this.integrationDir(run, repo);
|
|
29890
|
-
if (fs15.existsSync(
|
|
29906
|
+
if (fs15.existsSync(path38.join(dir, ".git"))) return dir;
|
|
29891
29907
|
await this.tryGit(repo.root, ["worktree", "prune"]);
|
|
29892
29908
|
ensureStateDirIgnored(run.workspaceRoot);
|
|
29893
|
-
fs15.mkdirSync(
|
|
29909
|
+
fs15.mkdirSync(path38.dirname(dir), { recursive: true });
|
|
29894
29910
|
await this.git(repo.root, ["worktree", "add", "-q", dir, repo.integrationBranch]);
|
|
29895
29911
|
return dir;
|
|
29896
29912
|
});
|
|
@@ -29913,7 +29929,7 @@ var GitWorktreeIsolation = class {
|
|
|
29913
29929
|
const removal = noRemoval();
|
|
29914
29930
|
for (const repo of opts.preserve === false || record.readOnly ? [] : run.repos) {
|
|
29915
29931
|
const entry = record.repos[repo.path];
|
|
29916
|
-
const target = { worktree: entry?.worktree, linked: entry?.linked ?? [], branch: record.branch, name:
|
|
29932
|
+
const target = { worktree: entry?.worktree, linked: entry?.linked ?? [], branch: record.branch, name: path38.basename(record.workspace), title: record.title, commit: record.commit };
|
|
29917
29933
|
try {
|
|
29918
29934
|
const kept = await this.preserve(run, repo, target, opts.intent);
|
|
29919
29935
|
if (kept) removal.preserved.push({ task: task2, ...kept });
|
|
@@ -29994,7 +30010,7 @@ var GitWorktreeIsolation = class {
|
|
|
29994
30010
|
return;
|
|
29995
30011
|
}
|
|
29996
30012
|
for (const entry of entries) {
|
|
29997
|
-
const target =
|
|
30013
|
+
const target = path38.join(dir, entry.name);
|
|
29998
30014
|
if (entry.isSymbolicLink()) this.unlinkIfLink(target);
|
|
29999
30015
|
else if (entry.isDirectory()) this.unlinkLinksUnder(target);
|
|
30000
30016
|
}
|
|
@@ -30016,20 +30032,20 @@ var GitWorktreeIsolation = class {
|
|
|
30016
30032
|
return false;
|
|
30017
30033
|
}
|
|
30018
30034
|
};
|
|
30019
|
-
const owned = new Set(Object.values(run.tasks).map((r) =>
|
|
30035
|
+
const owned = new Set(Object.values(run.tasks).map((r) => path38.resolve(r.workspace)));
|
|
30020
30036
|
const root = this.runRoot(run);
|
|
30021
30037
|
if (fs15.existsSync(root)) {
|
|
30022
30038
|
for (const entry of fs15.readdirSync(root)) {
|
|
30023
|
-
const dir =
|
|
30024
|
-
if (entry === INTEGRATION_DIR || owned.has(
|
|
30039
|
+
const dir = path38.join(root, entry);
|
|
30040
|
+
if (entry === INTEGRATION_DIR || owned.has(path38.resolve(dir))) continue;
|
|
30025
30041
|
let kept = true;
|
|
30026
30042
|
for (const repo of run.repos) {
|
|
30027
|
-
const worktree =
|
|
30028
|
-
const linked = leftoverLinks(
|
|
30043
|
+
const worktree = path38.join(dir, repo.path);
|
|
30044
|
+
const linked = leftoverLinks(path38.join(worktree, await this.prefixOf(repo)));
|
|
30029
30045
|
if (!await keep2(repo, { worktree, linked, branch: null, name: entry, title: entry }, worktree)) kept = false;
|
|
30030
30046
|
}
|
|
30031
30047
|
if (!kept) continue;
|
|
30032
|
-
for (const repo of run.repos) await this.removeWorktreeDir(run, repo,
|
|
30048
|
+
for (const repo of run.repos) await this.removeWorktreeDir(run, repo, path38.join(dir, repo.path), []);
|
|
30033
30049
|
this.removeTaskWorkspace(run, dir);
|
|
30034
30050
|
}
|
|
30035
30051
|
}
|
|
@@ -30047,13 +30063,13 @@ var GitWorktreeIsolation = class {
|
|
|
30047
30063
|
}
|
|
30048
30064
|
async removeWorktreeDir(run, repo, dir, linked) {
|
|
30049
30065
|
for (const name of /* @__PURE__ */ new Set([...linked, ...installDirs(dir)])) {
|
|
30050
|
-
const target =
|
|
30051
|
-
if (!resolvesAsNamed(this.runRoot(run),
|
|
30066
|
+
const target = path38.join(dir, name);
|
|
30067
|
+
if (!resolvesAsNamed(this.runRoot(run), path38.dirname(target))) continue;
|
|
30052
30068
|
this.unlinkIfLink(target);
|
|
30053
30069
|
this.unlinkLinksUnder(target);
|
|
30054
30070
|
}
|
|
30055
30071
|
for (const name of resolvesAsNamed(this.runRoot(run), dir) ? fs15.readdirSync(dir) : []) {
|
|
30056
|
-
if (LINKED_ARTIFACTS.has(name) || isEnvFile(name)) this.unlinkIfLink(
|
|
30072
|
+
if (LINKED_ARTIFACTS.has(name) || isEnvFile(name)) this.unlinkIfLink(path38.join(dir, name));
|
|
30057
30073
|
}
|
|
30058
30074
|
await this.tryGit(repo.root, ["worktree", "remove", "--force", dir]);
|
|
30059
30075
|
if (fs15.existsSync(dir) && isInside(this.runRoot(run), dir)) {
|
|
@@ -30061,7 +30077,7 @@ var GitWorktreeIsolation = class {
|
|
|
30061
30077
|
fs15.rmSync(dir, { recursive: true, force: true });
|
|
30062
30078
|
}
|
|
30063
30079
|
await this.tryGit(repo.root, ["worktree", "prune"]);
|
|
30064
|
-
for (let parent =
|
|
30080
|
+
for (let parent = path38.dirname(dir); isInside(this.runRoot(run), parent); parent = path38.dirname(parent)) this.removeIfEmpty(parent);
|
|
30065
30081
|
}
|
|
30066
30082
|
unlinkIfLink(target) {
|
|
30067
30083
|
try {
|
|
@@ -30076,14 +30092,14 @@ var GitWorktreeIsolation = class {
|
|
|
30076
30092
|
}
|
|
30077
30093
|
}
|
|
30078
30094
|
runRoot(run) {
|
|
30079
|
-
return
|
|
30095
|
+
return path38.join(run.workspaceRoot, STATE_DIR, "worktrees", run.id);
|
|
30080
30096
|
}
|
|
30081
30097
|
namesFor(run, task2) {
|
|
30082
30098
|
const slug = sanitizeSlug(task2.title).slice(0, 40).replace(/-+$/, "") || "task";
|
|
30083
30099
|
let name = `${task2.order}-${slug}`;
|
|
30084
30100
|
const clash = Object.values(run.tasks).some((r) => r.taskId !== task2.id && r.branch === `ordewell/${run.id}/${name}`);
|
|
30085
30101
|
if (clash) name = `${name}-${sanitizeSlug(task2.id) || "x"}`;
|
|
30086
|
-
return { branch: `ordewell/${run.id}/${name}`, dir:
|
|
30102
|
+
return { branch: `ordewell/${run.id}/${name}`, dir: path38.join(this.runRoot(run), name) };
|
|
30087
30103
|
}
|
|
30088
30104
|
async unmergedPaths(cwd) {
|
|
30089
30105
|
const listed3 = await this.tryGit(cwd, ["diff", "--name-only", "-z", "--diff-filter=U"]);
|
|
@@ -30097,7 +30113,7 @@ var GitWorktreeIsolation = class {
|
|
|
30097
30113
|
async rebaseInProgress(cwd) {
|
|
30098
30114
|
for (const dir of ["rebase-merge", "rebase-apply"]) {
|
|
30099
30115
|
const found = await this.tryGit(cwd, ["rev-parse", "--git-path", dir]);
|
|
30100
|
-
if (found.ok && fs15.existsSync(
|
|
30116
|
+
if (found.ok && fs15.existsSync(path38.resolve(cwd, found.stdout.trim()))) return true;
|
|
30101
30117
|
}
|
|
30102
30118
|
return false;
|
|
30103
30119
|
}
|
|
@@ -30171,6 +30187,29 @@ function describeIsolationPreview(preview) {
|
|
|
30171
30187
|
}
|
|
30172
30188
|
}
|
|
30173
30189
|
|
|
30190
|
+
// src/services/repositoryRunnerConfig.ts
|
|
30191
|
+
var RUNNER_CONFIG_ROOTS = [".mcp.json", ".claude", ".claude-plugin", "opencode.json", "opencode.jsonc", ".opencode", ".codex"];
|
|
30192
|
+
function repositoryRunnerConfigPaths(paths) {
|
|
30193
|
+
return [...new Set(paths.filter(
|
|
30194
|
+
(path50) => (
|
|
30195
|
+
// Project MCP servers start commands or send data to a repository-chosen URL.
|
|
30196
|
+
path50 === ".mcp.json" || // Settings can run hooks and helpers, load plugins, or redirect traffic.
|
|
30197
|
+
path50 === ".claude/settings.json" || // Local settings have the same execution capabilities as project settings.
|
|
30198
|
+
path50 === ".claude/settings.local.json" || // Hook files provide commands invoked by the runner.
|
|
30199
|
+
path50.startsWith(".claude/hooks/") || // Plugin files can provide code and hooks loaded by the runner.
|
|
30200
|
+
path50.startsWith(".claude/plugins/") || // Plugin metadata can load plugins and their executable components.
|
|
30201
|
+
path50.startsWith(".claude-plugin/") || // Plugin and marketplace manifests can select code for the runner to load.
|
|
30202
|
+
/^\.claude\/(?:[^/]+\/)*(?:plugin|marketplace)\.json$/.test(path50) || // OpenCode config declares MCP servers and plugins; its plugin and tool
|
|
30203
|
+
// directories are code it loads, and an agent definition sets the prompt,
|
|
30204
|
+
// model and permissions of the built-in agent its id names, which a task
|
|
30205
|
+
// launches with. The rest of `.opencode/` is dependencies OpenCode
|
|
30206
|
+
// installs itself, which a later launch must not be held for.
|
|
30207
|
+
/^(?:\.opencode\/)?opencode\.jsonc?$/.test(path50) || /^\.opencode\/(?:plugins?|tools?|agents?)\//.test(path50) || // Codex project config carries MCP servers, hooks and `notify` commands.
|
|
30208
|
+
path50.startsWith(".codex/")
|
|
30209
|
+
)
|
|
30210
|
+
))].sort();
|
|
30211
|
+
}
|
|
30212
|
+
|
|
30174
30213
|
// src/services/mergeWording.ts
|
|
30175
30214
|
function isRepoGroup(handoff) {
|
|
30176
30215
|
return handoff.repos.some((r) => r.path !== ".");
|
|
@@ -30205,7 +30244,7 @@ function handoffBaseLine(handoff, length) {
|
|
|
30205
30244
|
return handoff.repos.map((repo) => `${group ? `${repo.path}: ` : ""}${repoBaseLine(repo, length)}`).join(", ");
|
|
30206
30245
|
}
|
|
30207
30246
|
function repoResultLines(handoff) {
|
|
30208
|
-
return handoff.repos.map(({ path:
|
|
30247
|
+
return handoff.repos.map(({ path: path50, landed: landed2 }) => `${path50}: ${landed2.length === 0 ? "nothing to merge" : `${landed2.length} task${landed2.length === 1 ? "" : "s"} landed`}`);
|
|
30209
30248
|
}
|
|
30210
30249
|
|
|
30211
30250
|
// src/interfaces/ILogger.ts
|
|
@@ -33264,6 +33303,7 @@ var IsolationRunController = class {
|
|
|
33264
33303
|
/** Resolver task id → the conflicted task it resolves; see {@link linkResolver}. */
|
|
33265
33304
|
resolvers = {};
|
|
33266
33305
|
opening = null;
|
|
33306
|
+
opened = 0;
|
|
33267
33307
|
/** Bumped by an interrupt, so an activation in flight across it does not open the run it ended. */
|
|
33268
33308
|
activations = 0;
|
|
33269
33309
|
/** The start a dirty tree turned away, handed back once the user chooses how to go on. */
|
|
@@ -33295,6 +33335,10 @@ var IsolationRunController = class {
|
|
|
33295
33335
|
get isOpen() {
|
|
33296
33336
|
return this.mode !== null;
|
|
33297
33337
|
}
|
|
33338
|
+
/** How many runs have opened: what tells one run's launches from the next one's. */
|
|
33339
|
+
get epoch() {
|
|
33340
|
+
return this.opened;
|
|
33341
|
+
}
|
|
33298
33342
|
/** The open run has decided whether it isolates. */
|
|
33299
33343
|
get decided() {
|
|
33300
33344
|
return this.mode === "isolated" || this.mode === "shared";
|
|
@@ -33392,6 +33436,7 @@ var IsolationRunController = class {
|
|
|
33392
33436
|
open() {
|
|
33393
33437
|
if (this.mode) return;
|
|
33394
33438
|
this.mode = "undecided";
|
|
33439
|
+
this.opened += 1;
|
|
33395
33440
|
}
|
|
33396
33441
|
/**
|
|
33397
33442
|
* Decide once per run, as its first change task starts, whether it executes
|
|
@@ -34391,7 +34436,7 @@ function heldFrom(state) {
|
|
|
34391
34436
|
}
|
|
34392
34437
|
|
|
34393
34438
|
// src/services/Attempts.ts
|
|
34394
|
-
var
|
|
34439
|
+
var path42 = __toESM(require("path"));
|
|
34395
34440
|
|
|
34396
34441
|
// src/services/VerdictEngine.ts
|
|
34397
34442
|
var IDLE_TIMEOUT_MS = 10 * 6e4;
|
|
@@ -34779,10 +34824,132 @@ function reportedVerdict(report) {
|
|
|
34779
34824
|
return { outcome: "fail", reason: `The runner reported the task ${report.status}: ${why}`, checks, decidedAt, reported };
|
|
34780
34825
|
}
|
|
34781
34826
|
|
|
34827
|
+
// src/services/taskStartConfig.ts
|
|
34828
|
+
var path39 = __toESM(require("path"));
|
|
34829
|
+
var import_crypto15 = require("crypto");
|
|
34830
|
+
var import_fs13 = require("fs");
|
|
34831
|
+
var MAX_FILES = 2e3;
|
|
34832
|
+
var MAX_DEPTH = 8;
|
|
34833
|
+
function liveConfig(dir) {
|
|
34834
|
+
const found = /* @__PURE__ */ new Map();
|
|
34835
|
+
const visit = (rel, depth) => {
|
|
34836
|
+
if (found.size >= MAX_FILES || depth > MAX_DEPTH) return;
|
|
34837
|
+
const full = path39.join(dir, rel);
|
|
34838
|
+
try {
|
|
34839
|
+
const info = (0, import_fs13.statSync)(full);
|
|
34840
|
+
if (info.isFile()) {
|
|
34841
|
+
found.set(rel, (0, import_crypto15.createHash)("sha1").update((0, import_fs13.readFileSync)(full)).digest("hex"));
|
|
34842
|
+
} else if (info.isDirectory() && path39.basename(rel) !== "node_modules") {
|
|
34843
|
+
for (const name of (0, import_fs13.readdirSync)(full)) visit(path39.posix.join(rel, name), depth + 1);
|
|
34844
|
+
}
|
|
34845
|
+
} catch {
|
|
34846
|
+
}
|
|
34847
|
+
};
|
|
34848
|
+
for (const root of RUNNER_CONFIG_ROOTS) visit(root, 0);
|
|
34849
|
+
const selected = new Set(repositoryRunnerConfigPaths([...found.keys()]));
|
|
34850
|
+
return new Map([...found].filter(([name]) => selected.has(name)));
|
|
34851
|
+
}
|
|
34852
|
+
function linkedRoots(dir) {
|
|
34853
|
+
const linked = /* @__PURE__ */ new Set();
|
|
34854
|
+
for (const root of RUNNER_CONFIG_ROOTS) {
|
|
34855
|
+
try {
|
|
34856
|
+
if ((0, import_fs13.lstatSync)(path39.join(dir, root)).isSymbolicLink()) linked.add(root);
|
|
34857
|
+
} catch {
|
|
34858
|
+
}
|
|
34859
|
+
}
|
|
34860
|
+
return linked;
|
|
34861
|
+
}
|
|
34862
|
+
function readDirs(root) {
|
|
34863
|
+
const dirs = [{ dir: root, prefix: "" }];
|
|
34864
|
+
for (let dir = root, prefix = ""; !(0, import_fs13.existsSync)(path39.join(dir, ".git")); ) {
|
|
34865
|
+
const parent = path39.dirname(dir);
|
|
34866
|
+
if (parent === dir) return [dirs[0]];
|
|
34867
|
+
dir = parent;
|
|
34868
|
+
prefix += "../";
|
|
34869
|
+
dirs.push({ dir, prefix });
|
|
34870
|
+
}
|
|
34871
|
+
return dirs;
|
|
34872
|
+
}
|
|
34873
|
+
var TaskStartConfig = class {
|
|
34874
|
+
live = /* @__PURE__ */ new Map();
|
|
34875
|
+
/**
|
|
34876
|
+
* `epoch` names the run the check belongs to; a new run takes a new
|
|
34877
|
+
* baseline. `root` is the workspace root, the checkout a worktree run lands
|
|
34878
|
+
* in; `cwd` is where the runner starts, and `worktree` whether that is a
|
|
34879
|
+
* worktree prepared for it.
|
|
34880
|
+
*/
|
|
34881
|
+
async check(run, taskId, where) {
|
|
34882
|
+
const found = where.worktree ? await this.gitDifferences(run, taskId) : [];
|
|
34883
|
+
const id2 = String(where.epoch);
|
|
34884
|
+
const checkout = readDirs(where.root).flatMap(({ dir, prefix }) => this.liveDifferences(`${id2}:checkout:${dir}`, dir).map((name) => `${prefix}${name}`));
|
|
34885
|
+
if (!where.worktree) found.push(...checkout);
|
|
34886
|
+
else {
|
|
34887
|
+
const cwd = where.cwd ?? run?.tasks[taskId]?.workspace;
|
|
34888
|
+
if (cwd) found.push(...this.worktreeDifferences(id2, cwd, where.root));
|
|
34889
|
+
}
|
|
34890
|
+
return [...new Set(found)].sort();
|
|
34891
|
+
}
|
|
34892
|
+
/** The baselines go with the plan they belong to. */
|
|
34893
|
+
clear() {
|
|
34894
|
+
this.live.clear();
|
|
34895
|
+
}
|
|
34896
|
+
/**
|
|
34897
|
+
* What a worktree's runner reads that differs from where the run started.
|
|
34898
|
+
* The `.claude` and `.opencode` directories it links from the checkout are
|
|
34899
|
+
* the checkout's own, so they are compared with the checkout's first state,
|
|
34900
|
+
* which an earlier task's write there does not move. Anything else is the
|
|
34901
|
+
* worktree's, and is compared with its own first state: a setup command's
|
|
34902
|
+
* files are trusted, and a task's later write is not.
|
|
34903
|
+
*/
|
|
34904
|
+
worktreeDifferences(id2, dir, root) {
|
|
34905
|
+
const now = liveConfig(dir);
|
|
34906
|
+
const linked = linkedRoots(dir);
|
|
34907
|
+
const fromCheckout = (name) => linked.has(name.split("/")[0]);
|
|
34908
|
+
const key = `${id2}:worktree:${dir}`;
|
|
34909
|
+
let local = this.live.get(key);
|
|
34910
|
+
if (!local) {
|
|
34911
|
+
local = new Map([...now].filter(([name]) => !fromCheckout(name)));
|
|
34912
|
+
this.live.set(key, local);
|
|
34913
|
+
}
|
|
34914
|
+
const checkout = this.live.get(`${id2}:checkout:${root}`);
|
|
34915
|
+
return [...now].filter(([name, hash]) => fromCheckout(name) ? checkout?.get(name) !== hash : local.get(name) !== hash).map(([name]) => name);
|
|
34916
|
+
}
|
|
34917
|
+
liveDifferences(key, dir) {
|
|
34918
|
+
const now = liveConfig(dir);
|
|
34919
|
+
const before = this.live.get(key);
|
|
34920
|
+
if (!before) {
|
|
34921
|
+
this.live.set(key, now);
|
|
34922
|
+
return [];
|
|
34923
|
+
}
|
|
34924
|
+
return [...now].filter(([name, hash]) => before.get(name) !== hash).map(([name]) => name);
|
|
34925
|
+
}
|
|
34926
|
+
async gitDifferences(run, taskId) {
|
|
34927
|
+
if (!run) return [];
|
|
34928
|
+
const invoker = { exec: defaultExecFile2, resolvePath: augmentedPath };
|
|
34929
|
+
const found = [];
|
|
34930
|
+
for (const repo of run.repos) {
|
|
34931
|
+
const cwd = run.tasks[taskId]?.repos[repo.path]?.worktree;
|
|
34932
|
+
if (!cwd || !repo.baseRef || !(0, import_fs13.existsSync)(cwd)) continue;
|
|
34933
|
+
const prefix = repo.path === "." ? (await tryGit(invoker, repo.root, ["rev-parse", "--show-prefix"])).stdout.trim() : "";
|
|
34934
|
+
const roots = [...RUNNER_CONFIG_ROOTS, ...prefix ? RUNNER_CONFIG_ROOTS.map((r) => `${prefix}${r}`) : []];
|
|
34935
|
+
const diff = await tryGit(invoker, cwd, ["diff", "--no-ext-diff", "--no-textconv", "--no-renames", "--name-only", "--diff-filter=ACMRTU", "-z", repo.baseRef, "--"]);
|
|
34936
|
+
const untracked = await tryGit(invoker, cwd, ["ls-files", "--others", "-z", "--", ...roots]);
|
|
34937
|
+
if (!diff.ok || !untracked.ok) continue;
|
|
34938
|
+
for (const name of [...diff.stdout.split("\0"), ...untracked.stdout.split("\0")]) {
|
|
34939
|
+
const here = prefix && name.startsWith(prefix) ? name.slice(prefix.length) : void 0;
|
|
34940
|
+
if (repositoryRunnerConfigPaths([name]).length || here !== void 0 && repositoryRunnerConfigPaths([here]).length) {
|
|
34941
|
+
found.push(repo.path === "." ? name : path39.posix.join(repo.path, name));
|
|
34942
|
+
}
|
|
34943
|
+
}
|
|
34944
|
+
}
|
|
34945
|
+
return found;
|
|
34946
|
+
}
|
|
34947
|
+
};
|
|
34948
|
+
|
|
34782
34949
|
// src/services/ScriptRunner.ts
|
|
34783
34950
|
var import_child_process11 = require("child_process");
|
|
34784
34951
|
var fs16 = __toESM(require("fs"));
|
|
34785
|
-
var
|
|
34952
|
+
var path40 = __toESM(require("path"));
|
|
34786
34953
|
var import_events2 = require("events");
|
|
34787
34954
|
var import_string_decoder2 = require("string_decoder");
|
|
34788
34955
|
|
|
@@ -34923,7 +35090,7 @@ var ScriptSession = class extends AbstractRunnerSession {
|
|
|
34923
35090
|
async launchOf(step) {
|
|
34924
35091
|
if ("argv" in step) {
|
|
34925
35092
|
const [named3, ...args] = step.argv;
|
|
34926
|
-
const program = this.setup.platform === "win32" &&
|
|
35093
|
+
const program = this.setup.platform === "win32" && path40.win32.basename(named3) !== named3 && !path40.win32.isAbsolute(named3) ? path40.win32.resolve(this.setup.cwd, named3) : named3;
|
|
34927
35094
|
const plan = await planDirectLaunch(program, args, this.setup.launch);
|
|
34928
35095
|
return { file: plan.file, args: plan.args, shell: false, ...plan.verbatim ? { verbatim: true } : {} };
|
|
34929
35096
|
}
|
|
@@ -35156,10 +35323,10 @@ function passed(status) {
|
|
|
35156
35323
|
}
|
|
35157
35324
|
|
|
35158
35325
|
// src/services/PatchCapture.ts
|
|
35159
|
-
var
|
|
35326
|
+
var import_crypto16 = require("crypto");
|
|
35160
35327
|
var fs17 = __toESM(require("fs"));
|
|
35161
35328
|
var os10 = __toESM(require("os"));
|
|
35162
|
-
var
|
|
35329
|
+
var path41 = __toESM(require("path"));
|
|
35163
35330
|
|
|
35164
35331
|
// src/services/readTask.ts
|
|
35165
35332
|
function readTask2(args, readerId, plan, log) {
|
|
@@ -35426,7 +35593,7 @@ function linkInPatch(patch) {
|
|
|
35426
35593
|
function readOwn(scratch, name, max) {
|
|
35427
35594
|
let fd;
|
|
35428
35595
|
try {
|
|
35429
|
-
fd = fs17.openSync(
|
|
35596
|
+
fd = fs17.openSync(path41.join(scratch, name), fs17.constants.O_RDONLY | (fs17.constants.O_NOFOLLOW ?? 0));
|
|
35430
35597
|
} catch (err) {
|
|
35431
35598
|
throw new Refusal(`the capture left no ${name.split(".").pop()} Ordewell could read (${err.code ?? String(err)})`);
|
|
35432
35599
|
}
|
|
@@ -35463,8 +35630,8 @@ async function captureHeld(runs, opts, signal) {
|
|
|
35463
35630
|
if (!runs.touched) return { kind: "empty", reason: "no command of this task has run sealed, so its worktree holds only what Ordewell checked out.", flags: [] };
|
|
35464
35631
|
const [worktree] = runs.worktrees;
|
|
35465
35632
|
const scratch = runs.scratch;
|
|
35466
|
-
const tag = `ordewell-patch-${(0,
|
|
35467
|
-
const stem =
|
|
35633
|
+
const tag = `ordewell-patch-${(0, import_crypto16.randomBytes)(8).toString("hex")}`;
|
|
35634
|
+
const stem = path41.join(scratch, tag);
|
|
35468
35635
|
const own = (suffix, max = LISTING_BYTES) => readOwn(scratch, `${tag}.${suffix}`, max);
|
|
35469
35636
|
try {
|
|
35470
35637
|
const stage = await runs.run(stageScript(stem, opts.linked ?? []), worktree);
|
|
@@ -35502,7 +35669,7 @@ async function captureHeld(runs, opts, signal) {
|
|
|
35502
35669
|
return {
|
|
35503
35670
|
kind: "saved",
|
|
35504
35671
|
patch,
|
|
35505
|
-
stats: { base, ...countedIn(patch), bytes: patch.length, sha256: (0,
|
|
35672
|
+
stats: { base, ...countedIn(patch), bytes: patch.length, sha256: (0, import_crypto16.createHash)("sha256").update(patch).digest("hex"), flags: [...flags, ...flag("normalized", normalized2)] }
|
|
35506
35673
|
};
|
|
35507
35674
|
} catch (err) {
|
|
35508
35675
|
if (err instanceof Refusal) return { kind: "refused", reason: `${err.message}.` };
|
|
@@ -35556,8 +35723,8 @@ async function indexEntries(invoker, worktree) {
|
|
|
35556
35723
|
return entries;
|
|
35557
35724
|
}
|
|
35558
35725
|
async function trialApply(invoker, worktree, patchFile, scratch) {
|
|
35559
|
-
const index =
|
|
35560
|
-
const copy =
|
|
35726
|
+
const index = path41.resolve(worktree, (await git(invoker, worktree, [...APPLY_GIT, "rev-parse", "--git-path", "index"])).trim());
|
|
35727
|
+
const copy = path41.join(scratch, "index");
|
|
35561
35728
|
fs17.copyFileSync(index, copy);
|
|
35562
35729
|
const trial = { ...invoker, exec: (file, args, opts) => invoker.exec(file, args, { ...opts, env: { ...opts.env, GIT_INDEX_FILE: copy } }) };
|
|
35563
35730
|
const tried = await tryGit(trial, worktree, [...APPLY_GIT, "apply", "--cached", "--3way", "--whitespace=nowarn", patchFile]);
|
|
@@ -35577,7 +35744,7 @@ function gitRefused(lead, stderr) {
|
|
|
35577
35744
|
function onDisk3(worktree, names) {
|
|
35578
35745
|
return names.map((name) => {
|
|
35579
35746
|
try {
|
|
35580
|
-
const stat = fs17.lstatSync(
|
|
35747
|
+
const stat = fs17.lstatSync(path41.join(worktree, name), { bigint: true, throwIfNoEntry: false });
|
|
35581
35748
|
return stat ? `${stat.mode} ${stat.ino} ${stat.size} ${stat.mtimeNs} ${stat.ctimeNs}` : "none";
|
|
35582
35749
|
} catch (err) {
|
|
35583
35750
|
return err.code ?? "unreadable";
|
|
@@ -35617,7 +35784,7 @@ function leavesWorktree(worktree, names, linked, held2, left) {
|
|
|
35617
35784
|
if (i < parts.length && held2.get(at)?.some((entry) => entry.mode === SUBMODULE)) {
|
|
35618
35785
|
return `the patch writes ${name}, under ${at}, a submodule, whose files are another repository's.`;
|
|
35619
35786
|
}
|
|
35620
|
-
const full =
|
|
35787
|
+
const full = path41.join(worktree, ...parts.slice(0, i));
|
|
35621
35788
|
const stat = fs17.lstatSync(full, { throwIfNoEntry: false });
|
|
35622
35789
|
if (!stat) break;
|
|
35623
35790
|
const last = i === parts.length;
|
|
@@ -35638,14 +35805,14 @@ async function applyPatch(invoker, worktree, patch, saved, opts = {}) {
|
|
|
35638
35805
|
if (patch.length !== saved.bytes) {
|
|
35639
35806
|
return refused4(`the patch is ${byteSize(patch.length)} where its artifact says ${byteSize(saved.bytes)}, so it was cut short or changed after it was saved.`);
|
|
35640
35807
|
}
|
|
35641
|
-
if ((0,
|
|
35808
|
+
if ((0, import_crypto16.createHash)("sha256").update(patch).digest("hex") !== saved.sha256) {
|
|
35642
35809
|
return refused4("the patch is not the file that was saved: its hash is not the one its artifact records, so it was changed after it was saved.");
|
|
35643
35810
|
}
|
|
35644
35811
|
const link = linkInPatch(patch);
|
|
35645
35812
|
if (link !== void 0) {
|
|
35646
35813
|
return refused4(`the patch holds a link or a submodule (${JSON.stringify(link.slice(0, 80))}), which a saved patch never does, so it is not one that was saved.`);
|
|
35647
35814
|
}
|
|
35648
|
-
const dir = fs17.mkdtempSync(
|
|
35815
|
+
const dir = fs17.mkdtempSync(path41.join(os10.tmpdir(), "ordewell-apply-"));
|
|
35649
35816
|
try {
|
|
35650
35817
|
const toplevel = (await git(invoker, worktree, [...APPLY_GIT, "rev-parse", "--show-toplevel"])).trim();
|
|
35651
35818
|
if (fs17.realpathSync(toplevel) !== fs17.realpathSync(worktree)) return refused4(`${worktree} is not the root of a worktree of its own.`);
|
|
@@ -35655,7 +35822,7 @@ async function applyPatch(invoker, worktree, patch, saved, opts = {}) {
|
|
|
35655
35822
|
}
|
|
35656
35823
|
const before = await unmergedPaths(invoker, worktree);
|
|
35657
35824
|
if (before.length > 0) return refused4(`your worktree still has unresolved conflicts (${listed(before.slice(0, 10))}${before.length > 10 ? `, +${before.length - 10} more` : ""}). Resolve them and git add them, or undo them, then apply the patch.`);
|
|
35658
|
-
const file =
|
|
35825
|
+
const file = path41.join(dir, "saved.patch");
|
|
35659
35826
|
fs17.writeFileSync(file, patch, { flag: "wx", mode: 384 });
|
|
35660
35827
|
const held2 = await indexEntries(invoker, worktree);
|
|
35661
35828
|
const named3 = await pathsNamed(invoker, worktree, file);
|
|
@@ -35805,6 +35972,11 @@ var TaskWebReader = class {
|
|
|
35805
35972
|
};
|
|
35806
35973
|
|
|
35807
35974
|
// src/services/Attempts.ts
|
|
35975
|
+
var TaskStartConfigError = class extends Error {
|
|
35976
|
+
constructor(paths) {
|
|
35977
|
+
super(`repository configuration ${paths.map((p) => JSON.stringify(p)).join(", ")} differs from where this run started; remove it to continue, or start a new run once your branch holds it`);
|
|
35978
|
+
}
|
|
35979
|
+
};
|
|
35808
35980
|
var DEFAULT_GIT = { exec: defaultExecFile2, resolvePath: () => augmentedPath() };
|
|
35809
35981
|
var Attempts = class {
|
|
35810
35982
|
constructor(deps) {
|
|
@@ -35836,6 +36008,7 @@ var Attempts = class {
|
|
|
35836
36008
|
live = /* @__PURE__ */ new Map();
|
|
35837
36009
|
/** Bumped by every plan load: an ended attempt's wind-down belongs to the scope before it. */
|
|
35838
36010
|
planScope = 0;
|
|
36011
|
+
startConfig = new TaskStartConfig();
|
|
35839
36012
|
/** Each task's runners still winding down once stopped: a continue waits for them (ADR-0018, L1). */
|
|
35840
36013
|
windDowns = /* @__PURE__ */ new Map();
|
|
35841
36014
|
/**
|
|
@@ -36005,6 +36178,7 @@ var Attempts = class {
|
|
|
36005
36178
|
const ended = this.endAll("load");
|
|
36006
36179
|
this.planScope += 1;
|
|
36007
36180
|
this.spawnCounts.clear();
|
|
36181
|
+
this.startConfig.clear();
|
|
36008
36182
|
return ended;
|
|
36009
36183
|
}
|
|
36010
36184
|
/** A task leaving the plan: no later attempt of it is numbered from its runs. */
|
|
@@ -36137,9 +36311,17 @@ var Attempts = class {
|
|
|
36137
36311
|
if (unavailable2) throw new Error(unavailable2);
|
|
36138
36312
|
}
|
|
36139
36313
|
if (kind.kind === "continuation") await this.windDowns.get(task2.id);
|
|
36314
|
+
if (!attempt.script && kind.kind === "repair") {
|
|
36315
|
+
const paths = await this.startConfig.check(runs.current, task2.id, { epoch: runs.epoch, root: this.deps.workspaceRoot(), cwd: null, worktree: true });
|
|
36316
|
+
if (paths.length) throw new TaskStartConfigError(paths);
|
|
36317
|
+
}
|
|
36140
36318
|
const { cwd, worktree, previousWork, workspace } = await attemptCwd(kind, task2, runs);
|
|
36141
36319
|
attempt.cwd = cwd;
|
|
36142
36320
|
attempt.worktree = worktree;
|
|
36321
|
+
if (!attempt.script && kind.kind !== "repair" && !landsNothing(kind)) {
|
|
36322
|
+
const paths = await this.startConfig.check(runs.current, task2.id, { epoch: runs.epoch, root: this.deps.workspaceRoot(), cwd, worktree });
|
|
36323
|
+
if (paths.length) throw new TaskStartConfigError(paths);
|
|
36324
|
+
}
|
|
36143
36325
|
if (checksTree(kind)) attempt.snapshot = await runs.snapshotWorkspace();
|
|
36144
36326
|
if (this.live.get(task2.id) !== attempt) {
|
|
36145
36327
|
if (attempt.worktree && !this.live.has(task2.id) && !this.host.completing(task2.id)) await runs.release(task2.id, { keep: kind.kind === "repair" });
|
|
@@ -36222,6 +36404,9 @@ var Attempts = class {
|
|
|
36222
36404
|
return { kind: "usage-limited", taskId: task2.id, attempt, said: { message }, output: "" };
|
|
36223
36405
|
}
|
|
36224
36406
|
const failed = (failure2) => ({ kind: "spawn-failed", task: task2, attempt, failure: failure2 });
|
|
36407
|
+
if (err instanceof TaskStartConfigError) {
|
|
36408
|
+
return failed({ leaves: "held", hold: err.message, preserveWorktree: true, settles: false, notice: { level: "warn", text: `Task "${task2.title}" is on hold: ${err.message}` } });
|
|
36409
|
+
}
|
|
36225
36410
|
if (attempt.kind.kind === "continuation" && !attachTimeout) {
|
|
36226
36411
|
const refused4 = err instanceof RunnerStartupExit;
|
|
36227
36412
|
const reason = unresumedMessage(task2, refused4 ? `${attempt.runner} could not find its saved session` : `could not start: ${message}`);
|
|
@@ -36358,9 +36543,9 @@ var Attempts = class {
|
|
|
36358
36543
|
const repos = Object.values(this.deps.runs.openRecord(taskId)?.repos ?? {});
|
|
36359
36544
|
if (repos.length !== 1 || cwd === null) return [];
|
|
36360
36545
|
const [{ worktree, linked }] = repos;
|
|
36361
|
-
const prefix =
|
|
36362
|
-
if (prefix.startsWith("..") ||
|
|
36363
|
-
return linked.map((name) => (prefix ? `${prefix}/${name}` : name).split(
|
|
36546
|
+
const prefix = path42.relative(worktree, cwd).split(path42.sep).join("/");
|
|
36547
|
+
if (prefix.startsWith("..") || path42.isAbsolute(prefix)) return [];
|
|
36548
|
+
return linked.map((name) => (prefix ? `${prefix}/${name}` : name).split(path42.sep).join("/"));
|
|
36364
36549
|
}
|
|
36365
36550
|
/**
|
|
36366
36551
|
* A script task's start (ADR-0035): its body as the plan holds it now, run
|
|
@@ -36398,7 +36583,7 @@ var Attempts = class {
|
|
|
36398
36583
|
this.deps.notifications.warn(message);
|
|
36399
36584
|
};
|
|
36400
36585
|
if (resolved.blockedEnvrc) {
|
|
36401
|
-
warn(`blocked:${resolved.blockedEnvrc}`, `direnv has blocked ${resolved.blockedEnvrc}, so tasks start without its variables. Run \`direnv allow\` in ${
|
|
36586
|
+
warn(`blocked:${resolved.blockedEnvrc}`, `direnv has blocked ${resolved.blockedEnvrc}, so tasks start without its variables. Run \`direnv allow\` in ${path42.dirname(resolved.blockedEnvrc)} to use them.`);
|
|
36402
36587
|
}
|
|
36403
36588
|
if (resolved.trackedEnvFile) {
|
|
36404
36589
|
warn(`tracked:${resolved.trackedEnvFile}`, `Ignored ${resolved.trackedEnvFile}: git tracks it, and a committed file must not choose the environment agents run in. Untrack it to use it.`);
|
|
@@ -36424,7 +36609,7 @@ var Attempts = class {
|
|
|
36424
36609
|
uncommittedSkillFolder(name) {
|
|
36425
36610
|
const root = this.deps.workspaceRoot();
|
|
36426
36611
|
const skill = this.deps.skillsAt(this.skillRoots(root)).findSkill(name);
|
|
36427
|
-
return skill?.source === "workspace" ?
|
|
36612
|
+
return skill?.source === "workspace" ? path42.relative(root, path42.dirname(skill.path)).split(path42.sep).join("/") : void 0;
|
|
36428
36613
|
}
|
|
36429
36614
|
/**
|
|
36430
36615
|
* The roots whose `.ordewell/skills/` an attempt at `cwd` reads: in a repo
|
|
@@ -36854,29 +37039,29 @@ function ancestors(task2, store) {
|
|
|
36854
37039
|
|
|
36855
37040
|
// src/services/sessionLease.ts
|
|
36856
37041
|
var fs19 = __toESM(require("fs"));
|
|
36857
|
-
var
|
|
36858
|
-
var
|
|
37042
|
+
var path44 = __toESM(require("path"));
|
|
37043
|
+
var import_crypto18 = require("crypto");
|
|
36859
37044
|
|
|
36860
37045
|
// src/utils/sessionStore.ts
|
|
36861
37046
|
var fs18 = __toESM(require("fs"));
|
|
36862
|
-
var
|
|
37047
|
+
var path43 = __toESM(require("path"));
|
|
36863
37048
|
|
|
36864
37049
|
// src/utils/sessionId.ts
|
|
36865
|
-
var
|
|
37050
|
+
var import_crypto17 = require("crypto");
|
|
36866
37051
|
function mintSessionId() {
|
|
36867
|
-
return `session-${(0,
|
|
37052
|
+
return `session-${(0, import_crypto17.randomBytes)(16).toString("hex")}`;
|
|
36868
37053
|
}
|
|
36869
37054
|
|
|
36870
37055
|
// src/utils/sessionStore.ts
|
|
36871
37056
|
var SESSIONS_SUBDIR = "sessions";
|
|
36872
37057
|
function getSessionsDir(baseDir) {
|
|
36873
|
-
return
|
|
37058
|
+
return path43.join(getStateDir(baseDir), SESSIONS_SUBDIR);
|
|
36874
37059
|
}
|
|
36875
37060
|
function idSegment(id2) {
|
|
36876
37061
|
return /^[A-Za-z0-9_-][A-Za-z0-9._-]{0,127}$/.test(id2) ? id2 : `~${Buffer.from(id2, "utf-8").toString("hex")}`;
|
|
36877
37062
|
}
|
|
36878
37063
|
function sessionDataDir(sessionId, baseDir) {
|
|
36879
|
-
return
|
|
37064
|
+
return path43.join(getSessionsDir(baseDir), idSegment(sessionId));
|
|
36880
37065
|
}
|
|
36881
37066
|
var REJECTION_MESSAGE = "This session was created with an older version of Ordewell. Please re-plan.";
|
|
36882
37067
|
function isSessionMeta(value) {
|
|
@@ -36903,8 +37088,8 @@ function legacySessionFilename(session) {
|
|
|
36903
37088
|
return `${filenameStem(session)}_${session.id.slice(0, 8)}.json`;
|
|
36904
37089
|
}
|
|
36905
37090
|
function dropLegacyFile(sessionsDir, meta) {
|
|
36906
|
-
const legacy =
|
|
36907
|
-
if (legacy ===
|
|
37091
|
+
const legacy = path43.join(sessionsDir, legacySessionFilename(meta));
|
|
37092
|
+
if (legacy === path43.join(sessionsDir, sessionFilename(meta)) || !fs18.existsSync(legacy)) return;
|
|
36908
37093
|
try {
|
|
36909
37094
|
const held2 = JSON.parse(fs18.readFileSync(legacy, "utf-8")).meta?.id;
|
|
36910
37095
|
if (held2 === meta.id) fs18.unlinkSync(legacy);
|
|
@@ -36931,7 +37116,7 @@ function saveSession(plan, goal, baseDir, id2) {
|
|
|
36931
37116
|
};
|
|
36932
37117
|
dropRetiredPlanFields(session.plan);
|
|
36933
37118
|
const filename = sessionFilename(meta);
|
|
36934
|
-
const filePath =
|
|
37119
|
+
const filePath = path43.join(sessionsDir, filename);
|
|
36935
37120
|
writeFileAtomic(filePath, JSON.stringify(session, null, 2));
|
|
36936
37121
|
dropLegacyFile(sessionsDir, meta);
|
|
36937
37122
|
return meta;
|
|
@@ -36943,7 +37128,7 @@ function listSessions(baseDir, logger = defaultLogger) {
|
|
|
36943
37128
|
return files.map((f) => {
|
|
36944
37129
|
let parsed;
|
|
36945
37130
|
try {
|
|
36946
|
-
parsed = JSON.parse(fs18.readFileSync(
|
|
37131
|
+
parsed = JSON.parse(fs18.readFileSync(path43.join(sessionsDir, f), "utf-8"));
|
|
36947
37132
|
} catch (err) {
|
|
36948
37133
|
if (err instanceof SyntaxError) return moveAside(sessionsDir, f, "is not valid JSON", logger);
|
|
36949
37134
|
logger.warn("sessionStore", `failed to read session file ${f}; skipping`, err);
|
|
@@ -36964,7 +37149,7 @@ function listSessions(baseDir, logger = defaultLogger) {
|
|
|
36964
37149
|
function moveAside(sessionsDir, file, reason, logger) {
|
|
36965
37150
|
const aside = `${file}.${Date.now()}.corrupt`;
|
|
36966
37151
|
try {
|
|
36967
|
-
fs18.renameSync(
|
|
37152
|
+
fs18.renameSync(path43.join(sessionsDir, file), path43.join(sessionsDir, aside));
|
|
36968
37153
|
logger.warn("sessionStore", `session file ${file} ${reason}; moved aside to ${aside} rather than overwritten`);
|
|
36969
37154
|
} catch {
|
|
36970
37155
|
logger.warn("sessionStore", `failed to read session file ${file}; skipping`);
|
|
@@ -36975,7 +37160,7 @@ function findSessionFile(sessionsDir, sessionId, logger) {
|
|
|
36975
37160
|
const files = fs18.readdirSync(sessionsDir).filter((f) => f.endsWith(".json"));
|
|
36976
37161
|
for (const f of files) {
|
|
36977
37162
|
try {
|
|
36978
|
-
const raw = fs18.readFileSync(
|
|
37163
|
+
const raw = fs18.readFileSync(path43.join(sessionsDir, f), "utf-8");
|
|
36979
37164
|
const session = JSON.parse(raw);
|
|
36980
37165
|
if (session.meta.id === sessionId) return f;
|
|
36981
37166
|
} catch (err) {
|
|
@@ -36990,7 +37175,7 @@ function loadSession(sessionId, baseDir, logger = defaultLogger) {
|
|
|
36990
37175
|
try {
|
|
36991
37176
|
const file = findSessionFile(sessionsDir, sessionId, logger);
|
|
36992
37177
|
if (file) {
|
|
36993
|
-
const raw = fs18.readFileSync(
|
|
37178
|
+
const raw = fs18.readFileSync(path43.join(sessionsDir, file), "utf-8");
|
|
36994
37179
|
const parsed = JSON.parse(raw);
|
|
36995
37180
|
if (hasScalarRunner(parsed)) {
|
|
36996
37181
|
logger.warn("sessionStore", `session file ${file}: ${REJECTION_MESSAGE}`);
|
|
@@ -37032,7 +37217,7 @@ function deleteSession(sessionId, baseDir, logger = defaultLogger) {
|
|
|
37032
37217
|
try {
|
|
37033
37218
|
const file = findSessionFile(sessionsDir, sessionId, logger);
|
|
37034
37219
|
if (file) {
|
|
37035
|
-
fs18.unlinkSync(
|
|
37220
|
+
fs18.unlinkSync(path43.join(sessionsDir, file));
|
|
37036
37221
|
return true;
|
|
37037
37222
|
}
|
|
37038
37223
|
} catch (err) {
|
|
@@ -37085,7 +37270,7 @@ var UNLEASED = {
|
|
|
37085
37270
|
};
|
|
37086
37271
|
var hostsHere = /* @__PURE__ */ new Set();
|
|
37087
37272
|
function leaseFile(sessionId, workspace) {
|
|
37088
|
-
return
|
|
37273
|
+
return path44.join(sessionDataDir(sessionId, workspace), LEASE_FILE);
|
|
37089
37274
|
}
|
|
37090
37275
|
function isRecord9(value) {
|
|
37091
37276
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -37121,7 +37306,7 @@ var LeaseHost = class {
|
|
|
37121
37306
|
held = /* @__PURE__ */ new Map();
|
|
37122
37307
|
heartbeat = null;
|
|
37123
37308
|
constructor(options = {}) {
|
|
37124
|
-
this.id = options.id ?? (0,
|
|
37309
|
+
this.id = options.id ?? (0, import_crypto18.randomUUID)();
|
|
37125
37310
|
this.pid = options.pid ?? process.pid;
|
|
37126
37311
|
this.kindOf = options.kind ?? (() => void 0);
|
|
37127
37312
|
this.alive = options.alive ?? processAlive;
|
|
@@ -37174,7 +37359,7 @@ var LeaseHost = class {
|
|
|
37174
37359
|
*/
|
|
37175
37360
|
acquire(file, workspace, holder) {
|
|
37176
37361
|
ensureStateDirIgnored(workspace);
|
|
37177
|
-
ensurePrivateDir(
|
|
37362
|
+
ensurePrivateDir(path44.dirname(file));
|
|
37178
37363
|
const outcome = withFileLock(file, () => {
|
|
37179
37364
|
const current = readRecord(file);
|
|
37180
37365
|
const taken = current !== null && current.hostId !== this.id ? current : null;
|
|
@@ -37229,7 +37414,7 @@ var LeaseHost = class {
|
|
|
37229
37414
|
withFileLock(file, () => {
|
|
37230
37415
|
if (readRecord(file)?.hostId === this.id) fs19.rmSync(file, { force: true });
|
|
37231
37416
|
}, "release a session lease");
|
|
37232
|
-
fs19.rmdirSync(
|
|
37417
|
+
fs19.rmdirSync(path44.dirname(file));
|
|
37233
37418
|
} catch {
|
|
37234
37419
|
}
|
|
37235
37420
|
}
|
|
@@ -38175,7 +38360,9 @@ var TaskOrchestrator = class _TaskOrchestrator {
|
|
|
38175
38360
|
this.store.markPending(task2.id);
|
|
38176
38361
|
this.hold(task2.id, failure2.hold, false);
|
|
38177
38362
|
}
|
|
38178
|
-
|
|
38363
|
+
if (failure2.leaves !== "held" || !failure2.preserveWorktree) {
|
|
38364
|
+
await this.runs.release(task2.id, { keep: failure2.leaves === "failed" && failure2.keepWorktree });
|
|
38365
|
+
}
|
|
38179
38366
|
const { level, text: text6, toastOnly } = failure2.notice;
|
|
38180
38367
|
if (toastOnly) this.notifications[level](text6);
|
|
38181
38368
|
else this.tell(level, text6);
|
|
@@ -39988,8 +40175,8 @@ function codexWindow(slot, raw) {
|
|
|
39988
40175
|
|
|
39989
40176
|
// src/services/harness/claudeAccountLimits.ts
|
|
39990
40177
|
var import_child_process13 = require("child_process");
|
|
39991
|
-
var
|
|
39992
|
-
var
|
|
40178
|
+
var import_crypto19 = require("crypto");
|
|
40179
|
+
var import_fs14 = require("fs");
|
|
39993
40180
|
var import_os5 = require("os");
|
|
39994
40181
|
var import_path8 = require("path");
|
|
39995
40182
|
var DEFAULT_TIMEOUT_MS5 = 2e4;
|
|
@@ -40023,10 +40210,10 @@ function claudeAccountLimitCollector(options) {
|
|
|
40023
40210
|
};
|
|
40024
40211
|
}
|
|
40025
40212
|
async function readClaudeAccountLimits(options, signal) {
|
|
40026
|
-
const cwd = (0,
|
|
40213
|
+
const cwd = (0, import_fs14.mkdtempSync)((0, import_path8.join)((0, import_os5.tmpdir)(), "ordewell-claude-limits-"));
|
|
40027
40214
|
const removeCwd = () => {
|
|
40028
40215
|
try {
|
|
40029
|
-
(0,
|
|
40216
|
+
(0, import_fs14.rmSync)(cwd, { recursive: true, force: true });
|
|
40030
40217
|
} catch {
|
|
40031
40218
|
}
|
|
40032
40219
|
};
|
|
@@ -40068,7 +40255,7 @@ async function readClaudeAccountLimits(options, signal) {
|
|
|
40068
40255
|
}
|
|
40069
40256
|
function claudeAccountOwner(account) {
|
|
40070
40257
|
const email = isRecord11(account) ? text5(account.email) : void 0;
|
|
40071
|
-
if (!isRecord11(account) || !email) return `unnamed\0${(0,
|
|
40258
|
+
if (!isRecord11(account) || !email) return `unnamed\0${(0, import_crypto19.randomUUID)()}`;
|
|
40072
40259
|
return [text5(account.apiProvider) ?? "", email, text5(account.organization) ?? ""].join("\0");
|
|
40073
40260
|
}
|
|
40074
40261
|
function claudeLimitReading(usage, owner, accountPlan) {
|
|
@@ -40110,8 +40297,8 @@ function isoInstant(value) {
|
|
|
40110
40297
|
var import_os7 = require("os");
|
|
40111
40298
|
|
|
40112
40299
|
// src/services/harness/openCodeCredentials.ts
|
|
40113
|
-
var
|
|
40114
|
-
var
|
|
40300
|
+
var import_crypto20 = require("crypto");
|
|
40301
|
+
var import_fs15 = require("fs");
|
|
40115
40302
|
var import_os6 = require("os");
|
|
40116
40303
|
var import_path9 = require("path");
|
|
40117
40304
|
var import_worker_threads = require("worker_threads");
|
|
@@ -40168,7 +40355,7 @@ function walStore(path) {
|
|
|
40168
40355
|
parentPort.postMessage(select());
|
|
40169
40356
|
`;
|
|
40170
40357
|
var isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
40171
|
-
var digest = (...parts) => (0,
|
|
40358
|
+
var digest = (...parts) => (0, import_crypto20.createHash)("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
|
|
40172
40359
|
function openCodeStorePaths(env, home) {
|
|
40173
40360
|
const data = (0, import_path9.join)(env.XDG_DATA_HOME || (0, import_path9.join)(home, ".local", "share"), "opencode");
|
|
40174
40361
|
const file = env.OPENCODE_DB || "opencode.db";
|
|
@@ -40234,8 +40421,8 @@ function v2Login(db, row) {
|
|
|
40234
40421
|
login: { route: "console", owner: digest("console", db, row.id, account, orgID ?? ""), access: value.access, ...orgID ? { orgID } : {}, expires: value.expires }
|
|
40235
40422
|
};
|
|
40236
40423
|
}
|
|
40237
|
-
async function legacyLogin(
|
|
40238
|
-
const content = env.OPENCODE_AUTH_CONTENT ?? await readSmall(
|
|
40424
|
+
async function legacyLogin(path50, env) {
|
|
40425
|
+
const content = env.OPENCODE_AUTH_CONTENT ?? await readSmall(path50);
|
|
40239
40426
|
if (content === void 0) return env[ENV_KEY] ? { kind: "unsupported" } : { kind: "none" };
|
|
40240
40427
|
if (content === null) return { kind: "unreadable" };
|
|
40241
40428
|
const auth = parseJson(content);
|
|
@@ -40244,15 +40431,15 @@ async function legacyLogin(path48, env) {
|
|
|
40244
40431
|
if (entry === void 0) return env[ENV_KEY] ? { kind: "unsupported" } : { kind: "none" };
|
|
40245
40432
|
if (!isRecord12(entry) || entry.type !== "api") return { kind: "unsupported" };
|
|
40246
40433
|
if (typeof entry.key !== "string" || entry.key.length === 0) return { kind: "unreadable" };
|
|
40247
|
-
return { kind: "login", login: { route: "key", owner: digest("v1",
|
|
40434
|
+
return { kind: "login", login: { route: "key", owner: digest("v1", path50, entry.key), key: entry.key } };
|
|
40248
40435
|
}
|
|
40249
|
-
function queryStore(
|
|
40436
|
+
function queryStore(path50, signal, deps) {
|
|
40250
40437
|
return new Promise((settle) => {
|
|
40251
40438
|
let worker;
|
|
40252
40439
|
try {
|
|
40253
40440
|
worker = (deps.spawnWorker ?? ((source, options) => new import_worker_threads.Worker(source, options)))(WORKER_SOURCE, {
|
|
40254
40441
|
eval: true,
|
|
40255
|
-
workerData: { path:
|
|
40442
|
+
workerData: { path: path50, integrations: GO_INTEGRATIONS, busyMs: BUSY_MS, maxValueBytes: MAX_VALUE_BYTES },
|
|
40256
40443
|
execArgv: deps.workerExecArgv ?? [],
|
|
40257
40444
|
resourceLimits: { maxOldGenerationSizeMb: 64 }
|
|
40258
40445
|
});
|
|
@@ -40279,19 +40466,19 @@ function queryStore(path48, signal, deps) {
|
|
|
40279
40466
|
worker.once("exit", aborted);
|
|
40280
40467
|
});
|
|
40281
40468
|
}
|
|
40282
|
-
async function stamp(
|
|
40469
|
+
async function stamp(path50) {
|
|
40283
40470
|
try {
|
|
40284
|
-
const stat = await
|
|
40471
|
+
const stat = await import_fs15.promises.stat(path50);
|
|
40285
40472
|
return [stat.ino, stat.size, stat.mtimeMs];
|
|
40286
40473
|
} catch {
|
|
40287
40474
|
return null;
|
|
40288
40475
|
}
|
|
40289
40476
|
}
|
|
40290
|
-
async function readSmall(
|
|
40477
|
+
async function readSmall(path50) {
|
|
40291
40478
|
try {
|
|
40292
|
-
const stat = await
|
|
40479
|
+
const stat = await import_fs15.promises.stat(path50);
|
|
40293
40480
|
if (!stat.isFile() || stat.size > MAX_AUTH_FILE_BYTES) return null;
|
|
40294
|
-
return await
|
|
40481
|
+
return await import_fs15.promises.readFile(path50, "utf8");
|
|
40295
40482
|
} catch (err) {
|
|
40296
40483
|
return err.code === "ENOENT" ? void 0 : null;
|
|
40297
40484
|
}
|
|
@@ -41420,20 +41607,20 @@ function createAiService(config, deps) {
|
|
|
41420
41607
|
}
|
|
41421
41608
|
|
|
41422
41609
|
// src/services/createSession.ts
|
|
41423
|
-
var
|
|
41610
|
+
var path47 = __toESM(require("path"));
|
|
41424
41611
|
|
|
41425
41612
|
// src/services/handoffReferences.ts
|
|
41426
41613
|
var fs21 = __toESM(require("fs"));
|
|
41427
|
-
var
|
|
41614
|
+
var path45 = __toESM(require("path"));
|
|
41428
41615
|
var import_child_process15 = require("child_process");
|
|
41429
41616
|
function resolveHandoffReferences(handoff, workspace) {
|
|
41430
41617
|
const checked = /* @__PURE__ */ new Map();
|
|
41431
41618
|
const contained = (candidate) => {
|
|
41432
41619
|
try {
|
|
41433
41620
|
const root = fs21.realpathSync(workspace);
|
|
41434
|
-
const resolved = fs21.realpathSync(
|
|
41435
|
-
const relative17 =
|
|
41436
|
-
return relative17 !== ".." && !relative17.startsWith(`..${
|
|
41621
|
+
const resolved = fs21.realpathSync(path45.resolve(root, candidate));
|
|
41622
|
+
const relative17 = path45.relative(root, resolved);
|
|
41623
|
+
return relative17 !== ".." && !relative17.startsWith(`..${path45.sep}`) && !path45.isAbsolute(relative17) ? resolved : void 0;
|
|
41437
41624
|
} catch {
|
|
41438
41625
|
return void 0;
|
|
41439
41626
|
}
|
|
@@ -41454,7 +41641,7 @@ function resolveHandoffReferences(handoff, workspace) {
|
|
|
41454
41641
|
}
|
|
41455
41642
|
} else if (/^[0-9a-fA-F]{4,64}$/.test(ref.sha)) {
|
|
41456
41643
|
const repo = contained(ref.repo ?? ".");
|
|
41457
|
-
if (repo && fs21.existsSync(
|
|
41644
|
+
if (repo && fs21.existsSync(path45.join(repo, ".git"))) {
|
|
41458
41645
|
const result2 = (0, import_child_process15.spawnSync)("git", ["--no-optional-locks", "--no-replace-objects", "cat-file", "-t", ref.sha], {
|
|
41459
41646
|
cwd: repo,
|
|
41460
41647
|
encoding: "utf8",
|
|
@@ -42450,7 +42637,7 @@ function surfacePendingTurns(pending) {
|
|
|
42450
42637
|
function surfaceTask({ attemptSkills, subtasks, runnerSessionId: _runnerSessionId, ...task2 }) {
|
|
42451
42638
|
return {
|
|
42452
42639
|
...task2,
|
|
42453
|
-
...attemptSkills ? { attemptSkills: attemptSkills.map(({ name, source, path:
|
|
42640
|
+
...attemptSkills ? { attemptSkills: attemptSkills.map(({ name, source, path: path50 }) => ({ name, source, path: path50 })) } : {},
|
|
42454
42641
|
subtasks: (subtasks ?? []).map(surfaceTask)
|
|
42455
42642
|
};
|
|
42456
42643
|
}
|
|
@@ -43230,10 +43417,10 @@ var SessionEventRelay = class {
|
|
|
43230
43417
|
|
|
43231
43418
|
// src/utils/taskLogStore.ts
|
|
43232
43419
|
var fs22 = __toESM(require("fs"));
|
|
43233
|
-
var
|
|
43420
|
+
var path46 = __toESM(require("path"));
|
|
43234
43421
|
var EXTENSION = ".jsonl";
|
|
43235
43422
|
function taskDir({ baseDir, sessionId }, taskId) {
|
|
43236
|
-
return
|
|
43423
|
+
return path46.join(sessionDataDir(sessionId, baseDir), "tasks", idSegment(taskId));
|
|
43237
43424
|
}
|
|
43238
43425
|
function listTaskLogAttempts(location, taskId) {
|
|
43239
43426
|
let names;
|
|
@@ -43251,7 +43438,7 @@ function openTaskLog(location, taskId, attempt) {
|
|
|
43251
43438
|
const next = (listTaskLogAttempts(location, taskId).pop() ?? 0) + 1;
|
|
43252
43439
|
let number = attempt !== void 0 && Number.isInteger(attempt) && attempt >= 1 ? attempt : next;
|
|
43253
43440
|
for (; ; ) {
|
|
43254
|
-
const file =
|
|
43441
|
+
const file = path46.join(dir, `${number}${EXTENSION}`);
|
|
43255
43442
|
try {
|
|
43256
43443
|
fs22.writeFileSync(file, "", { flag: "wx" });
|
|
43257
43444
|
} catch (err) {
|
|
@@ -43275,15 +43462,15 @@ function prepareTaskOutputFile(location, taskId, attempt) {
|
|
|
43275
43462
|
ensureStateDirIgnored(location.baseDir);
|
|
43276
43463
|
const dir = taskDir(location, taskId);
|
|
43277
43464
|
fs22.mkdirSync(dir, { recursive: true });
|
|
43278
|
-
return
|
|
43465
|
+
return path46.join(dir, `${attempt}.output.txt`);
|
|
43279
43466
|
}
|
|
43280
43467
|
function taskPatchFile(location, taskId, attempt) {
|
|
43281
|
-
return
|
|
43468
|
+
return path46.join(taskDir(location, taskId), `${attempt}.patch`);
|
|
43282
43469
|
}
|
|
43283
43470
|
function saveTaskPatch(location, taskId, attempt, patch) {
|
|
43284
43471
|
ensureStateDirIgnored(location.baseDir);
|
|
43285
43472
|
const file = taskPatchFile(location, taskId, attempt);
|
|
43286
|
-
fs22.mkdirSync(
|
|
43473
|
+
fs22.mkdirSync(path46.dirname(file), { recursive: true });
|
|
43287
43474
|
const partial = `${file}.${process.pid}-${Date.now()}.partial`;
|
|
43288
43475
|
fs22.writeFileSync(partial, patch, { flag: "wx" });
|
|
43289
43476
|
fs22.renameSync(partial, file);
|
|
@@ -43304,7 +43491,7 @@ function readTaskLog(location, taskId, attempt) {
|
|
|
43304
43491
|
if (!Number.isInteger(attempt) || attempt < 1) return [];
|
|
43305
43492
|
let raw;
|
|
43306
43493
|
try {
|
|
43307
|
-
raw = fs22.readFileSync(
|
|
43494
|
+
raw = fs22.readFileSync(path46.join(taskDir(location, taskId), `${attempt}${EXTENSION}`), "utf-8");
|
|
43308
43495
|
} catch {
|
|
43309
43496
|
return [];
|
|
43310
43497
|
}
|
|
@@ -45366,7 +45553,7 @@ function createSession(deps) {
|
|
|
45366
45553
|
...deps.openTaskLog ? {} : {
|
|
45367
45554
|
keepPatch: (taskId, attempt, patch) => {
|
|
45368
45555
|
const location = session.taskLogLocation;
|
|
45369
|
-
return
|
|
45556
|
+
return path47.relative(location.baseDir, saveTaskPatch(location, taskId, attempt, patch)).split(path47.sep).join("/");
|
|
45370
45557
|
}
|
|
45371
45558
|
},
|
|
45372
45559
|
recordHandoff: (sessionId, taskId, handoff) => taskLogs.note(sessionId, taskId, { type: "handoff", handoff }),
|
|
@@ -49260,7 +49447,7 @@ var RunnerRegistry = class {
|
|
|
49260
49447
|
|
|
49261
49448
|
// src/plugins/removedPluginNotice.ts
|
|
49262
49449
|
var fs23 = __toESM(require("fs"));
|
|
49263
|
-
var
|
|
49450
|
+
var path48 = __toESM(require("path"));
|
|
49264
49451
|
function isManifestFile(file) {
|
|
49265
49452
|
try {
|
|
49266
49453
|
return fs23.statSync(file).isFile();
|
|
@@ -49269,10 +49456,10 @@ function isManifestFile(file) {
|
|
|
49269
49456
|
}
|
|
49270
49457
|
}
|
|
49271
49458
|
function removedPluginNotice(dataDir = globalDataDir()) {
|
|
49272
|
-
const directory =
|
|
49459
|
+
const directory = path48.join(dataDir, "plugins");
|
|
49273
49460
|
try {
|
|
49274
|
-
const hasManifest = isManifestFile(
|
|
49275
|
-
(entry) => (entry.isDirectory() || entry.isSymbolicLink()) && isManifestFile(
|
|
49461
|
+
const hasManifest = isManifestFile(path48.join(directory, "manifest.json")) || fs23.readdirSync(directory, { withFileTypes: true }).some(
|
|
49462
|
+
(entry) => (entry.isDirectory() || entry.isSymbolicLink()) && isManifestFile(path48.join(directory, entry.name, "manifest.json"))
|
|
49276
49463
|
);
|
|
49277
49464
|
if (hasManifest) return "Plugin runners were removed; manifests in ~/.ordewell/plugins/ are ignored. See the CHANGELOG.";
|
|
49278
49465
|
} catch {
|
|
@@ -49283,15 +49470,15 @@ function removedPluginNotice(dataDir = globalDataDir()) {
|
|
|
49283
49470
|
|
|
49284
49471
|
// src/utils/stateStore.ts
|
|
49285
49472
|
var fs24 = __toESM(require("fs"));
|
|
49286
|
-
var
|
|
49473
|
+
var path49 = __toESM(require("path"));
|
|
49287
49474
|
var STATE_FILE2 = "state.json";
|
|
49288
49475
|
function getStatePath(baseDir) {
|
|
49289
|
-
return
|
|
49476
|
+
return path49.join(getStateDir(baseDir), STATE_FILE2);
|
|
49290
49477
|
}
|
|
49291
49478
|
var SESSION_ID_KEY = "sessionId";
|
|
49292
49479
|
function saveState(plan, baseDir, sessionId) {
|
|
49293
49480
|
const statePath = getStatePath(baseDir ?? process.cwd());
|
|
49294
|
-
ensureDir(
|
|
49481
|
+
ensureDir(path49.dirname(statePath));
|
|
49295
49482
|
plan.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
49296
49483
|
const file = sessionId ? { ...plan, [SESSION_ID_KEY]: sessionId } : plan;
|
|
49297
49484
|
dropRetiredPlanFields(file);
|
|
@@ -49840,6 +50027,7 @@ var PlannerModelMemory = class {
|
|
|
49840
50027
|
repoBaseLine,
|
|
49841
50028
|
repoResultLines,
|
|
49842
50029
|
reposWithWork,
|
|
50030
|
+
repositoryRunnerConfigPaths,
|
|
49843
50031
|
researchShellWarning,
|
|
49844
50032
|
researchToolsPath,
|
|
49845
50033
|
resetInstalledPlanner,
|