@ordewell/core 0.4.20 → 0.4.22
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/{chunk-QJ63PD5K.mjs → chunk-MKUTJDT2.mjs} +2 -1
- package/dist/chunk-MKUTJDT2.mjs.map +1 -0
- package/dist/index.d.mts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +317 -127
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +310 -121
- package/dist/index.mjs.map +1 -1
- package/dist/parsing.js +1 -0
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-QJ63PD5K.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolveTaskMode,
|
|
14
14
|
runnerModesFrom,
|
|
15
15
|
validatePlanModification
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-MKUTJDT2.mjs";
|
|
17
17
|
import {
|
|
18
18
|
CHECKPOINT_TRUNCATE_LENGTH,
|
|
19
19
|
UPDATABLE_FIELDS,
|
|
@@ -6225,6 +6225,19 @@ function renderTerminalOutput(raw) {
|
|
|
6225
6225
|
}
|
|
6226
6226
|
var MARKER_SCAN_TAIL = 16384;
|
|
6227
6227
|
var IDLE_TIMEOUT_MS = 6e4;
|
|
6228
|
+
function renderCleanCapture(raw, doneToken) {
|
|
6229
|
+
const rendered = renderTerminalOutput(raw).replace(/[\s─-▟]+$/gm, "");
|
|
6230
|
+
if (!doneToken) return rendered.trim();
|
|
6231
|
+
const lines = rendered.split("\n");
|
|
6232
|
+
const flat = (s) => flattenTerminalOutput(s);
|
|
6233
|
+
for (let i = 0; i < lines.length; i++) {
|
|
6234
|
+
const own = flat(lines[i]).includes(doneToken);
|
|
6235
|
+
if (own) return lines.slice(0, i).join("\n").trim();
|
|
6236
|
+
const window = flat(lines[i]) + (i + 1 < lines.length ? flat(lines[i + 1]) : "");
|
|
6237
|
+
if (window.includes(doneToken)) return lines.slice(0, i + 1).join("\n").trim();
|
|
6238
|
+
}
|
|
6239
|
+
return rendered.trim();
|
|
6240
|
+
}
|
|
6228
6241
|
var VerdictEngine = class {
|
|
6229
6242
|
markerSeen = /* @__PURE__ */ new Set();
|
|
6230
6243
|
buffers = /* @__PURE__ */ new Map();
|
|
@@ -6452,6 +6465,167 @@ ${line}
|
|
|
6452
6465
|
}
|
|
6453
6466
|
};
|
|
6454
6467
|
|
|
6468
|
+
// src/services/transcriptCapture.ts
|
|
6469
|
+
import { readFileSync, readdirSync, statSync as statSync2, existsSync } from "fs";
|
|
6470
|
+
import * as os2 from "os";
|
|
6471
|
+
import * as path4 from "path";
|
|
6472
|
+
function homeDir() {
|
|
6473
|
+
return process.env.HOME || os2.homedir();
|
|
6474
|
+
}
|
|
6475
|
+
async function readFinalAssistantText(query, maxChars = 4e3) {
|
|
6476
|
+
try {
|
|
6477
|
+
if (query.runner === "claude-code") return claudeFinal(query, maxChars);
|
|
6478
|
+
if (query.runner === "opencode") return await opencodeFinal(query, maxChars);
|
|
6479
|
+
if (query.runner === "codex") return codexFinal(query, maxChars);
|
|
6480
|
+
} catch {
|
|
6481
|
+
}
|
|
6482
|
+
return null;
|
|
6483
|
+
}
|
|
6484
|
+
function claudeFinal(query, maxChars) {
|
|
6485
|
+
const munged = query.cwd.replaceAll("/", "-").replaceAll("_", "-");
|
|
6486
|
+
const dir = path4.join(homeDir(), ".claude", "projects", munged);
|
|
6487
|
+
if (!existsSync(dir)) return null;
|
|
6488
|
+
const cutoff = query.startedAt ? Date.parse(query.startedAt) : 0;
|
|
6489
|
+
const candidates = readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) => path4.join(dir, f)).filter((f) => cutoff ? statSync2(f).mtimeMs >= cutoff - 5e3 : true).sort((a, b) => statSync2(b).mtimeMs - statSync2(a).mtimeMs);
|
|
6490
|
+
for (const file of candidates) {
|
|
6491
|
+
const text = claudeLastAssistant(file);
|
|
6492
|
+
if (text) return clamp(text, maxChars);
|
|
6493
|
+
}
|
|
6494
|
+
return null;
|
|
6495
|
+
}
|
|
6496
|
+
function claudeLastAssistant(file) {
|
|
6497
|
+
let last = null;
|
|
6498
|
+
let buf = "";
|
|
6499
|
+
const fd = statSync2(file);
|
|
6500
|
+
const start = Math.max(0, fd.size - 512 * 1024);
|
|
6501
|
+
buf = readFileSync(file, { encoding: "utf8" }).toString();
|
|
6502
|
+
if (start > 0) buf = buf.slice(buf.indexOf("\n", Math.min(start, buf.length - 1)) + 1);
|
|
6503
|
+
for (const line of buf.split("\n")) {
|
|
6504
|
+
if (!line.trim()) continue;
|
|
6505
|
+
let rec;
|
|
6506
|
+
try {
|
|
6507
|
+
rec = JSON.parse(line);
|
|
6508
|
+
} catch {
|
|
6509
|
+
continue;
|
|
6510
|
+
}
|
|
6511
|
+
if (rec.type !== "assistant" || rec.isSidechain) continue;
|
|
6512
|
+
const content = rec.message?.content;
|
|
6513
|
+
if (!Array.isArray(content)) continue;
|
|
6514
|
+
const texts = content.filter((b) => typeof b === "object" && b !== null && b.type === "text").map((b) => b.text).join("\n").trim();
|
|
6515
|
+
if (texts) last = texts;
|
|
6516
|
+
}
|
|
6517
|
+
return last;
|
|
6518
|
+
}
|
|
6519
|
+
async function opencodeFinal(query, maxChars) {
|
|
6520
|
+
let DatabaseSync;
|
|
6521
|
+
try {
|
|
6522
|
+
({ DatabaseSync } = await import("sqlite"));
|
|
6523
|
+
} catch {
|
|
6524
|
+
return null;
|
|
6525
|
+
}
|
|
6526
|
+
const dbPath = path4.join(homeDir(), ".local", "share", "opencode", "opencode.db");
|
|
6527
|
+
if (!existsSync(dbPath)) return null;
|
|
6528
|
+
let db;
|
|
6529
|
+
try {
|
|
6530
|
+
db = new DatabaseSync(dbPath, { open: true });
|
|
6531
|
+
} catch {
|
|
6532
|
+
return null;
|
|
6533
|
+
}
|
|
6534
|
+
try {
|
|
6535
|
+
const cutoff = query.startedAt ? Date.parse(query.startedAt) : 0;
|
|
6536
|
+
const rows = db.prepare(
|
|
6537
|
+
`select s.id, s.time_updated from session s
|
|
6538
|
+
join project p on p.id = s.project_id
|
|
6539
|
+
where s.directory = ?
|
|
6540
|
+
order by s.time_updated desc limit 5`
|
|
6541
|
+
).all(query.cwd);
|
|
6542
|
+
for (const row of rows) {
|
|
6543
|
+
if (cutoff && row.time_updated < cutoff - 5e3) continue;
|
|
6544
|
+
const parts = db.prepare(
|
|
6545
|
+
`select pt.data from part pt
|
|
6546
|
+
join message m on m.id = pt.message_id
|
|
6547
|
+
where m.session_id = ? and m.data like '%"role":"assistant"%'
|
|
6548
|
+
order by pt.id asc`
|
|
6549
|
+
).all(row.id);
|
|
6550
|
+
let text = null;
|
|
6551
|
+
for (const p of parts) {
|
|
6552
|
+
try {
|
|
6553
|
+
const d = JSON.parse(p.data);
|
|
6554
|
+
if (d.type === "text" && d.text && d.text.trim()) text = d.text.trim();
|
|
6555
|
+
} catch {
|
|
6556
|
+
continue;
|
|
6557
|
+
}
|
|
6558
|
+
}
|
|
6559
|
+
if (text) return clamp(text, maxChars);
|
|
6560
|
+
}
|
|
6561
|
+
return null;
|
|
6562
|
+
} catch {
|
|
6563
|
+
return null;
|
|
6564
|
+
} finally {
|
|
6565
|
+
try {
|
|
6566
|
+
db.close();
|
|
6567
|
+
} catch {
|
|
6568
|
+
}
|
|
6569
|
+
}
|
|
6570
|
+
}
|
|
6571
|
+
function codexFinal(query, maxChars) {
|
|
6572
|
+
const root = path4.join(homeDir(), ".codex", "sessions");
|
|
6573
|
+
if (!existsSync(root)) return null;
|
|
6574
|
+
const cutoff = query.startedAt ? Date.parse(query.startedAt) : 0;
|
|
6575
|
+
const files = [];
|
|
6576
|
+
const stack = [root];
|
|
6577
|
+
while (stack.length) {
|
|
6578
|
+
const dir = stack.pop();
|
|
6579
|
+
let entries;
|
|
6580
|
+
try {
|
|
6581
|
+
entries = readdirSync(dir);
|
|
6582
|
+
} catch {
|
|
6583
|
+
continue;
|
|
6584
|
+
}
|
|
6585
|
+
for (const e of entries) {
|
|
6586
|
+
const full = path4.join(dir, e);
|
|
6587
|
+
let st;
|
|
6588
|
+
try {
|
|
6589
|
+
st = statSync2(full);
|
|
6590
|
+
} catch {
|
|
6591
|
+
continue;
|
|
6592
|
+
}
|
|
6593
|
+
if (st.isDirectory()) stack.push(full);
|
|
6594
|
+
else if (e.startsWith("rollout-") && e.endsWith(".jsonl") && (!cutoff || st.mtimeMs >= cutoff - 5e3)) files.push(full);
|
|
6595
|
+
}
|
|
6596
|
+
}
|
|
6597
|
+
files.sort((a, b) => statSync2(b).mtimeMs - statSync2(a).mtimeMs);
|
|
6598
|
+
for (const file of files.slice(0, 10)) {
|
|
6599
|
+
const text = codexLastAssistant(file, query.cwd);
|
|
6600
|
+
if (text) return clamp(text, maxChars);
|
|
6601
|
+
}
|
|
6602
|
+
return null;
|
|
6603
|
+
}
|
|
6604
|
+
function codexLastAssistant(file, cwd) {
|
|
6605
|
+
const raw = readFileSync(file, "utf8");
|
|
6606
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
6607
|
+
let sawCwd = false;
|
|
6608
|
+
let last = null;
|
|
6609
|
+
for (const line of lines) {
|
|
6610
|
+
let rec;
|
|
6611
|
+
try {
|
|
6612
|
+
rec = JSON.parse(line);
|
|
6613
|
+
} catch {
|
|
6614
|
+
continue;
|
|
6615
|
+
}
|
|
6616
|
+
if (rec.type === "session_meta" && rec.payload?.cwd === cwd) sawCwd = true;
|
|
6617
|
+
if (rec.type !== "response_item") continue;
|
|
6618
|
+
const p = rec.payload;
|
|
6619
|
+
if (p?.role !== "assistant" || p.type !== "message") continue;
|
|
6620
|
+
const texts = (Array.isArray(p.content) ? p.content : []).map((c) => typeof c === "object" && c !== null && c.text || "").join("\n").trim();
|
|
6621
|
+
if (texts) last = texts;
|
|
6622
|
+
}
|
|
6623
|
+
return sawCwd ? last : null;
|
|
6624
|
+
}
|
|
6625
|
+
function clamp(text, maxChars) {
|
|
6626
|
+
return text.length <= maxChars ? text : text.slice(-maxChars);
|
|
6627
|
+
}
|
|
6628
|
+
|
|
6455
6629
|
// src/services/PlanStore.ts
|
|
6456
6630
|
var PlanStore = class {
|
|
6457
6631
|
_planTasks = [];
|
|
@@ -6833,6 +7007,11 @@ var TaskOrchestrator = class {
|
|
|
6833
7007
|
workspaceRootFn = () => process.cwd();
|
|
6834
7008
|
observers = [];
|
|
6835
7009
|
tddEnabled = () => false;
|
|
7010
|
+
/**
|
|
7011
|
+
* Spawn context per active task, for locating the agent's own session
|
|
7012
|
+
* transcript at verdict time (issue #16). Cleared with the session entry.
|
|
7013
|
+
*/
|
|
7014
|
+
taskSpawnContext = /* @__PURE__ */ new Map();
|
|
6836
7015
|
/** Advisory silence timestamp for a task's live runner, or null if not idle. */
|
|
6837
7016
|
getIdleSince(taskId) {
|
|
6838
7017
|
return this.verifier.getIdleSince(taskId);
|
|
@@ -6995,6 +7174,8 @@ var TaskOrchestrator = class {
|
|
|
6995
7174
|
const task = this.store.get(taskId);
|
|
6996
7175
|
if (!task) return;
|
|
6997
7176
|
this.activeTaskSessions.delete(taskId);
|
|
7177
|
+
const spawnContext = this.taskSpawnContext.get(taskId);
|
|
7178
|
+
this.taskSpawnContext.delete(taskId);
|
|
6998
7179
|
console.error(`[TaskOrchestrator] Task #${task.order} "${task.title}" verdict=${verdict.outcome}`);
|
|
6999
7180
|
console.error(`[TaskOrchestrator] Runner: ${task.assignedRunner}, Model: ${task.assignedModel?.modelId ?? "default"}`);
|
|
7000
7181
|
console.error(`[TaskOrchestrator] Prompt preview: ${(task.prompt ?? "").slice(0, 200)}`);
|
|
@@ -7005,6 +7186,10 @@ ${output.slice(-3e3)}`);
|
|
|
7005
7186
|
console.error(`[TaskOrchestrator] Output: (empty \u2014 no stdout/stderr captured)`);
|
|
7006
7187
|
}
|
|
7007
7188
|
this.store.setTaskVerdict(taskId, verdict);
|
|
7189
|
+
const doneToken = `<<<ORDEWELL_DONE_${task.completionMarker}>>>`;
|
|
7190
|
+
const transcript = spawnContext ? await readFinalAssistantText(spawnContext) : null;
|
|
7191
|
+
const cleaned = transcript ?? renderCleanCapture(output, doneToken);
|
|
7192
|
+
const effective = cleaned.length > 0 ? cleaned : output;
|
|
7008
7193
|
if (verdict.outcome === "pass") {
|
|
7009
7194
|
this.store.markCompleted(taskId);
|
|
7010
7195
|
this.notifications.info(`Task "${task.title}" completed.`);
|
|
@@ -7014,7 +7199,7 @@ ${output.slice(-3e3)}`);
|
|
|
7014
7199
|
this.planStatus = "approved";
|
|
7015
7200
|
this.notifications.error(`Task "${task.title}" failed verification: ${verdict.reason}`);
|
|
7016
7201
|
}
|
|
7017
|
-
this.store.setTaskOutputSummary(taskId, summarizeOutput(verdict.reason,
|
|
7202
|
+
this.store.setTaskOutputSummary(taskId, summarizeOutput(verdict.reason, effective));
|
|
7018
7203
|
this.logAndArchive(task, verdict);
|
|
7019
7204
|
this.emit("onTaskChanged");
|
|
7020
7205
|
if (!this.running) {
|
|
@@ -7254,6 +7439,8 @@ ${output.slice(-3e3)}`);
|
|
|
7254
7439
|
try {
|
|
7255
7440
|
const cwd = this.workspaceRootFn();
|
|
7256
7441
|
const runner = this.store.resolveTaskRunner(task);
|
|
7442
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7443
|
+
this.taskSpawnContext.set(task.id, { runner, cwd, startedAt });
|
|
7257
7444
|
const finalPrompt = composeAugmentedPrompt(task, this.store.planTasks, {
|
|
7258
7445
|
planMapEnabled: this.config.planMapEnabled,
|
|
7259
7446
|
tddEnabled: this.tddEnabled()
|
|
@@ -7418,7 +7605,7 @@ ${errors.map((e) => `- ${e}`).join("\n")}`
|
|
|
7418
7605
|
};
|
|
7419
7606
|
|
|
7420
7607
|
// src/services/ModelDiscovery.ts
|
|
7421
|
-
import * as
|
|
7608
|
+
import * as path8 from "path";
|
|
7422
7609
|
import { exec as exec2, spawn } from "child_process";
|
|
7423
7610
|
import { promisify as promisify2 } from "util";
|
|
7424
7611
|
import * as fsSync3 from "fs";
|
|
@@ -7427,8 +7614,8 @@ import * as osMod from "os";
|
|
|
7427
7614
|
// src/utils/shellPath.ts
|
|
7428
7615
|
import { exec } from "child_process";
|
|
7429
7616
|
import { promisify } from "util";
|
|
7430
|
-
import * as
|
|
7431
|
-
import * as
|
|
7617
|
+
import * as os3 from "os";
|
|
7618
|
+
import * as path5 from "path";
|
|
7432
7619
|
var execAsync = promisify(exec);
|
|
7433
7620
|
var LOGIN_SHELL_TIMEOUT_MS = 5e3;
|
|
7434
7621
|
var PATH_MARKER = "__ORDEWELL_PATH__";
|
|
@@ -7437,42 +7624,42 @@ var defaultExec = async (command, options) => {
|
|
|
7437
7624
|
return { stdout: String(stdout) };
|
|
7438
7625
|
};
|
|
7439
7626
|
function posixBinDirs() {
|
|
7440
|
-
const home =
|
|
7627
|
+
const home = os3.homedir();
|
|
7441
7628
|
return [
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7629
|
+
path5.join(home, ".local", "bin"),
|
|
7630
|
+
path5.join(home, ".opencode", "bin"),
|
|
7631
|
+
path5.join(home, ".claude", "bin"),
|
|
7632
|
+
path5.join(home, ".bun", "bin"),
|
|
7633
|
+
path5.join(home, ".volta", "bin"),
|
|
7634
|
+
path5.join(home, ".npm-global", "bin"),
|
|
7635
|
+
path5.join(home, "bin"),
|
|
7449
7636
|
"/usr/local/bin",
|
|
7450
7637
|
"/opt/homebrew/bin"
|
|
7451
7638
|
];
|
|
7452
7639
|
}
|
|
7453
7640
|
function windowsBinDirs(env, home) {
|
|
7454
|
-
const
|
|
7455
|
-
const under = (base, ...parts) => base ? [
|
|
7641
|
+
const join20 = (...parts) => path5.win32.join(...parts);
|
|
7642
|
+
const under = (base, ...parts) => base ? [join20(base, ...parts)] : [];
|
|
7456
7643
|
const appData = env.APPDATA;
|
|
7457
7644
|
const localAppData = env.LOCALAPPDATA;
|
|
7458
7645
|
const programData = env.ProgramData;
|
|
7459
7646
|
return [
|
|
7460
7647
|
// Native per-user installers, PowerShell-driven and otherwise.
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7648
|
+
join20(home, ".local", "bin"),
|
|
7649
|
+
join20(home, ".opencode", "bin"),
|
|
7650
|
+
join20(home, ".claude", "bin"),
|
|
7651
|
+
join20(home, ".codex", "bin"),
|
|
7465
7652
|
...under(localAppData, "Programs", "claude"),
|
|
7466
7653
|
// Node package managers. npm's global prefix is `%APPDATA%\npm`; the
|
|
7467
7654
|
// literal spelling is kept as a fallback for a host that does not export
|
|
7468
7655
|
// APPDATA (a service account, a stripped CI container).
|
|
7469
7656
|
...under(appData, "npm"),
|
|
7470
|
-
|
|
7657
|
+
join20(home, "AppData", "Roaming", "npm"),
|
|
7471
7658
|
...under(localAppData, "pnpm"),
|
|
7472
7659
|
...under(localAppData, "Yarn", "bin"),
|
|
7473
|
-
|
|
7660
|
+
join20(home, ".bun", "bin"),
|
|
7474
7661
|
// Windows package managers.
|
|
7475
|
-
|
|
7662
|
+
join20(home, "scoop", "shims"),
|
|
7476
7663
|
...under(env.SCOOP, "shims"),
|
|
7477
7664
|
...under(env.SCOOP_GLOBAL ?? programData, "scoop", "shims"),
|
|
7478
7665
|
...under(programData, "chocolatey", "bin"),
|
|
@@ -7482,13 +7669,13 @@ function windowsBinDirs(env, home) {
|
|
|
7482
7669
|
...under(localAppData, "Microsoft", "WindowsApps"),
|
|
7483
7670
|
// Version managers. Volta's Windows home is not the POSIX `~/.volta`.
|
|
7484
7671
|
...under(localAppData, "Volta", "bin"),
|
|
7485
|
-
|
|
7672
|
+
join20(home, ".volta", "bin")
|
|
7486
7673
|
];
|
|
7487
7674
|
}
|
|
7488
7675
|
function wellKnownBinDirs(deps = {}) {
|
|
7489
7676
|
const platform = deps.platform ?? process.platform;
|
|
7490
7677
|
if (platform !== "win32") return posixBinDirs();
|
|
7491
|
-
return [...new Set(windowsBinDirs(deps.env ?? process.env, deps.home ??
|
|
7678
|
+
return [...new Set(windowsBinDirs(deps.env ?? process.env, deps.home ?? os3.homedir()))];
|
|
7492
7679
|
}
|
|
7493
7680
|
async function loginShellPath(execImpl) {
|
|
7494
7681
|
if (process.platform === "win32") return null;
|
|
@@ -7511,14 +7698,14 @@ function augmentedPath(execImpl = defaultExec) {
|
|
|
7511
7698
|
const segments = [];
|
|
7512
7699
|
const push = (p) => {
|
|
7513
7700
|
if (!p) return;
|
|
7514
|
-
for (const seg of p.split(
|
|
7701
|
+
for (const seg of p.split(path5.delimiter)) {
|
|
7515
7702
|
if (seg && !segments.includes(seg)) segments.push(seg);
|
|
7516
7703
|
}
|
|
7517
7704
|
};
|
|
7518
7705
|
push(process.env.PATH);
|
|
7519
7706
|
push(await loginShellPath(execImpl));
|
|
7520
7707
|
for (const dir of wellKnownBinDirs()) push(dir);
|
|
7521
|
-
return segments.join(
|
|
7708
|
+
return segments.join(path5.delimiter);
|
|
7522
7709
|
})();
|
|
7523
7710
|
}
|
|
7524
7711
|
return cachedPath;
|
|
@@ -7540,17 +7727,17 @@ function withPath(base, resolvedPath, overrides = {}) {
|
|
|
7540
7727
|
|
|
7541
7728
|
// src/utils/globalDataDir.ts
|
|
7542
7729
|
import * as fs from "fs";
|
|
7543
|
-
import * as
|
|
7544
|
-
import * as
|
|
7730
|
+
import * as path6 from "path";
|
|
7731
|
+
import * as os4 from "os";
|
|
7545
7732
|
function globalDataDir() {
|
|
7546
|
-
return
|
|
7733
|
+
return path6.join(os4.homedir(), ".ordewell");
|
|
7547
7734
|
}
|
|
7548
7735
|
function copyDirSync(src, dest) {
|
|
7549
7736
|
fs.mkdirSync(dest, { recursive: true });
|
|
7550
7737
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
7551
7738
|
for (const entry of entries) {
|
|
7552
|
-
const srcPath =
|
|
7553
|
-
const destPath =
|
|
7739
|
+
const srcPath = path6.join(src, entry.name);
|
|
7740
|
+
const destPath = path6.join(dest, entry.name);
|
|
7554
7741
|
if (entry.isDirectory()) {
|
|
7555
7742
|
copyDirSync(srcPath, destPath);
|
|
7556
7743
|
} else {
|
|
@@ -7562,12 +7749,12 @@ var migrated = false;
|
|
|
7562
7749
|
function migrateOldConfigDir() {
|
|
7563
7750
|
if (migrated) return;
|
|
7564
7751
|
migrated = true;
|
|
7565
|
-
const oldDir =
|
|
7752
|
+
const oldDir = path6.join(os4.homedir(), ".config", "ordewell");
|
|
7566
7753
|
if (!fs.existsSync(oldDir)) return;
|
|
7567
7754
|
const newDir = globalDataDir();
|
|
7568
7755
|
const liftFile = (name) => {
|
|
7569
|
-
const oldFile =
|
|
7570
|
-
const newFile =
|
|
7756
|
+
const oldFile = path6.join(oldDir, name);
|
|
7757
|
+
const newFile = path6.join(newDir, name);
|
|
7571
7758
|
if (fs.existsSync(oldFile) && !fs.existsSync(newFile)) {
|
|
7572
7759
|
fs.mkdirSync(newDir, { recursive: true });
|
|
7573
7760
|
fs.copyFileSync(oldFile, newFile);
|
|
@@ -7575,8 +7762,8 @@ function migrateOldConfigDir() {
|
|
|
7575
7762
|
};
|
|
7576
7763
|
liftFile("settings.json");
|
|
7577
7764
|
liftFile(".env");
|
|
7578
|
-
const oldPlugins =
|
|
7579
|
-
const newPlugins =
|
|
7765
|
+
const oldPlugins = path6.join(oldDir, "plugins");
|
|
7766
|
+
const newPlugins = path6.join(newDir, "plugins");
|
|
7580
7767
|
if (fs.existsSync(oldPlugins) && !fs.existsSync(newPlugins)) {
|
|
7581
7768
|
copyDirSync(oldPlugins, newPlugins);
|
|
7582
7769
|
}
|
|
@@ -7584,7 +7771,7 @@ function migrateOldConfigDir() {
|
|
|
7584
7771
|
|
|
7585
7772
|
// src/utils/launch.ts
|
|
7586
7773
|
import * as fsSync2 from "fs";
|
|
7587
|
-
import * as
|
|
7774
|
+
import * as path7 from "path";
|
|
7588
7775
|
|
|
7589
7776
|
// src/utils/shell.ts
|
|
7590
7777
|
var ANSI_RE = /\x1b\[[0-9;]*[A-Za-z]|\x1b\][^\x07]*\x07|\x1b[()][AB012]|\r/g;
|
|
@@ -7613,7 +7800,7 @@ var CMD_EXE_MAX_COMMAND_LINE = 8191;
|
|
|
7613
7800
|
var WINDOWS_MAX_COMMAND_LINE = 32767;
|
|
7614
7801
|
function defaultPowerShell() {
|
|
7615
7802
|
const root = process.env.SystemRoot || process.env.windir;
|
|
7616
|
-
return root ?
|
|
7803
|
+
return root ? path7.win32.join(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : "powershell.exe";
|
|
7617
7804
|
}
|
|
7618
7805
|
var POWERSHELL_FLAGS = ["-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File"];
|
|
7619
7806
|
var CommandLineTooLongError = class extends Error {
|
|
@@ -7665,7 +7852,7 @@ Searched: ${searchedPath || "(empty PATH)"}`);
|
|
|
7665
7852
|
};
|
|
7666
7853
|
function isResolvableOnPosixPath(command, PATH, exists) {
|
|
7667
7854
|
if (command.includes("/")) return exists(command);
|
|
7668
|
-
return PATH.split(
|
|
7855
|
+
return PATH.split(path7.delimiter).map((d) => d.trim()).filter(Boolean).some((dir) => exists(path7.join(dir, command)));
|
|
7669
7856
|
}
|
|
7670
7857
|
function isExecutableResolved(command, plan, PATH, deps = {}) {
|
|
7671
7858
|
if ((deps.platform ?? process.platform) === "win32") return plan.file !== command;
|
|
@@ -7705,9 +7892,9 @@ function cmdArgs(line) {
|
|
|
7705
7892
|
return ["/d", "/s", "/c", `"${line}"`];
|
|
7706
7893
|
}
|
|
7707
7894
|
function candidateExtensions(command, pathExt) {
|
|
7708
|
-
const declared = pathExt.split(
|
|
7895
|
+
const declared = pathExt.split(path7.win32.delimiter).map((e) => e.trim().toLowerCase()).filter(Boolean);
|
|
7709
7896
|
const known = /* @__PURE__ */ new Set([...DIRECT_EXTENSIONS, ...BATCH_EXTENSIONS, ...POWERSHELL_EXTENSIONS, ...declared]);
|
|
7710
|
-
const ext =
|
|
7897
|
+
const ext = path7.win32.extname(command).toLowerCase();
|
|
7711
7898
|
if (ext && known.has(ext)) {
|
|
7712
7899
|
const route = BATCH_EXTENSIONS.includes(ext) ? "cmd" : POWERSHELL_EXTENSIONS.includes(ext) ? "powershell" : "direct";
|
|
7713
7900
|
return { direct: [], cmd: [], powershell: [], [route]: [""] };
|
|
@@ -7728,13 +7915,13 @@ async function findWindowsExecutables(command, deps) {
|
|
|
7728
7915
|
const exists = deps.exists ?? defaultExists2;
|
|
7729
7916
|
const pathExt = (deps.pathExt ?? (() => process.env.PATHEXT ?? ""))();
|
|
7730
7917
|
const byRoute = candidateExtensions(command, pathExt);
|
|
7731
|
-
const dirs =
|
|
7732
|
-
const base =
|
|
7918
|
+
const dirs = path7.win32.basename(command) !== command ? [path7.win32.dirname(path7.win32.resolve(command))] : (await (deps.resolvePath ?? augmentedPath)() || "").split(path7.win32.delimiter).map((d) => d.trim().replace(/^"|"$/g, "")).filter(Boolean);
|
|
7919
|
+
const base = path7.win32.basename(command);
|
|
7733
7920
|
const found = [];
|
|
7734
7921
|
for (const route of ROUTES) {
|
|
7735
7922
|
outer: for (const ext of byRoute[route]) {
|
|
7736
7923
|
for (const dir of dirs) {
|
|
7737
|
-
const candidate =
|
|
7924
|
+
const candidate = path7.win32.join(dir, `${base}${ext}`);
|
|
7738
7925
|
if (exists(candidate)) {
|
|
7739
7926
|
found.push({ file: candidate, route });
|
|
7740
7927
|
break outer;
|
|
@@ -7914,7 +8101,7 @@ function geminiDiscoveryCacheKey(apiKey) {
|
|
|
7914
8101
|
return {
|
|
7915
8102
|
key: `gemini-models:${hash}`,
|
|
7916
8103
|
dir,
|
|
7917
|
-
file:
|
|
8104
|
+
file: path8.join(dir, `gemini_models_${hash}.json`)
|
|
7918
8105
|
};
|
|
7919
8106
|
}
|
|
7920
8107
|
function readGeminiCache(apiKey) {
|
|
@@ -8438,7 +8625,7 @@ var ModelDiscovery = class {
|
|
|
8438
8625
|
|
|
8439
8626
|
// src/services/ModelCatalog.ts
|
|
8440
8627
|
import * as fs2 from "fs";
|
|
8441
|
-
import * as
|
|
8628
|
+
import * as path9 from "path";
|
|
8442
8629
|
var CACHE_KEY = "model-catalog";
|
|
8443
8630
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
8444
8631
|
function storageKey(baseUrl) {
|
|
@@ -8490,7 +8677,7 @@ var ModelCatalog = class {
|
|
|
8490
8677
|
const url = (baseUrl || "https://openrouter.ai/api/v1").replace(/\/+$/, "");
|
|
8491
8678
|
const key = storageKey(url);
|
|
8492
8679
|
const cacheDir = globalCacheDir();
|
|
8493
|
-
const cacheFile =
|
|
8680
|
+
const cacheFile = path9.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
8494
8681
|
if (fs2.existsSync(cacheFile)) fs2.rmSync(cacheFile);
|
|
8495
8682
|
} catch {
|
|
8496
8683
|
}
|
|
@@ -8498,7 +8685,7 @@ var ModelCatalog = class {
|
|
|
8498
8685
|
static readCache(key) {
|
|
8499
8686
|
try {
|
|
8500
8687
|
const cacheDir = globalCacheDir();
|
|
8501
|
-
const cacheFile =
|
|
8688
|
+
const cacheFile = path9.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
8502
8689
|
if (!fs2.existsSync(cacheFile)) return null;
|
|
8503
8690
|
const raw = fs2.readFileSync(cacheFile, "utf8");
|
|
8504
8691
|
const data = JSON.parse(raw);
|
|
@@ -8512,7 +8699,7 @@ var ModelCatalog = class {
|
|
|
8512
8699
|
try {
|
|
8513
8700
|
const cacheDir = globalCacheDir();
|
|
8514
8701
|
fs2.mkdirSync(cacheDir, { recursive: true });
|
|
8515
|
-
const cacheFile =
|
|
8702
|
+
const cacheFile = path9.join(cacheDir, `${key.replace(/[:/]/g, "_")}.json`);
|
|
8516
8703
|
fs2.writeFileSync(
|
|
8517
8704
|
cacheFile,
|
|
8518
8705
|
JSON.stringify({ models, cachedAt: Date.now() }, null, 2)
|
|
@@ -8953,7 +9140,7 @@ import { spawn as nodeSpawn } from "child_process";
|
|
|
8953
9140
|
|
|
8954
9141
|
// src/utils/workspace.ts
|
|
8955
9142
|
import * as fs3 from "fs";
|
|
8956
|
-
import * as
|
|
9143
|
+
import * as path10 from "path";
|
|
8957
9144
|
var WorkspaceNotFoundError = class extends Error {
|
|
8958
9145
|
constructor(workspace) {
|
|
8959
9146
|
super(`Workspace "${workspace}" does not exist.`);
|
|
@@ -9009,7 +9196,7 @@ function assertWorkspaceIsProject(workspace, deps = {}) {
|
|
|
9009
9196
|
throw new WorkspaceNotAProjectError(workspace);
|
|
9010
9197
|
}
|
|
9011
9198
|
const hasMarker = [...PROJECT_MARKER_DIRS, ...PROJECT_MARKER_FILES].some(
|
|
9012
|
-
(marker2) => exists(
|
|
9199
|
+
(marker2) => exists(path10.join(resolved, marker2))
|
|
9013
9200
|
);
|
|
9014
9201
|
if (!hasMarker) throw new WorkspaceNotAProjectError(workspace);
|
|
9015
9202
|
}
|
|
@@ -10041,14 +10228,14 @@ ${part.text}` : part.text });
|
|
|
10041
10228
|
}
|
|
10042
10229
|
}
|
|
10043
10230
|
}
|
|
10044
|
-
async json(method,
|
|
10045
|
-
const response = await this.deps.fetch(`${this.baseUrl}${
|
|
10231
|
+
async json(method, path21, body, signal) {
|
|
10232
|
+
const response = await this.deps.fetch(`${this.baseUrl}${path21}`, {
|
|
10046
10233
|
method,
|
|
10047
10234
|
headers: { "content-type": "application/json" },
|
|
10048
10235
|
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
10049
10236
|
...signal ? { signal } : {}
|
|
10050
10237
|
});
|
|
10051
|
-
if (!response.ok) throw new Error(`${method} ${
|
|
10238
|
+
if (!response.ok) throw new Error(`${method} ${path21} failed: ${response.status} ${response.statusText}`);
|
|
10052
10239
|
return await response.json().catch(() => null);
|
|
10053
10240
|
}
|
|
10054
10241
|
nativeSessionId() {
|
|
@@ -10816,7 +11003,7 @@ function runnerAssignment(catalog, current) {
|
|
|
10816
11003
|
changes.thinkingEffort = thinkingEffort;
|
|
10817
11004
|
}
|
|
10818
11005
|
if (catalog.modes.length > 0) {
|
|
10819
|
-
changes.taskMode = catalog.modes.some((m) => m.id === current?.taskMode) ? current.taskMode : catalog.modes[0].id;
|
|
11006
|
+
changes.taskMode = catalog.modes.some((m) => m.id === current?.taskMode) ? current.taskMode : catalog.defaultMode ?? catalog.modes[0].id;
|
|
10820
11007
|
}
|
|
10821
11008
|
return changes;
|
|
10822
11009
|
}
|
|
@@ -10828,17 +11015,17 @@ function retargetTaskRunner(task, runner, catalog) {
|
|
|
10828
11015
|
|
|
10829
11016
|
// src/services/SkillsService.ts
|
|
10830
11017
|
import * as fs4 from "fs";
|
|
10831
|
-
import * as
|
|
11018
|
+
import * as path12 from "path";
|
|
10832
11019
|
|
|
10833
11020
|
// src/services/builtinSkills.ts
|
|
10834
|
-
import * as
|
|
11021
|
+
import * as path11 from "path";
|
|
10835
11022
|
import { fileURLToPath } from "url";
|
|
10836
11023
|
function builtinSkillsDir() {
|
|
10837
|
-
const dir = typeof __dirname !== "undefined" && __dirname ? __dirname :
|
|
11024
|
+
const dir = typeof __dirname !== "undefined" && __dirname ? __dirname : path11.dirname(fileURLToPath(
|
|
10838
11025
|
// @ts-expect-error - import.meta is only valid under an ESM module setting
|
|
10839
11026
|
import.meta.url
|
|
10840
11027
|
));
|
|
10841
|
-
return
|
|
11028
|
+
return path11.join(dir, "..", "skills");
|
|
10842
11029
|
}
|
|
10843
11030
|
|
|
10844
11031
|
// src/services/SkillsService.ts
|
|
@@ -10877,8 +11064,8 @@ function copyDirSync2(src, dest) {
|
|
|
10877
11064
|
fs4.mkdirSync(dest, { recursive: true });
|
|
10878
11065
|
const entries = fs4.readdirSync(src, { withFileTypes: true });
|
|
10879
11066
|
for (const entry of entries) {
|
|
10880
|
-
const srcPath =
|
|
10881
|
-
const destPath =
|
|
11067
|
+
const srcPath = path12.join(src, entry.name);
|
|
11068
|
+
const destPath = path12.join(dest, entry.name);
|
|
10882
11069
|
if (entry.isDirectory()) copyDirSync2(srcPath, destPath);
|
|
10883
11070
|
else fs4.copyFileSync(srcPath, destPath);
|
|
10884
11071
|
}
|
|
@@ -10889,7 +11076,7 @@ function readDir(dir, source) {
|
|
|
10889
11076
|
const skills = [];
|
|
10890
11077
|
for (const entry of entries) {
|
|
10891
11078
|
if (!entry.isDirectory()) continue;
|
|
10892
|
-
const skillFile =
|
|
11079
|
+
const skillFile = path12.join(dir, entry.name, "SKILL.md");
|
|
10893
11080
|
if (!fs4.existsSync(skillFile)) continue;
|
|
10894
11081
|
const parsed = parseSkillFile(skillFile, entry.name, source);
|
|
10895
11082
|
if (parsed) skills.push(parsed);
|
|
@@ -10902,17 +11089,17 @@ var SkillsService = class {
|
|
|
10902
11089
|
}
|
|
10903
11090
|
workspaceRoot;
|
|
10904
11091
|
localDir() {
|
|
10905
|
-
return this.workspaceRoot ?
|
|
11092
|
+
return this.workspaceRoot ? path12.join(this.workspaceRoot, ".ordewell", "skills") : void 0;
|
|
10906
11093
|
}
|
|
10907
11094
|
globalDir() {
|
|
10908
|
-
return
|
|
11095
|
+
return path12.join(globalDataDir(), "skills");
|
|
10909
11096
|
}
|
|
10910
11097
|
seed(name) {
|
|
10911
|
-
const dest =
|
|
11098
|
+
const dest = path12.join(this.globalDir(), name);
|
|
10912
11099
|
if (fs4.existsSync(dest)) return false;
|
|
10913
11100
|
let srcDir;
|
|
10914
11101
|
try {
|
|
10915
|
-
srcDir =
|
|
11102
|
+
srcDir = path12.join(builtinSkillsDir(), name);
|
|
10916
11103
|
} catch (err) {
|
|
10917
11104
|
console.warn(`Could not locate built-in skills dir: ${String(err)}`);
|
|
10918
11105
|
return false;
|
|
@@ -10938,7 +11125,7 @@ var SkillsService = class {
|
|
|
10938
11125
|
if (entries.length !== 1 || entries[0].name !== "SKILL.md" || !entries[0].isFile()) return false;
|
|
10939
11126
|
let raw;
|
|
10940
11127
|
try {
|
|
10941
|
-
raw = fs4.readFileSync(
|
|
11128
|
+
raw = fs4.readFileSync(path12.join(dir, "SKILL.md"), "utf8");
|
|
10942
11129
|
} catch {
|
|
10943
11130
|
return false;
|
|
10944
11131
|
}
|
|
@@ -10955,7 +11142,7 @@ var SkillsService = class {
|
|
|
10955
11142
|
}
|
|
10956
11143
|
pruneRetired() {
|
|
10957
11144
|
for (const name of RETIRED_BUILTIN_SKILL_NAMES) {
|
|
10958
|
-
const dest =
|
|
11145
|
+
const dest = path12.join(this.globalDir(), name);
|
|
10959
11146
|
if (!fs4.existsSync(dest)) continue;
|
|
10960
11147
|
if (!this.isUnmodifiedRetiredSeed(dest, name)) continue;
|
|
10961
11148
|
try {
|
|
@@ -10970,10 +11157,10 @@ var SkillsService = class {
|
|
|
10970
11157
|
if (BUILTIN_SKILL_NAMES.includes(name)) this.seed(name);
|
|
10971
11158
|
const localDir = this.localDir();
|
|
10972
11159
|
if (localDir) {
|
|
10973
|
-
const localFile =
|
|
11160
|
+
const localFile = path12.join(localDir, name, "SKILL.md");
|
|
10974
11161
|
if (fs4.existsSync(localFile)) return parseSkillFile(localFile, name, "local");
|
|
10975
11162
|
}
|
|
10976
|
-
const globalFile =
|
|
11163
|
+
const globalFile = path12.join(this.globalDir(), name, "SKILL.md");
|
|
10977
11164
|
if (fs4.existsSync(globalFile)) return parseSkillFile(globalFile, name, "global");
|
|
10978
11165
|
return void 0;
|
|
10979
11166
|
}
|
|
@@ -11002,11 +11189,11 @@ function createSkillsService(workspaceRoot) {
|
|
|
11002
11189
|
|
|
11003
11190
|
// src/utils/sessionStore.ts
|
|
11004
11191
|
import * as fs6 from "fs";
|
|
11005
|
-
import * as
|
|
11192
|
+
import * as path14 from "path";
|
|
11006
11193
|
|
|
11007
11194
|
// src/utils/fsHelpers.ts
|
|
11008
11195
|
import * as fs5 from "fs";
|
|
11009
|
-
import * as
|
|
11196
|
+
import * as path13 from "path";
|
|
11010
11197
|
var STATE_DIR = ".ordewell";
|
|
11011
11198
|
function ensureDir(dir) {
|
|
11012
11199
|
if (!fs5.existsSync(dir)) {
|
|
@@ -11014,14 +11201,14 @@ function ensureDir(dir) {
|
|
|
11014
11201
|
}
|
|
11015
11202
|
}
|
|
11016
11203
|
function getStateDir(baseDir) {
|
|
11017
|
-
return
|
|
11204
|
+
return path13.join(baseDir ?? process.cwd(), STATE_DIR);
|
|
11018
11205
|
}
|
|
11019
11206
|
var IGNORE_FILE = ".gitignore";
|
|
11020
11207
|
function ensureStateDirIgnored(baseDir) {
|
|
11021
11208
|
const dir = getStateDir(baseDir);
|
|
11022
11209
|
ensureDir(dir);
|
|
11023
11210
|
try {
|
|
11024
|
-
fs5.writeFileSync(
|
|
11211
|
+
fs5.writeFileSync(path13.join(dir, IGNORE_FILE), "*\n", { flag: "wx" });
|
|
11025
11212
|
} catch (err) {
|
|
11026
11213
|
if (err.code !== "EEXIST") throw err;
|
|
11027
11214
|
}
|
|
@@ -11036,7 +11223,7 @@ function mintSessionId() {
|
|
|
11036
11223
|
// src/utils/sessionStore.ts
|
|
11037
11224
|
var SESSIONS_SUBDIR = "sessions";
|
|
11038
11225
|
function getSessionsDir(baseDir) {
|
|
11039
|
-
return
|
|
11226
|
+
return path14.join(getStateDir(baseDir), SESSIONS_SUBDIR);
|
|
11040
11227
|
}
|
|
11041
11228
|
var REJECTION_MESSAGE = "This session was created with an older version of Ordewell. Please re-plan.";
|
|
11042
11229
|
function hasScalarRunner(parsed) {
|
|
@@ -11071,7 +11258,7 @@ function saveSession(plan, goal, baseDir, id) {
|
|
|
11071
11258
|
plan: JSON.parse(JSON.stringify(plan))
|
|
11072
11259
|
};
|
|
11073
11260
|
const filename = sessionFilename(meta);
|
|
11074
|
-
const filePath =
|
|
11261
|
+
const filePath = path14.join(sessionsDir, filename);
|
|
11075
11262
|
fs6.writeFileSync(filePath, JSON.stringify(session, null, 2));
|
|
11076
11263
|
return meta;
|
|
11077
11264
|
}
|
|
@@ -11081,7 +11268,7 @@ function listSessions(baseDir, logger = defaultLogger) {
|
|
|
11081
11268
|
const files = fs6.readdirSync(sessionsDir).filter((f) => f.endsWith(".json"));
|
|
11082
11269
|
return files.map((f) => {
|
|
11083
11270
|
try {
|
|
11084
|
-
const raw = fs6.readFileSync(
|
|
11271
|
+
const raw = fs6.readFileSync(path14.join(sessionsDir, f), "utf-8");
|
|
11085
11272
|
const parsed = JSON.parse(raw);
|
|
11086
11273
|
if (hasScalarRunner(parsed)) {
|
|
11087
11274
|
logger.warn("sessionStore", `session file ${f}: ${REJECTION_MESSAGE}`);
|
|
@@ -11099,7 +11286,7 @@ function findSessionFile(sessionsDir, sessionId, logger) {
|
|
|
11099
11286
|
const files = fs6.readdirSync(sessionsDir).filter((f) => f.endsWith(".json"));
|
|
11100
11287
|
for (const f of files) {
|
|
11101
11288
|
try {
|
|
11102
|
-
const raw = fs6.readFileSync(
|
|
11289
|
+
const raw = fs6.readFileSync(path14.join(sessionsDir, f), "utf-8");
|
|
11103
11290
|
const session = JSON.parse(raw);
|
|
11104
11291
|
if (session.meta.id === sessionId) return f;
|
|
11105
11292
|
} catch (err) {
|
|
@@ -11114,7 +11301,7 @@ function loadSession(sessionId, baseDir, logger = defaultLogger) {
|
|
|
11114
11301
|
try {
|
|
11115
11302
|
const file = findSessionFile(sessionsDir, sessionId, logger);
|
|
11116
11303
|
if (file) {
|
|
11117
|
-
const raw = fs6.readFileSync(
|
|
11304
|
+
const raw = fs6.readFileSync(path14.join(sessionsDir, file), "utf-8");
|
|
11118
11305
|
const parsed = JSON.parse(raw);
|
|
11119
11306
|
if (hasScalarRunner(parsed)) {
|
|
11120
11307
|
logger.warn("sessionStore", `session file ${file}: ${REJECTION_MESSAGE}`);
|
|
@@ -11148,7 +11335,7 @@ function deleteSession(sessionId, baseDir, logger = defaultLogger) {
|
|
|
11148
11335
|
try {
|
|
11149
11336
|
const file = findSessionFile(sessionsDir, sessionId, logger);
|
|
11150
11337
|
if (file) {
|
|
11151
|
-
fs6.unlinkSync(
|
|
11338
|
+
fs6.unlinkSync(path14.join(sessionsDir, file));
|
|
11152
11339
|
return true;
|
|
11153
11340
|
}
|
|
11154
11341
|
} catch (err) {
|
|
@@ -11159,7 +11346,7 @@ function deleteSession(sessionId, baseDir, logger = defaultLogger) {
|
|
|
11159
11346
|
|
|
11160
11347
|
// src/utils/prdStore.ts
|
|
11161
11348
|
import * as fs7 from "fs";
|
|
11162
|
-
import * as
|
|
11349
|
+
import * as path15 from "path";
|
|
11163
11350
|
var PRD_BLOCK_RE = /<!--\s*ORDEWELL_PRD_START\s+slug="([^"]+)"\s*-->\s*([\s\S]*?)\s*<!--\s*ORDEWELL_PRD_END\s*-->/;
|
|
11164
11351
|
function extractPrdBlock(text) {
|
|
11165
11352
|
const match = PRD_BLOCK_RE.exec(text);
|
|
@@ -11173,9 +11360,9 @@ function sanitizeSlug(raw) {
|
|
|
11173
11360
|
return raw.toLowerCase().replace(/[^a-z0-9-_]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
11174
11361
|
}
|
|
11175
11362
|
function savePrdMarkdown(workspace, slug2, markdown) {
|
|
11176
|
-
const dir =
|
|
11363
|
+
const dir = path15.join(workspace, ".scratch", sanitizeSlug(slug2));
|
|
11177
11364
|
fs7.mkdirSync(dir, { recursive: true });
|
|
11178
|
-
const file =
|
|
11365
|
+
const file = path15.join(dir, "PRD.md");
|
|
11179
11366
|
fs7.writeFileSync(file, markdown.endsWith("\n") ? markdown : markdown + "\n", "utf8");
|
|
11180
11367
|
return file;
|
|
11181
11368
|
}
|
|
@@ -12202,9 +12389,11 @@ Execution is RUNNING${locked.length ? ` \u2014 these tasks are locked: ${locked.
|
|
|
12202
12389
|
}
|
|
12203
12390
|
/** What a runner offers, as {@link runnerAssignment} needs it. Spawns the runner's CLI to list models. */
|
|
12204
12391
|
async catalogFor(runner) {
|
|
12392
|
+
const modes = this.runnerModesFor([runner])[runner];
|
|
12205
12393
|
return {
|
|
12206
12394
|
models: (await this.modelResolver.modelsForRunners([runner]))[runner] ?? [],
|
|
12207
|
-
modes
|
|
12395
|
+
modes,
|
|
12396
|
+
defaultMode: resolveDefaultMode(modes, this.config.autonomousMode)
|
|
12208
12397
|
};
|
|
12209
12398
|
}
|
|
12210
12399
|
/**
|
|
@@ -12829,8 +13018,8 @@ var HeadlessRunner = class extends AbstractRunner {
|
|
|
12829
13018
|
import { execFile as execFile2 } from "child_process";
|
|
12830
13019
|
import { promisify as promisify4 } from "util";
|
|
12831
13020
|
import { tmpdir } from "os";
|
|
12832
|
-
import { join as
|
|
12833
|
-
import { existsSync as
|
|
13021
|
+
import { join as join14 } from "path";
|
|
13022
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
12834
13023
|
|
|
12835
13024
|
// src/utils/tmux.ts
|
|
12836
13025
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -12937,7 +13126,7 @@ var TmuxSession = class extends AbstractTerminalSession {
|
|
|
12937
13126
|
if (this.exited) return;
|
|
12938
13127
|
let content;
|
|
12939
13128
|
try {
|
|
12940
|
-
content =
|
|
13129
|
+
content = existsSync9(this.logPath) ? readFileSync6(this.logPath, "utf8") : "";
|
|
12941
13130
|
} catch {
|
|
12942
13131
|
return;
|
|
12943
13132
|
}
|
|
@@ -13116,7 +13305,7 @@ var TmuxRunner = class extends AbstractRunner {
|
|
|
13116
13305
|
windowName,
|
|
13117
13306
|
this.execFileImpl,
|
|
13118
13307
|
this.pollIntervalMs,
|
|
13119
|
-
|
|
13308
|
+
join14(this.logDir, `${id}.log`),
|
|
13120
13309
|
this.socket
|
|
13121
13310
|
);
|
|
13122
13311
|
invocation.env = { ...invocation.env, PATH: await this.resolvePath() };
|
|
@@ -13129,8 +13318,8 @@ var TmuxRunner = class extends AbstractRunner {
|
|
|
13129
13318
|
|
|
13130
13319
|
// src/utils/daemonToken.ts
|
|
13131
13320
|
import { randomBytes as randomBytes2, timingSafeEqual } from "crypto";
|
|
13132
|
-
import { closeSync, mkdirSync as mkdirSync7, openSync, readFileSync as
|
|
13133
|
-
import { join as
|
|
13321
|
+
import { closeSync, mkdirSync as mkdirSync7, openSync, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync } from "fs";
|
|
13322
|
+
import { join as join15 } from "path";
|
|
13134
13323
|
var BEARER_PREFIX = "bearer ";
|
|
13135
13324
|
var DAEMON_TOKEN_SUBPROTOCOL_PREFIX = "ordewell.token.";
|
|
13136
13325
|
var DAEMON_SUBPROTOCOL = "ordewell.v1";
|
|
@@ -13138,7 +13327,7 @@ function configDir() {
|
|
|
13138
13327
|
return globalDataDir();
|
|
13139
13328
|
}
|
|
13140
13329
|
function daemonTokenPath(port) {
|
|
13141
|
-
return
|
|
13330
|
+
return join15(configDir(), `server-${port}.token`);
|
|
13142
13331
|
}
|
|
13143
13332
|
function mintDaemonToken(port) {
|
|
13144
13333
|
const token = randomBytes2(32).toString("base64url");
|
|
@@ -13158,7 +13347,7 @@ function mintDaemonToken(port) {
|
|
|
13158
13347
|
}
|
|
13159
13348
|
function readDaemonToken(port) {
|
|
13160
13349
|
try {
|
|
13161
|
-
const token =
|
|
13350
|
+
const token = readFileSync7(daemonTokenPath(port), "utf8").trim();
|
|
13162
13351
|
return token === "" ? void 0 : token;
|
|
13163
13352
|
} catch {
|
|
13164
13353
|
return void 0;
|
|
@@ -13200,17 +13389,17 @@ function tokensMatch(presented, expected) {
|
|
|
13200
13389
|
|
|
13201
13390
|
// src/plugins/RunnerRegistry.ts
|
|
13202
13391
|
import * as fs9 from "fs";
|
|
13203
|
-
import * as
|
|
13204
|
-
import * as
|
|
13392
|
+
import * as path18 from "path";
|
|
13393
|
+
import * as os5 from "os";
|
|
13205
13394
|
import { execFileSync } from "child_process";
|
|
13206
13395
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
13207
13396
|
|
|
13208
13397
|
// src/plugins/FsPluginStore.ts
|
|
13209
13398
|
import * as fs8 from "fs";
|
|
13210
|
-
import * as
|
|
13399
|
+
import * as path17 from "path";
|
|
13211
13400
|
|
|
13212
13401
|
// src/plugins/pluginNames.ts
|
|
13213
|
-
import * as
|
|
13402
|
+
import * as path16 from "path";
|
|
13214
13403
|
var PLUGIN_NAME_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
13215
13404
|
var MAX_PLUGIN_NAME_LENGTH = 64;
|
|
13216
13405
|
function isPlainPluginName(name) {
|
|
@@ -13225,10 +13414,10 @@ function assertPlainPluginName(name) {
|
|
|
13225
13414
|
}
|
|
13226
13415
|
function resolvePluginInstallDir(pluginsDir, name) {
|
|
13227
13416
|
assertPlainPluginName(name);
|
|
13228
|
-
const root =
|
|
13229
|
-
const dest =
|
|
13230
|
-
const relative3 =
|
|
13231
|
-
if (relative3 !== name || relative3 === "" ||
|
|
13417
|
+
const root = path16.resolve(pluginsDir);
|
|
13418
|
+
const dest = path16.resolve(root, name);
|
|
13419
|
+
const relative3 = path16.relative(root, dest);
|
|
13420
|
+
if (relative3 !== name || relative3 === "" || path16.isAbsolute(relative3)) {
|
|
13232
13421
|
throw new Error(`Plugin install path escapes the plugins directory: ${JSON.stringify(name)}`);
|
|
13233
13422
|
}
|
|
13234
13423
|
return dest;
|
|
@@ -13243,10 +13432,10 @@ function isValidManifest(obj) {
|
|
|
13243
13432
|
|
|
13244
13433
|
// src/plugins/FsPluginStore.ts
|
|
13245
13434
|
function userPluginsDir() {
|
|
13246
|
-
return
|
|
13435
|
+
return path17.join(globalDataDir(), "plugins");
|
|
13247
13436
|
}
|
|
13248
13437
|
function loadManifestFromDir(dir) {
|
|
13249
|
-
const manifestPath =
|
|
13438
|
+
const manifestPath = path17.join(dir, "manifest.json");
|
|
13250
13439
|
if (!fs8.existsSync(manifestPath)) return null;
|
|
13251
13440
|
try {
|
|
13252
13441
|
const raw = fs8.readFileSync(manifestPath, "utf8");
|
|
@@ -13261,8 +13450,8 @@ function copyDirSync3(src, dest) {
|
|
|
13261
13450
|
ensureDir(dest);
|
|
13262
13451
|
const entries = fs8.readdirSync(src, { withFileTypes: true });
|
|
13263
13452
|
for (const entry of entries) {
|
|
13264
|
-
const srcPath =
|
|
13265
|
-
const destPath =
|
|
13453
|
+
const srcPath = path17.join(src, entry.name);
|
|
13454
|
+
const destPath = path17.join(dest, entry.name);
|
|
13266
13455
|
if (entry.isDirectory()) {
|
|
13267
13456
|
copyDirSync3(srcPath, destPath);
|
|
13268
13457
|
} else {
|
|
@@ -13274,7 +13463,7 @@ function rmDirSync(dir) {
|
|
|
13274
13463
|
if (!fs8.existsSync(dir)) return;
|
|
13275
13464
|
const entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
13276
13465
|
for (const entry of entries) {
|
|
13277
|
-
const p =
|
|
13466
|
+
const p = path17.join(dir, entry.name);
|
|
13278
13467
|
if (entry.isDirectory()) {
|
|
13279
13468
|
rmDirSync(p);
|
|
13280
13469
|
} else {
|
|
@@ -13327,11 +13516,11 @@ var FsPluginStore = class {
|
|
|
13327
13516
|
return null;
|
|
13328
13517
|
}
|
|
13329
13518
|
}
|
|
13330
|
-
dirExists(
|
|
13331
|
-
return fs8.existsSync(
|
|
13519
|
+
dirExists(path21) {
|
|
13520
|
+
return fs8.existsSync(path21) && fs8.statSync(path21).isDirectory();
|
|
13332
13521
|
}
|
|
13333
|
-
exists(
|
|
13334
|
-
return fs8.existsSync(
|
|
13522
|
+
exists(path21) {
|
|
13523
|
+
return fs8.existsSync(path21);
|
|
13335
13524
|
}
|
|
13336
13525
|
};
|
|
13337
13526
|
|
|
@@ -13763,7 +13952,7 @@ var RunnerRegistry = class {
|
|
|
13763
13952
|
return entry?.source === "builtin";
|
|
13764
13953
|
}
|
|
13765
13954
|
installFromPath(sourcePath) {
|
|
13766
|
-
const absPath =
|
|
13955
|
+
const absPath = path18.resolve(sourcePath);
|
|
13767
13956
|
if (!this.store.dirExists(absPath)) {
|
|
13768
13957
|
throw new Error(`Plugin source must be a directory: ${absPath}`);
|
|
13769
13958
|
}
|
|
@@ -13775,7 +13964,7 @@ var RunnerRegistry = class {
|
|
|
13775
13964
|
}
|
|
13776
13965
|
installFromGit(url) {
|
|
13777
13966
|
const validated = assertInstallablePluginUrl(url);
|
|
13778
|
-
const tmpDir =
|
|
13967
|
+
const tmpDir = path18.join(os5.tmpdir(), `ordewell-plugin-${randomBytes3(12).toString("hex")}`);
|
|
13779
13968
|
this.store.ensureDir(tmpDir);
|
|
13780
13969
|
try {
|
|
13781
13970
|
try {
|
|
@@ -13788,7 +13977,7 @@ var RunnerRegistry = class {
|
|
|
13788
13977
|
const hasManifest = contents.some((f) => f === "manifest.json");
|
|
13789
13978
|
let sourceDir = tmpDir;
|
|
13790
13979
|
if (!hasManifest) {
|
|
13791
|
-
const onlyEntry = contents.length === 1 ?
|
|
13980
|
+
const onlyEntry = contents.length === 1 ? path18.join(tmpDir, contents[0]) : void 0;
|
|
13792
13981
|
if (!onlyEntry || !this.store.dirExists(onlyEntry)) {
|
|
13793
13982
|
throw new Error(`No manifest.json found in repository: ${validated.toString()}`);
|
|
13794
13983
|
}
|
|
@@ -13836,7 +14025,7 @@ var RunnerRegistry = class {
|
|
|
13836
14025
|
}
|
|
13837
14026
|
createSkeleton(name, outputDir) {
|
|
13838
14027
|
assertPlainPluginName(name);
|
|
13839
|
-
const dir =
|
|
14028
|
+
const dir = path18.resolve(outputDir, name);
|
|
13840
14029
|
this.store.ensureDir(dir);
|
|
13841
14030
|
const manifest = {
|
|
13842
14031
|
name,
|
|
@@ -13868,8 +14057,8 @@ var RunnerRegistry = class {
|
|
|
13868
14057
|
]
|
|
13869
14058
|
}
|
|
13870
14059
|
};
|
|
13871
|
-
this.store.writeFile(
|
|
13872
|
-
const runSh =
|
|
14060
|
+
this.store.writeFile(path18.join(dir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
14061
|
+
const runSh = path18.join(dir, "run.sh");
|
|
13873
14062
|
const scriptContent = `#!/usr/bin/env bash
|
|
13874
14063
|
# Custom runner script for ${name}
|
|
13875
14064
|
# Receives:
|
|
@@ -13902,14 +14091,14 @@ function fsChmodSync(fpath, mode) {
|
|
|
13902
14091
|
|
|
13903
14092
|
// src/utils/stateStore.ts
|
|
13904
14093
|
import * as fs10 from "fs";
|
|
13905
|
-
import * as
|
|
14094
|
+
import * as path19 from "path";
|
|
13906
14095
|
var STATE_FILE = "state.json";
|
|
13907
14096
|
function getStatePath(baseDir) {
|
|
13908
|
-
return
|
|
14097
|
+
return path19.join(getStateDir(baseDir), STATE_FILE);
|
|
13909
14098
|
}
|
|
13910
14099
|
function saveState(plan, baseDir) {
|
|
13911
14100
|
const statePath = getStatePath(baseDir ?? process.cwd());
|
|
13912
|
-
ensureDir(
|
|
14101
|
+
ensureDir(path19.dirname(statePath));
|
|
13913
14102
|
plan.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
13914
14103
|
fs10.writeFileSync(statePath, JSON.stringify(plan, null, 2));
|
|
13915
14104
|
}
|
|
@@ -13942,7 +14131,7 @@ function stateExists(baseDir) {
|
|
|
13942
14131
|
|
|
13943
14132
|
// src/services/SettingsService.ts
|
|
13944
14133
|
import * as fs11 from "fs";
|
|
13945
|
-
import * as
|
|
14134
|
+
import * as path20 from "path";
|
|
13946
14135
|
var DEFAULTS = {
|
|
13947
14136
|
tdd: { enabled: true },
|
|
13948
14137
|
verification: { enabled: false }
|
|
@@ -13950,7 +14139,7 @@ var DEFAULTS = {
|
|
|
13950
14139
|
function getSettingsPath() {
|
|
13951
14140
|
const override = process.env.ORDEWELL_SETTINGS_PATH;
|
|
13952
14141
|
if (override && override.trim()) return override.trim();
|
|
13953
|
-
return
|
|
14142
|
+
return path20.join(globalDataDir(), "settings.json");
|
|
13954
14143
|
}
|
|
13955
14144
|
function readPlannerModels(raw) {
|
|
13956
14145
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
@@ -14078,7 +14267,7 @@ var SettingsService = class {
|
|
|
14078
14267
|
return { ...DEFAULTS, tdd: { ...DEFAULTS.tdd }, verification: { ...DEFAULTS.verification } };
|
|
14079
14268
|
}
|
|
14080
14269
|
persist() {
|
|
14081
|
-
const dir =
|
|
14270
|
+
const dir = path20.dirname(this.filePath);
|
|
14082
14271
|
if (!fs11.existsSync(dir)) {
|
|
14083
14272
|
fs11.mkdirSync(dir, { recursive: true });
|
|
14084
14273
|
}
|