@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.mjs
CHANGED
|
@@ -4358,7 +4358,7 @@ function pathRefs(command, opts = {}) {
|
|
|
4358
4358
|
return lexAll(command.trim(), dialect, opts.cdpathSet).segments.flatMap((seg) => {
|
|
4359
4359
|
const patterns = patternArgs(seg);
|
|
4360
4360
|
const cwd = seg.cwd ?? [];
|
|
4361
|
-
return [...seg.args.filter((_, i) => !patterns.has(i)), ...seg.inputs].flatMap(pathIn).map((
|
|
4361
|
+
return [...seg.args.filter((_, i) => !patterns.has(i)), ...seg.inputs].flatMap(pathIn).map((path49) => ({ path: path49, cwd }));
|
|
4362
4362
|
});
|
|
4363
4363
|
}
|
|
4364
4364
|
function excludedBy(command, allow, opts = {}) {
|
|
@@ -6442,7 +6442,7 @@ ${outcome.output}${outcome.success ? "" : `
|
|
|
6442
6442
|
}
|
|
6443
6443
|
let shell;
|
|
6444
6444
|
try {
|
|
6445
|
-
const sealed = site.task?.gitBefore ? { ...site.sealed, gitEntries: site.task.gitBefore.entries.map(({ path:
|
|
6445
|
+
const sealed = site.task?.gitBefore ? { ...site.sealed, gitEntries: site.task.gitBefore.entries.map(({ path: path49, directory }) => ({ path: path49, directory })) } : site.sealed;
|
|
6446
6446
|
shell = await site.sandbox.launchSealed(this.researchShell, sealed);
|
|
6447
6447
|
} catch (err) {
|
|
6448
6448
|
return { refused: refusal(`Command not run: its sealed sandbox could not be prepared (${err instanceof Error ? err.message : String(err)}).`) };
|
|
@@ -8225,9 +8225,9 @@ function claudeManagedSettingsDir(platform = process.platform) {
|
|
|
8225
8225
|
}
|
|
8226
8226
|
function readClaudeSettingsModels(files, platform = process.platform) {
|
|
8227
8227
|
const managed = claudeManagedSettingsDir(platform);
|
|
8228
|
-
const
|
|
8229
|
-
const dropIns = files.list(
|
|
8230
|
-
const ranked = [...dropIns.reverse(),
|
|
8228
|
+
const join45 = platform === "win32" ? path12.win32.join : path12.posix.join;
|
|
8229
|
+
const dropIns = files.list(join45(managed, "managed-settings.d")).filter((name) => name.endsWith(".json") && !name.startsWith(".")).sort().map((name) => join45(managed, "managed-settings.d", name));
|
|
8230
|
+
const ranked = [...dropIns.reverse(), join45(managed, "managed-settings.json"), join45(claudeConfigDir(files.env), "settings.json")];
|
|
8231
8231
|
for (const file of ranked) {
|
|
8232
8232
|
const content = files.read(file);
|
|
8233
8233
|
const lineup = content === null ? null : parseClaudeSettingsModels(content);
|
|
@@ -9088,12 +9088,12 @@ function checkpointReply(answer2) {
|
|
|
9088
9088
|
return { text: `The checkpoint was withdrawn: ${answer2.why}`, isError: true };
|
|
9089
9089
|
}
|
|
9090
9090
|
}
|
|
9091
|
-
function fieldPath(
|
|
9092
|
-
return
|
|
9091
|
+
function fieldPath(path49) {
|
|
9092
|
+
return path49.reduce((text4, part) => typeof part === "number" ? `${text4}[${part}]` : text4 ? `${text4}.${String(part)}` : String(part), "");
|
|
9093
9093
|
}
|
|
9094
|
-
function valueAt(value,
|
|
9094
|
+
function valueAt(value, path49) {
|
|
9095
9095
|
let current = value;
|
|
9096
|
-
for (const part of
|
|
9096
|
+
for (const part of path49) {
|
|
9097
9097
|
if (typeof part === "number") {
|
|
9098
9098
|
if (!Array.isArray(current)) return void 0;
|
|
9099
9099
|
current = current[part];
|
|
@@ -9115,7 +9115,7 @@ function boundedRefusal(issue, args) {
|
|
|
9115
9115
|
var LEAKED_PARAMETER = /<\/parameter>|<parameter\s+name\s*=\s*"([^"]*)">/g;
|
|
9116
9116
|
function leakedMarkupIn(value) {
|
|
9117
9117
|
const found = [];
|
|
9118
|
-
const walk = (node,
|
|
9118
|
+
const walk = (node, path49) => {
|
|
9119
9119
|
if (typeof node === "string") {
|
|
9120
9120
|
const names = [];
|
|
9121
9121
|
let closing = false;
|
|
@@ -9123,25 +9123,25 @@ function leakedMarkupIn(value) {
|
|
|
9123
9123
|
if (match[1] !== void 0) names.push(match[1]);
|
|
9124
9124
|
else closing = true;
|
|
9125
9125
|
}
|
|
9126
|
-
if (names.length > 0 || closing) found.push({ path:
|
|
9126
|
+
if (names.length > 0 || closing) found.push({ path: path49, names: [...new Set(names)], closing });
|
|
9127
9127
|
return;
|
|
9128
9128
|
}
|
|
9129
9129
|
if (Array.isArray(node)) {
|
|
9130
|
-
node.forEach((item, i) => walk(item, `${
|
|
9130
|
+
node.forEach((item, i) => walk(item, `${path49}[${i}]`));
|
|
9131
9131
|
return;
|
|
9132
9132
|
}
|
|
9133
9133
|
if (node !== null && typeof node === "object") {
|
|
9134
|
-
for (const [key, item] of Object.entries(node)) walk(item,
|
|
9134
|
+
for (const [key, item] of Object.entries(node)) walk(item, path49 ? `${path49}.${key}` : key);
|
|
9135
9135
|
}
|
|
9136
9136
|
};
|
|
9137
9137
|
walk(value, "");
|
|
9138
9138
|
return found;
|
|
9139
9139
|
}
|
|
9140
9140
|
function markupRefusal(leaks) {
|
|
9141
|
-
return leaks.map(({ path:
|
|
9141
|
+
return leaks.map(({ path: path49, names, closing }) => {
|
|
9142
9142
|
const tags = [...names.map((n) => `<parameter name="${n}">`), ...closing ? ["</parameter>"] : []];
|
|
9143
|
-
const guide = names.length > 0 ? ` The parameters ${names.map((n) => JSON.stringify(n)).join(", ")} are inside it; pass them as separate arguments, not inside ${
|
|
9144
|
-
return `${
|
|
9143
|
+
const guide = names.length > 0 ? ` The parameters ${names.map((n) => JSON.stringify(n)).join(", ")} are inside it; pass them as separate arguments, not inside ${path49}.` : " Pass each argument separately, not inside one string.";
|
|
9144
|
+
return `${path49} contains leaked tool-call markup: ${tags.join(", ")}.${guide}`;
|
|
9145
9145
|
}).join("\n");
|
|
9146
9146
|
}
|
|
9147
9147
|
function invalidArguments(name, error, args) {
|
|
@@ -9606,9 +9606,9 @@ function mcpClientConfig(credential) {
|
|
|
9606
9606
|
}
|
|
9607
9607
|
function ownerOnlyConfigFile(fileName, contents) {
|
|
9608
9608
|
const dir = mkdtempSync2(join9(tmpdir2(), "ordewell-mcp-"));
|
|
9609
|
-
const
|
|
9610
|
-
writeFileSync(
|
|
9611
|
-
return { path:
|
|
9609
|
+
const path49 = join9(dir, fileName);
|
|
9610
|
+
writeFileSync(path49, contents, { mode: 384 });
|
|
9611
|
+
return { path: path49, remove: () => rmSync2(dir, { recursive: true, force: true }) };
|
|
9612
9612
|
}
|
|
9613
9613
|
|
|
9614
9614
|
// src/services/harness/repoConfig.ts
|
|
@@ -9737,33 +9737,33 @@ var TomlReader = class {
|
|
|
9737
9737
|
if (this.i >= this.src.length) return root;
|
|
9738
9738
|
if (this.src.startsWith("[[", this.i)) {
|
|
9739
9739
|
this.i += 2;
|
|
9740
|
-
const
|
|
9740
|
+
const path49 = this.key();
|
|
9741
9741
|
this.expect("]]");
|
|
9742
|
-
const parent = this.tableAt(root,
|
|
9743
|
-
const last =
|
|
9742
|
+
const parent = this.tableAt(root, path49.slice(0, -1));
|
|
9743
|
+
const last = path49[path49.length - 1];
|
|
9744
9744
|
const list = Object.hasOwn(parent, last) ? parent[last] : parent[last] = [];
|
|
9745
|
-
if (!Array.isArray(list)) throw this.fail(`${
|
|
9745
|
+
if (!Array.isArray(list)) throw this.fail(`${path49.join(".")} is not an array of tables`);
|
|
9746
9746
|
table = newTable();
|
|
9747
9747
|
list.push(table);
|
|
9748
9748
|
} else if (this.src[this.i] === "[") {
|
|
9749
9749
|
this.i += 1;
|
|
9750
|
-
const
|
|
9750
|
+
const path49 = this.key();
|
|
9751
9751
|
this.expect("]");
|
|
9752
|
-
table = this.tableAt(root,
|
|
9752
|
+
table = this.tableAt(root, path49);
|
|
9753
9753
|
} else {
|
|
9754
|
-
const
|
|
9754
|
+
const path49 = this.key();
|
|
9755
9755
|
this.skipBlank(false);
|
|
9756
9756
|
this.expect("=");
|
|
9757
9757
|
this.skipBlank(false);
|
|
9758
|
-
const owner = this.tableAt(table,
|
|
9759
|
-
owner[
|
|
9758
|
+
const owner = this.tableAt(table, path49.slice(0, -1));
|
|
9759
|
+
owner[path49[path49.length - 1]] = this.value();
|
|
9760
9760
|
}
|
|
9761
9761
|
this.endOfLine();
|
|
9762
9762
|
}
|
|
9763
9763
|
}
|
|
9764
|
-
tableAt(from,
|
|
9764
|
+
tableAt(from, path49) {
|
|
9765
9765
|
let table = from;
|
|
9766
|
-
for (const part of
|
|
9766
|
+
for (const part of path49) {
|
|
9767
9767
|
const next = Object.hasOwn(table, part) ? table[part] : void 0;
|
|
9768
9768
|
if (next === void 0) table = table[part] = newTable();
|
|
9769
9769
|
else if (isRecord(next)) table = next;
|
|
@@ -9832,10 +9832,10 @@ var TomlReader = class {
|
|
|
9832
9832
|
this.i++;
|
|
9833
9833
|
return table;
|
|
9834
9834
|
}
|
|
9835
|
-
const
|
|
9835
|
+
const path49 = this.key();
|
|
9836
9836
|
this.expect("=");
|
|
9837
9837
|
this.skipBlank(false);
|
|
9838
|
-
this.tableAt(table,
|
|
9838
|
+
this.tableAt(table, path49.slice(0, -1))[path49[path49.length - 1]] = this.value();
|
|
9839
9839
|
this.skipBlank(true);
|
|
9840
9840
|
if (this.src[this.i] === ",") this.i++;
|
|
9841
9841
|
else if (this.src[this.i] !== "}") throw this.fail("expected , or } in an inline table");
|
|
@@ -10210,7 +10210,7 @@ var LineBuffer = class {
|
|
|
10210
10210
|
// src/services/harness/ClaudeCodeAdapter.ts
|
|
10211
10211
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
10212
10212
|
import { realpathSync as realpathSync7 } from "fs";
|
|
10213
|
-
import * as
|
|
10213
|
+
import * as path22 from "path";
|
|
10214
10214
|
|
|
10215
10215
|
// src/plugins/resolveArgs.ts
|
|
10216
10216
|
function claudeThinkingArgs(effort) {
|
|
@@ -10293,28 +10293,28 @@ function posixBinDirs() {
|
|
|
10293
10293
|
];
|
|
10294
10294
|
}
|
|
10295
10295
|
function windowsBinDirs(env, home) {
|
|
10296
|
-
const
|
|
10297
|
-
const under = (base, ...parts) => base ? [
|
|
10296
|
+
const join45 = (...parts) => path14.win32.join(...parts);
|
|
10297
|
+
const under = (base, ...parts) => base ? [join45(base, ...parts)] : [];
|
|
10298
10298
|
const appData = env.APPDATA;
|
|
10299
10299
|
const localAppData = env.LOCALAPPDATA;
|
|
10300
10300
|
const programData = env.ProgramData;
|
|
10301
10301
|
return [
|
|
10302
10302
|
// Native per-user installers, PowerShell-driven and otherwise.
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10303
|
+
join45(home, ".local", "bin"),
|
|
10304
|
+
join45(home, ".opencode", "bin"),
|
|
10305
|
+
join45(home, ".claude", "bin"),
|
|
10306
|
+
join45(home, ".codex", "bin"),
|
|
10307
10307
|
...under(localAppData, "Programs", "claude"),
|
|
10308
10308
|
// Node package managers. npm's global prefix is `%APPDATA%\npm`; the
|
|
10309
10309
|
// literal spelling is kept as a fallback for a host that does not export
|
|
10310
10310
|
// APPDATA (a service account, a stripped CI container).
|
|
10311
10311
|
...under(appData, "npm"),
|
|
10312
|
-
|
|
10312
|
+
join45(home, "AppData", "Roaming", "npm"),
|
|
10313
10313
|
...under(localAppData, "pnpm"),
|
|
10314
10314
|
...under(localAppData, "Yarn", "bin"),
|
|
10315
|
-
|
|
10315
|
+
join45(home, ".bun", "bin"),
|
|
10316
10316
|
// Windows package managers.
|
|
10317
|
-
|
|
10317
|
+
join45(home, "scoop", "shims"),
|
|
10318
10318
|
...under(env.SCOOP, "shims"),
|
|
10319
10319
|
...under(env.SCOOP_GLOBAL ?? programData, "scoop", "shims"),
|
|
10320
10320
|
...under(programData, "chocolatey", "bin"),
|
|
@@ -10324,7 +10324,7 @@ function windowsBinDirs(env, home) {
|
|
|
10324
10324
|
...under(localAppData, "Microsoft", "WindowsApps"),
|
|
10325
10325
|
// Version managers. Volta's Windows home is not the POSIX `~/.volta`.
|
|
10326
10326
|
...under(localAppData, "Volta", "bin"),
|
|
10327
|
-
|
|
10327
|
+
join45(home, ".volta", "bin")
|
|
10328
10328
|
];
|
|
10329
10329
|
}
|
|
10330
10330
|
function wellKnownBinDirs(deps = {}) {
|
|
@@ -11572,7 +11572,7 @@ function readOnlySessionRules(site) {
|
|
|
11572
11572
|
real = realpathSync4.native(root);
|
|
11573
11573
|
} catch {
|
|
11574
11574
|
}
|
|
11575
|
-
for (const
|
|
11575
|
+
for (const path49 of /* @__PURE__ */ new Set([root, real])) rules.push({ action: "external_directory", resource: `${path49.replace(/[\\/]$/, "")}/*`, effect: "allow" });
|
|
11576
11576
|
}
|
|
11577
11577
|
return rules;
|
|
11578
11578
|
}
|
|
@@ -12294,6 +12294,20 @@ ${lines.map((line) => `${line}
|
|
|
12294
12294
|
}
|
|
12295
12295
|
|
|
12296
12296
|
// src/services/harness/claudeOrdewell.ts
|
|
12297
|
+
import * as path20 from "path";
|
|
12298
|
+
function assertNoClaudeTaskCollision(cwd) {
|
|
12299
|
+
const text4 = readText(path20.join(cwd, ".mcp.json"));
|
|
12300
|
+
if (text4 === void 0) return;
|
|
12301
|
+
let parsed;
|
|
12302
|
+
try {
|
|
12303
|
+
parsed = JSON.parse(text4);
|
|
12304
|
+
} catch {
|
|
12305
|
+
return;
|
|
12306
|
+
}
|
|
12307
|
+
if (isRecord(parsed) && isRecord(parsed.mcpServers) && Object.hasOwn(parsed.mcpServers, ORDEWELL_MCP_SERVER_NAME)) {
|
|
12308
|
+
throw new Error(".mcp.json declares an MCP server named ordewell; rename or remove the ordewell server before starting this task.");
|
|
12309
|
+
}
|
|
12310
|
+
}
|
|
12297
12311
|
var CLAUDE_ORDEWELL = {
|
|
12298
12312
|
toolName: MCP_CLIENT_TOOL_NAMES.toolName,
|
|
12299
12313
|
toolNames: MCP_CLIENT_TOOL_NAMES.toolNames,
|
|
@@ -12441,8 +12455,8 @@ var ReplyRuns = class {
|
|
|
12441
12455
|
};
|
|
12442
12456
|
|
|
12443
12457
|
// src/services/harness/claudeRepoConfig.ts
|
|
12444
|
-
import * as
|
|
12445
|
-
var MEMORY_FILES = ["CLAUDE.md",
|
|
12458
|
+
import * as path21 from "path";
|
|
12459
|
+
var MEMORY_FILES = ["CLAUDE.md", path21.join(".claude", "CLAUDE.md"), "CLAUDE.local.md"];
|
|
12446
12460
|
var MAX_IMPORT_DEPTH = 5;
|
|
12447
12461
|
function importsOf(text4) {
|
|
12448
12462
|
const prose = text4.replace(/```[\s\S]*?```/g, "").replace(/`[^`\n]*`/g, "");
|
|
@@ -12453,11 +12467,11 @@ function withImports(workspace, file, depth, seen, into) {
|
|
|
12453
12467
|
seen.add(file);
|
|
12454
12468
|
const text4 = readText(file);
|
|
12455
12469
|
if (text4 === void 0) return;
|
|
12456
|
-
into.push({ path:
|
|
12470
|
+
into.push({ path: path21.relative(workspace, file), text: text4 });
|
|
12457
12471
|
if (depth >= MAX_IMPORT_DEPTH) return;
|
|
12458
12472
|
for (const target of importsOf(text4)) {
|
|
12459
12473
|
if (target.startsWith("~")) continue;
|
|
12460
|
-
const abs =
|
|
12474
|
+
const abs = path21.resolve(path21.dirname(file), target);
|
|
12461
12475
|
if (insideOnDisk(workspace, abs)) withImports(workspace, abs, depth + 1, seen, into);
|
|
12462
12476
|
}
|
|
12463
12477
|
}
|
|
@@ -12478,12 +12492,12 @@ var CLAUDE_REPO_CONFIG = {
|
|
|
12478
12492
|
instructions(workspace) {
|
|
12479
12493
|
const files = [];
|
|
12480
12494
|
const seen = /* @__PURE__ */ new Set();
|
|
12481
|
-
for (const name of MEMORY_FILES) withImports(workspace,
|
|
12495
|
+
for (const name of MEMORY_FILES) withImports(workspace, path21.join(workspace, name), 0, seen, files);
|
|
12482
12496
|
return files;
|
|
12483
12497
|
},
|
|
12484
12498
|
projectServers(workspace) {
|
|
12485
12499
|
const source = ".mcp.json";
|
|
12486
|
-
const text4 = readText(
|
|
12500
|
+
const text4 = readText(path21.join(workspace, source));
|
|
12487
12501
|
if (text4 === void 0) return NO_SERVERS;
|
|
12488
12502
|
let parsed;
|
|
12489
12503
|
try {
|
|
@@ -12503,12 +12517,12 @@ var CLAUDE_REPO_CONFIG = {
|
|
|
12503
12517
|
};
|
|
12504
12518
|
function claudeLocalServers(env, workspace) {
|
|
12505
12519
|
const configDir2 = env.CLAUDE_CONFIG_DIR?.trim();
|
|
12506
|
-
const file = expandRunnerHome(configDir2 ?
|
|
12520
|
+
const file = expandRunnerHome(configDir2 ? path21.join(configDir2, ".claude.json") : "~/.claude.json", env);
|
|
12507
12521
|
const text4 = file === null ? void 0 : readText(file);
|
|
12508
12522
|
if (text4 === void 0) return {};
|
|
12509
12523
|
try {
|
|
12510
12524
|
const parsed = JSON.parse(text4);
|
|
12511
|
-
const project = isRecord(parsed) && isRecord(parsed.projects) ? parsed.projects[
|
|
12525
|
+
const project = isRecord(parsed) && isRecord(parsed.projects) ? parsed.projects[path21.resolve(workspace)] : void 0;
|
|
12512
12526
|
return isRecord(project) && isRecord(project.mcpServers) ? project.mcpServers : {};
|
|
12513
12527
|
} catch {
|
|
12514
12528
|
return {};
|
|
@@ -12763,13 +12777,13 @@ var NO_AUTO_MEMORY = { CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1" };
|
|
|
12763
12777
|
function inSavedOutput(abs, configDir2, sessionId) {
|
|
12764
12778
|
let projects;
|
|
12765
12779
|
try {
|
|
12766
|
-
projects = realpathSync7.native(
|
|
12780
|
+
projects = realpathSync7.native(path22.join(configDir2, "projects"));
|
|
12767
12781
|
} catch {
|
|
12768
12782
|
return false;
|
|
12769
12783
|
}
|
|
12770
|
-
const rel =
|
|
12771
|
-
if (rel.startsWith("..") ||
|
|
12772
|
-
const [project, session, folder] = rel.split(
|
|
12784
|
+
const rel = path22.relative(projects, abs);
|
|
12785
|
+
if (rel.startsWith("..") || path22.isAbsolute(rel)) return false;
|
|
12786
|
+
const [project, session, folder] = rel.split(path22.sep);
|
|
12773
12787
|
return Boolean(project) && session === sessionId && folder === "tool-results";
|
|
12774
12788
|
}
|
|
12775
12789
|
var PATH_TOOLS = {
|
|
@@ -13060,6 +13074,7 @@ var ClaudeCodeAdapter = class extends StdioAgentAdapter {
|
|
|
13060
13074
|
*/
|
|
13061
13075
|
taskSpawnSpec(opts) {
|
|
13062
13076
|
const readOnly = readOnlyTask(opts);
|
|
13077
|
+
if (!readOnly) assertNoClaudeTaskCollision(opts.cwd);
|
|
13063
13078
|
this.readOnlySite = readOnly ? opts : null;
|
|
13064
13079
|
this.requestedMode = readOnly ? PLANNER_PERMISSION_MODE : opts.flags.permissionMode;
|
|
13065
13080
|
this.followedModel = opts.model;
|
|
@@ -13855,8 +13870,8 @@ function runProbe(deps, cwd, env, flags) {
|
|
|
13855
13870
|
}
|
|
13856
13871
|
|
|
13857
13872
|
// src/services/harness/codexRepoConfig.ts
|
|
13858
|
-
import * as
|
|
13859
|
-
var CONFIG_FILE =
|
|
13873
|
+
import * as path23 from "path";
|
|
13874
|
+
var CONFIG_FILE = path23.join(".codex", "config.toml");
|
|
13860
13875
|
function stringsOf(value) {
|
|
13861
13876
|
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
13862
13877
|
}
|
|
@@ -13882,9 +13897,9 @@ var CODEX_REPO_CONFIG = {
|
|
|
13882
13897
|
const files = [];
|
|
13883
13898
|
for (const dir of repoLevels(workspace)) {
|
|
13884
13899
|
for (const name of ["AGENTS.override.md", "AGENTS.md"]) {
|
|
13885
|
-
const text4 = readText(
|
|
13900
|
+
const text4 = readText(path23.join(dir, name));
|
|
13886
13901
|
if (text4 === void 0) continue;
|
|
13887
|
-
files.push({ path:
|
|
13902
|
+
files.push({ path: path23.relative(workspace, path23.join(dir, name)) || name, text: text4 });
|
|
13888
13903
|
break;
|
|
13889
13904
|
}
|
|
13890
13905
|
}
|
|
@@ -13895,10 +13910,10 @@ var CODEX_REPO_CONFIG = {
|
|
|
13895
13910
|
const byName = /* @__PURE__ */ new Map();
|
|
13896
13911
|
const unreadable = [];
|
|
13897
13912
|
for (const dir of repoLevels(workspace)) {
|
|
13898
|
-
const file =
|
|
13913
|
+
const file = path23.join(dir, CONFIG_FILE);
|
|
13899
13914
|
const text4 = readText(file);
|
|
13900
13915
|
if (text4 === void 0) continue;
|
|
13901
|
-
const source =
|
|
13916
|
+
const source = path23.relative(workspace, file);
|
|
13902
13917
|
let parsed;
|
|
13903
13918
|
try {
|
|
13904
13919
|
parsed = parseToml(text4);
|
|
@@ -13918,9 +13933,9 @@ var CODEX_REPO_CONFIG = {
|
|
|
13918
13933
|
};
|
|
13919
13934
|
function untrustedProjects(workspace) {
|
|
13920
13935
|
const projects = {};
|
|
13921
|
-
for (let dir =
|
|
13936
|
+
for (let dir = path23.resolve(workspace); ; dir = path23.dirname(dir)) {
|
|
13922
13937
|
projects[dir] = { trust_level: "untrusted" };
|
|
13923
|
-
if (
|
|
13938
|
+
if (path23.dirname(dir) === dir) return projects;
|
|
13924
13939
|
}
|
|
13925
13940
|
}
|
|
13926
13941
|
|
|
@@ -15041,7 +15056,7 @@ ${this.exitMessage()}`);
|
|
|
15041
15056
|
case "webSearch":
|
|
15042
15057
|
return;
|
|
15043
15058
|
case "fileChange": {
|
|
15044
|
-
const paths = (item.changes ?? []).map((change) => change.path).filter((
|
|
15059
|
+
const paths = (item.changes ?? []).map((change) => change.path).filter((path49) => !!path49);
|
|
15045
15060
|
this.fileChangePaths.set(item.id, paths);
|
|
15046
15061
|
if (this.startOpts?.kind === "task") {
|
|
15047
15062
|
for (const change of item.changes ?? []) this.announceFileChange(item.id, change, emit, subagentId);
|
|
@@ -15144,20 +15159,20 @@ ${this.exitMessage()}`);
|
|
|
15144
15159
|
announceFileChange(itemId, change, emit, subagentId) {
|
|
15145
15160
|
const rows = this.fileChangeRows.get(itemId) ?? /* @__PURE__ */ new Map();
|
|
15146
15161
|
this.fileChangeRows.set(itemId, rows);
|
|
15147
|
-
const
|
|
15148
|
-
const known = rows.get(
|
|
15162
|
+
const path49 = this.shownChangePath(change);
|
|
15163
|
+
const known = rows.get(path49);
|
|
15149
15164
|
if (known) return known;
|
|
15150
|
-
const row = rows.size === 0 ? itemId : `${itemId}:${
|
|
15151
|
-
rows.set(
|
|
15152
|
-
emit({ type: "tool_call", id: row, name: changeName(change), args: { path:
|
|
15165
|
+
const row = rows.size === 0 ? itemId : `${itemId}:${path49}`;
|
|
15166
|
+
rows.set(path49, row);
|
|
15167
|
+
emit({ type: "tool_call", id: row, name: changeName(change), args: { path: path49 }, ...subagentId ? { subagentId } : {} });
|
|
15153
15168
|
return row;
|
|
15154
15169
|
}
|
|
15155
15170
|
/** Relative to the task's worktree, where every path but a stray one lies; a move names both ends. */
|
|
15156
15171
|
shownChangePath(change) {
|
|
15157
|
-
const shown = (
|
|
15172
|
+
const shown = (path49) => {
|
|
15158
15173
|
const cwd = this.startOpts?.cwd;
|
|
15159
|
-
const rel = cwd ? relative8(cwd,
|
|
15160
|
-
return rel && rel !== ".." && !rel.startsWith(`..${sep3}`) && !isAbsolute6(rel) ? rel :
|
|
15174
|
+
const rel = cwd ? relative8(cwd, path49) : path49;
|
|
15175
|
+
return rel && rel !== ".." && !rel.startsWith(`..${sep3}`) && !isAbsolute6(rel) ? rel : path49;
|
|
15161
15176
|
};
|
|
15162
15177
|
const from = shown(change.path ?? "");
|
|
15163
15178
|
return change.kind?.move_path ? `${from} \u2192 ${shown(change.kind.move_path)}` : from;
|
|
@@ -15208,7 +15223,7 @@ import { realpathSync as realpathSync8 } from "fs";
|
|
|
15208
15223
|
|
|
15209
15224
|
// src/services/harness/projectServers.ts
|
|
15210
15225
|
import { createHash } from "crypto";
|
|
15211
|
-
import * as
|
|
15226
|
+
import * as path24 from "path";
|
|
15212
15227
|
function canonical2(value) {
|
|
15213
15228
|
if (Array.isArray(value)) return value.map(canonical2);
|
|
15214
15229
|
if (!isRecord(value)) return value;
|
|
@@ -15219,7 +15234,7 @@ function projectServerScope(server4) {
|
|
|
15219
15234
|
return `mcp-server:${server4.name}@${hash}`;
|
|
15220
15235
|
}
|
|
15221
15236
|
var scopeName = (scope) => scope.slice(0, scope.lastIndexOf("@"));
|
|
15222
|
-
function fileProjectServerApprovals(file =
|
|
15237
|
+
function fileProjectServerApprovals(file = path24.join(globalDataDir(), "project-mcp-servers.json")) {
|
|
15223
15238
|
const load = () => {
|
|
15224
15239
|
const text4 = readText(file);
|
|
15225
15240
|
if (text4 === void 0) return {};
|
|
@@ -16382,8 +16397,8 @@ var OpenCodeAdapter = class extends ProcessLifecycle {
|
|
|
16382
16397
|
this.v2 = new OpenCodeV2({
|
|
16383
16398
|
version,
|
|
16384
16399
|
nativeShell: this.nativeShell?.prefix ?? null,
|
|
16385
|
-
request: (method,
|
|
16386
|
-
json: (method,
|
|
16400
|
+
request: (method, path49, body, signal, timeoutMs) => this.request(method, path49, body, signal, timeoutMs),
|
|
16401
|
+
json: (method, path49, body, signal, timeoutMs) => this.json(method, path49, body, signal, timeoutMs),
|
|
16387
16402
|
openEvents: (signal) => this.deps.fetch(`${this.baseUrl}/api/event`, { signal, headers: this.headers() }),
|
|
16388
16403
|
processEnded: this.processEnded,
|
|
16389
16404
|
isExited: () => this.exited,
|
|
@@ -17020,15 +17035,15 @@ var OpenCodeAdapter = class extends ProcessLifecycle {
|
|
|
17020
17035
|
onActivity
|
|
17021
17036
|
);
|
|
17022
17037
|
}
|
|
17023
|
-
async json(method,
|
|
17024
|
-
const response = await this.request(method,
|
|
17025
|
-
if (!response.ok) throw new OpenCodeHttpError(`${method} ${
|
|
17038
|
+
async json(method, path49, body, signal, timeoutMs) {
|
|
17039
|
+
const response = await this.request(method, path49, body, signal, timeoutMs);
|
|
17040
|
+
if (!response.ok) throw new OpenCodeHttpError(`${method} ${path49} failed: ${response.status} ${response.statusText}`);
|
|
17026
17041
|
return await response.json().catch(() => null);
|
|
17027
17042
|
}
|
|
17028
17043
|
/** `timeoutMs` null is for a turn's own POST, which the server answers when the turn is done. */
|
|
17029
|
-
request(method,
|
|
17044
|
+
request(method, path49, body, signal, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
17030
17045
|
const deadline = withDeadline(signal, timeoutMs);
|
|
17031
|
-
return this.deps.fetch(`${this.baseUrl}${
|
|
17046
|
+
return this.deps.fetch(`${this.baseUrl}${path49}`, {
|
|
17032
17047
|
method,
|
|
17033
17048
|
headers: this.headers({ "content-type": "application/json" }),
|
|
17034
17049
|
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
@@ -17089,8 +17104,8 @@ var OpenCodeAdapter = class extends ProcessLifecycle {
|
|
|
17089
17104
|
};
|
|
17090
17105
|
|
|
17091
17106
|
// src/services/harness/openCodeRepoConfig.ts
|
|
17092
|
-
import * as
|
|
17093
|
-
var CONFIG_FILES = ["opencode.json", "opencode.jsonc",
|
|
17107
|
+
import * as path25 from "path";
|
|
17108
|
+
var CONFIG_FILES = ["opencode.json", "opencode.jsonc", path25.join(".opencode", "opencode.json"), path25.join(".opencode", "opencode.jsonc")];
|
|
17094
17109
|
var INSTRUCTION_NAMES = ["AGENTS.md", "CLAUDE.md", "CONTEXT.md"];
|
|
17095
17110
|
function server3(name, entry, source) {
|
|
17096
17111
|
if (!isRecord(entry)) return "not an object";
|
|
@@ -17109,8 +17124,8 @@ var OPENCODE_REPO_CONFIG = {
|
|
|
17109
17124
|
const levels = repoLevels(workspace);
|
|
17110
17125
|
for (const name of INSTRUCTION_NAMES) {
|
|
17111
17126
|
const files = levels.flatMap((dir) => {
|
|
17112
|
-
const text4 = readText(
|
|
17113
|
-
return text4 === void 0 ? [] : [{ path:
|
|
17127
|
+
const text4 = readText(path25.join(dir, name));
|
|
17128
|
+
return text4 === void 0 ? [] : [{ path: path25.relative(workspace, path25.join(dir, name)) || name, text: text4 }];
|
|
17114
17129
|
});
|
|
17115
17130
|
if (files.length > 0) return files;
|
|
17116
17131
|
}
|
|
@@ -17122,10 +17137,10 @@ var OPENCODE_REPO_CONFIG = {
|
|
|
17122
17137
|
const unreadable = [];
|
|
17123
17138
|
for (const dir of repoLevels(workspace)) {
|
|
17124
17139
|
for (const name of CONFIG_FILES) {
|
|
17125
|
-
const file =
|
|
17140
|
+
const file = path25.join(dir, name);
|
|
17126
17141
|
const text4 = readText(file);
|
|
17127
17142
|
if (text4 === void 0) continue;
|
|
17128
|
-
const source =
|
|
17143
|
+
const source = path25.relative(workspace, file);
|
|
17129
17144
|
let parsed;
|
|
17130
17145
|
try {
|
|
17131
17146
|
parsed = parseJsonc(text4);
|
|
@@ -17314,7 +17329,7 @@ function knownModelId(value, optionIds, shortcuts) {
|
|
|
17314
17329
|
|
|
17315
17330
|
// src/services/ModelCatalog.ts
|
|
17316
17331
|
import * as fs6 from "fs";
|
|
17317
|
-
import * as
|
|
17332
|
+
import * as path26 from "path";
|
|
17318
17333
|
var CACHE_KEY = "model-catalog";
|
|
17319
17334
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
17320
17335
|
function storageKey(baseUrl) {
|
|
@@ -17367,7 +17382,7 @@ var ModelCatalog = class {
|
|
|
17367
17382
|
const url = (baseUrl || "https://openrouter.ai/api/v1").replace(/\/+$/, "");
|
|
17368
17383
|
const key = storageKey(url);
|
|
17369
17384
|
const cacheDir = globalCacheDir();
|
|
17370
|
-
const cacheFile =
|
|
17385
|
+
const cacheFile = path26.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
17371
17386
|
if (fs6.existsSync(cacheFile)) fs6.rmSync(cacheFile);
|
|
17372
17387
|
} catch {
|
|
17373
17388
|
}
|
|
@@ -17375,7 +17390,7 @@ var ModelCatalog = class {
|
|
|
17375
17390
|
static readCache(key) {
|
|
17376
17391
|
try {
|
|
17377
17392
|
const cacheDir = globalCacheDir();
|
|
17378
|
-
const cacheFile =
|
|
17393
|
+
const cacheFile = path26.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
17379
17394
|
if (!fs6.existsSync(cacheFile)) return null;
|
|
17380
17395
|
const raw = fs6.readFileSync(cacheFile, "utf8");
|
|
17381
17396
|
const data = JSON.parse(raw);
|
|
@@ -17389,7 +17404,7 @@ var ModelCatalog = class {
|
|
|
17389
17404
|
try {
|
|
17390
17405
|
const cacheDir = globalCacheDir();
|
|
17391
17406
|
fs6.mkdirSync(cacheDir, { recursive: true });
|
|
17392
|
-
const cacheFile =
|
|
17407
|
+
const cacheFile = path26.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
17393
17408
|
fs6.writeFileSync(
|
|
17394
17409
|
cacheFile,
|
|
17395
17410
|
JSON.stringify({ models, cachedAt: Date.now() }, null, 2)
|
|
@@ -17400,7 +17415,7 @@ var ModelCatalog = class {
|
|
|
17400
17415
|
};
|
|
17401
17416
|
|
|
17402
17417
|
// src/services/ModelDiscovery.ts
|
|
17403
|
-
import * as
|
|
17418
|
+
import * as path27 from "path";
|
|
17404
17419
|
import { exec as exec2 } from "child_process";
|
|
17405
17420
|
import { promisify as promisify2 } from "util";
|
|
17406
17421
|
import * as fsSync5 from "fs";
|
|
@@ -17546,7 +17561,7 @@ function geminiDiscoveryCacheKey(apiKey) {
|
|
|
17546
17561
|
return {
|
|
17547
17562
|
key: `gemini-models:${hash}`,
|
|
17548
17563
|
dir,
|
|
17549
|
-
file:
|
|
17564
|
+
file: path27.join(dir, `gemini_models_${hash}.json`)
|
|
17550
17565
|
};
|
|
17551
17566
|
}
|
|
17552
17567
|
function readGeminiCache(apiKey) {
|
|
@@ -18054,7 +18069,7 @@ function parseMaxParallel(value) {
|
|
|
18054
18069
|
|
|
18055
18070
|
// src/services/SettingsService.ts
|
|
18056
18071
|
import * as fs12 from "fs";
|
|
18057
|
-
import * as
|
|
18072
|
+
import * as path34 from "path";
|
|
18058
18073
|
|
|
18059
18074
|
// src/utils/fileLock.ts
|
|
18060
18075
|
import * as fs7 from "fs";
|
|
@@ -18658,33 +18673,33 @@ ${skillBlock(entry.skill)}`, timestamp: entry.timestamp });
|
|
|
18658
18673
|
}
|
|
18659
18674
|
|
|
18660
18675
|
// src/services/taskSkills.ts
|
|
18661
|
-
import * as
|
|
18676
|
+
import * as path33 from "path";
|
|
18662
18677
|
|
|
18663
18678
|
// src/services/SkillsService.ts
|
|
18664
18679
|
import { createHash as createHash2 } from "crypto";
|
|
18665
18680
|
import * as fs11 from "fs";
|
|
18666
|
-
import * as
|
|
18681
|
+
import * as path32 from "path";
|
|
18667
18682
|
|
|
18668
18683
|
// src/services/builtinSkills.ts
|
|
18669
|
-
import * as
|
|
18684
|
+
import * as path28 from "path";
|
|
18670
18685
|
import { fileURLToPath } from "url";
|
|
18671
18686
|
function builtinSkillsDir() {
|
|
18672
|
-
const dir = typeof __dirname !== "undefined" && __dirname ? __dirname :
|
|
18687
|
+
const dir = typeof __dirname !== "undefined" && __dirname ? __dirname : path28.dirname(fileURLToPath(
|
|
18673
18688
|
// @ts-expect-error - import.meta is only valid under an ESM module setting
|
|
18674
18689
|
import.meta.url
|
|
18675
18690
|
));
|
|
18676
|
-
return
|
|
18691
|
+
return path28.join(dir, "..", "skills");
|
|
18677
18692
|
}
|
|
18678
18693
|
|
|
18679
18694
|
// src/services/repoGroup.ts
|
|
18680
18695
|
import * as fs10 from "fs";
|
|
18681
|
-
import * as
|
|
18696
|
+
import * as path31 from "path";
|
|
18682
18697
|
|
|
18683
18698
|
// src/services/worktreeBootstrap.ts
|
|
18684
18699
|
import { exec as exec3 } from "child_process";
|
|
18685
18700
|
import { promisify as promisify4 } from "util";
|
|
18686
18701
|
import * as fs9 from "fs";
|
|
18687
|
-
import * as
|
|
18702
|
+
import * as path30 from "path";
|
|
18688
18703
|
|
|
18689
18704
|
// src/services/gitExec.ts
|
|
18690
18705
|
import { execFile as execFile4 } from "child_process";
|
|
@@ -18766,7 +18781,7 @@ function subcommandOf2(args) {
|
|
|
18766
18781
|
|
|
18767
18782
|
// src/services/worktreeLink.ts
|
|
18768
18783
|
import * as fs8 from "fs";
|
|
18769
|
-
import * as
|
|
18784
|
+
import * as path29 from "path";
|
|
18770
18785
|
function linkPath(source, target, platform, hardLink = fs8.linkSync) {
|
|
18771
18786
|
const isDir = fs8.statSync(source).isDirectory();
|
|
18772
18787
|
if (platform !== "win32") {
|
|
@@ -18791,8 +18806,8 @@ function mirrorDir(source, target, opts) {
|
|
|
18791
18806
|
const mirror = (from, to, prefix, top) => {
|
|
18792
18807
|
fs8.mkdirSync(to, { recursive: true });
|
|
18793
18808
|
for (const entry of fs8.readdirSync(from, { withFileTypes: true })) {
|
|
18794
|
-
const name =
|
|
18795
|
-
const at = { from:
|
|
18809
|
+
const name = path29.join(prefix, entry.name);
|
|
18810
|
+
const at = { from: path29.join(from, entry.name), to: path29.join(to, entry.name), name };
|
|
18796
18811
|
if (entry.isSymbolicLink()) links.push(at);
|
|
18797
18812
|
else if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin")) mirror(at.from, at.to, name, false);
|
|
18798
18813
|
else if (linkPath(at.from, at.to, opts.platform, opts.hardLink) === "copy") copied.push(name);
|
|
@@ -18812,16 +18827,16 @@ function mirrorDir(source, target, opts) {
|
|
|
18812
18827
|
}
|
|
18813
18828
|
function relink(from, to, opts) {
|
|
18814
18829
|
const text4 = fs8.readlinkSync(from);
|
|
18815
|
-
const pointee =
|
|
18830
|
+
const pointee = path29.isAbsolute(text4) ? rebased(text4, opts) : text4;
|
|
18816
18831
|
if (opts.platform !== "win32") {
|
|
18817
|
-
if (!fs8.existsSync(
|
|
18818
|
-
fs8.symlinkSync(rebased(
|
|
18832
|
+
if (!fs8.existsSync(path29.resolve(path29.dirname(to), pointee)) && fs8.existsSync(path29.resolve(path29.dirname(from), pointee))) {
|
|
18833
|
+
fs8.symlinkSync(rebased(path29.resolve(path29.dirname(from), pointee), opts), to);
|
|
18819
18834
|
return "symlink";
|
|
18820
18835
|
}
|
|
18821
18836
|
fs8.symlinkSync(pointee, to);
|
|
18822
18837
|
return "symlink";
|
|
18823
18838
|
}
|
|
18824
|
-
const resolved = fs8.existsSync(
|
|
18839
|
+
const resolved = fs8.existsSync(path29.resolve(path29.dirname(to), pointee)) ? path29.resolve(path29.dirname(to), pointee) : rebased(path29.resolve(path29.dirname(from), pointee), opts);
|
|
18825
18840
|
try {
|
|
18826
18841
|
fs8.statSync(resolved);
|
|
18827
18842
|
} catch {
|
|
@@ -18830,9 +18845,9 @@ function relink(from, to, opts) {
|
|
|
18830
18845
|
return linkPath(resolved, to, opts.platform, opts.hardLink);
|
|
18831
18846
|
}
|
|
18832
18847
|
function rebased(pointee, opts) {
|
|
18833
|
-
const rel =
|
|
18834
|
-
const inside2 = rel !== "" && !rel.startsWith("..") && !
|
|
18835
|
-
return inside2 && !rel.split(/[\\/]/).includes("node_modules") ?
|
|
18848
|
+
const rel = path29.relative(opts.from, pointee);
|
|
18849
|
+
const inside2 = rel !== "" && !rel.startsWith("..") && !path29.isAbsolute(rel);
|
|
18850
|
+
return inside2 && !rel.split(/[\\/]/).includes("node_modules") ? path29.join(opts.to, rel) : pointee;
|
|
18836
18851
|
}
|
|
18837
18852
|
|
|
18838
18853
|
// src/services/worktreeBootstrap.ts
|
|
@@ -18869,18 +18884,18 @@ function matchLinks(root, patterns) {
|
|
|
18869
18884
|
}
|
|
18870
18885
|
function segmentMatches(root, base, segment) {
|
|
18871
18886
|
const under = (name) => base ? `${base}/${name}` : name;
|
|
18872
|
-
if (!/[*?]/.test(segment)) return lexists(
|
|
18887
|
+
if (!/[*?]/.test(segment)) return lexists(path30.join(root, base, segment)) ? [under(segment)] : [];
|
|
18873
18888
|
const pattern = new RegExp(`^${segment.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
|
|
18874
|
-
return listDir2(
|
|
18889
|
+
return listDir2(path30.join(root, base)).filter((name) => !NEVER_SCANNED.has(name) && pattern.test(name)).map(under);
|
|
18875
18890
|
}
|
|
18876
18891
|
function installDirs(root) {
|
|
18877
18892
|
const packages = matchLinks(root, workspaceGlobs(root)).map((pkg) => `${pkg}/node_modules`);
|
|
18878
|
-
return ["node_modules", ...packages].filter((dir) => lexists(
|
|
18893
|
+
return ["node_modules", ...packages].filter((dir) => lexists(path30.join(root, dir)));
|
|
18879
18894
|
}
|
|
18880
18895
|
function workspaceGlobs(root) {
|
|
18881
18896
|
let manifest;
|
|
18882
18897
|
try {
|
|
18883
|
-
manifest = JSON.parse(fs9.readFileSync(
|
|
18898
|
+
manifest = JSON.parse(fs9.readFileSync(path30.join(root, "package.json"), "utf8"));
|
|
18884
18899
|
} catch {
|
|
18885
18900
|
return [];
|
|
18886
18901
|
}
|
|
@@ -18895,19 +18910,19 @@ async function bootstrap(repo, cwd, opts) {
|
|
|
18895
18910
|
const linked = [];
|
|
18896
18911
|
const copied = [];
|
|
18897
18912
|
const link = (name) => {
|
|
18898
|
-
const target =
|
|
18913
|
+
const target = path30.join(cwd, name);
|
|
18899
18914
|
if (lexists(target)) return;
|
|
18900
|
-
fs9.mkdirSync(
|
|
18901
|
-
if (linkPath(
|
|
18915
|
+
fs9.mkdirSync(path30.dirname(target), { recursive: true });
|
|
18916
|
+
if (linkPath(path30.join(repo.root, name), target, opts.platform) === "copy") copied.push(name);
|
|
18902
18917
|
linked.push(name);
|
|
18903
18918
|
};
|
|
18904
18919
|
const mirror = (name) => {
|
|
18905
|
-
const target =
|
|
18906
|
-
if (lexists(target) || !fs9.existsSync(
|
|
18907
|
-
const source =
|
|
18920
|
+
const target = path30.join(cwd, name);
|
|
18921
|
+
if (lexists(target) || !fs9.existsSync(path30.dirname(target))) return;
|
|
18922
|
+
const source = path30.join(repo.root, name);
|
|
18908
18923
|
if (!fs9.lstatSync(source).isDirectory()) return link(name);
|
|
18909
18924
|
const mirrored = mirrorDir(source, target, { platform: opts.platform, from: repo.root, to: cwd });
|
|
18910
|
-
copied.push(...mirrored.map((entry) =>
|
|
18925
|
+
copied.push(...mirrored.map((entry) => path30.join(name, entry)));
|
|
18911
18926
|
linked.push(name);
|
|
18912
18927
|
};
|
|
18913
18928
|
if (!setup) {
|
|
@@ -18942,12 +18957,12 @@ async function runSetup(command, repo, cwd, resolvePath) {
|
|
|
18942
18957
|
|
|
18943
18958
|
// src/services/repoGroup.ts
|
|
18944
18959
|
function hasGitEntry(dir) {
|
|
18945
|
-
return fs10.existsSync(
|
|
18960
|
+
return fs10.existsSync(path31.join(dir, ".git"));
|
|
18946
18961
|
}
|
|
18947
18962
|
function groupPathOf(listed3) {
|
|
18948
18963
|
const slashed = listed3.trim().replace(/\\/g, "/");
|
|
18949
|
-
if (
|
|
18950
|
-
const rel =
|
|
18964
|
+
if (path31.posix.isAbsolute(slashed) || path31.win32.isAbsolute(slashed)) return null;
|
|
18965
|
+
const rel = path31.posix.normalize(slashed).replace(/\/+$/, "");
|
|
18951
18966
|
return rel === "" || rel === "." || rel === ".." || rel.startsWith("../") ? null : rel;
|
|
18952
18967
|
}
|
|
18953
18968
|
function childDirs(dir) {
|
|
@@ -18958,14 +18973,14 @@ function childDirs(dir) {
|
|
|
18958
18973
|
}
|
|
18959
18974
|
}
|
|
18960
18975
|
function groupPaths(workspaceRoot, listed3) {
|
|
18961
|
-
if (listed3.length === 0) return childDirs(workspaceRoot).filter((name) => hasGitEntry(
|
|
18962
|
-
const paths = listed3.map(groupPathOf).filter((rel) => rel !== null && hasGitEntry(
|
|
18976
|
+
if (listed3.length === 0) return childDirs(workspaceRoot).filter((name) => hasGitEntry(path31.join(workspaceRoot, name)));
|
|
18977
|
+
const paths = listed3.map(groupPathOf).filter((rel) => rel !== null && hasGitEntry(path31.join(workspaceRoot, rel)));
|
|
18963
18978
|
return [...new Set(paths)].sort();
|
|
18964
18979
|
}
|
|
18965
18980
|
function workspaceRepoGroup(workspaceRoot, listed3) {
|
|
18966
|
-
for (let dir =
|
|
18981
|
+
for (let dir = path31.resolve(workspaceRoot); ; dir = path31.dirname(dir)) {
|
|
18967
18982
|
if (hasGitEntry(dir)) return [SELF_REPO];
|
|
18968
|
-
if (
|
|
18983
|
+
if (path31.dirname(dir) === dir) break;
|
|
18969
18984
|
}
|
|
18970
18985
|
return groupPaths(workspaceRoot, listed3);
|
|
18971
18986
|
}
|
|
@@ -19046,8 +19061,8 @@ function copyDirSync(src, dest) {
|
|
|
19046
19061
|
fs11.mkdirSync(dest, { recursive: true });
|
|
19047
19062
|
const entries = fs11.readdirSync(src, { withFileTypes: true });
|
|
19048
19063
|
for (const entry of entries) {
|
|
19049
|
-
const srcPath =
|
|
19050
|
-
const destPath =
|
|
19064
|
+
const srcPath = path32.join(src, entry.name);
|
|
19065
|
+
const destPath = path32.join(dest, entry.name);
|
|
19051
19066
|
if (entry.isDirectory()) copyDirSync(srcPath, destPath);
|
|
19052
19067
|
else fs11.copyFileSync(srcPath, destPath);
|
|
19053
19068
|
}
|
|
@@ -19071,7 +19086,7 @@ function readDir(dir, source) {
|
|
|
19071
19086
|
if (!fs11.existsSync(dir)) return { skills, invalid };
|
|
19072
19087
|
for (const entry of fs11.readdirSync(dir, { withFileTypes: true })) {
|
|
19073
19088
|
if (!entry.isDirectory()) continue;
|
|
19074
|
-
const skillFile =
|
|
19089
|
+
const skillFile = path32.join(dir, entry.name, "SKILL.md");
|
|
19075
19090
|
if (!fs11.existsSync(skillFile)) continue;
|
|
19076
19091
|
if (!isSkillName(entry.name)) {
|
|
19077
19092
|
invalid.push({ name: entry.name, path: skillFile, source, reason: INVALID_SKILL_NAME_REASON });
|
|
@@ -19090,15 +19105,15 @@ function skillFileIn(dir, name) {
|
|
|
19090
19105
|
return void 0;
|
|
19091
19106
|
}
|
|
19092
19107
|
if (!entries.some((entry) => entry.isDirectory() && entry.name === name)) return void 0;
|
|
19093
|
-
const skillFile =
|
|
19108
|
+
const skillFile = path32.join(dir, name, "SKILL.md");
|
|
19094
19109
|
return fs11.existsSync(skillFile) ? skillFile : void 0;
|
|
19095
19110
|
}
|
|
19096
19111
|
function skillsDirOf(root) {
|
|
19097
|
-
return
|
|
19112
|
+
return path32.join(root, STATE_DIR, "skills");
|
|
19098
19113
|
}
|
|
19099
19114
|
function workspaceSkillRoots(workspaceRoot, repos, checkout = workspaceRoot) {
|
|
19100
19115
|
if (repos.length === 0 || repos.includes(SELF_REPO)) return [checkout];
|
|
19101
|
-
return [workspaceRoot, ...repos.map((repo) =>
|
|
19116
|
+
return [workspaceRoot, ...repos.map((repo) => path32.join(checkout, repo))];
|
|
19102
19117
|
}
|
|
19103
19118
|
var SkillsService = class _SkillsService {
|
|
19104
19119
|
workspaceRoots;
|
|
@@ -19121,11 +19136,11 @@ var SkillsService = class _SkillsService {
|
|
|
19121
19136
|
return this.workspaceRoots.map(skillsDirOf);
|
|
19122
19137
|
}
|
|
19123
19138
|
globalDir() {
|
|
19124
|
-
return
|
|
19139
|
+
return path32.join(globalDataDir(), "skills");
|
|
19125
19140
|
}
|
|
19126
19141
|
readSeedManifest() {
|
|
19127
19142
|
try {
|
|
19128
|
-
const parsed = JSON.parse(fs11.readFileSync(
|
|
19143
|
+
const parsed = JSON.parse(fs11.readFileSync(path32.join(this.globalDir(), SEED_MANIFEST), "utf8"));
|
|
19129
19144
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
19130
19145
|
return Object.fromEntries(
|
|
19131
19146
|
Object.entries(parsed).filter((entry) => typeof entry[1] === "string")
|
|
@@ -19141,7 +19156,7 @@ var SkillsService = class _SkillsService {
|
|
|
19141
19156
|
manifest[name] = hash;
|
|
19142
19157
|
try {
|
|
19143
19158
|
fs11.mkdirSync(this.globalDir(), { recursive: true });
|
|
19144
|
-
fs11.writeFileSync(
|
|
19159
|
+
fs11.writeFileSync(path32.join(this.globalDir(), SEED_MANIFEST), JSON.stringify(manifest, null, 2));
|
|
19145
19160
|
} catch (err) {
|
|
19146
19161
|
console.warn(`Could not record seeded skill ${name}: ${String(err)}`);
|
|
19147
19162
|
}
|
|
@@ -19152,11 +19167,11 @@ var SkillsService = class _SkillsService {
|
|
|
19152
19167
|
return this.readSeedManifest()[name] === currentHash || (PRIOR_BUILTIN_HASHES[name] ?? []).includes(currentHash);
|
|
19153
19168
|
}
|
|
19154
19169
|
seed(name) {
|
|
19155
|
-
const dest =
|
|
19170
|
+
const dest = path32.join(this.globalDir(), name);
|
|
19156
19171
|
const exists = fs11.existsSync(dest);
|
|
19157
19172
|
let srcDir;
|
|
19158
19173
|
try {
|
|
19159
|
-
srcDir =
|
|
19174
|
+
srcDir = path32.join(builtinSkillsDir(), name);
|
|
19160
19175
|
} catch (err) {
|
|
19161
19176
|
if (!exists) console.warn(`Could not locate built-in skills dir: ${String(err)}`);
|
|
19162
19177
|
return false;
|
|
@@ -19165,9 +19180,9 @@ var SkillsService = class _SkillsService {
|
|
|
19165
19180
|
if (!exists) console.warn(`Built-in skill not found in package: ${name}`);
|
|
19166
19181
|
return false;
|
|
19167
19182
|
}
|
|
19168
|
-
const srcHash = fileHash(
|
|
19183
|
+
const srcHash = fileHash(path32.join(srcDir, "SKILL.md"));
|
|
19169
19184
|
if (exists) {
|
|
19170
|
-
const currentHash = fileHash(
|
|
19185
|
+
const currentHash = fileHash(path32.join(dest, "SKILL.md"));
|
|
19171
19186
|
if (currentHash !== void 0 && currentHash === srcHash) {
|
|
19172
19187
|
this.recordSeed(name, currentHash);
|
|
19173
19188
|
return false;
|
|
@@ -19211,7 +19226,7 @@ var SkillsService = class _SkillsService {
|
|
|
19211
19226
|
if (entries.length !== 1 || entries[0].name !== "SKILL.md" || !entries[0].isFile()) return false;
|
|
19212
19227
|
let raw;
|
|
19213
19228
|
try {
|
|
19214
|
-
raw = readSkillText(
|
|
19229
|
+
raw = readSkillText(path32.join(dir, "SKILL.md"));
|
|
19215
19230
|
} catch {
|
|
19216
19231
|
return false;
|
|
19217
19232
|
}
|
|
@@ -19219,7 +19234,7 @@ var SkillsService = class _SkillsService {
|
|
|
19219
19234
|
}
|
|
19220
19235
|
pruneRetired() {
|
|
19221
19236
|
for (const name of RETIRED_BUILTIN_SKILL_NAMES) {
|
|
19222
|
-
const dest =
|
|
19237
|
+
const dest = path32.join(this.globalDir(), name);
|
|
19223
19238
|
if (!fs11.existsSync(dest)) continue;
|
|
19224
19239
|
if (!this.isUnmodifiedRetiredSeed(dest, name)) continue;
|
|
19225
19240
|
try {
|
|
@@ -19357,12 +19372,12 @@ var runGit = execFileWithTimeout(1e4);
|
|
|
19357
19372
|
async function committedInHead(files) {
|
|
19358
19373
|
const byDir = /* @__PURE__ */ new Map();
|
|
19359
19374
|
for (const file of new Set(files)) {
|
|
19360
|
-
const dir =
|
|
19375
|
+
const dir = path33.dirname(path33.dirname(file));
|
|
19361
19376
|
byDir.set(dir, [...byDir.get(dir) ?? [], file]);
|
|
19362
19377
|
}
|
|
19363
19378
|
const result = /* @__PURE__ */ new Map();
|
|
19364
19379
|
await Promise.all([...byDir].map(async ([dir, inDir]) => {
|
|
19365
|
-
const relative17 = (file) =>
|
|
19380
|
+
const relative17 = (file) => path33.relative(dir, file).split(path33.sep).join("/");
|
|
19366
19381
|
try {
|
|
19367
19382
|
const { stdout } = await runGit("git", ["ls-tree", "--name-only", "HEAD", "--", ...inDir.map(relative17)], { cwd: dir, env: cleanEnv() });
|
|
19368
19383
|
const listed3 = new Set(stdout.split("\n").map((line) => line.trim()).filter(Boolean));
|
|
@@ -19382,9 +19397,9 @@ function plannedSkillLookup(skillsAt, workspaceRoot, layout) {
|
|
|
19382
19397
|
searchedDirs: () => lookup2.searchedDirs(),
|
|
19383
19398
|
listSkills: () => lookup2.listSkills(),
|
|
19384
19399
|
uncommitted: async (skills) => {
|
|
19385
|
-
const checked = skills.filter((skill) => skill.source === "workspace" && !(readInPlace &&
|
|
19400
|
+
const checked = skills.filter((skill) => skill.source === "workspace" && !(readInPlace && path33.dirname(path33.dirname(skill.path)) === readInPlace));
|
|
19386
19401
|
const committed = await committedInHead(checked.map((skill) => skill.path));
|
|
19387
|
-
return new Map(checked.filter((skill) => committed.get(skill.path) === false).map((skill) => [skill.path,
|
|
19402
|
+
return new Map(checked.filter((skill) => committed.get(skill.path) === false).map((skill) => [skill.path, path33.relative(workspaceRoot, path33.dirname(skill.path)).split(path33.sep).join("/")]));
|
|
19388
19403
|
}
|
|
19389
19404
|
};
|
|
19390
19405
|
}
|
|
@@ -19397,13 +19412,13 @@ function checkPlanSkills(tasks, lookup2) {
|
|
|
19397
19412
|
function checkTaskSkillsEdit(task2, skills, lookup2) {
|
|
19398
19413
|
return check([{ taskId: task2.id, owner: `Task "${task2.title}"`, ...attached(skills) }], lookup2);
|
|
19399
19414
|
}
|
|
19400
|
-
function subtaskEntries(op, spec,
|
|
19415
|
+
function subtaskEntries(op, spec, path49 = []) {
|
|
19401
19416
|
const subtasks = spec?.subtasks;
|
|
19402
19417
|
if (!Array.isArray(subtasks)) return [];
|
|
19403
19418
|
return subtasks.flatMap((sub, i) => {
|
|
19404
19419
|
if (typeof sub !== "object" || sub === null) return [];
|
|
19405
19420
|
const child = sub;
|
|
19406
|
-
const at = [...
|
|
19421
|
+
const at = [...path49, typeof child.title === "string" && child.title.trim() ? `"${child.title}"` : `#${i + 1}`];
|
|
19407
19422
|
return [{ op, owner: `subtask ${at.join(" > ")}`, ...attached(child.skills) }, ...subtaskEntries(op, child, at)];
|
|
19408
19423
|
});
|
|
19409
19424
|
}
|
|
@@ -23245,7 +23260,7 @@ var RUN_SETTING_KEYS = Object.keys(RUN_SETTING_CHECKS);
|
|
|
23245
23260
|
function getSettingsPath() {
|
|
23246
23261
|
const override = process.env.ORDEWELL_SETTINGS_PATH;
|
|
23247
23262
|
if (override && override.trim()) return override.trim();
|
|
23248
|
-
return
|
|
23263
|
+
return path34.join(globalDataDir(), "settings.json");
|
|
23249
23264
|
}
|
|
23250
23265
|
function readPlannerModels(raw) {
|
|
23251
23266
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
@@ -23325,8 +23340,8 @@ var SettingsService = class {
|
|
|
23325
23340
|
* a watch on the old one pointing at nothing.
|
|
23326
23341
|
*/
|
|
23327
23342
|
watch(listener) {
|
|
23328
|
-
const dir =
|
|
23329
|
-
const name =
|
|
23343
|
+
const dir = path34.dirname(this.filePath);
|
|
23344
|
+
const name = path34.basename(this.filePath);
|
|
23330
23345
|
let seen = this.fileStamp();
|
|
23331
23346
|
let timer;
|
|
23332
23347
|
let dead = false;
|
|
@@ -23335,7 +23350,7 @@ var SettingsService = class {
|
|
|
23335
23350
|
fs12.mkdirSync(dir, { recursive: true });
|
|
23336
23351
|
watcher = fs12.watch(dir, (_event, changed) => {
|
|
23337
23352
|
if (dead) return;
|
|
23338
|
-
if (changed && changed !== name && changed !==
|
|
23353
|
+
if (changed && changed !== name && changed !== path34.basename(dir)) return;
|
|
23339
23354
|
clearTimeout(timer);
|
|
23340
23355
|
timer = setTimeout(() => {
|
|
23341
23356
|
const stamp2 = this.fileStamp();
|
|
@@ -23568,7 +23583,7 @@ var SettingsService = class {
|
|
|
23568
23583
|
if (this.unreadable) {
|
|
23569
23584
|
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.`);
|
|
23570
23585
|
}
|
|
23571
|
-
const dir =
|
|
23586
|
+
const dir = path34.dirname(this.filePath);
|
|
23572
23587
|
if (!fs12.existsSync(dir)) {
|
|
23573
23588
|
fs12.mkdirSync(dir, { recursive: true });
|
|
23574
23589
|
}
|
|
@@ -24085,11 +24100,11 @@ var EnvConfig = class extends BaseConfig {
|
|
|
24085
24100
|
// src/services/taskDiffRead.ts
|
|
24086
24101
|
import { createHash as createHash3 } from "crypto";
|
|
24087
24102
|
import * as fs13 from "fs";
|
|
24088
|
-
import * as
|
|
24103
|
+
import * as path35 from "path";
|
|
24089
24104
|
import { devNull } from "os";
|
|
24090
24105
|
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).";
|
|
24091
24106
|
function allowedPath(file) {
|
|
24092
|
-
return file.length > 0 && !
|
|
24107
|
+
return file.length > 0 && !path35.isAbsolute(file) && !/^[A-Za-z]:/.test(file) && !file.split(/[\\/]/).some((part) => part === ".." || part === ".git" || part === ".ordewell");
|
|
24093
24108
|
}
|
|
24094
24109
|
function stats(raw) {
|
|
24095
24110
|
return raw.split("\0").flatMap((row) => {
|
|
@@ -24098,8 +24113,8 @@ function stats(raw) {
|
|
|
24098
24113
|
});
|
|
24099
24114
|
}
|
|
24100
24115
|
function inside(root, target) {
|
|
24101
|
-
const rel =
|
|
24102
|
-
return rel === "" || !rel.startsWith(`..${
|
|
24116
|
+
const rel = path35.relative(root, target);
|
|
24117
|
+
return rel === "" || !rel.startsWith(`..${path35.sep}`) && rel !== ".." && !path35.isAbsolute(rel);
|
|
24103
24118
|
}
|
|
24104
24119
|
function unquoted(quoted4) {
|
|
24105
24120
|
const bytes = [];
|
|
@@ -24147,10 +24162,10 @@ function patchFiles(patch) {
|
|
|
24147
24162
|
const sections = patch.toString("utf8").split(/(?<![^\n])(?=diff --git )/).filter((section) => section.startsWith("diff --git "));
|
|
24148
24163
|
const files = /* @__PURE__ */ new Map();
|
|
24149
24164
|
for (const section of sections) {
|
|
24150
|
-
const
|
|
24165
|
+
const path49 = sectionPath(section);
|
|
24151
24166
|
const counts = sectionStats(section);
|
|
24152
|
-
const earlier = files.get(
|
|
24153
|
-
files.set(
|
|
24167
|
+
const earlier = files.get(path49);
|
|
24168
|
+
files.set(path49, earlier ? { path: path49, section: earlier.section + section, added: summed(earlier.added, counts.added), removed: summed(earlier.removed, counts.removed) } : { path: path49, section, ...counts });
|
|
24154
24169
|
}
|
|
24155
24170
|
return [...files.values()];
|
|
24156
24171
|
}
|
|
@@ -24220,11 +24235,11 @@ async function readTaskDiff(invoker, run, taskId, options) {
|
|
|
24220
24235
|
files.push({ ...file, repo: repo.path, patch: () => git(reader, cwd, [...diffArgs, "--", `:(top,literal)${prefix}${file.path}`]) });
|
|
24221
24236
|
}
|
|
24222
24237
|
if (live2) {
|
|
24223
|
-
const workspace =
|
|
24238
|
+
const workspace = path35.join(entry.worktree, prefix);
|
|
24224
24239
|
const others = await git(reader, workspace, [...common, "ls-files", "--others", "--exclude-standard", "-z", "--", "."]);
|
|
24225
24240
|
for (const file of others.split("\0").filter((f) => allowed(f))) {
|
|
24226
|
-
const full =
|
|
24227
|
-
if (!inside(fs13.realpathSync(workspace), fs13.realpathSync(
|
|
24241
|
+
const full = path35.join(workspace, file);
|
|
24242
|
+
if (!inside(fs13.realpathSync(workspace), fs13.realpathSync(path35.dirname(full)))) continue;
|
|
24228
24243
|
const untracked = async (numstat) => {
|
|
24229
24244
|
const result = await tryGit(reader, workspace, [...common, "diff", "--no-index", "--no-renames", "--no-ext-diff", "--no-textconv", ...numstat ? ["--numstat", "-z"] : [], "--", devNull, file]);
|
|
24230
24245
|
if (!result.ok && result.code !== 1) throw new Error(result.stderr.trim() || "Could not read an untracked file diff.");
|
|
@@ -24254,11 +24269,11 @@ ${await file.patch()}`);
|
|
|
24254
24269
|
import { randomBytes as randomBytes6 } from "crypto";
|
|
24255
24270
|
import { spawnSync } from "child_process";
|
|
24256
24271
|
import * as fs15 from "fs";
|
|
24257
|
-
import * as
|
|
24272
|
+
import * as path37 from "path";
|
|
24258
24273
|
|
|
24259
24274
|
// src/utils/prdStore.ts
|
|
24260
24275
|
import * as fs14 from "fs";
|
|
24261
|
-
import * as
|
|
24276
|
+
import * as path36 from "path";
|
|
24262
24277
|
var PRD_BLOCK_RE = /<!--\s*ORDEWELL_PRD_START\s+slug="([^"]+)"\s*-->\s*([\s\S]*?)\s*<!--\s*ORDEWELL_PRD_END\s*-->/;
|
|
24263
24278
|
function extractPrdBlock(text4) {
|
|
24264
24279
|
const match = PRD_BLOCK_RE.exec(text4);
|
|
@@ -24272,9 +24287,9 @@ function sanitizeSlug(raw) {
|
|
|
24272
24287
|
return raw.toLowerCase().replace(/[^a-z0-9-_]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
24273
24288
|
}
|
|
24274
24289
|
function savePrdMarkdown(workspace, slug, markdown) {
|
|
24275
|
-
const dir =
|
|
24290
|
+
const dir = path36.join(workspace, ".scratch", sanitizeSlug(slug));
|
|
24276
24291
|
fs14.mkdirSync(dir, { recursive: true });
|
|
24277
|
-
const file =
|
|
24292
|
+
const file = path36.join(dir, "PRD.md");
|
|
24278
24293
|
fs14.writeFileSync(file, markdown.endsWith("\n") ? markdown : markdown + "\n", "utf8");
|
|
24279
24294
|
return file;
|
|
24280
24295
|
}
|
|
@@ -24306,12 +24321,12 @@ var NESTED_REPO_DEPTH = 2;
|
|
|
24306
24321
|
var GITLINK_MODE = "160000";
|
|
24307
24322
|
var READ_ONLY = ["--no-optional-locks", "-c", "core.fsmonitor=false"];
|
|
24308
24323
|
function isInside(parent, child) {
|
|
24309
|
-
const rel =
|
|
24310
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
24324
|
+
const rel = path37.relative(parent, child);
|
|
24325
|
+
return rel !== "" && !rel.startsWith("..") && !path37.isAbsolute(rel);
|
|
24311
24326
|
}
|
|
24312
24327
|
function resolvesAsNamed(base, p) {
|
|
24313
24328
|
try {
|
|
24314
|
-
return fs15.realpathSync(p) ===
|
|
24329
|
+
return fs15.realpathSync(p) === path37.join(fs15.realpathSync(base), path37.relative(base, p));
|
|
24315
24330
|
} catch {
|
|
24316
24331
|
return false;
|
|
24317
24332
|
}
|
|
@@ -24366,7 +24381,7 @@ function sameDir(a, b) {
|
|
|
24366
24381
|
try {
|
|
24367
24382
|
return fs15.realpathSync.native(p);
|
|
24368
24383
|
} catch {
|
|
24369
|
-
return
|
|
24384
|
+
return path37.resolve(p);
|
|
24370
24385
|
}
|
|
24371
24386
|
};
|
|
24372
24387
|
return real(a) === real(b);
|
|
@@ -24388,7 +24403,7 @@ function clearImmutableFlags(platform, dir) {
|
|
|
24388
24403
|
spawnSync("/usr/bin/chflags", ["-R", "nouchg", dir], { stdio: "ignore" });
|
|
24389
24404
|
}
|
|
24390
24405
|
function leftoverLinks(dir) {
|
|
24391
|
-
const named3 = listDir2(dir).filter((name) => LINKED_ARTIFACTS.has(name) || isEnvFile(name) || isLink(
|
|
24406
|
+
const named3 = listDir2(dir).filter((name) => LINKED_ARTIFACTS.has(name) || isEnvFile(name) || isLink(path37.join(dir, name)));
|
|
24392
24407
|
return [.../* @__PURE__ */ new Set([...named3, ...installDirs(dir)])];
|
|
24393
24408
|
}
|
|
24394
24409
|
function isLink(target) {
|
|
@@ -24461,7 +24476,7 @@ var GitWorktreeIsolation = class {
|
|
|
24461
24476
|
const head = await this.headOf(root);
|
|
24462
24477
|
const repo = { path: repoPath, head };
|
|
24463
24478
|
if (scan.toplevel !== void 0) {
|
|
24464
|
-
const top =
|
|
24479
|
+
const top = path37.relative(workspaceRoot, scan.toplevel).split(path37.sep).join("/");
|
|
24465
24480
|
if (top !== "") repo.top = top;
|
|
24466
24481
|
}
|
|
24467
24482
|
if (enabled && (head.kind === "branch" || head.kind === "detached")) {
|
|
@@ -24518,9 +24533,9 @@ var GitWorktreeIsolation = class {
|
|
|
24518
24533
|
async nestedRepos(workspaceRoot, toplevel) {
|
|
24519
24534
|
const found = [];
|
|
24520
24535
|
const walk = (rel, depth) => {
|
|
24521
|
-
for (const name of childDirs(
|
|
24536
|
+
for (const name of childDirs(path37.join(workspaceRoot, rel))) {
|
|
24522
24537
|
const child = rel ? `${rel}/${name}` : name;
|
|
24523
|
-
if (hasGitEntry(
|
|
24538
|
+
if (hasGitEntry(path37.join(workspaceRoot, child))) found.push(child);
|
|
24524
24539
|
else if (depth < NESTED_REPO_DEPTH) walk(child, depth + 1);
|
|
24525
24540
|
}
|
|
24526
24541
|
};
|
|
@@ -24538,7 +24553,7 @@ var GitWorktreeIsolation = class {
|
|
|
24538
24553
|
const [meta, file] = entry.split(" ");
|
|
24539
24554
|
if (file !== void 0 && meta.startsWith(`${GITLINK_MODE} `)) paths.add(file);
|
|
24540
24555
|
}
|
|
24541
|
-
const declared = await this.tryGit(workspaceRoot, ["config", "-z", "-f",
|
|
24556
|
+
const declared = await this.tryGit(workspaceRoot, ["config", "-z", "-f", path37.join(toplevel, ".gitmodules"), "--get-regexp", "^submodule\\..*\\.path$"]);
|
|
24542
24557
|
for (const entry of declared.stdout.split("\0")) {
|
|
24543
24558
|
const value = entry.split("\n")[1];
|
|
24544
24559
|
if (value) paths.add(value.replace(/\/+$/, ""));
|
|
@@ -24596,7 +24611,7 @@ var GitWorktreeIsolation = class {
|
|
|
24596
24611
|
async acceptsWorktree(run, repo) {
|
|
24597
24612
|
const dir = this.integrationDir(run, repo);
|
|
24598
24613
|
ensureStateDirIgnored(run.workspaceRoot);
|
|
24599
|
-
fs15.mkdirSync(
|
|
24614
|
+
fs15.mkdirSync(path37.dirname(dir), { recursive: true });
|
|
24600
24615
|
const added = await this.tryGit(repo.root, ["worktree", "add", "-q", "--no-checkout", dir, repo.integrationBranch]);
|
|
24601
24616
|
await this.removeWorktreeDir(run, repo, dir, []);
|
|
24602
24617
|
return added.ok;
|
|
@@ -24611,12 +24626,12 @@ var GitWorktreeIsolation = class {
|
|
|
24611
24626
|
if (isolated.includes(SELF_REPO)) return [];
|
|
24612
24627
|
const shared2 = [];
|
|
24613
24628
|
const walk = (rel) => {
|
|
24614
|
-
for (const name of listDir2(
|
|
24629
|
+
for (const name of listDir2(path37.join(workspaceRoot, rel))) {
|
|
24615
24630
|
if (!rel && (name === STATE_DIR || name === ".git")) continue;
|
|
24616
24631
|
const child = rel ? `${rel}/${name}` : name;
|
|
24617
24632
|
if (isolated.includes(child)) continue;
|
|
24618
24633
|
if (isolated.some((p) => p.startsWith(`${child}/`))) walk(child);
|
|
24619
|
-
else if (resolves(
|
|
24634
|
+
else if (resolves(path37.join(workspaceRoot, child))) shared2.push(child);
|
|
24620
24635
|
}
|
|
24621
24636
|
};
|
|
24622
24637
|
walk("");
|
|
@@ -24656,9 +24671,9 @@ var GitWorktreeIsolation = class {
|
|
|
24656
24671
|
try {
|
|
24657
24672
|
ensureStateDirIgnored(run.workspaceRoot);
|
|
24658
24673
|
for (const repo of run.repos) {
|
|
24659
|
-
const worktree =
|
|
24674
|
+
const worktree = path37.join(dir, repo.path);
|
|
24660
24675
|
const tip = (await this.git(repo.root, ["rev-parse", repo.integrationBranch])).trim();
|
|
24661
|
-
fs15.mkdirSync(
|
|
24676
|
+
fs15.mkdirSync(path37.dirname(worktree), { recursive: true });
|
|
24662
24677
|
await this.git(repo.root, ["worktree", "add", "-q", "-B", branch, worktree, tip]);
|
|
24663
24678
|
record.repos[repo.path] = { worktree, linked: [], baseRef: tip };
|
|
24664
24679
|
}
|
|
@@ -24683,13 +24698,13 @@ var GitWorktreeIsolation = class {
|
|
|
24683
24698
|
setupFailed.push({ repo: repo.path, detail: err.detail });
|
|
24684
24699
|
}
|
|
24685
24700
|
entry.linked = boot.linked;
|
|
24686
|
-
copied.push(...boot.copied.map((name) =>
|
|
24701
|
+
copied.push(...boot.copied.map((name) => path37.posix.join(repo.path, name)));
|
|
24687
24702
|
}
|
|
24688
24703
|
for (const rel of run.shared) {
|
|
24689
|
-
const source =
|
|
24690
|
-
const target =
|
|
24704
|
+
const source = path37.join(run.workspaceRoot, rel);
|
|
24705
|
+
const target = path37.join(cwd, rel);
|
|
24691
24706
|
if (!resolves(source) || lexists(target)) continue;
|
|
24692
|
-
fs15.mkdirSync(
|
|
24707
|
+
fs15.mkdirSync(path37.dirname(target), { recursive: true });
|
|
24693
24708
|
if (linkPath(source, target, this.platform) === "copy") copied.push(rel);
|
|
24694
24709
|
const entry = self ? record.repos[SELF_REPO] : void 0;
|
|
24695
24710
|
if (entry) entry.linked.push(rel);
|
|
@@ -24721,7 +24736,7 @@ var GitWorktreeIsolation = class {
|
|
|
24721
24736
|
*/
|
|
24722
24737
|
async clearLeftovers(run, task2, names) {
|
|
24723
24738
|
const removal = noRemoval();
|
|
24724
|
-
const holder = Object.values(run.tasks).find((r) => r.taskId !== task2.id && (r.branch === names.branch ||
|
|
24739
|
+
const holder = Object.values(run.tasks).find((r) => r.taskId !== task2.id && (r.branch === names.branch || path37.resolve(r.workspace) === path37.resolve(names.dir) || isInside(r.workspace, names.dir)));
|
|
24725
24740
|
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`);
|
|
24726
24741
|
const found = [];
|
|
24727
24742
|
for (const repo of run.repos) {
|
|
@@ -24731,14 +24746,14 @@ var GitWorktreeIsolation = class {
|
|
|
24731
24746
|
worktree: /^worktree (.+)$/m.exec(block)?.[1],
|
|
24732
24747
|
branch: /^branch refs\/heads\/(.+)$/m.exec(block)?.[1]
|
|
24733
24748
|
}));
|
|
24734
|
-
const at = /* @__PURE__ */ new Set([
|
|
24749
|
+
const at = /* @__PURE__ */ new Set([path37.join(names.dir, repo.path)]);
|
|
24735
24750
|
for (const entry of registered) {
|
|
24736
|
-
if (entry.worktree && entry.branch === names.branch && isInside(this.runRoot(run),
|
|
24751
|
+
if (entry.worktree && entry.branch === names.branch && isInside(this.runRoot(run), path37.resolve(entry.worktree))) at.add(entry.worktree);
|
|
24737
24752
|
}
|
|
24738
|
-
const base = { branch: names.branch, name:
|
|
24753
|
+
const base = { branch: names.branch, name: path37.basename(names.dir), title: task2.title };
|
|
24739
24754
|
for (const worktree of at) {
|
|
24740
24755
|
if (!fs15.existsSync(worktree)) continue;
|
|
24741
|
-
const linked = leftoverLinks(
|
|
24756
|
+
const linked = leftoverLinks(path37.join(worktree, await this.prefixOf(repo)));
|
|
24742
24757
|
found.push({ repo, worktree, target: { ...base, worktree, linked } });
|
|
24743
24758
|
}
|
|
24744
24759
|
found.push({ repo, worktree: names.dir, target: { ...base, linked: [] } });
|
|
@@ -24831,7 +24846,7 @@ var GitWorktreeIsolation = class {
|
|
|
24831
24846
|
*/
|
|
24832
24847
|
async inWorkspacePlace(repo, worktree) {
|
|
24833
24848
|
const prefix = await this.prefixOf(repo);
|
|
24834
|
-
return prefix ?
|
|
24849
|
+
return prefix ? path37.join(worktree, prefix) : worktree;
|
|
24835
24850
|
}
|
|
24836
24851
|
async prefixOf(repo) {
|
|
24837
24852
|
return (await this.git(repo.root, ["rev-parse", "--show-prefix"])).trim();
|
|
@@ -25361,15 +25376,15 @@ var GitWorktreeIsolation = class {
|
|
|
25361
25376
|
return landingMessage(kind, from, this.deps.plannedWith?.() ?? false);
|
|
25362
25377
|
}
|
|
25363
25378
|
integrationDir(run, repo) {
|
|
25364
|
-
return
|
|
25379
|
+
return path37.join(this.runRoot(run), INTEGRATION_DIR, repo.path);
|
|
25365
25380
|
}
|
|
25366
25381
|
async ensureIntegrationWorktree(run, repo) {
|
|
25367
25382
|
return this.admin(run.workspaceRoot, async () => {
|
|
25368
25383
|
const dir = this.integrationDir(run, repo);
|
|
25369
|
-
if (fs15.existsSync(
|
|
25384
|
+
if (fs15.existsSync(path37.join(dir, ".git"))) return dir;
|
|
25370
25385
|
await this.tryGit(repo.root, ["worktree", "prune"]);
|
|
25371
25386
|
ensureStateDirIgnored(run.workspaceRoot);
|
|
25372
|
-
fs15.mkdirSync(
|
|
25387
|
+
fs15.mkdirSync(path37.dirname(dir), { recursive: true });
|
|
25373
25388
|
await this.git(repo.root, ["worktree", "add", "-q", dir, repo.integrationBranch]);
|
|
25374
25389
|
return dir;
|
|
25375
25390
|
});
|
|
@@ -25392,7 +25407,7 @@ var GitWorktreeIsolation = class {
|
|
|
25392
25407
|
const removal = noRemoval();
|
|
25393
25408
|
for (const repo of opts.preserve === false || record.readOnly ? [] : run.repos) {
|
|
25394
25409
|
const entry = record.repos[repo.path];
|
|
25395
|
-
const target = { worktree: entry?.worktree, linked: entry?.linked ?? [], branch: record.branch, name:
|
|
25410
|
+
const target = { worktree: entry?.worktree, linked: entry?.linked ?? [], branch: record.branch, name: path37.basename(record.workspace), title: record.title, commit: record.commit };
|
|
25396
25411
|
try {
|
|
25397
25412
|
const kept = await this.preserve(run, repo, target, opts.intent);
|
|
25398
25413
|
if (kept) removal.preserved.push({ task: task2, ...kept });
|
|
@@ -25473,7 +25488,7 @@ var GitWorktreeIsolation = class {
|
|
|
25473
25488
|
return;
|
|
25474
25489
|
}
|
|
25475
25490
|
for (const entry of entries) {
|
|
25476
|
-
const target =
|
|
25491
|
+
const target = path37.join(dir, entry.name);
|
|
25477
25492
|
if (entry.isSymbolicLink()) this.unlinkIfLink(target);
|
|
25478
25493
|
else if (entry.isDirectory()) this.unlinkLinksUnder(target);
|
|
25479
25494
|
}
|
|
@@ -25495,20 +25510,20 @@ var GitWorktreeIsolation = class {
|
|
|
25495
25510
|
return false;
|
|
25496
25511
|
}
|
|
25497
25512
|
};
|
|
25498
|
-
const owned = new Set(Object.values(run.tasks).map((r) =>
|
|
25513
|
+
const owned = new Set(Object.values(run.tasks).map((r) => path37.resolve(r.workspace)));
|
|
25499
25514
|
const root = this.runRoot(run);
|
|
25500
25515
|
if (fs15.existsSync(root)) {
|
|
25501
25516
|
for (const entry of fs15.readdirSync(root)) {
|
|
25502
|
-
const dir =
|
|
25503
|
-
if (entry === INTEGRATION_DIR || owned.has(
|
|
25517
|
+
const dir = path37.join(root, entry);
|
|
25518
|
+
if (entry === INTEGRATION_DIR || owned.has(path37.resolve(dir))) continue;
|
|
25504
25519
|
let kept = true;
|
|
25505
25520
|
for (const repo of run.repos) {
|
|
25506
|
-
const worktree =
|
|
25507
|
-
const linked = leftoverLinks(
|
|
25521
|
+
const worktree = path37.join(dir, repo.path);
|
|
25522
|
+
const linked = leftoverLinks(path37.join(worktree, await this.prefixOf(repo)));
|
|
25508
25523
|
if (!await keep2(repo, { worktree, linked, branch: null, name: entry, title: entry }, worktree)) kept = false;
|
|
25509
25524
|
}
|
|
25510
25525
|
if (!kept) continue;
|
|
25511
|
-
for (const repo of run.repos) await this.removeWorktreeDir(run, repo,
|
|
25526
|
+
for (const repo of run.repos) await this.removeWorktreeDir(run, repo, path37.join(dir, repo.path), []);
|
|
25512
25527
|
this.removeTaskWorkspace(run, dir);
|
|
25513
25528
|
}
|
|
25514
25529
|
}
|
|
@@ -25526,13 +25541,13 @@ var GitWorktreeIsolation = class {
|
|
|
25526
25541
|
}
|
|
25527
25542
|
async removeWorktreeDir(run, repo, dir, linked) {
|
|
25528
25543
|
for (const name of /* @__PURE__ */ new Set([...linked, ...installDirs(dir)])) {
|
|
25529
|
-
const target =
|
|
25530
|
-
if (!resolvesAsNamed(this.runRoot(run),
|
|
25544
|
+
const target = path37.join(dir, name);
|
|
25545
|
+
if (!resolvesAsNamed(this.runRoot(run), path37.dirname(target))) continue;
|
|
25531
25546
|
this.unlinkIfLink(target);
|
|
25532
25547
|
this.unlinkLinksUnder(target);
|
|
25533
25548
|
}
|
|
25534
25549
|
for (const name of resolvesAsNamed(this.runRoot(run), dir) ? fs15.readdirSync(dir) : []) {
|
|
25535
|
-
if (LINKED_ARTIFACTS.has(name) || isEnvFile(name)) this.unlinkIfLink(
|
|
25550
|
+
if (LINKED_ARTIFACTS.has(name) || isEnvFile(name)) this.unlinkIfLink(path37.join(dir, name));
|
|
25536
25551
|
}
|
|
25537
25552
|
await this.tryGit(repo.root, ["worktree", "remove", "--force", dir]);
|
|
25538
25553
|
if (fs15.existsSync(dir) && isInside(this.runRoot(run), dir)) {
|
|
@@ -25540,7 +25555,7 @@ var GitWorktreeIsolation = class {
|
|
|
25540
25555
|
fs15.rmSync(dir, { recursive: true, force: true });
|
|
25541
25556
|
}
|
|
25542
25557
|
await this.tryGit(repo.root, ["worktree", "prune"]);
|
|
25543
|
-
for (let parent =
|
|
25558
|
+
for (let parent = path37.dirname(dir); isInside(this.runRoot(run), parent); parent = path37.dirname(parent)) this.removeIfEmpty(parent);
|
|
25544
25559
|
}
|
|
25545
25560
|
unlinkIfLink(target) {
|
|
25546
25561
|
try {
|
|
@@ -25555,14 +25570,14 @@ var GitWorktreeIsolation = class {
|
|
|
25555
25570
|
}
|
|
25556
25571
|
}
|
|
25557
25572
|
runRoot(run) {
|
|
25558
|
-
return
|
|
25573
|
+
return path37.join(run.workspaceRoot, STATE_DIR, "worktrees", run.id);
|
|
25559
25574
|
}
|
|
25560
25575
|
namesFor(run, task2) {
|
|
25561
25576
|
const slug = sanitizeSlug(task2.title).slice(0, 40).replace(/-+$/, "") || "task";
|
|
25562
25577
|
let name = `${task2.order}-${slug}`;
|
|
25563
25578
|
const clash = Object.values(run.tasks).some((r) => r.taskId !== task2.id && r.branch === `ordewell/${run.id}/${name}`);
|
|
25564
25579
|
if (clash) name = `${name}-${sanitizeSlug(task2.id) || "x"}`;
|
|
25565
|
-
return { branch: `ordewell/${run.id}/${name}`, dir:
|
|
25580
|
+
return { branch: `ordewell/${run.id}/${name}`, dir: path37.join(this.runRoot(run), name) };
|
|
25566
25581
|
}
|
|
25567
25582
|
async unmergedPaths(cwd) {
|
|
25568
25583
|
const listed3 = await this.tryGit(cwd, ["diff", "--name-only", "-z", "--diff-filter=U"]);
|
|
@@ -25576,7 +25591,7 @@ var GitWorktreeIsolation = class {
|
|
|
25576
25591
|
async rebaseInProgress(cwd) {
|
|
25577
25592
|
for (const dir of ["rebase-merge", "rebase-apply"]) {
|
|
25578
25593
|
const found = await this.tryGit(cwd, ["rev-parse", "--git-path", dir]);
|
|
25579
|
-
if (found.ok && fs15.existsSync(
|
|
25594
|
+
if (found.ok && fs15.existsSync(path37.resolve(cwd, found.stdout.trim()))) return true;
|
|
25580
25595
|
}
|
|
25581
25596
|
return false;
|
|
25582
25597
|
}
|
|
@@ -25603,6 +25618,29 @@ function createWorktreeIsolation(deps) {
|
|
|
25603
25618
|
return new GitWorktreeIsolation(deps);
|
|
25604
25619
|
}
|
|
25605
25620
|
|
|
25621
|
+
// src/services/repositoryRunnerConfig.ts
|
|
25622
|
+
var RUNNER_CONFIG_ROOTS = [".mcp.json", ".claude", ".claude-plugin", "opencode.json", "opencode.jsonc", ".opencode", ".codex"];
|
|
25623
|
+
function repositoryRunnerConfigPaths(paths) {
|
|
25624
|
+
return [...new Set(paths.filter(
|
|
25625
|
+
(path49) => (
|
|
25626
|
+
// Project MCP servers start commands or send data to a repository-chosen URL.
|
|
25627
|
+
path49 === ".mcp.json" || // Settings can run hooks and helpers, load plugins, or redirect traffic.
|
|
25628
|
+
path49 === ".claude/settings.json" || // Local settings have the same execution capabilities as project settings.
|
|
25629
|
+
path49 === ".claude/settings.local.json" || // Hook files provide commands invoked by the runner.
|
|
25630
|
+
path49.startsWith(".claude/hooks/") || // Plugin files can provide code and hooks loaded by the runner.
|
|
25631
|
+
path49.startsWith(".claude/plugins/") || // Plugin metadata can load plugins and their executable components.
|
|
25632
|
+
path49.startsWith(".claude-plugin/") || // Plugin and marketplace manifests can select code for the runner to load.
|
|
25633
|
+
/^\.claude\/(?:[^/]+\/)*(?:plugin|marketplace)\.json$/.test(path49) || // OpenCode config declares MCP servers and plugins; its plugin and tool
|
|
25634
|
+
// directories are code it loads, and an agent definition sets the prompt,
|
|
25635
|
+
// model and permissions of the built-in agent its id names, which a task
|
|
25636
|
+
// launches with. The rest of `.opencode/` is dependencies OpenCode
|
|
25637
|
+
// installs itself, which a later launch must not be held for.
|
|
25638
|
+
/^(?:\.opencode\/)?opencode\.jsonc?$/.test(path49) || /^\.opencode\/(?:plugins?|tools?|agents?)\//.test(path49) || // Codex project config carries MCP servers, hooks and `notify` commands.
|
|
25639
|
+
path49.startsWith(".codex/")
|
|
25640
|
+
)
|
|
25641
|
+
))].sort();
|
|
25642
|
+
}
|
|
25643
|
+
|
|
25606
25644
|
// src/interfaces/ILogger.ts
|
|
25607
25645
|
var ConsoleLogger = class {
|
|
25608
25646
|
warn(scope, message, err) {
|
|
@@ -28638,6 +28676,7 @@ var IsolationRunController = class {
|
|
|
28638
28676
|
/** Resolver task id → the conflicted task it resolves; see {@link linkResolver}. */
|
|
28639
28677
|
resolvers = {};
|
|
28640
28678
|
opening = null;
|
|
28679
|
+
opened = 0;
|
|
28641
28680
|
/** Bumped by an interrupt, so an activation in flight across it does not open the run it ended. */
|
|
28642
28681
|
activations = 0;
|
|
28643
28682
|
/** The start a dirty tree turned away, handed back once the user chooses how to go on. */
|
|
@@ -28669,6 +28708,10 @@ var IsolationRunController = class {
|
|
|
28669
28708
|
get isOpen() {
|
|
28670
28709
|
return this.mode !== null;
|
|
28671
28710
|
}
|
|
28711
|
+
/** How many runs have opened: what tells one run's launches from the next one's. */
|
|
28712
|
+
get epoch() {
|
|
28713
|
+
return this.opened;
|
|
28714
|
+
}
|
|
28672
28715
|
/** The open run has decided whether it isolates. */
|
|
28673
28716
|
get decided() {
|
|
28674
28717
|
return this.mode === "isolated" || this.mode === "shared";
|
|
@@ -28766,6 +28809,7 @@ var IsolationRunController = class {
|
|
|
28766
28809
|
open() {
|
|
28767
28810
|
if (this.mode) return;
|
|
28768
28811
|
this.mode = "undecided";
|
|
28812
|
+
this.opened += 1;
|
|
28769
28813
|
}
|
|
28770
28814
|
/**
|
|
28771
28815
|
* Decide once per run, as its first change task starts, whether it executes
|
|
@@ -29765,7 +29809,7 @@ function heldFrom(state) {
|
|
|
29765
29809
|
}
|
|
29766
29810
|
|
|
29767
29811
|
// src/services/Attempts.ts
|
|
29768
|
-
import * as
|
|
29812
|
+
import * as path41 from "path";
|
|
29769
29813
|
|
|
29770
29814
|
// src/services/VerdictEngine.ts
|
|
29771
29815
|
var IDLE_TIMEOUT_MS = 10 * 6e4;
|
|
@@ -30153,10 +30197,132 @@ function reportedVerdict(report) {
|
|
|
30153
30197
|
return { outcome: "fail", reason: `The runner reported the task ${report.status}: ${why}`, checks, decidedAt, reported };
|
|
30154
30198
|
}
|
|
30155
30199
|
|
|
30200
|
+
// src/services/taskStartConfig.ts
|
|
30201
|
+
import * as path38 from "path";
|
|
30202
|
+
import { createHash as createHash4 } from "crypto";
|
|
30203
|
+
import { existsSync as existsSync15, lstatSync as lstatSync4, readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync12 } from "fs";
|
|
30204
|
+
var MAX_FILES = 2e3;
|
|
30205
|
+
var MAX_DEPTH = 8;
|
|
30206
|
+
function liveConfig(dir) {
|
|
30207
|
+
const found = /* @__PURE__ */ new Map();
|
|
30208
|
+
const visit = (rel, depth) => {
|
|
30209
|
+
if (found.size >= MAX_FILES || depth > MAX_DEPTH) return;
|
|
30210
|
+
const full = path38.join(dir, rel);
|
|
30211
|
+
try {
|
|
30212
|
+
const info = statSync12(full);
|
|
30213
|
+
if (info.isFile()) {
|
|
30214
|
+
found.set(rel, createHash4("sha1").update(readFileSync13(full)).digest("hex"));
|
|
30215
|
+
} else if (info.isDirectory() && path38.basename(rel) !== "node_modules") {
|
|
30216
|
+
for (const name of readdirSync8(full)) visit(path38.posix.join(rel, name), depth + 1);
|
|
30217
|
+
}
|
|
30218
|
+
} catch {
|
|
30219
|
+
}
|
|
30220
|
+
};
|
|
30221
|
+
for (const root of RUNNER_CONFIG_ROOTS) visit(root, 0);
|
|
30222
|
+
const selected = new Set(repositoryRunnerConfigPaths([...found.keys()]));
|
|
30223
|
+
return new Map([...found].filter(([name]) => selected.has(name)));
|
|
30224
|
+
}
|
|
30225
|
+
function linkedRoots(dir) {
|
|
30226
|
+
const linked = /* @__PURE__ */ new Set();
|
|
30227
|
+
for (const root of RUNNER_CONFIG_ROOTS) {
|
|
30228
|
+
try {
|
|
30229
|
+
if (lstatSync4(path38.join(dir, root)).isSymbolicLink()) linked.add(root);
|
|
30230
|
+
} catch {
|
|
30231
|
+
}
|
|
30232
|
+
}
|
|
30233
|
+
return linked;
|
|
30234
|
+
}
|
|
30235
|
+
function readDirs(root) {
|
|
30236
|
+
const dirs = [{ dir: root, prefix: "" }];
|
|
30237
|
+
for (let dir = root, prefix = ""; !existsSync15(path38.join(dir, ".git")); ) {
|
|
30238
|
+
const parent = path38.dirname(dir);
|
|
30239
|
+
if (parent === dir) return [dirs[0]];
|
|
30240
|
+
dir = parent;
|
|
30241
|
+
prefix += "../";
|
|
30242
|
+
dirs.push({ dir, prefix });
|
|
30243
|
+
}
|
|
30244
|
+
return dirs;
|
|
30245
|
+
}
|
|
30246
|
+
var TaskStartConfig = class {
|
|
30247
|
+
live = /* @__PURE__ */ new Map();
|
|
30248
|
+
/**
|
|
30249
|
+
* `epoch` names the run the check belongs to; a new run takes a new
|
|
30250
|
+
* baseline. `root` is the workspace root, the checkout a worktree run lands
|
|
30251
|
+
* in; `cwd` is where the runner starts, and `worktree` whether that is a
|
|
30252
|
+
* worktree prepared for it.
|
|
30253
|
+
*/
|
|
30254
|
+
async check(run, taskId, where) {
|
|
30255
|
+
const found = where.worktree ? await this.gitDifferences(run, taskId) : [];
|
|
30256
|
+
const id2 = String(where.epoch);
|
|
30257
|
+
const checkout = readDirs(where.root).flatMap(({ dir, prefix }) => this.liveDifferences(`${id2}:checkout:${dir}`, dir).map((name) => `${prefix}${name}`));
|
|
30258
|
+
if (!where.worktree) found.push(...checkout);
|
|
30259
|
+
else {
|
|
30260
|
+
const cwd = where.cwd ?? run?.tasks[taskId]?.workspace;
|
|
30261
|
+
if (cwd) found.push(...this.worktreeDifferences(id2, cwd, where.root));
|
|
30262
|
+
}
|
|
30263
|
+
return [...new Set(found)].sort();
|
|
30264
|
+
}
|
|
30265
|
+
/** The baselines go with the plan they belong to. */
|
|
30266
|
+
clear() {
|
|
30267
|
+
this.live.clear();
|
|
30268
|
+
}
|
|
30269
|
+
/**
|
|
30270
|
+
* What a worktree's runner reads that differs from where the run started.
|
|
30271
|
+
* The `.claude` and `.opencode` directories it links from the checkout are
|
|
30272
|
+
* the checkout's own, so they are compared with the checkout's first state,
|
|
30273
|
+
* which an earlier task's write there does not move. Anything else is the
|
|
30274
|
+
* worktree's, and is compared with its own first state: a setup command's
|
|
30275
|
+
* files are trusted, and a task's later write is not.
|
|
30276
|
+
*/
|
|
30277
|
+
worktreeDifferences(id2, dir, root) {
|
|
30278
|
+
const now = liveConfig(dir);
|
|
30279
|
+
const linked = linkedRoots(dir);
|
|
30280
|
+
const fromCheckout = (name) => linked.has(name.split("/")[0]);
|
|
30281
|
+
const key = `${id2}:worktree:${dir}`;
|
|
30282
|
+
let local = this.live.get(key);
|
|
30283
|
+
if (!local) {
|
|
30284
|
+
local = new Map([...now].filter(([name]) => !fromCheckout(name)));
|
|
30285
|
+
this.live.set(key, local);
|
|
30286
|
+
}
|
|
30287
|
+
const checkout = this.live.get(`${id2}:checkout:${root}`);
|
|
30288
|
+
return [...now].filter(([name, hash]) => fromCheckout(name) ? checkout?.get(name) !== hash : local.get(name) !== hash).map(([name]) => name);
|
|
30289
|
+
}
|
|
30290
|
+
liveDifferences(key, dir) {
|
|
30291
|
+
const now = liveConfig(dir);
|
|
30292
|
+
const before = this.live.get(key);
|
|
30293
|
+
if (!before) {
|
|
30294
|
+
this.live.set(key, now);
|
|
30295
|
+
return [];
|
|
30296
|
+
}
|
|
30297
|
+
return [...now].filter(([name, hash]) => before.get(name) !== hash).map(([name]) => name);
|
|
30298
|
+
}
|
|
30299
|
+
async gitDifferences(run, taskId) {
|
|
30300
|
+
if (!run) return [];
|
|
30301
|
+
const invoker = { exec: defaultExecFile2, resolvePath: augmentedPath };
|
|
30302
|
+
const found = [];
|
|
30303
|
+
for (const repo of run.repos) {
|
|
30304
|
+
const cwd = run.tasks[taskId]?.repos[repo.path]?.worktree;
|
|
30305
|
+
if (!cwd || !repo.baseRef || !existsSync15(cwd)) continue;
|
|
30306
|
+
const prefix = repo.path === "." ? (await tryGit(invoker, repo.root, ["rev-parse", "--show-prefix"])).stdout.trim() : "";
|
|
30307
|
+
const roots = [...RUNNER_CONFIG_ROOTS, ...prefix ? RUNNER_CONFIG_ROOTS.map((r) => `${prefix}${r}`) : []];
|
|
30308
|
+
const diff = await tryGit(invoker, cwd, ["diff", "--no-ext-diff", "--no-textconv", "--no-renames", "--name-only", "--diff-filter=ACMRTU", "-z", repo.baseRef, "--"]);
|
|
30309
|
+
const untracked = await tryGit(invoker, cwd, ["ls-files", "--others", "-z", "--", ...roots]);
|
|
30310
|
+
if (!diff.ok || !untracked.ok) continue;
|
|
30311
|
+
for (const name of [...diff.stdout.split("\0"), ...untracked.stdout.split("\0")]) {
|
|
30312
|
+
const here = prefix && name.startsWith(prefix) ? name.slice(prefix.length) : void 0;
|
|
30313
|
+
if (repositoryRunnerConfigPaths([name]).length || here !== void 0 && repositoryRunnerConfigPaths([here]).length) {
|
|
30314
|
+
found.push(repo.path === "." ? name : path38.posix.join(repo.path, name));
|
|
30315
|
+
}
|
|
30316
|
+
}
|
|
30317
|
+
}
|
|
30318
|
+
return found;
|
|
30319
|
+
}
|
|
30320
|
+
};
|
|
30321
|
+
|
|
30156
30322
|
// src/services/ScriptRunner.ts
|
|
30157
30323
|
import { spawn as nodeSpawn2 } from "child_process";
|
|
30158
30324
|
import * as fs16 from "fs";
|
|
30159
|
-
import * as
|
|
30325
|
+
import * as path39 from "path";
|
|
30160
30326
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
30161
30327
|
import { StringDecoder as StringDecoder2 } from "string_decoder";
|
|
30162
30328
|
|
|
@@ -30297,7 +30463,7 @@ var ScriptSession = class extends AbstractRunnerSession {
|
|
|
30297
30463
|
async launchOf(step) {
|
|
30298
30464
|
if ("argv" in step) {
|
|
30299
30465
|
const [named3, ...args] = step.argv;
|
|
30300
|
-
const program = this.setup.platform === "win32" &&
|
|
30466
|
+
const program = this.setup.platform === "win32" && path39.win32.basename(named3) !== named3 && !path39.win32.isAbsolute(named3) ? path39.win32.resolve(this.setup.cwd, named3) : named3;
|
|
30301
30467
|
const plan = await planDirectLaunch(program, args, this.setup.launch);
|
|
30302
30468
|
return { file: plan.file, args: plan.args, shell: false, ...plan.verbatim ? { verbatim: true } : {} };
|
|
30303
30469
|
}
|
|
@@ -30530,10 +30696,10 @@ function passed(status) {
|
|
|
30530
30696
|
}
|
|
30531
30697
|
|
|
30532
30698
|
// src/services/PatchCapture.ts
|
|
30533
|
-
import { createHash as
|
|
30699
|
+
import { createHash as createHash5, randomBytes as randomBytes7 } from "crypto";
|
|
30534
30700
|
import * as fs17 from "fs";
|
|
30535
30701
|
import * as os10 from "os";
|
|
30536
|
-
import * as
|
|
30702
|
+
import * as path40 from "path";
|
|
30537
30703
|
|
|
30538
30704
|
// src/services/readTask.ts
|
|
30539
30705
|
function readTask2(args, readerId, plan, log) {
|
|
@@ -30800,7 +30966,7 @@ function linkInPatch(patch) {
|
|
|
30800
30966
|
function readOwn(scratch, name, max) {
|
|
30801
30967
|
let fd;
|
|
30802
30968
|
try {
|
|
30803
|
-
fd = fs17.openSync(
|
|
30969
|
+
fd = fs17.openSync(path40.join(scratch, name), fs17.constants.O_RDONLY | (fs17.constants.O_NOFOLLOW ?? 0));
|
|
30804
30970
|
} catch (err) {
|
|
30805
30971
|
throw new Refusal(`the capture left no ${name.split(".").pop()} Ordewell could read (${err.code ?? String(err)})`);
|
|
30806
30972
|
}
|
|
@@ -30838,7 +31004,7 @@ async function captureHeld(runs, opts, signal) {
|
|
|
30838
31004
|
const [worktree] = runs.worktrees;
|
|
30839
31005
|
const scratch = runs.scratch;
|
|
30840
31006
|
const tag = `ordewell-patch-${randomBytes7(8).toString("hex")}`;
|
|
30841
|
-
const stem =
|
|
31007
|
+
const stem = path40.join(scratch, tag);
|
|
30842
31008
|
const own = (suffix, max = LISTING_BYTES) => readOwn(scratch, `${tag}.${suffix}`, max);
|
|
30843
31009
|
try {
|
|
30844
31010
|
const stage = await runs.run(stageScript(stem, opts.linked ?? []), worktree);
|
|
@@ -30876,7 +31042,7 @@ async function captureHeld(runs, opts, signal) {
|
|
|
30876
31042
|
return {
|
|
30877
31043
|
kind: "saved",
|
|
30878
31044
|
patch,
|
|
30879
|
-
stats: { base, ...countedIn(patch), bytes: patch.length, sha256:
|
|
31045
|
+
stats: { base, ...countedIn(patch), bytes: patch.length, sha256: createHash5("sha256").update(patch).digest("hex"), flags: [...flags, ...flag("normalized", normalized2)] }
|
|
30880
31046
|
};
|
|
30881
31047
|
} catch (err) {
|
|
30882
31048
|
if (err instanceof Refusal) return { kind: "refused", reason: `${err.message}.` };
|
|
@@ -30930,8 +31096,8 @@ async function indexEntries(invoker, worktree) {
|
|
|
30930
31096
|
return entries;
|
|
30931
31097
|
}
|
|
30932
31098
|
async function trialApply(invoker, worktree, patchFile, scratch) {
|
|
30933
|
-
const index =
|
|
30934
|
-
const copy =
|
|
31099
|
+
const index = path40.resolve(worktree, (await git(invoker, worktree, [...APPLY_GIT, "rev-parse", "--git-path", "index"])).trim());
|
|
31100
|
+
const copy = path40.join(scratch, "index");
|
|
30935
31101
|
fs17.copyFileSync(index, copy);
|
|
30936
31102
|
const trial = { ...invoker, exec: (file, args, opts) => invoker.exec(file, args, { ...opts, env: { ...opts.env, GIT_INDEX_FILE: copy } }) };
|
|
30937
31103
|
const tried = await tryGit(trial, worktree, [...APPLY_GIT, "apply", "--cached", "--3way", "--whitespace=nowarn", patchFile]);
|
|
@@ -30951,7 +31117,7 @@ function gitRefused(lead, stderr) {
|
|
|
30951
31117
|
function onDisk3(worktree, names) {
|
|
30952
31118
|
return names.map((name) => {
|
|
30953
31119
|
try {
|
|
30954
|
-
const stat = fs17.lstatSync(
|
|
31120
|
+
const stat = fs17.lstatSync(path40.join(worktree, name), { bigint: true, throwIfNoEntry: false });
|
|
30955
31121
|
return stat ? `${stat.mode} ${stat.ino} ${stat.size} ${stat.mtimeNs} ${stat.ctimeNs}` : "none";
|
|
30956
31122
|
} catch (err) {
|
|
30957
31123
|
return err.code ?? "unreadable";
|
|
@@ -30991,7 +31157,7 @@ function leavesWorktree(worktree, names, linked, held2, left) {
|
|
|
30991
31157
|
if (i < parts.length && held2.get(at)?.some((entry) => entry.mode === SUBMODULE)) {
|
|
30992
31158
|
return `the patch writes ${name}, under ${at}, a submodule, whose files are another repository's.`;
|
|
30993
31159
|
}
|
|
30994
|
-
const full =
|
|
31160
|
+
const full = path40.join(worktree, ...parts.slice(0, i));
|
|
30995
31161
|
const stat = fs17.lstatSync(full, { throwIfNoEntry: false });
|
|
30996
31162
|
if (!stat) break;
|
|
30997
31163
|
const last = i === parts.length;
|
|
@@ -31012,14 +31178,14 @@ async function applyPatch(invoker, worktree, patch, saved, opts = {}) {
|
|
|
31012
31178
|
if (patch.length !== saved.bytes) {
|
|
31013
31179
|
return refused3(`the patch is ${byteSize(patch.length)} where its artifact says ${byteSize(saved.bytes)}, so it was cut short or changed after it was saved.`);
|
|
31014
31180
|
}
|
|
31015
|
-
if (
|
|
31181
|
+
if (createHash5("sha256").update(patch).digest("hex") !== saved.sha256) {
|
|
31016
31182
|
return refused3("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.");
|
|
31017
31183
|
}
|
|
31018
31184
|
const link = linkInPatch(patch);
|
|
31019
31185
|
if (link !== void 0) {
|
|
31020
31186
|
return refused3(`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.`);
|
|
31021
31187
|
}
|
|
31022
|
-
const dir = fs17.mkdtempSync(
|
|
31188
|
+
const dir = fs17.mkdtempSync(path40.join(os10.tmpdir(), "ordewell-apply-"));
|
|
31023
31189
|
try {
|
|
31024
31190
|
const toplevel = (await git(invoker, worktree, [...APPLY_GIT, "rev-parse", "--show-toplevel"])).trim();
|
|
31025
31191
|
if (fs17.realpathSync(toplevel) !== fs17.realpathSync(worktree)) return refused3(`${worktree} is not the root of a worktree of its own.`);
|
|
@@ -31029,7 +31195,7 @@ async function applyPatch(invoker, worktree, patch, saved, opts = {}) {
|
|
|
31029
31195
|
}
|
|
31030
31196
|
const before = await unmergedPaths(invoker, worktree);
|
|
31031
31197
|
if (before.length > 0) return refused3(`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.`);
|
|
31032
|
-
const file =
|
|
31198
|
+
const file = path40.join(dir, "saved.patch");
|
|
31033
31199
|
fs17.writeFileSync(file, patch, { flag: "wx", mode: 384 });
|
|
31034
31200
|
const held2 = await indexEntries(invoker, worktree);
|
|
31035
31201
|
const named3 = await pathsNamed(invoker, worktree, file);
|
|
@@ -31179,6 +31345,11 @@ var TaskWebReader = class {
|
|
|
31179
31345
|
};
|
|
31180
31346
|
|
|
31181
31347
|
// src/services/Attempts.ts
|
|
31348
|
+
var TaskStartConfigError = class extends Error {
|
|
31349
|
+
constructor(paths) {
|
|
31350
|
+
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`);
|
|
31351
|
+
}
|
|
31352
|
+
};
|
|
31182
31353
|
var DEFAULT_GIT = { exec: defaultExecFile2, resolvePath: () => augmentedPath() };
|
|
31183
31354
|
var Attempts = class {
|
|
31184
31355
|
constructor(deps) {
|
|
@@ -31210,6 +31381,7 @@ var Attempts = class {
|
|
|
31210
31381
|
live = /* @__PURE__ */ new Map();
|
|
31211
31382
|
/** Bumped by every plan load: an ended attempt's wind-down belongs to the scope before it. */
|
|
31212
31383
|
planScope = 0;
|
|
31384
|
+
startConfig = new TaskStartConfig();
|
|
31213
31385
|
/** Each task's runners still winding down once stopped: a continue waits for them (ADR-0018, L1). */
|
|
31214
31386
|
windDowns = /* @__PURE__ */ new Map();
|
|
31215
31387
|
/**
|
|
@@ -31379,6 +31551,7 @@ var Attempts = class {
|
|
|
31379
31551
|
const ended = this.endAll("load");
|
|
31380
31552
|
this.planScope += 1;
|
|
31381
31553
|
this.spawnCounts.clear();
|
|
31554
|
+
this.startConfig.clear();
|
|
31382
31555
|
return ended;
|
|
31383
31556
|
}
|
|
31384
31557
|
/** A task leaving the plan: no later attempt of it is numbered from its runs. */
|
|
@@ -31511,9 +31684,17 @@ var Attempts = class {
|
|
|
31511
31684
|
if (unavailable2) throw new Error(unavailable2);
|
|
31512
31685
|
}
|
|
31513
31686
|
if (kind.kind === "continuation") await this.windDowns.get(task2.id);
|
|
31687
|
+
if (!attempt.script && kind.kind === "repair") {
|
|
31688
|
+
const paths = await this.startConfig.check(runs.current, task2.id, { epoch: runs.epoch, root: this.deps.workspaceRoot(), cwd: null, worktree: true });
|
|
31689
|
+
if (paths.length) throw new TaskStartConfigError(paths);
|
|
31690
|
+
}
|
|
31514
31691
|
const { cwd, worktree, previousWork, workspace } = await attemptCwd(kind, task2, runs);
|
|
31515
31692
|
attempt.cwd = cwd;
|
|
31516
31693
|
attempt.worktree = worktree;
|
|
31694
|
+
if (!attempt.script && kind.kind !== "repair" && !landsNothing(kind)) {
|
|
31695
|
+
const paths = await this.startConfig.check(runs.current, task2.id, { epoch: runs.epoch, root: this.deps.workspaceRoot(), cwd, worktree });
|
|
31696
|
+
if (paths.length) throw new TaskStartConfigError(paths);
|
|
31697
|
+
}
|
|
31517
31698
|
if (checksTree(kind)) attempt.snapshot = await runs.snapshotWorkspace();
|
|
31518
31699
|
if (this.live.get(task2.id) !== attempt) {
|
|
31519
31700
|
if (attempt.worktree && !this.live.has(task2.id) && !this.host.completing(task2.id)) await runs.release(task2.id, { keep: kind.kind === "repair" });
|
|
@@ -31596,6 +31777,9 @@ var Attempts = class {
|
|
|
31596
31777
|
return { kind: "usage-limited", taskId: task2.id, attempt, said: { message }, output: "" };
|
|
31597
31778
|
}
|
|
31598
31779
|
const failed = (failure2) => ({ kind: "spawn-failed", task: task2, attempt, failure: failure2 });
|
|
31780
|
+
if (err instanceof TaskStartConfigError) {
|
|
31781
|
+
return failed({ leaves: "held", hold: err.message, preserveWorktree: true, settles: false, notice: { level: "warn", text: `Task "${task2.title}" is on hold: ${err.message}` } });
|
|
31782
|
+
}
|
|
31599
31783
|
if (attempt.kind.kind === "continuation" && !attachTimeout) {
|
|
31600
31784
|
const refused3 = err instanceof RunnerStartupExit;
|
|
31601
31785
|
const reason = unresumedMessage(task2, refused3 ? `${attempt.runner} could not find its saved session` : `could not start: ${message}`);
|
|
@@ -31732,9 +31916,9 @@ var Attempts = class {
|
|
|
31732
31916
|
const repos = Object.values(this.deps.runs.openRecord(taskId)?.repos ?? {});
|
|
31733
31917
|
if (repos.length !== 1 || cwd === null) return [];
|
|
31734
31918
|
const [{ worktree, linked }] = repos;
|
|
31735
|
-
const prefix =
|
|
31736
|
-
if (prefix.startsWith("..") ||
|
|
31737
|
-
return linked.map((name) => (prefix ? `${prefix}/${name}` : name).split(
|
|
31919
|
+
const prefix = path41.relative(worktree, cwd).split(path41.sep).join("/");
|
|
31920
|
+
if (prefix.startsWith("..") || path41.isAbsolute(prefix)) return [];
|
|
31921
|
+
return linked.map((name) => (prefix ? `${prefix}/${name}` : name).split(path41.sep).join("/"));
|
|
31738
31922
|
}
|
|
31739
31923
|
/**
|
|
31740
31924
|
* A script task's start (ADR-0035): its body as the plan holds it now, run
|
|
@@ -31772,7 +31956,7 @@ var Attempts = class {
|
|
|
31772
31956
|
this.deps.notifications.warn(message);
|
|
31773
31957
|
};
|
|
31774
31958
|
if (resolved.blockedEnvrc) {
|
|
31775
|
-
warn(`blocked:${resolved.blockedEnvrc}`, `direnv has blocked ${resolved.blockedEnvrc}, so tasks start without its variables. Run \`direnv allow\` in ${
|
|
31959
|
+
warn(`blocked:${resolved.blockedEnvrc}`, `direnv has blocked ${resolved.blockedEnvrc}, so tasks start without its variables. Run \`direnv allow\` in ${path41.dirname(resolved.blockedEnvrc)} to use them.`);
|
|
31776
31960
|
}
|
|
31777
31961
|
if (resolved.trackedEnvFile) {
|
|
31778
31962
|
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.`);
|
|
@@ -31798,7 +31982,7 @@ var Attempts = class {
|
|
|
31798
31982
|
uncommittedSkillFolder(name) {
|
|
31799
31983
|
const root = this.deps.workspaceRoot();
|
|
31800
31984
|
const skill = this.deps.skillsAt(this.skillRoots(root)).findSkill(name);
|
|
31801
|
-
return skill?.source === "workspace" ?
|
|
31985
|
+
return skill?.source === "workspace" ? path41.relative(root, path41.dirname(skill.path)).split(path41.sep).join("/") : void 0;
|
|
31802
31986
|
}
|
|
31803
31987
|
/**
|
|
31804
31988
|
* The roots whose `.ordewell/skills/` an attempt at `cwd` reads: in a repo
|
|
@@ -32167,12 +32351,12 @@ function ancestors(task2, store) {
|
|
|
32167
32351
|
|
|
32168
32352
|
// src/services/sessionLease.ts
|
|
32169
32353
|
import * as fs19 from "fs";
|
|
32170
|
-
import * as
|
|
32354
|
+
import * as path43 from "path";
|
|
32171
32355
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
32172
32356
|
|
|
32173
32357
|
// src/utils/sessionStore.ts
|
|
32174
32358
|
import * as fs18 from "fs";
|
|
32175
|
-
import * as
|
|
32359
|
+
import * as path42 from "path";
|
|
32176
32360
|
|
|
32177
32361
|
// src/utils/sessionId.ts
|
|
32178
32362
|
import { randomBytes as randomBytes8 } from "crypto";
|
|
@@ -32183,13 +32367,13 @@ function mintSessionId() {
|
|
|
32183
32367
|
// src/utils/sessionStore.ts
|
|
32184
32368
|
var SESSIONS_SUBDIR = "sessions";
|
|
32185
32369
|
function getSessionsDir(baseDir) {
|
|
32186
|
-
return
|
|
32370
|
+
return path42.join(getStateDir(baseDir), SESSIONS_SUBDIR);
|
|
32187
32371
|
}
|
|
32188
32372
|
function idSegment(id2) {
|
|
32189
32373
|
return /^[A-Za-z0-9_-][A-Za-z0-9._-]{0,127}$/.test(id2) ? id2 : `~${Buffer.from(id2, "utf-8").toString("hex")}`;
|
|
32190
32374
|
}
|
|
32191
32375
|
function sessionDataDir(sessionId, baseDir) {
|
|
32192
|
-
return
|
|
32376
|
+
return path42.join(getSessionsDir(baseDir), idSegment(sessionId));
|
|
32193
32377
|
}
|
|
32194
32378
|
var REJECTION_MESSAGE = "This session was created with an older version of Ordewell. Please re-plan.";
|
|
32195
32379
|
function isSessionMeta(value) {
|
|
@@ -32216,8 +32400,8 @@ function legacySessionFilename(session) {
|
|
|
32216
32400
|
return `${filenameStem(session)}_${session.id.slice(0, 8)}.json`;
|
|
32217
32401
|
}
|
|
32218
32402
|
function dropLegacyFile(sessionsDir, meta) {
|
|
32219
|
-
const legacy =
|
|
32220
|
-
if (legacy ===
|
|
32403
|
+
const legacy = path42.join(sessionsDir, legacySessionFilename(meta));
|
|
32404
|
+
if (legacy === path42.join(sessionsDir, sessionFilename(meta)) || !fs18.existsSync(legacy)) return;
|
|
32221
32405
|
try {
|
|
32222
32406
|
const held2 = JSON.parse(fs18.readFileSync(legacy, "utf-8")).meta?.id;
|
|
32223
32407
|
if (held2 === meta.id) fs18.unlinkSync(legacy);
|
|
@@ -32244,7 +32428,7 @@ function saveSession(plan, goal, baseDir, id2) {
|
|
|
32244
32428
|
};
|
|
32245
32429
|
dropRetiredPlanFields(session.plan);
|
|
32246
32430
|
const filename = sessionFilename(meta);
|
|
32247
|
-
const filePath =
|
|
32431
|
+
const filePath = path42.join(sessionsDir, filename);
|
|
32248
32432
|
writeFileAtomic(filePath, JSON.stringify(session, null, 2));
|
|
32249
32433
|
dropLegacyFile(sessionsDir, meta);
|
|
32250
32434
|
return meta;
|
|
@@ -32256,7 +32440,7 @@ function listSessions(baseDir, logger = defaultLogger) {
|
|
|
32256
32440
|
return files.map((f) => {
|
|
32257
32441
|
let parsed;
|
|
32258
32442
|
try {
|
|
32259
|
-
parsed = JSON.parse(fs18.readFileSync(
|
|
32443
|
+
parsed = JSON.parse(fs18.readFileSync(path42.join(sessionsDir, f), "utf-8"));
|
|
32260
32444
|
} catch (err) {
|
|
32261
32445
|
if (err instanceof SyntaxError) return moveAside(sessionsDir, f, "is not valid JSON", logger);
|
|
32262
32446
|
logger.warn("sessionStore", `failed to read session file ${f}; skipping`, err);
|
|
@@ -32277,7 +32461,7 @@ function listSessions(baseDir, logger = defaultLogger) {
|
|
|
32277
32461
|
function moveAside(sessionsDir, file, reason, logger) {
|
|
32278
32462
|
const aside = `${file}.${Date.now()}.corrupt`;
|
|
32279
32463
|
try {
|
|
32280
|
-
fs18.renameSync(
|
|
32464
|
+
fs18.renameSync(path42.join(sessionsDir, file), path42.join(sessionsDir, aside));
|
|
32281
32465
|
logger.warn("sessionStore", `session file ${file} ${reason}; moved aside to ${aside} rather than overwritten`);
|
|
32282
32466
|
} catch {
|
|
32283
32467
|
logger.warn("sessionStore", `failed to read session file ${file}; skipping`);
|
|
@@ -32288,7 +32472,7 @@ function findSessionFile(sessionsDir, sessionId, logger) {
|
|
|
32288
32472
|
const files = fs18.readdirSync(sessionsDir).filter((f) => f.endsWith(".json"));
|
|
32289
32473
|
for (const f of files) {
|
|
32290
32474
|
try {
|
|
32291
|
-
const raw = fs18.readFileSync(
|
|
32475
|
+
const raw = fs18.readFileSync(path42.join(sessionsDir, f), "utf-8");
|
|
32292
32476
|
const session = JSON.parse(raw);
|
|
32293
32477
|
if (session.meta.id === sessionId) return f;
|
|
32294
32478
|
} catch (err) {
|
|
@@ -32303,7 +32487,7 @@ function loadSession(sessionId, baseDir, logger = defaultLogger) {
|
|
|
32303
32487
|
try {
|
|
32304
32488
|
const file = findSessionFile(sessionsDir, sessionId, logger);
|
|
32305
32489
|
if (file) {
|
|
32306
|
-
const raw = fs18.readFileSync(
|
|
32490
|
+
const raw = fs18.readFileSync(path42.join(sessionsDir, file), "utf-8");
|
|
32307
32491
|
const parsed = JSON.parse(raw);
|
|
32308
32492
|
if (hasScalarRunner(parsed)) {
|
|
32309
32493
|
logger.warn("sessionStore", `session file ${file}: ${REJECTION_MESSAGE}`);
|
|
@@ -32345,7 +32529,7 @@ function deleteSession(sessionId, baseDir, logger = defaultLogger) {
|
|
|
32345
32529
|
try {
|
|
32346
32530
|
const file = findSessionFile(sessionsDir, sessionId, logger);
|
|
32347
32531
|
if (file) {
|
|
32348
|
-
fs18.unlinkSync(
|
|
32532
|
+
fs18.unlinkSync(path42.join(sessionsDir, file));
|
|
32349
32533
|
return true;
|
|
32350
32534
|
}
|
|
32351
32535
|
} catch (err) {
|
|
@@ -32398,7 +32582,7 @@ var UNLEASED = {
|
|
|
32398
32582
|
};
|
|
32399
32583
|
var hostsHere = /* @__PURE__ */ new Set();
|
|
32400
32584
|
function leaseFile(sessionId, workspace) {
|
|
32401
|
-
return
|
|
32585
|
+
return path43.join(sessionDataDir(sessionId, workspace), LEASE_FILE);
|
|
32402
32586
|
}
|
|
32403
32587
|
function isRecord6(value) {
|
|
32404
32588
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -32487,7 +32671,7 @@ var LeaseHost = class {
|
|
|
32487
32671
|
*/
|
|
32488
32672
|
acquire(file, workspace, holder) {
|
|
32489
32673
|
ensureStateDirIgnored(workspace);
|
|
32490
|
-
ensurePrivateDir(
|
|
32674
|
+
ensurePrivateDir(path43.dirname(file));
|
|
32491
32675
|
const outcome = withFileLock(file, () => {
|
|
32492
32676
|
const current = readRecord(file);
|
|
32493
32677
|
const taken = current !== null && current.hostId !== this.id ? current : null;
|
|
@@ -32542,7 +32726,7 @@ var LeaseHost = class {
|
|
|
32542
32726
|
withFileLock(file, () => {
|
|
32543
32727
|
if (readRecord(file)?.hostId === this.id) fs19.rmSync(file, { force: true });
|
|
32544
32728
|
}, "release a session lease");
|
|
32545
|
-
fs19.rmdirSync(
|
|
32729
|
+
fs19.rmdirSync(path43.dirname(file));
|
|
32546
32730
|
} catch {
|
|
32547
32731
|
}
|
|
32548
32732
|
}
|
|
@@ -33488,7 +33672,9 @@ var TaskOrchestrator = class _TaskOrchestrator {
|
|
|
33488
33672
|
this.store.markPending(task2.id);
|
|
33489
33673
|
this.hold(task2.id, failure2.hold, false);
|
|
33490
33674
|
}
|
|
33491
|
-
|
|
33675
|
+
if (failure2.leaves !== "held" || !failure2.preserveWorktree) {
|
|
33676
|
+
await this.runs.release(task2.id, { keep: failure2.leaves === "failed" && failure2.keepWorktree });
|
|
33677
|
+
}
|
|
33492
33678
|
const { level, text: text4, toastOnly } = failure2.notice;
|
|
33493
33679
|
if (toastOnly) this.notifications[level](text4);
|
|
33494
33680
|
else this.tell(level, text4);
|
|
@@ -35304,7 +35490,7 @@ import { spawn as nodeSpawn3 } from "child_process";
|
|
|
35304
35490
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
35305
35491
|
import { mkdtempSync as mkdtempSync5, rmSync as rmSync12 } from "fs";
|
|
35306
35492
|
import { tmpdir as tmpdir6 } from "os";
|
|
35307
|
-
import { join as
|
|
35493
|
+
import { join as join39 } from "path";
|
|
35308
35494
|
var DEFAULT_TIMEOUT_MS5 = 2e4;
|
|
35309
35495
|
var INITIALIZE_TIMEOUT_MS2 = 1e4;
|
|
35310
35496
|
var USAGE_TIMEOUT_MS = 1e4;
|
|
@@ -35336,7 +35522,7 @@ function claudeAccountLimitCollector(options) {
|
|
|
35336
35522
|
};
|
|
35337
35523
|
}
|
|
35338
35524
|
async function readClaudeAccountLimits(options, signal) {
|
|
35339
|
-
const cwd = mkdtempSync5(
|
|
35525
|
+
const cwd = mkdtempSync5(join39(tmpdir6(), "ordewell-claude-limits-"));
|
|
35340
35526
|
const removeCwd = () => {
|
|
35341
35527
|
try {
|
|
35342
35528
|
rmSync12(cwd, { recursive: true, force: true });
|
|
@@ -35423,10 +35609,10 @@ function isoInstant(value) {
|
|
|
35423
35609
|
import { homedir as homedir9 } from "os";
|
|
35424
35610
|
|
|
35425
35611
|
// src/services/harness/openCodeCredentials.ts
|
|
35426
|
-
import { createHash as
|
|
35612
|
+
import { createHash as createHash6 } from "crypto";
|
|
35427
35613
|
import { promises as fs20 } from "fs";
|
|
35428
35614
|
import { homedir as osHomedir } from "os";
|
|
35429
|
-
import { join as
|
|
35615
|
+
import { join as join40, resolve as resolve13 } from "path";
|
|
35430
35616
|
import { Worker } from "worker_threads";
|
|
35431
35617
|
var DEFAULT_TIMEOUT_MS6 = 5e3;
|
|
35432
35618
|
var BUSY_MS = 250;
|
|
@@ -35481,11 +35667,11 @@ function walStore(path) {
|
|
|
35481
35667
|
parentPort.postMessage(select());
|
|
35482
35668
|
`;
|
|
35483
35669
|
var isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35484
|
-
var digest = (...parts) =>
|
|
35670
|
+
var digest = (...parts) => createHash6("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
|
|
35485
35671
|
function openCodeStorePaths(env, home) {
|
|
35486
|
-
const data =
|
|
35672
|
+
const data = join40(env.XDG_DATA_HOME || join40(home, ".local", "share"), "opencode");
|
|
35487
35673
|
const file = env.OPENCODE_DB || "opencode.db";
|
|
35488
|
-
return { db: file === ":memory:" ? null : resolve13(data, file), auth:
|
|
35674
|
+
return { db: file === ":memory:" ? null : resolve13(data, file), auth: join40(data, "auth.json") };
|
|
35489
35675
|
}
|
|
35490
35676
|
function openCodeGoLoginReader(deps = {}) {
|
|
35491
35677
|
const homedir10 = deps.homedir ?? osHomedir;
|
|
@@ -35547,8 +35733,8 @@ function v2Login(db, row) {
|
|
|
35547
35733
|
login: { route: "console", owner: digest("console", db, row.id, account, orgID ?? ""), access: value.access, ...orgID ? { orgID } : {}, expires: value.expires }
|
|
35548
35734
|
};
|
|
35549
35735
|
}
|
|
35550
|
-
async function legacyLogin(
|
|
35551
|
-
const content = env.OPENCODE_AUTH_CONTENT ?? await readSmall(
|
|
35736
|
+
async function legacyLogin(path49, env) {
|
|
35737
|
+
const content = env.OPENCODE_AUTH_CONTENT ?? await readSmall(path49);
|
|
35552
35738
|
if (content === void 0) return env[ENV_KEY] ? { kind: "unsupported" } : { kind: "none" };
|
|
35553
35739
|
if (content === null) return { kind: "unreadable" };
|
|
35554
35740
|
const auth = parseJson(content);
|
|
@@ -35557,15 +35743,15 @@ async function legacyLogin(path47, env) {
|
|
|
35557
35743
|
if (entry === void 0) return env[ENV_KEY] ? { kind: "unsupported" } : { kind: "none" };
|
|
35558
35744
|
if (!isRecord9(entry) || entry.type !== "api") return { kind: "unsupported" };
|
|
35559
35745
|
if (typeof entry.key !== "string" || entry.key.length === 0) return { kind: "unreadable" };
|
|
35560
|
-
return { kind: "login", login: { route: "key", owner: digest("v1",
|
|
35746
|
+
return { kind: "login", login: { route: "key", owner: digest("v1", path49, entry.key), key: entry.key } };
|
|
35561
35747
|
}
|
|
35562
|
-
function queryStore(
|
|
35748
|
+
function queryStore(path49, signal, deps) {
|
|
35563
35749
|
return new Promise((settle) => {
|
|
35564
35750
|
let worker;
|
|
35565
35751
|
try {
|
|
35566
35752
|
worker = (deps.spawnWorker ?? ((source, options) => new Worker(source, options)))(WORKER_SOURCE, {
|
|
35567
35753
|
eval: true,
|
|
35568
|
-
workerData: { path:
|
|
35754
|
+
workerData: { path: path49, integrations: GO_INTEGRATIONS, busyMs: BUSY_MS, maxValueBytes: MAX_VALUE_BYTES },
|
|
35569
35755
|
execArgv: deps.workerExecArgv ?? [],
|
|
35570
35756
|
resourceLimits: { maxOldGenerationSizeMb: 64 }
|
|
35571
35757
|
});
|
|
@@ -35592,19 +35778,19 @@ function queryStore(path47, signal, deps) {
|
|
|
35592
35778
|
worker.once("exit", aborted);
|
|
35593
35779
|
});
|
|
35594
35780
|
}
|
|
35595
|
-
async function stamp(
|
|
35781
|
+
async function stamp(path49) {
|
|
35596
35782
|
try {
|
|
35597
|
-
const stat = await fs20.stat(
|
|
35783
|
+
const stat = await fs20.stat(path49);
|
|
35598
35784
|
return [stat.ino, stat.size, stat.mtimeMs];
|
|
35599
35785
|
} catch {
|
|
35600
35786
|
return null;
|
|
35601
35787
|
}
|
|
35602
35788
|
}
|
|
35603
|
-
async function readSmall(
|
|
35789
|
+
async function readSmall(path49) {
|
|
35604
35790
|
try {
|
|
35605
|
-
const stat = await fs20.stat(
|
|
35791
|
+
const stat = await fs20.stat(path49);
|
|
35606
35792
|
if (!stat.isFile() || stat.size > MAX_AUTH_FILE_BYTES) return null;
|
|
35607
|
-
return await fs20.readFile(
|
|
35793
|
+
return await fs20.readFile(path49, "utf8");
|
|
35608
35794
|
} catch (err) {
|
|
35609
35795
|
return err.code === "ENOENT" ? void 0 : null;
|
|
35610
35796
|
}
|
|
@@ -36733,20 +36919,20 @@ function createAiService(config, deps) {
|
|
|
36733
36919
|
}
|
|
36734
36920
|
|
|
36735
36921
|
// src/services/createSession.ts
|
|
36736
|
-
import * as
|
|
36922
|
+
import * as path46 from "path";
|
|
36737
36923
|
|
|
36738
36924
|
// src/services/handoffReferences.ts
|
|
36739
36925
|
import * as fs21 from "fs";
|
|
36740
|
-
import * as
|
|
36926
|
+
import * as path44 from "path";
|
|
36741
36927
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
36742
36928
|
function resolveHandoffReferences(handoff, workspace) {
|
|
36743
36929
|
const checked = /* @__PURE__ */ new Map();
|
|
36744
36930
|
const contained = (candidate) => {
|
|
36745
36931
|
try {
|
|
36746
36932
|
const root = fs21.realpathSync(workspace);
|
|
36747
|
-
const resolved = fs21.realpathSync(
|
|
36748
|
-
const relative17 =
|
|
36749
|
-
return relative17 !== ".." && !relative17.startsWith(`..${
|
|
36933
|
+
const resolved = fs21.realpathSync(path44.resolve(root, candidate));
|
|
36934
|
+
const relative17 = path44.relative(root, resolved);
|
|
36935
|
+
return relative17 !== ".." && !relative17.startsWith(`..${path44.sep}`) && !path44.isAbsolute(relative17) ? resolved : void 0;
|
|
36750
36936
|
} catch {
|
|
36751
36937
|
return void 0;
|
|
36752
36938
|
}
|
|
@@ -36767,7 +36953,7 @@ function resolveHandoffReferences(handoff, workspace) {
|
|
|
36767
36953
|
}
|
|
36768
36954
|
} else if (/^[0-9a-fA-F]{4,64}$/.test(ref.sha)) {
|
|
36769
36955
|
const repo = contained(ref.repo ?? ".");
|
|
36770
|
-
if (repo && fs21.existsSync(
|
|
36956
|
+
if (repo && fs21.existsSync(path44.join(repo, ".git"))) {
|
|
36771
36957
|
const result2 = spawnSync2("git", ["--no-optional-locks", "--no-replace-objects", "cat-file", "-t", ref.sha], {
|
|
36772
36958
|
cwd: repo,
|
|
36773
36959
|
encoding: "utf8",
|
|
@@ -38242,10 +38428,10 @@ var SessionEventRelay = class {
|
|
|
38242
38428
|
|
|
38243
38429
|
// src/utils/taskLogStore.ts
|
|
38244
38430
|
import * as fs22 from "fs";
|
|
38245
|
-
import * as
|
|
38431
|
+
import * as path45 from "path";
|
|
38246
38432
|
var EXTENSION = ".jsonl";
|
|
38247
38433
|
function taskDir({ baseDir, sessionId }, taskId) {
|
|
38248
|
-
return
|
|
38434
|
+
return path45.join(sessionDataDir(sessionId, baseDir), "tasks", idSegment(taskId));
|
|
38249
38435
|
}
|
|
38250
38436
|
function listTaskLogAttempts(location, taskId) {
|
|
38251
38437
|
let names;
|
|
@@ -38263,7 +38449,7 @@ function openTaskLog(location, taskId, attempt) {
|
|
|
38263
38449
|
const next = (listTaskLogAttempts(location, taskId).pop() ?? 0) + 1;
|
|
38264
38450
|
let number = attempt !== void 0 && Number.isInteger(attempt) && attempt >= 1 ? attempt : next;
|
|
38265
38451
|
for (; ; ) {
|
|
38266
|
-
const file =
|
|
38452
|
+
const file = path45.join(dir, `${number}${EXTENSION}`);
|
|
38267
38453
|
try {
|
|
38268
38454
|
fs22.writeFileSync(file, "", { flag: "wx" });
|
|
38269
38455
|
} catch (err) {
|
|
@@ -38287,15 +38473,15 @@ function prepareTaskOutputFile(location, taskId, attempt) {
|
|
|
38287
38473
|
ensureStateDirIgnored(location.baseDir);
|
|
38288
38474
|
const dir = taskDir(location, taskId);
|
|
38289
38475
|
fs22.mkdirSync(dir, { recursive: true });
|
|
38290
|
-
return
|
|
38476
|
+
return path45.join(dir, `${attempt}.output.txt`);
|
|
38291
38477
|
}
|
|
38292
38478
|
function taskPatchFile(location, taskId, attempt) {
|
|
38293
|
-
return
|
|
38479
|
+
return path45.join(taskDir(location, taskId), `${attempt}.patch`);
|
|
38294
38480
|
}
|
|
38295
38481
|
function saveTaskPatch(location, taskId, attempt, patch) {
|
|
38296
38482
|
ensureStateDirIgnored(location.baseDir);
|
|
38297
38483
|
const file = taskPatchFile(location, taskId, attempt);
|
|
38298
|
-
fs22.mkdirSync(
|
|
38484
|
+
fs22.mkdirSync(path45.dirname(file), { recursive: true });
|
|
38299
38485
|
const partial = `${file}.${process.pid}-${Date.now()}.partial`;
|
|
38300
38486
|
fs22.writeFileSync(partial, patch, { flag: "wx" });
|
|
38301
38487
|
fs22.renameSync(partial, file);
|
|
@@ -38316,7 +38502,7 @@ function readTaskLog(location, taskId, attempt) {
|
|
|
38316
38502
|
if (!Number.isInteger(attempt) || attempt < 1) return [];
|
|
38317
38503
|
let raw;
|
|
38318
38504
|
try {
|
|
38319
|
-
raw = fs22.readFileSync(
|
|
38505
|
+
raw = fs22.readFileSync(path45.join(taskDir(location, taskId), `${attempt}${EXTENSION}`), "utf-8");
|
|
38320
38506
|
} catch {
|
|
38321
38507
|
return [];
|
|
38322
38508
|
}
|
|
@@ -40345,7 +40531,7 @@ function createSession(deps) {
|
|
|
40345
40531
|
...deps.openTaskLog ? {} : {
|
|
40346
40532
|
keepPatch: (taskId, attempt, patch) => {
|
|
40347
40533
|
const location = session.taskLogLocation;
|
|
40348
|
-
return
|
|
40534
|
+
return path46.relative(location.baseDir, saveTaskPatch(location, taskId, attempt, patch)).split(path46.sep).join("/");
|
|
40349
40535
|
}
|
|
40350
40536
|
},
|
|
40351
40537
|
recordHandoff: (sessionId, taskId, handoff) => taskLogs.note(sessionId, taskId, { type: "handoff", handoff }),
|
|
@@ -43186,7 +43372,7 @@ var RunnerRegistry = class {
|
|
|
43186
43372
|
|
|
43187
43373
|
// src/plugins/removedPluginNotice.ts
|
|
43188
43374
|
import * as fs23 from "fs";
|
|
43189
|
-
import * as
|
|
43375
|
+
import * as path47 from "path";
|
|
43190
43376
|
function isManifestFile(file) {
|
|
43191
43377
|
try {
|
|
43192
43378
|
return fs23.statSync(file).isFile();
|
|
@@ -43195,10 +43381,10 @@ function isManifestFile(file) {
|
|
|
43195
43381
|
}
|
|
43196
43382
|
}
|
|
43197
43383
|
function removedPluginNotice(dataDir = globalDataDir()) {
|
|
43198
|
-
const directory =
|
|
43384
|
+
const directory = path47.join(dataDir, "plugins");
|
|
43199
43385
|
try {
|
|
43200
|
-
const hasManifest = isManifestFile(
|
|
43201
|
-
(entry) => (entry.isDirectory() || entry.isSymbolicLink()) && isManifestFile(
|
|
43386
|
+
const hasManifest = isManifestFile(path47.join(directory, "manifest.json")) || fs23.readdirSync(directory, { withFileTypes: true }).some(
|
|
43387
|
+
(entry) => (entry.isDirectory() || entry.isSymbolicLink()) && isManifestFile(path47.join(directory, entry.name, "manifest.json"))
|
|
43202
43388
|
);
|
|
43203
43389
|
if (hasManifest) return "Plugin runners were removed; manifests in ~/.ordewell/plugins/ are ignored. See the CHANGELOG.";
|
|
43204
43390
|
} catch {
|
|
@@ -43209,15 +43395,15 @@ function removedPluginNotice(dataDir = globalDataDir()) {
|
|
|
43209
43395
|
|
|
43210
43396
|
// src/utils/stateStore.ts
|
|
43211
43397
|
import * as fs24 from "fs";
|
|
43212
|
-
import * as
|
|
43398
|
+
import * as path48 from "path";
|
|
43213
43399
|
var STATE_FILE2 = "state.json";
|
|
43214
43400
|
function getStatePath(baseDir) {
|
|
43215
|
-
return
|
|
43401
|
+
return path48.join(getStateDir(baseDir), STATE_FILE2);
|
|
43216
43402
|
}
|
|
43217
43403
|
var SESSION_ID_KEY = "sessionId";
|
|
43218
43404
|
function saveState(plan, baseDir, sessionId) {
|
|
43219
43405
|
const statePath = getStatePath(baseDir ?? process.cwd());
|
|
43220
|
-
ensureDir(
|
|
43406
|
+
ensureDir(path48.dirname(statePath));
|
|
43221
43407
|
plan.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
43222
43408
|
const file = sessionId ? { ...plan, [SESSION_ID_KEY]: sessionId } : plan;
|
|
43223
43409
|
dropRetiredPlanFields(file);
|
|
@@ -43765,6 +43951,7 @@ export {
|
|
|
43765
43951
|
repoBaseLine,
|
|
43766
43952
|
repoResultLines,
|
|
43767
43953
|
reposWithWork,
|
|
43954
|
+
repositoryRunnerConfigPaths,
|
|
43768
43955
|
researchShellWarning,
|
|
43769
43956
|
researchToolsPath,
|
|
43770
43957
|
resetInstalledPlanner,
|