@adhdev/daemon-core 0.9.82-rc.333 → 0.9.82-rc.334
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/commands/router.d.ts +10 -0
- package/dist/index.js +586 -507
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +577 -498
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-runtime-store.d.ts +18 -1
- package/dist/mesh/mesh-work-queue.d.ts +1 -0
- package/dist/mesh/refine-config.d.ts +1 -0
- package/package.json +2 -2
- package/src/commands/router.ts +65 -10
- package/src/mesh/mesh-events-coordinator.ts +4 -0
- package/src/mesh/mesh-runtime-store.ts +59 -8
- package/src/mesh/mesh-work-queue.ts +18 -4
- package/src/mesh/refine-config.ts +23 -3
- package/src/mesh/worktree-bootstrap-config.ts +6 -1
package/dist/index.mjs
CHANGED
|
@@ -311,10 +311,10 @@ function readInjected(value) {
|
|
|
311
311
|
}
|
|
312
312
|
function getDaemonBuildInfo() {
|
|
313
313
|
if (cached) return cached;
|
|
314
|
-
const commit = readInjected(true ? "
|
|
315
|
-
const commitShort = readInjected(true ? "
|
|
316
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
317
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
314
|
+
const commit = readInjected(true ? "9e5ae5d2814077a6bf9e982b17066ca2051da97b" : void 0) ?? "unknown";
|
|
315
|
+
const commitShort = readInjected(true ? "9e5ae5d2" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
316
|
+
const version = readInjected(true ? "0.9.82-rc.334" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
317
|
+
const builtAt = readInjected(true ? "2026-06-20T03:55:49.426Z" : void 0);
|
|
318
318
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
319
319
|
return cached;
|
|
320
320
|
}
|
|
@@ -3254,6 +3254,297 @@ var init_mesh_ledger = __esm({
|
|
|
3254
3254
|
}
|
|
3255
3255
|
});
|
|
3256
3256
|
|
|
3257
|
+
// src/logging/async-batch-writer.ts
|
|
3258
|
+
import * as fs3 from "fs";
|
|
3259
|
+
var AsyncBatchWriter;
|
|
3260
|
+
var init_async_batch_writer = __esm({
|
|
3261
|
+
"src/logging/async-batch-writer.ts"() {
|
|
3262
|
+
"use strict";
|
|
3263
|
+
AsyncBatchWriter = class {
|
|
3264
|
+
// Maps filePath -> string buffer
|
|
3265
|
+
static buffers = /* @__PURE__ */ new Map();
|
|
3266
|
+
static writePromises = /* @__PURE__ */ new Map();
|
|
3267
|
+
static flushTimer = null;
|
|
3268
|
+
/**
|
|
3269
|
+
* Queues data to be written to a file asynchronously in a batch.
|
|
3270
|
+
*/
|
|
3271
|
+
static write(filePath, data) {
|
|
3272
|
+
let buf = this.buffers.get(filePath);
|
|
3273
|
+
if (!buf) {
|
|
3274
|
+
buf = [];
|
|
3275
|
+
this.buffers.set(filePath, buf);
|
|
3276
|
+
}
|
|
3277
|
+
buf.push(data);
|
|
3278
|
+
if (!this.flushTimer) {
|
|
3279
|
+
this.flushTimer = setTimeout(() => {
|
|
3280
|
+
this.flushTimer = null;
|
|
3281
|
+
this.flushAll();
|
|
3282
|
+
}, 50);
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
static async flushAll() {
|
|
3286
|
+
const entries = Array.from(this.buffers.entries());
|
|
3287
|
+
this.buffers.clear();
|
|
3288
|
+
for (const [filePath, buffer] of entries) {
|
|
3289
|
+
const dataToWrite = buffer.join("");
|
|
3290
|
+
const doWrite = async () => {
|
|
3291
|
+
try {
|
|
3292
|
+
const prevPromise = this.writePromises.get(filePath);
|
|
3293
|
+
if (prevPromise) await prevPromise;
|
|
3294
|
+
await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
|
|
3295
|
+
} catch {
|
|
3296
|
+
}
|
|
3297
|
+
};
|
|
3298
|
+
const writePromise = doWrite();
|
|
3299
|
+
this.writePromises.set(filePath, writePromise);
|
|
3300
|
+
writePromise.finally(() => {
|
|
3301
|
+
if (this.writePromises.get(filePath) === writePromise) {
|
|
3302
|
+
this.writePromises.delete(filePath);
|
|
3303
|
+
}
|
|
3304
|
+
});
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
};
|
|
3308
|
+
}
|
|
3309
|
+
});
|
|
3310
|
+
|
|
3311
|
+
// src/logging/logger.ts
|
|
3312
|
+
var logger_exports = {};
|
|
3313
|
+
__export(logger_exports, {
|
|
3314
|
+
LOG: () => LOG,
|
|
3315
|
+
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
3316
|
+
LOG_PATH: () => LOG_PATH,
|
|
3317
|
+
daemonLog: () => daemonLog,
|
|
3318
|
+
getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
|
|
3319
|
+
getDaemonLogDir: () => getDaemonLogDir,
|
|
3320
|
+
getLogBufferSize: () => getLogBufferSize,
|
|
3321
|
+
getLogLevel: () => getLogLevel,
|
|
3322
|
+
getLogPath: () => getLogPath,
|
|
3323
|
+
getRecentLogs: () => getRecentLogs,
|
|
3324
|
+
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
3325
|
+
setLogLevel: () => setLogLevel
|
|
3326
|
+
});
|
|
3327
|
+
import * as fs4 from "fs";
|
|
3328
|
+
import * as path9 from "path";
|
|
3329
|
+
import * as os3 from "os";
|
|
3330
|
+
function setLogLevel(level) {
|
|
3331
|
+
currentLevel = level;
|
|
3332
|
+
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
3333
|
+
}
|
|
3334
|
+
function getLogLevel() {
|
|
3335
|
+
return currentLevel;
|
|
3336
|
+
}
|
|
3337
|
+
function getDateStr() {
|
|
3338
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3339
|
+
}
|
|
3340
|
+
function getDaemonLogDir() {
|
|
3341
|
+
return LOG_DIR;
|
|
3342
|
+
}
|
|
3343
|
+
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
3344
|
+
return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
3345
|
+
}
|
|
3346
|
+
function checkDateRotation() {
|
|
3347
|
+
const today = getDateStr();
|
|
3348
|
+
if (today !== currentDate) {
|
|
3349
|
+
currentDate = today;
|
|
3350
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
3351
|
+
cleanOldLogs();
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
function cleanOldLogs() {
|
|
3355
|
+
try {
|
|
3356
|
+
const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
3357
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
3358
|
+
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
3359
|
+
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
3360
|
+
for (const file of files) {
|
|
3361
|
+
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
3362
|
+
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
3363
|
+
try {
|
|
3364
|
+
fs4.unlinkSync(path9.join(LOG_DIR, file));
|
|
3365
|
+
} catch {
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
} catch {
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
function rotateSizeIfNeeded() {
|
|
3373
|
+
try {
|
|
3374
|
+
const stat2 = fs4.statSync(currentLogFile);
|
|
3375
|
+
if (stat2.size > MAX_LOG_SIZE) {
|
|
3376
|
+
const backup = currentLogFile.replace(".log", ".1.log");
|
|
3377
|
+
try {
|
|
3378
|
+
fs4.unlinkSync(backup);
|
|
3379
|
+
} catch {
|
|
3380
|
+
}
|
|
3381
|
+
fs4.renameSync(currentLogFile, backup);
|
|
3382
|
+
}
|
|
3383
|
+
} catch {
|
|
3384
|
+
}
|
|
3385
|
+
}
|
|
3386
|
+
function writeToFile(line) {
|
|
3387
|
+
try {
|
|
3388
|
+
if (++writeCount % 1e3 === 0) {
|
|
3389
|
+
checkDateRotation();
|
|
3390
|
+
rotateSizeIfNeeded();
|
|
3391
|
+
}
|
|
3392
|
+
AsyncBatchWriter.write(currentLogFile, line + "\n");
|
|
3393
|
+
} catch {
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
function getRecentLogs(count = 50, minLevel = "info") {
|
|
3397
|
+
const minNum = LEVEL_NUM[minLevel];
|
|
3398
|
+
const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
|
|
3399
|
+
return filtered.slice(-count);
|
|
3400
|
+
}
|
|
3401
|
+
function getLogBufferSize() {
|
|
3402
|
+
return ringBuffer.length;
|
|
3403
|
+
}
|
|
3404
|
+
function ts() {
|
|
3405
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
3406
|
+
}
|
|
3407
|
+
function fullTs() {
|
|
3408
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3409
|
+
}
|
|
3410
|
+
function daemonLog(category, msg, level = "info") {
|
|
3411
|
+
const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
|
|
3412
|
+
const label = LEVEL_LABEL[level];
|
|
3413
|
+
const line = `[${ts()}] [${label}] [${category}] ${msg}`;
|
|
3414
|
+
if (!shouldOutput) return;
|
|
3415
|
+
writeToFile(line);
|
|
3416
|
+
ringBuffer.push({ ts: Date.now(), level, category, message: msg });
|
|
3417
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3418
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3419
|
+
}
|
|
3420
|
+
origConsoleLog(line);
|
|
3421
|
+
}
|
|
3422
|
+
function installGlobalInterceptor() {
|
|
3423
|
+
if (interceptorInstalled) return;
|
|
3424
|
+
interceptorInstalled = true;
|
|
3425
|
+
const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3426
|
+
const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
|
|
3427
|
+
console.log = (...args) => {
|
|
3428
|
+
origConsoleLog(...args);
|
|
3429
|
+
try {
|
|
3430
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
3431
|
+
const clean = stripAnsi4(msg);
|
|
3432
|
+
if (isDaemonLogLine(clean)) return;
|
|
3433
|
+
const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
|
|
3434
|
+
writeToFile(line);
|
|
3435
|
+
const catMatch = clean.match(/\[([^\]]+)\]/);
|
|
3436
|
+
ringBuffer.push({
|
|
3437
|
+
ts: Date.now(),
|
|
3438
|
+
level: "info",
|
|
3439
|
+
category: catMatch?.[1] || "System",
|
|
3440
|
+
message: clean
|
|
3441
|
+
});
|
|
3442
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3443
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3444
|
+
}
|
|
3445
|
+
} catch {
|
|
3446
|
+
}
|
|
3447
|
+
};
|
|
3448
|
+
console.error = (...args) => {
|
|
3449
|
+
origConsoleError(...args);
|
|
3450
|
+
try {
|
|
3451
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
3452
|
+
const clean = stripAnsi4(msg);
|
|
3453
|
+
if (isDaemonLogLine(clean)) return;
|
|
3454
|
+
const line = `[${fullTs()}] [ERROR] ${clean}`;
|
|
3455
|
+
writeToFile(line);
|
|
3456
|
+
ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
|
|
3457
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3458
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3459
|
+
}
|
|
3460
|
+
} catch {
|
|
3461
|
+
}
|
|
3462
|
+
};
|
|
3463
|
+
console.warn = (...args) => {
|
|
3464
|
+
origConsoleWarn(...args);
|
|
3465
|
+
try {
|
|
3466
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
3467
|
+
const clean = stripAnsi4(msg);
|
|
3468
|
+
if (isDaemonLogLine(clean)) return;
|
|
3469
|
+
const line = `[${fullTs()}] [WARN] ${clean}`;
|
|
3470
|
+
writeToFile(line);
|
|
3471
|
+
ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
|
|
3472
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3473
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3474
|
+
}
|
|
3475
|
+
} catch {
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
writeToFile(`
|
|
3479
|
+
=== ADHDev Daemon started at ${fullTs()} ===`);
|
|
3480
|
+
writeToFile(`Log file: ${currentLogFile}`);
|
|
3481
|
+
writeToFile(`Log level: ${currentLevel}`);
|
|
3482
|
+
}
|
|
3483
|
+
function getLogPath() {
|
|
3484
|
+
return currentLogFile;
|
|
3485
|
+
}
|
|
3486
|
+
var LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
|
|
3487
|
+
var init_logger = __esm({
|
|
3488
|
+
"src/logging/logger.ts"() {
|
|
3489
|
+
"use strict";
|
|
3490
|
+
init_async_batch_writer();
|
|
3491
|
+
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
3492
|
+
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
3493
|
+
currentLevel = "info";
|
|
3494
|
+
LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os3.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os3.homedir(), "Library", "Logs", "adhdev") : path9.join(os3.homedir(), ".local", "share", "adhdev", "logs");
|
|
3495
|
+
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
3496
|
+
MAX_LOG_DAYS = 7;
|
|
3497
|
+
try {
|
|
3498
|
+
fs4.mkdirSync(LOG_DIR, { recursive: true });
|
|
3499
|
+
} catch {
|
|
3500
|
+
}
|
|
3501
|
+
currentDate = getDateStr();
|
|
3502
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
3503
|
+
cleanOldLogs();
|
|
3504
|
+
try {
|
|
3505
|
+
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
3506
|
+
if (fs4.existsSync(oldLog)) {
|
|
3507
|
+
const stat2 = fs4.statSync(oldLog);
|
|
3508
|
+
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
3509
|
+
fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
3510
|
+
}
|
|
3511
|
+
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
3512
|
+
if (fs4.existsSync(oldLogBackup)) {
|
|
3513
|
+
fs4.unlinkSync(oldLogBackup);
|
|
3514
|
+
}
|
|
3515
|
+
} catch {
|
|
3516
|
+
}
|
|
3517
|
+
writeCount = 0;
|
|
3518
|
+
RING_BUFFER_SIZE = 200;
|
|
3519
|
+
ringBuffer = [];
|
|
3520
|
+
origConsoleLog = console.log.bind(console);
|
|
3521
|
+
origConsoleError = console.error.bind(console);
|
|
3522
|
+
origConsoleWarn = console.warn.bind(console);
|
|
3523
|
+
LOG = {
|
|
3524
|
+
debug: (category, msg) => daemonLog(category, msg, "debug"),
|
|
3525
|
+
info: (category, msg) => daemonLog(category, msg, "info"),
|
|
3526
|
+
warn: (category, msg) => daemonLog(category, msg, "warn"),
|
|
3527
|
+
error: (category, msg) => daemonLog(category, msg, "error"),
|
|
3528
|
+
/**
|
|
3529
|
+
* Create a scoped logger for a specific component.
|
|
3530
|
+
* Category is baked in so callers only pass the message.
|
|
3531
|
+
*/
|
|
3532
|
+
forComponent(category) {
|
|
3533
|
+
return {
|
|
3534
|
+
debug: (msg) => daemonLog(category, msg, "debug"),
|
|
3535
|
+
info: (msg) => daemonLog(category, msg, "info"),
|
|
3536
|
+
warn: (msg) => daemonLog(category, msg, "warn"),
|
|
3537
|
+
error: (msg) => daemonLog(category, msg, "error"),
|
|
3538
|
+
asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
};
|
|
3542
|
+
interceptorInstalled = false;
|
|
3543
|
+
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
3544
|
+
LOG_DIR_PATH = LOG_DIR;
|
|
3545
|
+
}
|
|
3546
|
+
});
|
|
3547
|
+
|
|
3257
3548
|
// src/mesh/mesh-work-queue.ts
|
|
3258
3549
|
var mesh_work_queue_exports = {};
|
|
3259
3550
|
__export(mesh_work_queue_exports, {
|
|
@@ -3719,11 +4010,18 @@ function requeueTask(meshId, taskId, opts) {
|
|
|
3719
4010
|
}
|
|
3720
4011
|
function updateSessionTaskStatus(meshId, sessionId, status, opts) {
|
|
3721
4012
|
return withQueueLock(meshId, () => {
|
|
4013
|
+
const store = MeshRuntimeStore.getInstance();
|
|
3722
4014
|
const occurredAtIso = opts?.occurredAt ? new Date(opts.occurredAt).toISOString() : void 0;
|
|
3723
|
-
const entry =
|
|
3724
|
-
if (!entry)
|
|
4015
|
+
const entry = store.findAssignedBySession(meshId, sessionId, occurredAtIso, opts?.taskId);
|
|
4016
|
+
if (!entry) {
|
|
4017
|
+
const assignedRows = store.getActiveAssignmentDetails(meshId).filter((r) => r.sessionId === sessionId);
|
|
4018
|
+
if (assignedRows.length > 0) {
|
|
4019
|
+
LOG.warn("MeshQueue", `No assigned queue row matched completion for mesh ${meshId} session ${sessionId} (taskId=${opts?.taskId ?? "none"}, occurredAt=${occurredAtIso ?? "none"}); ${assignedRows.length} assigned row(s) exist: ${assignedRows.map((r) => r.id).join(",")}`);
|
|
4020
|
+
}
|
|
4021
|
+
return null;
|
|
4022
|
+
}
|
|
3725
4023
|
entry.status = status;
|
|
3726
|
-
|
|
4024
|
+
store.updateQueueEntry(entry);
|
|
3727
4025
|
if (DEPENDENCY_FAILURE_TERMINALS.has(status)) propagateDependencyFailure(meshId, entry.id);
|
|
3728
4026
|
return entry;
|
|
3729
4027
|
});
|
|
@@ -3831,6 +4129,7 @@ var init_mesh_work_queue = __esm({
|
|
|
3831
4129
|
init_repo_mesh_types();
|
|
3832
4130
|
init_mesh_runtime_store();
|
|
3833
4131
|
init_mesh_config();
|
|
4132
|
+
init_logger();
|
|
3834
4133
|
ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
|
|
3835
4134
|
HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
|
|
3836
4135
|
MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
|
|
@@ -3887,8 +4186,8 @@ var init_mesh_work_queue = __esm({
|
|
|
3887
4186
|
});
|
|
3888
4187
|
|
|
3889
4188
|
// src/mesh/mesh-runtime-store.ts
|
|
3890
|
-
import { existsSync as
|
|
3891
|
-
import { dirname as dirname2, join as
|
|
4189
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync3, statSync as statSync5 } from "fs";
|
|
4190
|
+
import { dirname as dirname2, join as join9 } from "path";
|
|
3892
4191
|
function loadDatabaseCtor() {
|
|
3893
4192
|
if (DatabaseCtor) return DatabaseCtor;
|
|
3894
4193
|
DatabaseCtor = loadBetterSqlite3();
|
|
@@ -3898,20 +4197,20 @@ function safeMeshId(meshId) {
|
|
|
3898
4197
|
return meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3899
4198
|
}
|
|
3900
4199
|
function legacyQueuePath(meshId) {
|
|
3901
|
-
return
|
|
4200
|
+
return join9(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
|
|
3902
4201
|
}
|
|
3903
4202
|
function meshRuntimeStorePath() {
|
|
3904
4203
|
const dir = getLedgerDir();
|
|
3905
|
-
const nextPath =
|
|
3906
|
-
if (
|
|
3907
|
-
const legacyPath =
|
|
3908
|
-
if (!
|
|
4204
|
+
const nextPath = join9(dir, "mesh-runtime.db");
|
|
4205
|
+
if (existsSync8(nextPath)) return nextPath;
|
|
4206
|
+
const legacyPath = join9(dir, "beads.db");
|
|
4207
|
+
if (!existsSync8(legacyPath)) return nextPath;
|
|
3909
4208
|
try {
|
|
3910
|
-
|
|
4209
|
+
renameSync3(legacyPath, nextPath);
|
|
3911
4210
|
for (const suffix of ["-wal", "-shm"]) {
|
|
3912
4211
|
const legacyCompanion = `${legacyPath}${suffix}`;
|
|
3913
|
-
if (
|
|
3914
|
-
|
|
4212
|
+
if (existsSync8(legacyCompanion)) {
|
|
4213
|
+
renameSync3(legacyCompanion, `${nextPath}${suffix}`);
|
|
3915
4214
|
}
|
|
3916
4215
|
}
|
|
3917
4216
|
} catch {
|
|
@@ -3937,7 +4236,7 @@ var init_mesh_runtime_store = __esm({
|
|
|
3937
4236
|
// 50 MB
|
|
3938
4237
|
constructor(dbPath) {
|
|
3939
4238
|
const dir = dirname2(dbPath);
|
|
3940
|
-
if (!
|
|
4239
|
+
if (!existsSync8(dir)) mkdirSync5(dir, { recursive: true });
|
|
3941
4240
|
this.dbPath = dbPath;
|
|
3942
4241
|
this.db = new (loadDatabaseCtor())(dbPath);
|
|
3943
4242
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -4192,8 +4491,8 @@ var init_mesh_runtime_store = __esm({
|
|
|
4192
4491
|
this.walWriteCounter = 0;
|
|
4193
4492
|
try {
|
|
4194
4493
|
const walPath = `${this.dbPath}-wal`;
|
|
4195
|
-
if (!
|
|
4196
|
-
const size =
|
|
4494
|
+
if (!existsSync8(walPath)) return;
|
|
4495
|
+
const size = statSync5(walPath).size;
|
|
4197
4496
|
if (size < _MeshRuntimeStore.WAL_MAX_BYTES) return;
|
|
4198
4497
|
process.stderr.write(
|
|
4199
4498
|
`[adhdev-mesh] WAL file ${Math.round(size / 1024 / 1024)}MB exceeds threshold; forcing checkpoint
|
|
@@ -4209,7 +4508,7 @@ var init_mesh_runtime_store = __esm({
|
|
|
4209
4508
|
const count = this.db.prepare("SELECT COUNT(*) AS count FROM mesh_queue WHERE mesh_id = ?").get(meshId);
|
|
4210
4509
|
if (count.count > 0) return;
|
|
4211
4510
|
const path42 = legacyQueuePath(meshId);
|
|
4212
|
-
if (!
|
|
4511
|
+
if (!existsSync8(path42)) return;
|
|
4213
4512
|
try {
|
|
4214
4513
|
const entries = JSON.parse(readFileSync6(path42, "utf-8"));
|
|
4215
4514
|
if (!Array.isArray(entries)) return;
|
|
@@ -4489,12 +4788,51 @@ var init_mesh_runtime_store = __esm({
|
|
|
4489
4788
|
return { id, nodeId: r.assigned_node_id ?? void 0, sessionId: r.assigned_session_id ?? void 0, message };
|
|
4490
4789
|
});
|
|
4491
4790
|
}
|
|
4492
|
-
|
|
4791
|
+
/**
|
|
4792
|
+
* Resolve the `assigned` queue row a completion event belongs to.
|
|
4793
|
+
*
|
|
4794
|
+
* Clock-skew safety (C2): a completion event's `occurredAtIso` carries the
|
|
4795
|
+
* REMOTE WORKER's clock, while `updated_at` carries the COORDINATOR's clock
|
|
4796
|
+
* (set at assignment and re-bumped on every mutation). For a remote node,
|
|
4797
|
+
* coordinator-clock > worker-clock skew used to make an `updated_at <= occurredAt`
|
|
4798
|
+
* filter return nothing, stranding the finished task as `assigned` forever.
|
|
4799
|
+
*
|
|
4800
|
+
* We therefore NEVER filter completion-matching on the mutable `updated_at`:
|
|
4801
|
+
* 1. If `taskId` is given, match the exact `assigned` row by id (no time filter).
|
|
4802
|
+
* 2. Otherwise a session holds at most one `assigned` task — match it without a
|
|
4803
|
+
* time filter. If several exist (shouldn't normally), disambiguate by the
|
|
4804
|
+
* IMMUTABLE `dispatchTimestamp`: latest `dispatchTimestamp <= occurredAt`,
|
|
4805
|
+
* and if skew makes ALL of them later than `occurredAt`, fall back to the
|
|
4806
|
+
* most-recent `dispatchTimestamp` rather than returning null.
|
|
4807
|
+
*/
|
|
4808
|
+
findAssignedBySession(meshId, sessionId, occurredAtIso, taskId) {
|
|
4493
4809
|
this.ensureLegacyQueueMigrated(meshId);
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4810
|
+
if (taskId) {
|
|
4811
|
+
const row = this.db.prepare(
|
|
4812
|
+
`SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned' AND id = ? LIMIT 1`
|
|
4813
|
+
).get(meshId, sessionId, taskId);
|
|
4814
|
+
if (row) return JSON.parse(row.payload);
|
|
4815
|
+
}
|
|
4816
|
+
const rows = this.db.prepare(
|
|
4817
|
+
`SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned'`
|
|
4818
|
+
).all(meshId, sessionId);
|
|
4819
|
+
if (rows.length === 0) return null;
|
|
4820
|
+
const entries = rows.map((r) => {
|
|
4821
|
+
try {
|
|
4822
|
+
return JSON.parse(r.payload);
|
|
4823
|
+
} catch {
|
|
4824
|
+
return null;
|
|
4825
|
+
}
|
|
4826
|
+
}).filter((e) => e !== null);
|
|
4827
|
+
if (entries.length === 0) return null;
|
|
4828
|
+
if (entries.length === 1) return entries[0];
|
|
4829
|
+
const orderKey = (e) => e.dispatchTimestamp ?? e.updatedAt ?? "";
|
|
4830
|
+
const byDispatchDesc = [...entries].sort((a, b) => orderKey(b).localeCompare(orderKey(a)));
|
|
4831
|
+
if (occurredAtIso) {
|
|
4832
|
+
const atOrBefore = byDispatchDesc.find((e) => orderKey(e) <= occurredAtIso);
|
|
4833
|
+
if (atOrBefore) return atOrBefore;
|
|
4834
|
+
}
|
|
4835
|
+
return byDispatchDesc[0];
|
|
4498
4836
|
}
|
|
4499
4837
|
toRow(entry) {
|
|
4500
4838
|
return {
|
|
@@ -5750,297 +6088,6 @@ var init_mesh_review_inbox = __esm({
|
|
|
5750
6088
|
}
|
|
5751
6089
|
});
|
|
5752
6090
|
|
|
5753
|
-
// src/logging/async-batch-writer.ts
|
|
5754
|
-
import * as fs3 from "fs";
|
|
5755
|
-
var AsyncBatchWriter;
|
|
5756
|
-
var init_async_batch_writer = __esm({
|
|
5757
|
-
"src/logging/async-batch-writer.ts"() {
|
|
5758
|
-
"use strict";
|
|
5759
|
-
AsyncBatchWriter = class {
|
|
5760
|
-
// Maps filePath -> string buffer
|
|
5761
|
-
static buffers = /* @__PURE__ */ new Map();
|
|
5762
|
-
static writePromises = /* @__PURE__ */ new Map();
|
|
5763
|
-
static flushTimer = null;
|
|
5764
|
-
/**
|
|
5765
|
-
* Queues data to be written to a file asynchronously in a batch.
|
|
5766
|
-
*/
|
|
5767
|
-
static write(filePath, data) {
|
|
5768
|
-
let buf = this.buffers.get(filePath);
|
|
5769
|
-
if (!buf) {
|
|
5770
|
-
buf = [];
|
|
5771
|
-
this.buffers.set(filePath, buf);
|
|
5772
|
-
}
|
|
5773
|
-
buf.push(data);
|
|
5774
|
-
if (!this.flushTimer) {
|
|
5775
|
-
this.flushTimer = setTimeout(() => {
|
|
5776
|
-
this.flushTimer = null;
|
|
5777
|
-
this.flushAll();
|
|
5778
|
-
}, 50);
|
|
5779
|
-
}
|
|
5780
|
-
}
|
|
5781
|
-
static async flushAll() {
|
|
5782
|
-
const entries = Array.from(this.buffers.entries());
|
|
5783
|
-
this.buffers.clear();
|
|
5784
|
-
for (const [filePath, buffer] of entries) {
|
|
5785
|
-
const dataToWrite = buffer.join("");
|
|
5786
|
-
const doWrite = async () => {
|
|
5787
|
-
try {
|
|
5788
|
-
const prevPromise = this.writePromises.get(filePath);
|
|
5789
|
-
if (prevPromise) await prevPromise;
|
|
5790
|
-
await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
|
|
5791
|
-
} catch {
|
|
5792
|
-
}
|
|
5793
|
-
};
|
|
5794
|
-
const writePromise = doWrite();
|
|
5795
|
-
this.writePromises.set(filePath, writePromise);
|
|
5796
|
-
writePromise.finally(() => {
|
|
5797
|
-
if (this.writePromises.get(filePath) === writePromise) {
|
|
5798
|
-
this.writePromises.delete(filePath);
|
|
5799
|
-
}
|
|
5800
|
-
});
|
|
5801
|
-
}
|
|
5802
|
-
}
|
|
5803
|
-
};
|
|
5804
|
-
}
|
|
5805
|
-
});
|
|
5806
|
-
|
|
5807
|
-
// src/logging/logger.ts
|
|
5808
|
-
var logger_exports = {};
|
|
5809
|
-
__export(logger_exports, {
|
|
5810
|
-
LOG: () => LOG,
|
|
5811
|
-
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
5812
|
-
LOG_PATH: () => LOG_PATH,
|
|
5813
|
-
daemonLog: () => daemonLog,
|
|
5814
|
-
getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
|
|
5815
|
-
getDaemonLogDir: () => getDaemonLogDir,
|
|
5816
|
-
getLogBufferSize: () => getLogBufferSize,
|
|
5817
|
-
getLogLevel: () => getLogLevel,
|
|
5818
|
-
getLogPath: () => getLogPath,
|
|
5819
|
-
getRecentLogs: () => getRecentLogs,
|
|
5820
|
-
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
5821
|
-
setLogLevel: () => setLogLevel
|
|
5822
|
-
});
|
|
5823
|
-
import * as fs4 from "fs";
|
|
5824
|
-
import * as path9 from "path";
|
|
5825
|
-
import * as os3 from "os";
|
|
5826
|
-
function setLogLevel(level) {
|
|
5827
|
-
currentLevel = level;
|
|
5828
|
-
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
5829
|
-
}
|
|
5830
|
-
function getLogLevel() {
|
|
5831
|
-
return currentLevel;
|
|
5832
|
-
}
|
|
5833
|
-
function getDateStr() {
|
|
5834
|
-
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
5835
|
-
}
|
|
5836
|
-
function getDaemonLogDir() {
|
|
5837
|
-
return LOG_DIR;
|
|
5838
|
-
}
|
|
5839
|
-
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
5840
|
-
return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
5841
|
-
}
|
|
5842
|
-
function checkDateRotation() {
|
|
5843
|
-
const today = getDateStr();
|
|
5844
|
-
if (today !== currentDate) {
|
|
5845
|
-
currentDate = today;
|
|
5846
|
-
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
5847
|
-
cleanOldLogs();
|
|
5848
|
-
}
|
|
5849
|
-
}
|
|
5850
|
-
function cleanOldLogs() {
|
|
5851
|
-
try {
|
|
5852
|
-
const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
5853
|
-
const cutoff = /* @__PURE__ */ new Date();
|
|
5854
|
-
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
5855
|
-
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
5856
|
-
for (const file of files) {
|
|
5857
|
-
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
5858
|
-
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
5859
|
-
try {
|
|
5860
|
-
fs4.unlinkSync(path9.join(LOG_DIR, file));
|
|
5861
|
-
} catch {
|
|
5862
|
-
}
|
|
5863
|
-
}
|
|
5864
|
-
}
|
|
5865
|
-
} catch {
|
|
5866
|
-
}
|
|
5867
|
-
}
|
|
5868
|
-
function rotateSizeIfNeeded() {
|
|
5869
|
-
try {
|
|
5870
|
-
const stat2 = fs4.statSync(currentLogFile);
|
|
5871
|
-
if (stat2.size > MAX_LOG_SIZE) {
|
|
5872
|
-
const backup = currentLogFile.replace(".log", ".1.log");
|
|
5873
|
-
try {
|
|
5874
|
-
fs4.unlinkSync(backup);
|
|
5875
|
-
} catch {
|
|
5876
|
-
}
|
|
5877
|
-
fs4.renameSync(currentLogFile, backup);
|
|
5878
|
-
}
|
|
5879
|
-
} catch {
|
|
5880
|
-
}
|
|
5881
|
-
}
|
|
5882
|
-
function writeToFile(line) {
|
|
5883
|
-
try {
|
|
5884
|
-
if (++writeCount % 1e3 === 0) {
|
|
5885
|
-
checkDateRotation();
|
|
5886
|
-
rotateSizeIfNeeded();
|
|
5887
|
-
}
|
|
5888
|
-
AsyncBatchWriter.write(currentLogFile, line + "\n");
|
|
5889
|
-
} catch {
|
|
5890
|
-
}
|
|
5891
|
-
}
|
|
5892
|
-
function getRecentLogs(count = 50, minLevel = "info") {
|
|
5893
|
-
const minNum = LEVEL_NUM[minLevel];
|
|
5894
|
-
const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
|
|
5895
|
-
return filtered.slice(-count);
|
|
5896
|
-
}
|
|
5897
|
-
function getLogBufferSize() {
|
|
5898
|
-
return ringBuffer.length;
|
|
5899
|
-
}
|
|
5900
|
-
function ts() {
|
|
5901
|
-
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
5902
|
-
}
|
|
5903
|
-
function fullTs() {
|
|
5904
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
5905
|
-
}
|
|
5906
|
-
function daemonLog(category, msg, level = "info") {
|
|
5907
|
-
const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
|
|
5908
|
-
const label = LEVEL_LABEL[level];
|
|
5909
|
-
const line = `[${ts()}] [${label}] [${category}] ${msg}`;
|
|
5910
|
-
if (!shouldOutput) return;
|
|
5911
|
-
writeToFile(line);
|
|
5912
|
-
ringBuffer.push({ ts: Date.now(), level, category, message: msg });
|
|
5913
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5914
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5915
|
-
}
|
|
5916
|
-
origConsoleLog(line);
|
|
5917
|
-
}
|
|
5918
|
-
function installGlobalInterceptor() {
|
|
5919
|
-
if (interceptorInstalled) return;
|
|
5920
|
-
interceptorInstalled = true;
|
|
5921
|
-
const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
5922
|
-
const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
|
|
5923
|
-
console.log = (...args) => {
|
|
5924
|
-
origConsoleLog(...args);
|
|
5925
|
-
try {
|
|
5926
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5927
|
-
const clean = stripAnsi4(msg);
|
|
5928
|
-
if (isDaemonLogLine(clean)) return;
|
|
5929
|
-
const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
|
|
5930
|
-
writeToFile(line);
|
|
5931
|
-
const catMatch = clean.match(/\[([^\]]+)\]/);
|
|
5932
|
-
ringBuffer.push({
|
|
5933
|
-
ts: Date.now(),
|
|
5934
|
-
level: "info",
|
|
5935
|
-
category: catMatch?.[1] || "System",
|
|
5936
|
-
message: clean
|
|
5937
|
-
});
|
|
5938
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5939
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5940
|
-
}
|
|
5941
|
-
} catch {
|
|
5942
|
-
}
|
|
5943
|
-
};
|
|
5944
|
-
console.error = (...args) => {
|
|
5945
|
-
origConsoleError(...args);
|
|
5946
|
-
try {
|
|
5947
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5948
|
-
const clean = stripAnsi4(msg);
|
|
5949
|
-
if (isDaemonLogLine(clean)) return;
|
|
5950
|
-
const line = `[${fullTs()}] [ERROR] ${clean}`;
|
|
5951
|
-
writeToFile(line);
|
|
5952
|
-
ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
|
|
5953
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5954
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5955
|
-
}
|
|
5956
|
-
} catch {
|
|
5957
|
-
}
|
|
5958
|
-
};
|
|
5959
|
-
console.warn = (...args) => {
|
|
5960
|
-
origConsoleWarn(...args);
|
|
5961
|
-
try {
|
|
5962
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5963
|
-
const clean = stripAnsi4(msg);
|
|
5964
|
-
if (isDaemonLogLine(clean)) return;
|
|
5965
|
-
const line = `[${fullTs()}] [WARN] ${clean}`;
|
|
5966
|
-
writeToFile(line);
|
|
5967
|
-
ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
|
|
5968
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5969
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5970
|
-
}
|
|
5971
|
-
} catch {
|
|
5972
|
-
}
|
|
5973
|
-
};
|
|
5974
|
-
writeToFile(`
|
|
5975
|
-
=== ADHDev Daemon started at ${fullTs()} ===`);
|
|
5976
|
-
writeToFile(`Log file: ${currentLogFile}`);
|
|
5977
|
-
writeToFile(`Log level: ${currentLevel}`);
|
|
5978
|
-
}
|
|
5979
|
-
function getLogPath() {
|
|
5980
|
-
return currentLogFile;
|
|
5981
|
-
}
|
|
5982
|
-
var LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
|
|
5983
|
-
var init_logger = __esm({
|
|
5984
|
-
"src/logging/logger.ts"() {
|
|
5985
|
-
"use strict";
|
|
5986
|
-
init_async_batch_writer();
|
|
5987
|
-
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
5988
|
-
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
5989
|
-
currentLevel = "info";
|
|
5990
|
-
LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os3.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os3.homedir(), "Library", "Logs", "adhdev") : path9.join(os3.homedir(), ".local", "share", "adhdev", "logs");
|
|
5991
|
-
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
5992
|
-
MAX_LOG_DAYS = 7;
|
|
5993
|
-
try {
|
|
5994
|
-
fs4.mkdirSync(LOG_DIR, { recursive: true });
|
|
5995
|
-
} catch {
|
|
5996
|
-
}
|
|
5997
|
-
currentDate = getDateStr();
|
|
5998
|
-
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
5999
|
-
cleanOldLogs();
|
|
6000
|
-
try {
|
|
6001
|
-
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
6002
|
-
if (fs4.existsSync(oldLog)) {
|
|
6003
|
-
const stat2 = fs4.statSync(oldLog);
|
|
6004
|
-
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
6005
|
-
fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
6006
|
-
}
|
|
6007
|
-
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
6008
|
-
if (fs4.existsSync(oldLogBackup)) {
|
|
6009
|
-
fs4.unlinkSync(oldLogBackup);
|
|
6010
|
-
}
|
|
6011
|
-
} catch {
|
|
6012
|
-
}
|
|
6013
|
-
writeCount = 0;
|
|
6014
|
-
RING_BUFFER_SIZE = 200;
|
|
6015
|
-
ringBuffer = [];
|
|
6016
|
-
origConsoleLog = console.log.bind(console);
|
|
6017
|
-
origConsoleError = console.error.bind(console);
|
|
6018
|
-
origConsoleWarn = console.warn.bind(console);
|
|
6019
|
-
LOG = {
|
|
6020
|
-
debug: (category, msg) => daemonLog(category, msg, "debug"),
|
|
6021
|
-
info: (category, msg) => daemonLog(category, msg, "info"),
|
|
6022
|
-
warn: (category, msg) => daemonLog(category, msg, "warn"),
|
|
6023
|
-
error: (category, msg) => daemonLog(category, msg, "error"),
|
|
6024
|
-
/**
|
|
6025
|
-
* Create a scoped logger for a specific component.
|
|
6026
|
-
* Category is baked in so callers only pass the message.
|
|
6027
|
-
*/
|
|
6028
|
-
forComponent(category) {
|
|
6029
|
-
return {
|
|
6030
|
-
debug: (msg) => daemonLog(category, msg, "debug"),
|
|
6031
|
-
info: (msg) => daemonLog(category, msg, "info"),
|
|
6032
|
-
warn: (msg) => daemonLog(category, msg, "warn"),
|
|
6033
|
-
error: (msg) => daemonLog(category, msg, "error"),
|
|
6034
|
-
asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
|
|
6035
|
-
};
|
|
6036
|
-
}
|
|
6037
|
-
};
|
|
6038
|
-
interceptorInstalled = false;
|
|
6039
|
-
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
6040
|
-
LOG_DIR_PATH = LOG_DIR;
|
|
6041
|
-
}
|
|
6042
|
-
});
|
|
6043
|
-
|
|
6044
6091
|
// src/commands/mesh-coordinator.ts
|
|
6045
6092
|
var mesh_coordinator_exports = {};
|
|
6046
6093
|
__export(mesh_coordinator_exports, {
|
|
@@ -6442,6 +6489,59 @@ var init_mesh_coordinator = __esm({
|
|
|
6442
6489
|
}
|
|
6443
6490
|
});
|
|
6444
6491
|
|
|
6492
|
+
// src/cli-adapters/resolve-executable.ts
|
|
6493
|
+
import { execFileSync } from "child_process";
|
|
6494
|
+
import { existsSync as existsSync12 } from "fs";
|
|
6495
|
+
import * as path10 from "path";
|
|
6496
|
+
function resolveWin32GlobalBin(trimmed) {
|
|
6497
|
+
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
|
|
6498
|
+
return null;
|
|
6499
|
+
}
|
|
6500
|
+
const extraDirs = [];
|
|
6501
|
+
if (process.env.APPDATA) extraDirs.push(path10.join(process.env.APPDATA, "npm"));
|
|
6502
|
+
try {
|
|
6503
|
+
extraDirs.push(path10.dirname(process.execPath));
|
|
6504
|
+
} catch {
|
|
6505
|
+
}
|
|
6506
|
+
for (const dir of extraDirs) {
|
|
6507
|
+
if (!dir) continue;
|
|
6508
|
+
for (const ext of WIN_EXEC_EXT) {
|
|
6509
|
+
const full = path10.join(dir, trimmed + ext);
|
|
6510
|
+
if (existsSync12(full)) return full;
|
|
6511
|
+
}
|
|
6512
|
+
}
|
|
6513
|
+
return null;
|
|
6514
|
+
}
|
|
6515
|
+
function resolveWin32Executable(command) {
|
|
6516
|
+
if (process.platform !== "win32") return command;
|
|
6517
|
+
const trimmed = (command || "").trim();
|
|
6518
|
+
if (!trimmed) return command;
|
|
6519
|
+
if (path10.isAbsolute(trimmed) && existsSync12(trimmed)) return trimmed;
|
|
6520
|
+
try {
|
|
6521
|
+
const out = execFileSync("where", [trimmed], {
|
|
6522
|
+
encoding: "utf8",
|
|
6523
|
+
windowsHide: true
|
|
6524
|
+
}).trim();
|
|
6525
|
+
if (out) {
|
|
6526
|
+
const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
6527
|
+
const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
|
|
6528
|
+
return direct || matches[0] || command;
|
|
6529
|
+
}
|
|
6530
|
+
} catch {
|
|
6531
|
+
}
|
|
6532
|
+
const globalBin = resolveWin32GlobalBin(trimmed);
|
|
6533
|
+
if (globalBin) return globalBin;
|
|
6534
|
+
return command;
|
|
6535
|
+
}
|
|
6536
|
+
var DIRECT_EXEC_EXT, WIN_EXEC_EXT;
|
|
6537
|
+
var init_resolve_executable = __esm({
|
|
6538
|
+
"src/cli-adapters/resolve-executable.ts"() {
|
|
6539
|
+
"use strict";
|
|
6540
|
+
DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
|
|
6541
|
+
WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
|
|
6542
|
+
}
|
|
6543
|
+
});
|
|
6544
|
+
|
|
6445
6545
|
// src/mesh/mesh-fast-forward.ts
|
|
6446
6546
|
async function fastForwardMeshNode(args) {
|
|
6447
6547
|
const workspace = typeof args.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -7893,8 +7993,8 @@ var init_mesh_events_utils = __esm({
|
|
|
7893
7993
|
});
|
|
7894
7994
|
|
|
7895
7995
|
// src/mesh/mesh-events-pending.ts
|
|
7896
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
7897
|
-
import { join as
|
|
7996
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync14, readFileSync as readFileSync11, renameSync as renameSync4, statSync as statSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
7997
|
+
import { join as join15 } from "path";
|
|
7898
7998
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
7899
7999
|
function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
|
|
7900
8000
|
const raw = Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId != null ? [coordinatorDaemonId] : [];
|
|
@@ -7957,9 +8057,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
|
|
|
7957
8057
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7958
8058
|
if (coordinatorDaemonId) {
|
|
7959
8059
|
const safeDaemon = coordinatorDaemonId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7960
|
-
return
|
|
8060
|
+
return join15(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
|
|
7961
8061
|
}
|
|
7962
|
-
return
|
|
8062
|
+
return join15(getLedgerDir(), `${safe}.pending-events.jsonl`);
|
|
7963
8063
|
}
|
|
7964
8064
|
function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
7965
8065
|
if (!meshId) return [];
|
|
@@ -7968,7 +8068,7 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
|
7968
8068
|
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
7969
8069
|
const events = [];
|
|
7970
8070
|
for (const path42 of paths) {
|
|
7971
|
-
if (!
|
|
8071
|
+
if (!existsSync14(path42)) continue;
|
|
7972
8072
|
try {
|
|
7973
8073
|
const raw = readFileSync11(path42, "utf-8");
|
|
7974
8074
|
const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
@@ -8045,7 +8145,7 @@ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
|
|
|
8045
8145
|
}
|
|
8046
8146
|
function trimPendingEventsIfNeeded(path42) {
|
|
8047
8147
|
try {
|
|
8048
|
-
if (!
|
|
8148
|
+
if (!existsSync14(path42)) return;
|
|
8049
8149
|
if (statSync6(path42).size <= MAX_PENDING_EVENTS_BYTES) return;
|
|
8050
8150
|
const lines = readFileSync11(path42, "utf-8").split("\n").filter(Boolean);
|
|
8051
8151
|
if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
|
|
@@ -8147,7 +8247,7 @@ function selectiveDrainFile(path42, predicate) {
|
|
|
8147
8247
|
unlinkSync2(tmpPath);
|
|
8148
8248
|
} catch {
|
|
8149
8249
|
try {
|
|
8150
|
-
if (
|
|
8250
|
+
if (existsSync14(tmpPath) && !existsSync14(path42)) renameSync4(tmpPath, path42);
|
|
8151
8251
|
} catch {
|
|
8152
8252
|
}
|
|
8153
8253
|
return [];
|
|
@@ -8241,7 +8341,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
8241
8341
|
}
|
|
8242
8342
|
const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
8243
8343
|
for (const path42 of paths) {
|
|
8244
|
-
if (
|
|
8344
|
+
if (existsSync14(path42)) try {
|
|
8245
8345
|
unlinkSync2(path42);
|
|
8246
8346
|
} catch {
|
|
8247
8347
|
}
|
|
@@ -8672,7 +8772,7 @@ var init_spawn_env = __esm({
|
|
|
8672
8772
|
|
|
8673
8773
|
// src/cli-adapters/provider-cli-shared.ts
|
|
8674
8774
|
import * as os5 from "os";
|
|
8675
|
-
import * as
|
|
8775
|
+
import * as path11 from "path";
|
|
8676
8776
|
function stripAnsi(str) {
|
|
8677
8777
|
return str.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
8678
8778
|
}
|
|
@@ -8748,24 +8848,24 @@ function buildCliScreenSnapshot(text) {
|
|
|
8748
8848
|
function findBinary(name) {
|
|
8749
8849
|
const trimmed = String(name || "").trim();
|
|
8750
8850
|
if (!trimmed) return trimmed;
|
|
8751
|
-
const expanded = trimmed.startsWith("~") ?
|
|
8752
|
-
if (
|
|
8753
|
-
return
|
|
8851
|
+
const expanded = trimmed.startsWith("~") ? path11.join(os5.homedir(), trimmed.slice(1)) : trimmed;
|
|
8852
|
+
if (path11.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
8853
|
+
return path11.isAbsolute(expanded) ? expanded : path11.resolve(expanded);
|
|
8754
8854
|
}
|
|
8755
8855
|
const isWin = os5.platform() === "win32";
|
|
8756
|
-
const paths = (process.env.PATH || "").split(
|
|
8856
|
+
const paths = (process.env.PATH || "").split(path11.delimiter);
|
|
8757
8857
|
const extraDirs = [];
|
|
8758
8858
|
if (isWin) {
|
|
8759
|
-
if (process.env.APPDATA) extraDirs.push(
|
|
8859
|
+
if (process.env.APPDATA) extraDirs.push(path11.join(process.env.APPDATA, "npm"));
|
|
8760
8860
|
try {
|
|
8761
|
-
extraDirs.push(
|
|
8861
|
+
extraDirs.push(path11.dirname(process.execPath));
|
|
8762
8862
|
} catch {
|
|
8763
8863
|
}
|
|
8764
8864
|
} else {
|
|
8765
|
-
extraDirs.push(
|
|
8865
|
+
extraDirs.push(path11.join(os5.homedir(), ".npm-global", "bin"));
|
|
8766
8866
|
extraDirs.push("/usr/local/bin", "/opt/homebrew/bin");
|
|
8767
8867
|
try {
|
|
8768
|
-
extraDirs.push(
|
|
8868
|
+
extraDirs.push(path11.dirname(process.execPath));
|
|
8769
8869
|
} catch {
|
|
8770
8870
|
}
|
|
8771
8871
|
}
|
|
@@ -8774,7 +8874,7 @@ function findBinary(name) {
|
|
|
8774
8874
|
for (const p of searchDirs) {
|
|
8775
8875
|
if (!p) continue;
|
|
8776
8876
|
for (const ext of exes) {
|
|
8777
|
-
const fullPath =
|
|
8877
|
+
const fullPath = path11.join(p, trimmed + ext);
|
|
8778
8878
|
try {
|
|
8779
8879
|
const fs32 = __require("fs");
|
|
8780
8880
|
if (fs32.existsSync(fullPath)) {
|
|
@@ -8790,7 +8890,7 @@ function findBinary(name) {
|
|
|
8790
8890
|
return isWin ? `${trimmed}.cmd` : trimmed;
|
|
8791
8891
|
}
|
|
8792
8892
|
function isScriptBinary(binaryPath) {
|
|
8793
|
-
if (!
|
|
8893
|
+
if (!path11.isAbsolute(binaryPath)) return false;
|
|
8794
8894
|
try {
|
|
8795
8895
|
const fs32 = __require("fs");
|
|
8796
8896
|
const resolved = fs32.realpathSync(binaryPath);
|
|
@@ -8806,7 +8906,7 @@ function isScriptBinary(binaryPath) {
|
|
|
8806
8906
|
}
|
|
8807
8907
|
}
|
|
8808
8908
|
function looksLikeMachOOrElf(filePath) {
|
|
8809
|
-
if (!
|
|
8909
|
+
if (!path11.isAbsolute(filePath)) return false;
|
|
8810
8910
|
try {
|
|
8811
8911
|
const fs32 = __require("fs");
|
|
8812
8912
|
const resolved = fs32.realpathSync(filePath);
|
|
@@ -9063,8 +9163,8 @@ var init_provider_cli_shared = __esm({
|
|
|
9063
9163
|
// src/detection/cli-detector.ts
|
|
9064
9164
|
import { exec } from "child_process";
|
|
9065
9165
|
import * as os6 from "os";
|
|
9066
|
-
import * as
|
|
9067
|
-
import { existsSync as
|
|
9166
|
+
import * as path12 from "path";
|
|
9167
|
+
import { existsSync as existsSync15 } from "fs";
|
|
9068
9168
|
function parseVersion(raw) {
|
|
9069
9169
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
9070
9170
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
@@ -9076,19 +9176,19 @@ function shellQuote(value) {
|
|
|
9076
9176
|
function expandHome(value) {
|
|
9077
9177
|
const trimmed = value.trim();
|
|
9078
9178
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
9079
|
-
return
|
|
9179
|
+
return path12.join(os6.homedir(), trimmed.slice(1));
|
|
9080
9180
|
}
|
|
9081
9181
|
function isExplicitCommandPath(command) {
|
|
9082
9182
|
const trimmed = command.trim();
|
|
9083
|
-
return
|
|
9183
|
+
return path12.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
9084
9184
|
}
|
|
9085
9185
|
function resolveCommandPath(command) {
|
|
9086
9186
|
const trimmed = command.trim();
|
|
9087
9187
|
if (!trimmed) return null;
|
|
9088
9188
|
if (isExplicitCommandPath(trimmed)) {
|
|
9089
9189
|
const expanded = expandHome(trimmed);
|
|
9090
|
-
const candidate =
|
|
9091
|
-
return
|
|
9190
|
+
const candidate = path12.isAbsolute(expanded) ? expanded : path12.resolve(expanded);
|
|
9191
|
+
return existsSync15(candidate) ? candidate : null;
|
|
9092
9192
|
}
|
|
9093
9193
|
return null;
|
|
9094
9194
|
}
|
|
@@ -9098,7 +9198,7 @@ async function resolveDetectionPath(command, whichCmd) {
|
|
|
9098
9198
|
const whichResult = await execAsync(`${whichCmd} ${shellQuote(command)}`);
|
|
9099
9199
|
if (whichResult) return whichResult.split("\n")[0];
|
|
9100
9200
|
const resolved = findBinary(command);
|
|
9101
|
-
if (
|
|
9201
|
+
if (path12.isAbsolute(resolved) && existsSync15(resolved)) return resolved;
|
|
9102
9202
|
return null;
|
|
9103
9203
|
}
|
|
9104
9204
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
@@ -9443,7 +9543,7 @@ var init_mesh_unresolved_forward_outbox = __esm({
|
|
|
9443
9543
|
});
|
|
9444
9544
|
|
|
9445
9545
|
// src/mesh/mesh-events-coordinator.ts
|
|
9446
|
-
import { existsSync as
|
|
9546
|
+
import { existsSync as existsSync16 } from "fs";
|
|
9447
9547
|
function resolveCoordinatorDrainDaemonIds(components) {
|
|
9448
9548
|
const ids = /* @__PURE__ */ new Set();
|
|
9449
9549
|
const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
|
|
@@ -10231,7 +10331,7 @@ async function maybeAutoFastForwardIdleNode(components, args) {
|
|
|
10231
10331
|
const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
|
|
10232
10332
|
const workspace = readNonEmptyString2(node?.workspace);
|
|
10233
10333
|
if (!workspace) return;
|
|
10234
|
-
if (!
|
|
10334
|
+
if (!existsSync16(workspace)) return;
|
|
10235
10335
|
const policy = resolveAutoFastForwardPolicy(mesh);
|
|
10236
10336
|
if (!policy.enabled) return;
|
|
10237
10337
|
if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
|
|
@@ -10430,8 +10530,10 @@ function injectMeshSystemMessage(components, args) {
|
|
|
10430
10530
|
}
|
|
10431
10531
|
}
|
|
10432
10532
|
function markSessionTerminal(sessionId, outcome, occurredAtMs) {
|
|
10533
|
+
const eventTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
|
|
10433
10534
|
const task = updateSessionTaskStatus(args.meshId, sessionId, outcome, {
|
|
10434
|
-
occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0
|
|
10535
|
+
occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
|
|
10536
|
+
taskId: eventTaskId
|
|
10435
10537
|
});
|
|
10436
10538
|
updateDirectDispatchStatus(args.meshId, sessionId, outcome);
|
|
10437
10539
|
markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
|
|
@@ -12728,18 +12830,18 @@ __export(external_sources_exports, {
|
|
|
12728
12830
|
});
|
|
12729
12831
|
import * as fs9 from "fs";
|
|
12730
12832
|
import * as os11 from "os";
|
|
12731
|
-
import * as
|
|
12833
|
+
import * as path18 from "path";
|
|
12732
12834
|
function adhdevDir() {
|
|
12733
|
-
return
|
|
12835
|
+
return path18.join(os11.homedir(), ".adhdev");
|
|
12734
12836
|
}
|
|
12735
12837
|
function externalRoot() {
|
|
12736
|
-
return
|
|
12838
|
+
return path18.join(adhdevDir(), "external");
|
|
12737
12839
|
}
|
|
12738
12840
|
function sourcesFilePath() {
|
|
12739
|
-
return
|
|
12841
|
+
return path18.join(adhdevDir(), SOURCES_FILENAME);
|
|
12740
12842
|
}
|
|
12741
12843
|
function activeFilePath() {
|
|
12742
|
-
return
|
|
12844
|
+
return path18.join(adhdevDir(), ACTIVE_FILENAME);
|
|
12743
12845
|
}
|
|
12744
12846
|
function ensureAdhdevDir() {
|
|
12745
12847
|
const d = adhdevDir();
|
|
@@ -12806,7 +12908,7 @@ function inventoryExternalSources() {
|
|
|
12806
12908
|
for (const sourceEntry of entries) {
|
|
12807
12909
|
if (!sourceEntry.isDirectory()) continue;
|
|
12808
12910
|
const sourceName = sourceEntry.name;
|
|
12809
|
-
const sourceDir =
|
|
12911
|
+
const sourceDir = path18.join(root, sourceName);
|
|
12810
12912
|
const providers = {};
|
|
12811
12913
|
let categoryEntries;
|
|
12812
12914
|
try {
|
|
@@ -12817,7 +12919,7 @@ function inventoryExternalSources() {
|
|
|
12817
12919
|
for (const categoryEntry of categoryEntries) {
|
|
12818
12920
|
if (!categoryEntry.isDirectory()) continue;
|
|
12819
12921
|
const category = categoryEntry.name;
|
|
12820
|
-
const categoryDir =
|
|
12922
|
+
const categoryDir = path18.join(sourceDir, category);
|
|
12821
12923
|
let typeEntries;
|
|
12822
12924
|
try {
|
|
12823
12925
|
typeEntries = fs9.readdirSync(categoryDir, { withFileTypes: true });
|
|
@@ -12827,9 +12929,9 @@ function inventoryExternalSources() {
|
|
|
12827
12929
|
const types = [];
|
|
12828
12930
|
for (const typeEntry of typeEntries) {
|
|
12829
12931
|
if (!typeEntry.isDirectory()) continue;
|
|
12830
|
-
const typeDir =
|
|
12831
|
-
const hasV1 = fs9.existsSync(
|
|
12832
|
-
const hasV0 = fs9.existsSync(
|
|
12932
|
+
const typeDir = path18.join(categoryDir, typeEntry.name);
|
|
12933
|
+
const hasV1 = fs9.existsSync(path18.join(typeDir, "provider.v1.json"));
|
|
12934
|
+
const hasV0 = fs9.existsSync(path18.join(typeDir, "provider.json"));
|
|
12833
12935
|
if (hasV1 || hasV0) types.push(typeEntry.name);
|
|
12834
12936
|
}
|
|
12835
12937
|
if (types.length > 0) providers[category] = types;
|
|
@@ -13033,59 +13135,6 @@ var init_terminal_screen = __esm({
|
|
|
13033
13135
|
}
|
|
13034
13136
|
});
|
|
13035
13137
|
|
|
13036
|
-
// src/cli-adapters/resolve-executable.ts
|
|
13037
|
-
import { execFileSync } from "child_process";
|
|
13038
|
-
import { existsSync as existsSync22 } from "fs";
|
|
13039
|
-
import * as path18 from "path";
|
|
13040
|
-
function resolveWin32GlobalBin(trimmed) {
|
|
13041
|
-
if (path18.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
|
|
13042
|
-
return null;
|
|
13043
|
-
}
|
|
13044
|
-
const extraDirs = [];
|
|
13045
|
-
if (process.env.APPDATA) extraDirs.push(path18.join(process.env.APPDATA, "npm"));
|
|
13046
|
-
try {
|
|
13047
|
-
extraDirs.push(path18.dirname(process.execPath));
|
|
13048
|
-
} catch {
|
|
13049
|
-
}
|
|
13050
|
-
for (const dir of extraDirs) {
|
|
13051
|
-
if (!dir) continue;
|
|
13052
|
-
for (const ext of WIN_EXEC_EXT) {
|
|
13053
|
-
const full = path18.join(dir, trimmed + ext);
|
|
13054
|
-
if (existsSync22(full)) return full;
|
|
13055
|
-
}
|
|
13056
|
-
}
|
|
13057
|
-
return null;
|
|
13058
|
-
}
|
|
13059
|
-
function resolveWin32Executable(command) {
|
|
13060
|
-
if (process.platform !== "win32") return command;
|
|
13061
|
-
const trimmed = (command || "").trim();
|
|
13062
|
-
if (!trimmed) return command;
|
|
13063
|
-
if (path18.isAbsolute(trimmed) && existsSync22(trimmed)) return trimmed;
|
|
13064
|
-
try {
|
|
13065
|
-
const out = execFileSync("where", [trimmed], {
|
|
13066
|
-
encoding: "utf8",
|
|
13067
|
-
windowsHide: true
|
|
13068
|
-
}).trim();
|
|
13069
|
-
if (out) {
|
|
13070
|
-
const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
13071
|
-
const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path18.extname(m).toLowerCase()));
|
|
13072
|
-
return direct || matches[0] || command;
|
|
13073
|
-
}
|
|
13074
|
-
} catch {
|
|
13075
|
-
}
|
|
13076
|
-
const globalBin = resolveWin32GlobalBin(trimmed);
|
|
13077
|
-
if (globalBin) return globalBin;
|
|
13078
|
-
return command;
|
|
13079
|
-
}
|
|
13080
|
-
var DIRECT_EXEC_EXT, WIN_EXEC_EXT;
|
|
13081
|
-
var init_resolve_executable = __esm({
|
|
13082
|
-
"src/cli-adapters/resolve-executable.ts"() {
|
|
13083
|
-
"use strict";
|
|
13084
|
-
DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
|
|
13085
|
-
WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
|
|
13086
|
-
}
|
|
13087
|
-
});
|
|
13088
|
-
|
|
13089
13138
|
// src/cli-adapters/pty-transport.ts
|
|
13090
13139
|
var pty_transport_exports = {};
|
|
13091
13140
|
__export(pty_transport_exports, {
|
|
@@ -19433,13 +19482,20 @@ var MESH_REFINE_CONFIG_SCHEMA = {
|
|
|
19433
19482
|
function isMeshConfigRecord(value) {
|
|
19434
19483
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
19435
19484
|
}
|
|
19485
|
+
var SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
|
|
19486
|
+
var SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
|
|
19487
|
+
var SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
|
|
19436
19488
|
function tokenizeCommandString(command) {
|
|
19437
19489
|
const trimmed = command.trim();
|
|
19438
19490
|
if (!trimmed) return null;
|
|
19439
|
-
if (
|
|
19491
|
+
if (SHELL_METACHAR_RE.test(trimmed)) return null;
|
|
19440
19492
|
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
19441
19493
|
if (!tokens.length) return null;
|
|
19442
|
-
|
|
19494
|
+
const isWin32 = process.platform === "win32";
|
|
19495
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
19496
|
+
const re = isWin32 && i === 0 ? SAFE_WIN32_EXEC_TOKEN_RE : SAFE_TOKEN_RE;
|
|
19497
|
+
if (!re.test(tokens[i])) return null;
|
|
19498
|
+
}
|
|
19443
19499
|
return tokens;
|
|
19444
19500
|
}
|
|
19445
19501
|
function validateCategory(value) {
|
|
@@ -19649,8 +19705,9 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
|
|
|
19649
19705
|
}
|
|
19650
19706
|
|
|
19651
19707
|
// src/mesh/worktree-bootstrap-config.ts
|
|
19652
|
-
|
|
19653
|
-
import {
|
|
19708
|
+
init_resolve_executable();
|
|
19709
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
19710
|
+
import { join as join14, resolve as pathResolve } from "path";
|
|
19654
19711
|
import { execFile as execFile3 } from "child_process";
|
|
19655
19712
|
import { createHash as createHash3 } from "crypto";
|
|
19656
19713
|
import { promisify as promisify3 } from "util";
|
|
@@ -19741,8 +19798,8 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
19741
19798
|
return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
|
|
19742
19799
|
}
|
|
19743
19800
|
for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
|
|
19744
|
-
const configPath =
|
|
19745
|
-
if (!
|
|
19801
|
+
const configPath = join14(workspace, relative5);
|
|
19802
|
+
if (!existsSync13(configPath)) continue;
|
|
19746
19803
|
try {
|
|
19747
19804
|
const parsed = parseConfigText3(configPath, readFileSync10(configPath, "utf-8"));
|
|
19748
19805
|
const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
|
|
@@ -19757,7 +19814,7 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
19757
19814
|
function computeStaleInputsDigest(workspace, staleInputs) {
|
|
19758
19815
|
const digest = {};
|
|
19759
19816
|
for (const relative5 of staleInputs ?? []) {
|
|
19760
|
-
const filePath =
|
|
19817
|
+
const filePath = join14(workspace, relative5);
|
|
19761
19818
|
try {
|
|
19762
19819
|
digest[relative5] = createHash3("sha256").update(readFileSync10(filePath)).digest("hex");
|
|
19763
19820
|
} catch {
|
|
@@ -19829,10 +19886,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
19829
19886
|
staleInputs: loaded.config.staleInputs
|
|
19830
19887
|
};
|
|
19831
19888
|
const staleInputPaths = loaded.config.staleInputs ?? [];
|
|
19832
|
-
const initiallyAbsent = staleInputPaths.filter((p) => !
|
|
19889
|
+
const initiallyAbsent = staleInputPaths.filter((p) => !existsSync13(join14(workspace, p)));
|
|
19833
19890
|
for (const command of validation.commands) {
|
|
19834
19891
|
if (initiallyAbsent.length > 0) {
|
|
19835
|
-
const appearedNow = initiallyAbsent.filter((p) =>
|
|
19892
|
+
const appearedNow = initiallyAbsent.filter((p) => existsSync13(join14(workspace, p)));
|
|
19836
19893
|
if (appearedNow.length > 0) {
|
|
19837
19894
|
state.status = "stale";
|
|
19838
19895
|
state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -19843,8 +19900,9 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
19843
19900
|
const cwd = command.cwd ? pathResolve(workspace, command.cwd) : workspace;
|
|
19844
19901
|
const startedAt = Date.now();
|
|
19845
19902
|
state.lastCommand = command.displayCommand;
|
|
19903
|
+
const resolvedCommand = resolveWin32Executable(command.command);
|
|
19846
19904
|
try {
|
|
19847
|
-
const result = await execFileAsync4(
|
|
19905
|
+
const result = await execFileAsync4(resolvedCommand, command.args, {
|
|
19848
19906
|
cwd,
|
|
19849
19907
|
encoding: "utf8",
|
|
19850
19908
|
timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
|
|
@@ -20080,8 +20138,8 @@ var P2pRelayFailureError = class extends Error {
|
|
|
20080
20138
|
|
|
20081
20139
|
// src/config/state-store.ts
|
|
20082
20140
|
init_config();
|
|
20083
|
-
import { existsSync as
|
|
20084
|
-
import { join as
|
|
20141
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
20142
|
+
import { join as join18 } from "path";
|
|
20085
20143
|
var DEFAULT_STATE = {
|
|
20086
20144
|
recentActivity: [],
|
|
20087
20145
|
savedProviderSessions: [],
|
|
@@ -20094,7 +20152,7 @@ function isPlainObject2(value) {
|
|
|
20094
20152
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
20095
20153
|
}
|
|
20096
20154
|
function getStatePath() {
|
|
20097
|
-
return
|
|
20155
|
+
return join18(getConfigDir(), "state.json");
|
|
20098
20156
|
}
|
|
20099
20157
|
function normalizeState(raw) {
|
|
20100
20158
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -20130,7 +20188,7 @@ function normalizeState(raw) {
|
|
|
20130
20188
|
}
|
|
20131
20189
|
function loadState() {
|
|
20132
20190
|
const statePath = getStatePath();
|
|
20133
|
-
if (!
|
|
20191
|
+
if (!existsSync17(statePath)) {
|
|
20134
20192
|
return { ...DEFAULT_STATE };
|
|
20135
20193
|
}
|
|
20136
20194
|
try {
|
|
@@ -20152,19 +20210,19 @@ function resetState() {
|
|
|
20152
20210
|
// src/detection/ide-detector.ts
|
|
20153
20211
|
import { exec as exec2 } from "child_process";
|
|
20154
20212
|
import { promisify as promisify4 } from "util";
|
|
20155
|
-
import { existsSync as
|
|
20213
|
+
import { existsSync as existsSync19, statSync as statSync8 } from "fs";
|
|
20156
20214
|
import { platform as platform3, homedir as homedir8 } from "os";
|
|
20157
|
-
import * as
|
|
20215
|
+
import * as path14 from "path";
|
|
20158
20216
|
|
|
20159
20217
|
// src/detection/win32-ide-version.ts
|
|
20160
20218
|
import * as fs5 from "fs";
|
|
20161
|
-
import * as
|
|
20219
|
+
import * as path13 from "path";
|
|
20162
20220
|
function manifestCandidates(exeDir) {
|
|
20163
20221
|
return [
|
|
20164
|
-
|
|
20165
|
-
|
|
20222
|
+
path13.join(exeDir, "resources", "app", "product.json"),
|
|
20223
|
+
path13.join(exeDir, "resources", "app", "package.json"),
|
|
20166
20224
|
// Some packagings keep product.json one level up.
|
|
20167
|
-
|
|
20225
|
+
path13.join(exeDir, "product.json")
|
|
20168
20226
|
];
|
|
20169
20227
|
}
|
|
20170
20228
|
function parseVersionFromManifest(raw) {
|
|
@@ -20182,9 +20240,9 @@ function readWin32IdeVersionFromDisk(exePath) {
|
|
|
20182
20240
|
if (!exePath) return null;
|
|
20183
20241
|
let exeDir;
|
|
20184
20242
|
try {
|
|
20185
|
-
exeDir = fs5.statSync(exePath).isDirectory() ? exePath :
|
|
20243
|
+
exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path13.dirname(exePath);
|
|
20186
20244
|
} catch {
|
|
20187
|
-
exeDir =
|
|
20245
|
+
exeDir = path13.dirname(exePath);
|
|
20188
20246
|
}
|
|
20189
20247
|
for (const candidate of manifestCandidates(exeDir)) {
|
|
20190
20248
|
try {
|
|
@@ -20198,7 +20256,7 @@ function readWin32IdeVersionFromDisk(exePath) {
|
|
|
20198
20256
|
}
|
|
20199
20257
|
function isKnownWin32GuiExe(binPath, win32ProcessNames) {
|
|
20200
20258
|
if (!binPath) return false;
|
|
20201
|
-
const base =
|
|
20259
|
+
const base = path13.win32.basename(binPath).toLowerCase();
|
|
20202
20260
|
if (!base.endsWith(".exe")) return false;
|
|
20203
20261
|
for (const names of Object.values(win32ProcessNames)) {
|
|
20204
20262
|
for (const name of names) {
|
|
@@ -20230,10 +20288,10 @@ function getMergedDefinitions() {
|
|
|
20230
20288
|
function findCliCommand(command) {
|
|
20231
20289
|
const trimmed = String(command || "").trim();
|
|
20232
20290
|
if (!trimmed) return null;
|
|
20233
|
-
if (
|
|
20234
|
-
const candidate = trimmed.startsWith("~") ?
|
|
20235
|
-
const resolved =
|
|
20236
|
-
return
|
|
20291
|
+
if (path14.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
20292
|
+
const candidate = trimmed.startsWith("~") ? path14.join(homedir8(), trimmed.slice(1)) : trimmed;
|
|
20293
|
+
const resolved = path14.isAbsolute(candidate) ? candidate : path14.resolve(candidate);
|
|
20294
|
+
return existsSync19(resolved) ? resolved : null;
|
|
20237
20295
|
}
|
|
20238
20296
|
const isWin = platform3() === "win32";
|
|
20239
20297
|
const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
|
|
@@ -20241,9 +20299,9 @@ function findCliCommand(command) {
|
|
|
20241
20299
|
for (const p of paths) {
|
|
20242
20300
|
if (!p) continue;
|
|
20243
20301
|
for (const ext of exes) {
|
|
20244
|
-
const fullPath =
|
|
20302
|
+
const fullPath = path14.join(p, trimmed + ext);
|
|
20245
20303
|
try {
|
|
20246
|
-
if (
|
|
20304
|
+
if (existsSync19(fullPath)) {
|
|
20247
20305
|
const stat2 = statSync8(fullPath);
|
|
20248
20306
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
20249
20307
|
return fullPath;
|
|
@@ -20258,13 +20316,13 @@ function findCliCommand(command) {
|
|
|
20258
20316
|
function checkPathExists(paths) {
|
|
20259
20317
|
const home = homedir8();
|
|
20260
20318
|
for (const p of paths) {
|
|
20261
|
-
const normalized = p.startsWith("~") ?
|
|
20319
|
+
const normalized = p.startsWith("~") ? path14.join(home, p.slice(1)) : p;
|
|
20262
20320
|
if (normalized.includes("*")) {
|
|
20263
20321
|
const username = home.split(/[\\/]/).pop() || "";
|
|
20264
20322
|
const resolved = normalized.replace("*", username);
|
|
20265
|
-
if (
|
|
20323
|
+
if (existsSync19(resolved)) return resolved;
|
|
20266
20324
|
} else {
|
|
20267
|
-
if (
|
|
20325
|
+
if (existsSync19(normalized)) return normalized;
|
|
20268
20326
|
}
|
|
20269
20327
|
}
|
|
20270
20328
|
return null;
|
|
@@ -20278,7 +20336,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20278
20336
|
let resolvedCli = cliPath;
|
|
20279
20337
|
if (!resolvedCli && appPath && os30 === "darwin") {
|
|
20280
20338
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
20281
|
-
if (
|
|
20339
|
+
if (existsSync19(bundledCli)) resolvedCli = bundledCli;
|
|
20282
20340
|
}
|
|
20283
20341
|
if (!resolvedCli && appPath && os30 === "win32") {
|
|
20284
20342
|
const { dirname: dirname17 } = await import("path");
|
|
@@ -20291,7 +20349,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20291
20349
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
20292
20350
|
];
|
|
20293
20351
|
for (const c of candidates) {
|
|
20294
|
-
if (
|
|
20352
|
+
if (existsSync19(c)) {
|
|
20295
20353
|
resolvedCli = c;
|
|
20296
20354
|
break;
|
|
20297
20355
|
}
|
|
@@ -22150,9 +22208,9 @@ ${cleanBody}`;
|
|
|
22150
22208
|
// src/config/chat-history.ts
|
|
22151
22209
|
init_chat_message_normalization();
|
|
22152
22210
|
import * as fs6 from "fs";
|
|
22153
|
-
import * as
|
|
22211
|
+
import * as path15 from "path";
|
|
22154
22212
|
import * as os8 from "os";
|
|
22155
|
-
var HISTORY_DIR =
|
|
22213
|
+
var HISTORY_DIR = path15.join(os8.homedir(), ".adhdev", "history");
|
|
22156
22214
|
var RETAIN_DAYS = 30;
|
|
22157
22215
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
22158
22216
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -22338,7 +22396,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
22338
22396
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
22339
22397
|
return new Map(files.map((file) => {
|
|
22340
22398
|
try {
|
|
22341
|
-
const stat2 = fs6.statSync(
|
|
22399
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22342
22400
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
22343
22401
|
} catch {
|
|
22344
22402
|
return [file, `${file}:missing`];
|
|
@@ -22349,7 +22407,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
22349
22407
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
22350
22408
|
}
|
|
22351
22409
|
function getSavedHistoryIndexFilePath(dir) {
|
|
22352
|
-
return
|
|
22410
|
+
return path15.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
22353
22411
|
}
|
|
22354
22412
|
function getSavedHistoryIndexLockPath(dir) {
|
|
22355
22413
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -22451,7 +22509,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
22451
22509
|
}
|
|
22452
22510
|
for (const file of Array.from(currentEntries.keys())) {
|
|
22453
22511
|
if (incomingFiles.has(file)) continue;
|
|
22454
|
-
if (!fs6.existsSync(
|
|
22512
|
+
if (!fs6.existsSync(path15.join(dir, file))) {
|
|
22455
22513
|
currentEntries.delete(file);
|
|
22456
22514
|
}
|
|
22457
22515
|
}
|
|
@@ -22477,7 +22535,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
22477
22535
|
const indexStat = fs6.statSync(getSavedHistoryIndexFilePath(dir));
|
|
22478
22536
|
const files = listHistoryFiles(dir);
|
|
22479
22537
|
for (const file of files) {
|
|
22480
|
-
const stat2 = fs6.statSync(
|
|
22538
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22481
22539
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
22482
22540
|
}
|
|
22483
22541
|
return false;
|
|
@@ -22487,14 +22545,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
22487
22545
|
}
|
|
22488
22546
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
22489
22547
|
try {
|
|
22490
|
-
const stat2 = fs6.statSync(
|
|
22548
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22491
22549
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
22492
22550
|
} catch {
|
|
22493
22551
|
return `${file}:missing`;
|
|
22494
22552
|
}
|
|
22495
22553
|
}
|
|
22496
22554
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
22497
|
-
const filePath =
|
|
22555
|
+
const filePath = path15.join(dir, file);
|
|
22498
22556
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
22499
22557
|
const currentEntry = entries.get(file) || null;
|
|
22500
22558
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -22567,7 +22625,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
22567
22625
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
22568
22626
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
22569
22627
|
if (!historySessionId) return null;
|
|
22570
|
-
const filePath =
|
|
22628
|
+
const filePath = path15.join(dir, file);
|
|
22571
22629
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
22572
22630
|
const lines = content.split("\n").filter(Boolean);
|
|
22573
22631
|
let messageCount = 0;
|
|
@@ -22654,7 +22712,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
22654
22712
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
22655
22713
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
22656
22714
|
for (const file of files.slice().sort()) {
|
|
22657
|
-
const filePath =
|
|
22715
|
+
const filePath = path15.join(dir, file);
|
|
22658
22716
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
22659
22717
|
const cached3 = savedHistoryFileSummaryCache.get(filePath);
|
|
22660
22718
|
const persisted = persistedEntries.get(file);
|
|
@@ -22774,12 +22832,12 @@ var ChatHistoryWriter = class {
|
|
|
22774
22832
|
});
|
|
22775
22833
|
}
|
|
22776
22834
|
if (newMessages.length === 0) return;
|
|
22777
|
-
const dir =
|
|
22835
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22778
22836
|
fs6.mkdirSync(dir, { recursive: true });
|
|
22779
22837
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
22780
22838
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
22781
22839
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
22782
|
-
const filePath =
|
|
22840
|
+
const filePath = path15.join(dir, fileName);
|
|
22783
22841
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
22784
22842
|
fs6.appendFileSync(filePath, lines, "utf-8");
|
|
22785
22843
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -22870,11 +22928,11 @@ var ChatHistoryWriter = class {
|
|
|
22870
22928
|
const ws = String(workspace || "").trim();
|
|
22871
22929
|
if (!id || !ws) return;
|
|
22872
22930
|
try {
|
|
22873
|
-
const dir =
|
|
22931
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22874
22932
|
fs6.mkdirSync(dir, { recursive: true });
|
|
22875
22933
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
22876
22934
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
22877
|
-
const filePath =
|
|
22935
|
+
const filePath = path15.join(dir, fileName);
|
|
22878
22936
|
const record = {
|
|
22879
22937
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22880
22938
|
receivedAt: Date.now(),
|
|
@@ -22920,14 +22978,14 @@ var ChatHistoryWriter = class {
|
|
|
22920
22978
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
22921
22979
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
22922
22980
|
}
|
|
22923
|
-
const dir =
|
|
22981
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22924
22982
|
if (!fs6.existsSync(dir)) return;
|
|
22925
22983
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
22926
22984
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
22927
22985
|
const files = fs6.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
22928
22986
|
for (const file of files) {
|
|
22929
|
-
const sourcePath =
|
|
22930
|
-
const targetPath =
|
|
22987
|
+
const sourcePath = path15.join(dir, file);
|
|
22988
|
+
const targetPath = path15.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
22931
22989
|
const sourceLines = fs6.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
22932
22990
|
const rewritten = sourceLines.map((line) => {
|
|
22933
22991
|
try {
|
|
@@ -22961,13 +23019,13 @@ var ChatHistoryWriter = class {
|
|
|
22961
23019
|
const sessionId = String(historySessionId || "").trim();
|
|
22962
23020
|
if (!sessionId) return;
|
|
22963
23021
|
try {
|
|
22964
|
-
const dir =
|
|
23022
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22965
23023
|
if (!fs6.existsSync(dir)) return;
|
|
22966
23024
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
22967
23025
|
const files = fs6.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
22968
23026
|
const seen = /* @__PURE__ */ new Set();
|
|
22969
23027
|
for (const file of files) {
|
|
22970
|
-
const filePath =
|
|
23028
|
+
const filePath = path15.join(dir, file);
|
|
22971
23029
|
const lines = fs6.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
22972
23030
|
const next = [];
|
|
22973
23031
|
for (const line of lines) {
|
|
@@ -23021,11 +23079,11 @@ var ChatHistoryWriter = class {
|
|
|
23021
23079
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
23022
23080
|
const agentDirs = fs6.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
23023
23081
|
for (const dir of agentDirs) {
|
|
23024
|
-
const dirPath =
|
|
23082
|
+
const dirPath = path15.join(HISTORY_DIR, dir.name);
|
|
23025
23083
|
const files = fs6.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
23026
23084
|
let removedAny = false;
|
|
23027
23085
|
for (const file of files) {
|
|
23028
|
-
const filePath =
|
|
23086
|
+
const filePath = path15.join(dirPath, file);
|
|
23029
23087
|
const stat2 = fs6.statSync(filePath);
|
|
23030
23088
|
if (stat2.mtimeMs < cutoff) {
|
|
23031
23089
|
fs6.unlinkSync(filePath);
|
|
@@ -23228,7 +23286,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
|
23228
23286
|
const seen = /* @__PURE__ */ new Set();
|
|
23229
23287
|
let readAllFiles = true;
|
|
23230
23288
|
for (let f = 0; f < files.length; f++) {
|
|
23231
|
-
const filePath =
|
|
23289
|
+
const filePath = path15.join(dir, files[f]);
|
|
23232
23290
|
const remaining = Math.max(0, needed - collected.length);
|
|
23233
23291
|
const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
|
|
23234
23292
|
const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
|
|
@@ -23261,7 +23319,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
|
23261
23319
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
23262
23320
|
try {
|
|
23263
23321
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
23264
|
-
const dir =
|
|
23322
|
+
const dir = path15.join(HISTORY_DIR, sanitized);
|
|
23265
23323
|
if (!fs6.existsSync(dir)) return { messages: [], hasMore: false };
|
|
23266
23324
|
const files = listHistoryFiles(dir, historySessionId);
|
|
23267
23325
|
const bounded = isBoundedTailRequest(limit, offset, excludeRecentCount);
|
|
@@ -23284,7 +23342,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
23284
23342
|
const allMessages = [];
|
|
23285
23343
|
const seen = /* @__PURE__ */ new Set();
|
|
23286
23344
|
for (const file of files) {
|
|
23287
|
-
const filePath =
|
|
23345
|
+
const filePath = path15.join(dir, file);
|
|
23288
23346
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
23289
23347
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
23290
23348
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -23308,7 +23366,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
23308
23366
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
23309
23367
|
try {
|
|
23310
23368
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
23311
|
-
const dir =
|
|
23369
|
+
const dir = path15.join(HISTORY_DIR, sanitized);
|
|
23312
23370
|
if (!fs6.existsSync(dir)) {
|
|
23313
23371
|
savedHistorySessionCache.delete(sanitized);
|
|
23314
23372
|
return { sessions: [], hasMore: false };
|
|
@@ -23369,11 +23427,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
23369
23427
|
}
|
|
23370
23428
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
23371
23429
|
try {
|
|
23372
|
-
const dir =
|
|
23430
|
+
const dir = path15.join(HISTORY_DIR, agentType);
|
|
23373
23431
|
if (!fs6.existsSync(dir)) return null;
|
|
23374
23432
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
23375
23433
|
for (const file of files) {
|
|
23376
|
-
const lines = fs6.readFileSync(
|
|
23434
|
+
const lines = fs6.readFileSync(path15.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
23377
23435
|
for (const line of lines) {
|
|
23378
23436
|
try {
|
|
23379
23437
|
const parsed = JSON.parse(line);
|
|
@@ -23393,16 +23451,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
23393
23451
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
23394
23452
|
if (records.length === 0) return false;
|
|
23395
23453
|
try {
|
|
23396
|
-
const dir =
|
|
23454
|
+
const dir = path15.join(HISTORY_DIR, agentType);
|
|
23397
23455
|
fs6.mkdirSync(dir, { recursive: true });
|
|
23398
23456
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
23399
23457
|
for (const file of fs6.readdirSync(dir)) {
|
|
23400
23458
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
23401
|
-
fs6.unlinkSync(
|
|
23459
|
+
fs6.unlinkSync(path15.join(dir, file));
|
|
23402
23460
|
}
|
|
23403
23461
|
}
|
|
23404
23462
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
23405
|
-
const filePath =
|
|
23463
|
+
const filePath = path15.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
23406
23464
|
fs6.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
23407
23465
|
`, "utf-8");
|
|
23408
23466
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -26008,7 +26066,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
26008
26066
|
init_contracts();
|
|
26009
26067
|
import * as fs7 from "fs";
|
|
26010
26068
|
import * as os9 from "os";
|
|
26011
|
-
import * as
|
|
26069
|
+
import * as path16 from "path";
|
|
26012
26070
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
26013
26071
|
init_logger();
|
|
26014
26072
|
|
|
@@ -27058,7 +27116,7 @@ function readExactRuntimeMirrorMessages(args) {
|
|
|
27058
27116
|
function normalizeComparableWorkspace(value) {
|
|
27059
27117
|
const text = typeof value === "string" ? value.trim() : "";
|
|
27060
27118
|
if (!text) return "";
|
|
27061
|
-
return
|
|
27119
|
+
return path16.resolve(text);
|
|
27062
27120
|
}
|
|
27063
27121
|
function isCurrentRuntimePtySafelyAttributed(args) {
|
|
27064
27122
|
if (args.adapter.cliType !== "codex-cli") return false;
|
|
@@ -27543,7 +27601,7 @@ function buildDebugBundleText(bundle) {
|
|
|
27543
27601
|
}
|
|
27544
27602
|
function getChatDebugBundleDir() {
|
|
27545
27603
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
27546
|
-
return override ||
|
|
27604
|
+
return override || path16.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
27547
27605
|
}
|
|
27548
27606
|
function safeBundleIdSegment(value, fallback) {
|
|
27549
27607
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -27600,7 +27658,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
27600
27658
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
27601
27659
|
const dir = getChatDebugBundleDir();
|
|
27602
27660
|
fs7.mkdirSync(dir, { recursive: true });
|
|
27603
|
-
const savedPath =
|
|
27661
|
+
const savedPath = path16.join(dir, `${bundleId}.json`);
|
|
27604
27662
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
27605
27663
|
`;
|
|
27606
27664
|
fs7.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -29164,7 +29222,7 @@ async function handleResolveAction(h, args) {
|
|
|
29164
29222
|
|
|
29165
29223
|
// src/commands/cdp-commands.ts
|
|
29166
29224
|
import * as fs8 from "fs";
|
|
29167
|
-
import * as
|
|
29225
|
+
import * as path17 from "path";
|
|
29168
29226
|
import * as os10 from "os";
|
|
29169
29227
|
var KEY_TO_VK = {
|
|
29170
29228
|
Backspace: 8,
|
|
@@ -29421,25 +29479,25 @@ function resolveSafePath(requestedPath) {
|
|
|
29421
29479
|
const inputPath = rawPath || ".";
|
|
29422
29480
|
const home = os10.homedir();
|
|
29423
29481
|
if (inputPath.startsWith("~")) {
|
|
29424
|
-
return
|
|
29482
|
+
return path17.resolve(path17.join(home, inputPath.slice(1)));
|
|
29425
29483
|
}
|
|
29426
29484
|
if (process.platform === "win32") {
|
|
29427
29485
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
29428
|
-
if (
|
|
29429
|
-
return
|
|
29486
|
+
if (path17.win32.isAbsolute(normalized)) {
|
|
29487
|
+
return path17.win32.normalize(normalized);
|
|
29430
29488
|
}
|
|
29431
|
-
return
|
|
29489
|
+
return path17.win32.resolve(normalized);
|
|
29432
29490
|
}
|
|
29433
|
-
if (
|
|
29434
|
-
return
|
|
29491
|
+
if (path17.isAbsolute(inputPath)) {
|
|
29492
|
+
return path17.normalize(inputPath);
|
|
29435
29493
|
}
|
|
29436
|
-
return
|
|
29494
|
+
return path17.resolve(inputPath);
|
|
29437
29495
|
}
|
|
29438
29496
|
function listDirectoryEntriesSafe(dirPath) {
|
|
29439
29497
|
const entries = fs8.readdirSync(dirPath, { withFileTypes: true });
|
|
29440
29498
|
const files = [];
|
|
29441
29499
|
for (const entry of entries) {
|
|
29442
|
-
const entryPath =
|
|
29500
|
+
const entryPath = path17.join(dirPath, entry.name);
|
|
29443
29501
|
try {
|
|
29444
29502
|
if (entry.isDirectory()) {
|
|
29445
29503
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -29493,7 +29551,7 @@ async function handleFileRead(h, args) {
|
|
|
29493
29551
|
async function handleFileWrite(h, args) {
|
|
29494
29552
|
try {
|
|
29495
29553
|
const filePath = resolveSafePath(args?.path);
|
|
29496
|
-
fs8.mkdirSync(
|
|
29554
|
+
fs8.mkdirSync(path17.dirname(filePath), { recursive: true });
|
|
29497
29555
|
fs8.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
29498
29556
|
return { success: true, path: filePath };
|
|
29499
29557
|
} catch (e) {
|
|
@@ -43306,6 +43364,7 @@ import { homedir as homedir26, hostname as osHostname } from "os";
|
|
|
43306
43364
|
import { basename as pathBasename, join as pathJoin, resolve as pathResolve2 } from "path";
|
|
43307
43365
|
import * as fs26 from "fs";
|
|
43308
43366
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
43367
|
+
init_resolve_executable();
|
|
43309
43368
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
43310
43369
|
var CHANNEL_SERVER_URL = {
|
|
43311
43370
|
stable: "https://api.adhf.dev",
|
|
@@ -44404,6 +44463,18 @@ function truncateValidationOutput(value) {
|
|
|
44404
44463
|
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
44405
44464
|
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
44406
44465
|
}
|
|
44466
|
+
function isSpawnResolutionError(error) {
|
|
44467
|
+
if (!error) return false;
|
|
44468
|
+
if (error.code === "ENOENT" && typeof error.syscall === "string" && error.syscall.startsWith("spawn")) return true;
|
|
44469
|
+
return error.code === "ENOENT" && (error.syscall === void 0 || String(error.syscall).startsWith("spawn"));
|
|
44470
|
+
}
|
|
44471
|
+
function describeSpawnError(error, command, spawnResolutionFailed) {
|
|
44472
|
+
if (spawnResolutionFailed) {
|
|
44473
|
+
const hint = process.platform === "win32" ? " On Windows, npm-family commands (npm/npx/tsc/vitest) are .cmd shims that the bare-command spawn search does not resolve; configure an absolute path or ensure the command is on PATH." : "";
|
|
44474
|
+
return `Could not resolve executable "${command}" (spawn ENOENT).${hint}`;
|
|
44475
|
+
}
|
|
44476
|
+
return String(error?.message || error);
|
|
44477
|
+
}
|
|
44407
44478
|
function recordMeshRefineStage(stages, stage, status, startedAt, details) {
|
|
44408
44479
|
stages.push({
|
|
44409
44480
|
stage,
|
|
@@ -45305,8 +45376,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45305
45376
|
const startedAt = Date.now();
|
|
45306
45377
|
const cwd = candidate.cwd ? pathResolve2(workspace, candidate.cwd) : workspace;
|
|
45307
45378
|
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
45379
|
+
const resolvedCommand = resolveWin32Executable(candidate.command);
|
|
45308
45380
|
try {
|
|
45309
|
-
const result = await execFileAsync4(
|
|
45381
|
+
const result = await execFileAsync4(resolvedCommand, candidate.args, {
|
|
45310
45382
|
cwd,
|
|
45311
45383
|
encoding: "utf8",
|
|
45312
45384
|
timeout,
|
|
@@ -45315,16 +45387,17 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45315
45387
|
});
|
|
45316
45388
|
summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
|
|
45317
45389
|
} catch (error) {
|
|
45390
|
+
const spawnResolutionFailed = isSpawnResolutionError(error);
|
|
45318
45391
|
summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
|
|
45319
45392
|
exitCode: typeof error?.code === "number" ? error.code : null,
|
|
45320
45393
|
signal: typeof error?.signal === "string" ? error.signal : null,
|
|
45321
45394
|
timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
|
|
45322
|
-
failureKind: "dependency_bootstrap_failed"
|
|
45395
|
+
...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : { failureKind: "dependency_bootstrap_failed" }
|
|
45323
45396
|
}));
|
|
45324
|
-
summary.bootstrap = { stage: "failed", error:
|
|
45397
|
+
summary.bootstrap = { stage: "failed", error: describeSpawnError(error, candidate.command, spawnResolutionFailed) };
|
|
45325
45398
|
summary.status = "failed";
|
|
45326
|
-
summary.failureKind = "dependency_bootstrap_failed";
|
|
45327
|
-
summary.failureCode = "dependency_bootstrap_failed";
|
|
45399
|
+
summary.failureKind = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
|
|
45400
|
+
summary.failureCode = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
|
|
45328
45401
|
return summary;
|
|
45329
45402
|
}
|
|
45330
45403
|
}
|
|
@@ -45347,8 +45420,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45347
45420
|
summary.failureCode = "missing_dependencies";
|
|
45348
45421
|
return summary;
|
|
45349
45422
|
}
|
|
45423
|
+
const resolvedCommand = resolveWin32Executable(candidate.command);
|
|
45350
45424
|
try {
|
|
45351
|
-
const result = await execFileAsync4(
|
|
45425
|
+
const result = await execFileAsync4(resolvedCommand, candidate.args, {
|
|
45352
45426
|
cwd,
|
|
45353
45427
|
encoding: "utf8",
|
|
45354
45428
|
timeout,
|
|
@@ -45357,16 +45431,21 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45357
45431
|
});
|
|
45358
45432
|
summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
|
|
45359
45433
|
} catch (error) {
|
|
45434
|
+
const spawnResolutionFailed = isSpawnResolutionError(error);
|
|
45360
45435
|
const stderr = truncateValidationOutput(error?.stderr || error?.message);
|
|
45361
|
-
const missingDependencyFailure = /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
|
|
45436
|
+
const missingDependencyFailure = !spawnResolutionFailed && /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
|
|
45362
45437
|
summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
|
|
45363
45438
|
exitCode: typeof error?.code === "number" ? error.code : null,
|
|
45364
45439
|
signal: typeof error?.signal === "string" ? error.signal : null,
|
|
45365
45440
|
timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
|
|
45366
|
-
...missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
|
|
45441
|
+
...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
|
|
45367
45442
|
}));
|
|
45368
45443
|
summary.status = "failed";
|
|
45369
|
-
if (
|
|
45444
|
+
if (spawnResolutionFailed) {
|
|
45445
|
+
summary.failureKind = "spawn_resolution_failed";
|
|
45446
|
+
summary.failureCode = "spawn_resolution_failed";
|
|
45447
|
+
summary.spawnResolutionError = describeSpawnError(error, candidate.command, true);
|
|
45448
|
+
} else if (missingDependencyFailure) {
|
|
45370
45449
|
summary.failureKind = "missing_dependencies";
|
|
45371
45450
|
summary.failureCode = "missing_dependencies";
|
|
45372
45451
|
}
|
|
@@ -46627,7 +46706,7 @@ var DaemonCommandRouter = class {
|
|
|
46627
46706
|
if (validationSummary.status === "failed") {
|
|
46628
46707
|
const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
|
|
46629
46708
|
const buildValidationFailedError = () => {
|
|
46630
|
-
const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
|
|
46709
|
+
const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : validationSummary.failureCode === "spawn_resolution_failed" ? validationSummary.spawnResolutionError || "Refinery validation command could not be spawned (executable not found); merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
|
|
46631
46710
|
if (!firstFailedCmd) return base;
|
|
46632
46711
|
const cmdName = typeof firstFailedCmd.displayCommand === "string" ? firstFailedCmd.displayCommand : typeof firstFailedCmd.command === "string" ? [firstFailedCmd.command, ...Array.isArray(firstFailedCmd.args) ? firstFailedCmd.args : []].join(" ").trim() : typeof firstFailedCmd.cmd === "string" ? firstFailedCmd.cmd : "";
|
|
46633
46712
|
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
|