@adhdev/daemon-core 0.9.82-rc.333 → 0.9.82-rc.335
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/cli-adapters/provider-cli-adapter.d.ts +1 -0
- package/dist/commands/router.d.ts +10 -0
- package/dist/index.js +605 -509
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +596 -500
- 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/cli-adapters/provider-cli-adapter.ts +41 -1
- 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 ? "e9e62c9770c0f4a419a90f5287125f3d3bb0fd95" : void 0) ?? "unknown";
|
|
315
|
+
const commitShort = readInjected(true ? "e9e62c97" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
316
|
+
const version = readInjected(true ? "0.9.82-rc.335" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
317
|
+
const builtAt = readInjected(true ? "2026-06-20T04:30:54.863Z" : 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, {
|
|
@@ -15076,7 +15125,7 @@ function appendBoundedText(current, chunk, maxChars) {
|
|
|
15076
15125
|
if (current.length <= keepFromCurrent) return current + chunk;
|
|
15077
15126
|
return current.slice(-keepFromCurrent) + chunk;
|
|
15078
15127
|
}
|
|
15079
|
-
var ProviderCliAdapter;
|
|
15128
|
+
var FORCE_SUBMIT_SETTLE_MS, FORCE_SUBMIT_MAX_WAIT_MS, FORCE_SUBMIT_POLL_MS, ProviderCliAdapter;
|
|
15080
15129
|
var init_provider_cli_adapter = __esm({
|
|
15081
15130
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
15082
15131
|
"use strict";
|
|
@@ -15091,6 +15140,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
15091
15140
|
init_provider_cli_config();
|
|
15092
15141
|
init_provider_cli_runtime();
|
|
15093
15142
|
init_provider_cli_shared();
|
|
15143
|
+
FORCE_SUBMIT_SETTLE_MS = 150;
|
|
15144
|
+
FORCE_SUBMIT_MAX_WAIT_MS = 1500;
|
|
15145
|
+
FORCE_SUBMIT_POLL_MS = 50;
|
|
15094
15146
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
15095
15147
|
constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
|
|
15096
15148
|
this.extraArgs = extraArgs;
|
|
@@ -16019,9 +16071,23 @@ ${lastSnapshot}`;
|
|
|
16019
16071
|
return;
|
|
16020
16072
|
}
|
|
16021
16073
|
LOG.info("CLI", `[${this.cliType}] force-sending prompt while status=${this.engine.currentStatus}`);
|
|
16022
|
-
await this.writeToPty(content
|
|
16074
|
+
await this.writeToPty(content);
|
|
16075
|
+
await this.waitForForceSubmitSettle(content);
|
|
16076
|
+
await this.writeToPty(this.sendKey);
|
|
16023
16077
|
this.onStatusChange?.();
|
|
16024
16078
|
}
|
|
16079
|
+
async waitForForceSubmitSettle(content) {
|
|
16080
|
+
const startedAt = Date.now();
|
|
16081
|
+
const normalizedPromptSnippet = normalizePromptText(extractPromptRetrySnippet(content));
|
|
16082
|
+
await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_SETTLE_MS));
|
|
16083
|
+
if (!normalizedPromptSnippet) return;
|
|
16084
|
+
while (Date.now() - startedAt < FORCE_SUBMIT_MAX_WAIT_MS) {
|
|
16085
|
+
if (!this.ptyProcess) return;
|
|
16086
|
+
const screenText = this.terminalScreen.getText();
|
|
16087
|
+
if (promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
16088
|
+
await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_POLL_MS));
|
|
16089
|
+
}
|
|
16090
|
+
}
|
|
16025
16091
|
enqueuePendingOutboundMessage(text, reason) {
|
|
16026
16092
|
const content = String(text || "");
|
|
16027
16093
|
const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
|
|
@@ -19433,13 +19499,20 @@ var MESH_REFINE_CONFIG_SCHEMA = {
|
|
|
19433
19499
|
function isMeshConfigRecord(value) {
|
|
19434
19500
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
19435
19501
|
}
|
|
19502
|
+
var SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
|
|
19503
|
+
var SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
|
|
19504
|
+
var SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
|
|
19436
19505
|
function tokenizeCommandString(command) {
|
|
19437
19506
|
const trimmed = command.trim();
|
|
19438
19507
|
if (!trimmed) return null;
|
|
19439
|
-
if (
|
|
19508
|
+
if (SHELL_METACHAR_RE.test(trimmed)) return null;
|
|
19440
19509
|
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
19441
19510
|
if (!tokens.length) return null;
|
|
19442
|
-
|
|
19511
|
+
const isWin32 = process.platform === "win32";
|
|
19512
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
19513
|
+
const re = isWin32 && i === 0 ? SAFE_WIN32_EXEC_TOKEN_RE : SAFE_TOKEN_RE;
|
|
19514
|
+
if (!re.test(tokens[i])) return null;
|
|
19515
|
+
}
|
|
19443
19516
|
return tokens;
|
|
19444
19517
|
}
|
|
19445
19518
|
function validateCategory(value) {
|
|
@@ -19649,8 +19722,9 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
|
|
|
19649
19722
|
}
|
|
19650
19723
|
|
|
19651
19724
|
// src/mesh/worktree-bootstrap-config.ts
|
|
19652
|
-
|
|
19653
|
-
import {
|
|
19725
|
+
init_resolve_executable();
|
|
19726
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
|
|
19727
|
+
import { join as join14, resolve as pathResolve } from "path";
|
|
19654
19728
|
import { execFile as execFile3 } from "child_process";
|
|
19655
19729
|
import { createHash as createHash3 } from "crypto";
|
|
19656
19730
|
import { promisify as promisify3 } from "util";
|
|
@@ -19741,8 +19815,8 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
19741
19815
|
return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
|
|
19742
19816
|
}
|
|
19743
19817
|
for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
|
|
19744
|
-
const configPath =
|
|
19745
|
-
if (!
|
|
19818
|
+
const configPath = join14(workspace, relative5);
|
|
19819
|
+
if (!existsSync13(configPath)) continue;
|
|
19746
19820
|
try {
|
|
19747
19821
|
const parsed = parseConfigText3(configPath, readFileSync10(configPath, "utf-8"));
|
|
19748
19822
|
const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
|
|
@@ -19757,7 +19831,7 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
19757
19831
|
function computeStaleInputsDigest(workspace, staleInputs) {
|
|
19758
19832
|
const digest = {};
|
|
19759
19833
|
for (const relative5 of staleInputs ?? []) {
|
|
19760
|
-
const filePath =
|
|
19834
|
+
const filePath = join14(workspace, relative5);
|
|
19761
19835
|
try {
|
|
19762
19836
|
digest[relative5] = createHash3("sha256").update(readFileSync10(filePath)).digest("hex");
|
|
19763
19837
|
} catch {
|
|
@@ -19829,10 +19903,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
19829
19903
|
staleInputs: loaded.config.staleInputs
|
|
19830
19904
|
};
|
|
19831
19905
|
const staleInputPaths = loaded.config.staleInputs ?? [];
|
|
19832
|
-
const initiallyAbsent = staleInputPaths.filter((p) => !
|
|
19906
|
+
const initiallyAbsent = staleInputPaths.filter((p) => !existsSync13(join14(workspace, p)));
|
|
19833
19907
|
for (const command of validation.commands) {
|
|
19834
19908
|
if (initiallyAbsent.length > 0) {
|
|
19835
|
-
const appearedNow = initiallyAbsent.filter((p) =>
|
|
19909
|
+
const appearedNow = initiallyAbsent.filter((p) => existsSync13(join14(workspace, p)));
|
|
19836
19910
|
if (appearedNow.length > 0) {
|
|
19837
19911
|
state.status = "stale";
|
|
19838
19912
|
state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -19843,8 +19917,9 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
19843
19917
|
const cwd = command.cwd ? pathResolve(workspace, command.cwd) : workspace;
|
|
19844
19918
|
const startedAt = Date.now();
|
|
19845
19919
|
state.lastCommand = command.displayCommand;
|
|
19920
|
+
const resolvedCommand = resolveWin32Executable(command.command);
|
|
19846
19921
|
try {
|
|
19847
|
-
const result = await execFileAsync4(
|
|
19922
|
+
const result = await execFileAsync4(resolvedCommand, command.args, {
|
|
19848
19923
|
cwd,
|
|
19849
19924
|
encoding: "utf8",
|
|
19850
19925
|
timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
|
|
@@ -20080,8 +20155,8 @@ var P2pRelayFailureError = class extends Error {
|
|
|
20080
20155
|
|
|
20081
20156
|
// src/config/state-store.ts
|
|
20082
20157
|
init_config();
|
|
20083
|
-
import { existsSync as
|
|
20084
|
-
import { join as
|
|
20158
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
|
|
20159
|
+
import { join as join18 } from "path";
|
|
20085
20160
|
var DEFAULT_STATE = {
|
|
20086
20161
|
recentActivity: [],
|
|
20087
20162
|
savedProviderSessions: [],
|
|
@@ -20094,7 +20169,7 @@ function isPlainObject2(value) {
|
|
|
20094
20169
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
20095
20170
|
}
|
|
20096
20171
|
function getStatePath() {
|
|
20097
|
-
return
|
|
20172
|
+
return join18(getConfigDir(), "state.json");
|
|
20098
20173
|
}
|
|
20099
20174
|
function normalizeState(raw) {
|
|
20100
20175
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -20130,7 +20205,7 @@ function normalizeState(raw) {
|
|
|
20130
20205
|
}
|
|
20131
20206
|
function loadState() {
|
|
20132
20207
|
const statePath = getStatePath();
|
|
20133
|
-
if (!
|
|
20208
|
+
if (!existsSync17(statePath)) {
|
|
20134
20209
|
return { ...DEFAULT_STATE };
|
|
20135
20210
|
}
|
|
20136
20211
|
try {
|
|
@@ -20152,19 +20227,19 @@ function resetState() {
|
|
|
20152
20227
|
// src/detection/ide-detector.ts
|
|
20153
20228
|
import { exec as exec2 } from "child_process";
|
|
20154
20229
|
import { promisify as promisify4 } from "util";
|
|
20155
|
-
import { existsSync as
|
|
20230
|
+
import { existsSync as existsSync19, statSync as statSync8 } from "fs";
|
|
20156
20231
|
import { platform as platform3, homedir as homedir8 } from "os";
|
|
20157
|
-
import * as
|
|
20232
|
+
import * as path14 from "path";
|
|
20158
20233
|
|
|
20159
20234
|
// src/detection/win32-ide-version.ts
|
|
20160
20235
|
import * as fs5 from "fs";
|
|
20161
|
-
import * as
|
|
20236
|
+
import * as path13 from "path";
|
|
20162
20237
|
function manifestCandidates(exeDir) {
|
|
20163
20238
|
return [
|
|
20164
|
-
|
|
20165
|
-
|
|
20239
|
+
path13.join(exeDir, "resources", "app", "product.json"),
|
|
20240
|
+
path13.join(exeDir, "resources", "app", "package.json"),
|
|
20166
20241
|
// Some packagings keep product.json one level up.
|
|
20167
|
-
|
|
20242
|
+
path13.join(exeDir, "product.json")
|
|
20168
20243
|
];
|
|
20169
20244
|
}
|
|
20170
20245
|
function parseVersionFromManifest(raw) {
|
|
@@ -20182,9 +20257,9 @@ function readWin32IdeVersionFromDisk(exePath) {
|
|
|
20182
20257
|
if (!exePath) return null;
|
|
20183
20258
|
let exeDir;
|
|
20184
20259
|
try {
|
|
20185
|
-
exeDir = fs5.statSync(exePath).isDirectory() ? exePath :
|
|
20260
|
+
exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path13.dirname(exePath);
|
|
20186
20261
|
} catch {
|
|
20187
|
-
exeDir =
|
|
20262
|
+
exeDir = path13.dirname(exePath);
|
|
20188
20263
|
}
|
|
20189
20264
|
for (const candidate of manifestCandidates(exeDir)) {
|
|
20190
20265
|
try {
|
|
@@ -20198,7 +20273,7 @@ function readWin32IdeVersionFromDisk(exePath) {
|
|
|
20198
20273
|
}
|
|
20199
20274
|
function isKnownWin32GuiExe(binPath, win32ProcessNames) {
|
|
20200
20275
|
if (!binPath) return false;
|
|
20201
|
-
const base =
|
|
20276
|
+
const base = path13.win32.basename(binPath).toLowerCase();
|
|
20202
20277
|
if (!base.endsWith(".exe")) return false;
|
|
20203
20278
|
for (const names of Object.values(win32ProcessNames)) {
|
|
20204
20279
|
for (const name of names) {
|
|
@@ -20230,10 +20305,10 @@ function getMergedDefinitions() {
|
|
|
20230
20305
|
function findCliCommand(command) {
|
|
20231
20306
|
const trimmed = String(command || "").trim();
|
|
20232
20307
|
if (!trimmed) return null;
|
|
20233
|
-
if (
|
|
20234
|
-
const candidate = trimmed.startsWith("~") ?
|
|
20235
|
-
const resolved =
|
|
20236
|
-
return
|
|
20308
|
+
if (path14.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
20309
|
+
const candidate = trimmed.startsWith("~") ? path14.join(homedir8(), trimmed.slice(1)) : trimmed;
|
|
20310
|
+
const resolved = path14.isAbsolute(candidate) ? candidate : path14.resolve(candidate);
|
|
20311
|
+
return existsSync19(resolved) ? resolved : null;
|
|
20237
20312
|
}
|
|
20238
20313
|
const isWin = platform3() === "win32";
|
|
20239
20314
|
const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
|
|
@@ -20241,9 +20316,9 @@ function findCliCommand(command) {
|
|
|
20241
20316
|
for (const p of paths) {
|
|
20242
20317
|
if (!p) continue;
|
|
20243
20318
|
for (const ext of exes) {
|
|
20244
|
-
const fullPath =
|
|
20319
|
+
const fullPath = path14.join(p, trimmed + ext);
|
|
20245
20320
|
try {
|
|
20246
|
-
if (
|
|
20321
|
+
if (existsSync19(fullPath)) {
|
|
20247
20322
|
const stat2 = statSync8(fullPath);
|
|
20248
20323
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
20249
20324
|
return fullPath;
|
|
@@ -20258,13 +20333,13 @@ function findCliCommand(command) {
|
|
|
20258
20333
|
function checkPathExists(paths) {
|
|
20259
20334
|
const home = homedir8();
|
|
20260
20335
|
for (const p of paths) {
|
|
20261
|
-
const normalized = p.startsWith("~") ?
|
|
20336
|
+
const normalized = p.startsWith("~") ? path14.join(home, p.slice(1)) : p;
|
|
20262
20337
|
if (normalized.includes("*")) {
|
|
20263
20338
|
const username = home.split(/[\\/]/).pop() || "";
|
|
20264
20339
|
const resolved = normalized.replace("*", username);
|
|
20265
|
-
if (
|
|
20340
|
+
if (existsSync19(resolved)) return resolved;
|
|
20266
20341
|
} else {
|
|
20267
|
-
if (
|
|
20342
|
+
if (existsSync19(normalized)) return normalized;
|
|
20268
20343
|
}
|
|
20269
20344
|
}
|
|
20270
20345
|
return null;
|
|
@@ -20278,7 +20353,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20278
20353
|
let resolvedCli = cliPath;
|
|
20279
20354
|
if (!resolvedCli && appPath && os30 === "darwin") {
|
|
20280
20355
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
20281
|
-
if (
|
|
20356
|
+
if (existsSync19(bundledCli)) resolvedCli = bundledCli;
|
|
20282
20357
|
}
|
|
20283
20358
|
if (!resolvedCli && appPath && os30 === "win32") {
|
|
20284
20359
|
const { dirname: dirname17 } = await import("path");
|
|
@@ -20291,7 +20366,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20291
20366
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
20292
20367
|
];
|
|
20293
20368
|
for (const c of candidates) {
|
|
20294
|
-
if (
|
|
20369
|
+
if (existsSync19(c)) {
|
|
20295
20370
|
resolvedCli = c;
|
|
20296
20371
|
break;
|
|
20297
20372
|
}
|
|
@@ -22150,9 +22225,9 @@ ${cleanBody}`;
|
|
|
22150
22225
|
// src/config/chat-history.ts
|
|
22151
22226
|
init_chat_message_normalization();
|
|
22152
22227
|
import * as fs6 from "fs";
|
|
22153
|
-
import * as
|
|
22228
|
+
import * as path15 from "path";
|
|
22154
22229
|
import * as os8 from "os";
|
|
22155
|
-
var HISTORY_DIR =
|
|
22230
|
+
var HISTORY_DIR = path15.join(os8.homedir(), ".adhdev", "history");
|
|
22156
22231
|
var RETAIN_DAYS = 30;
|
|
22157
22232
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
22158
22233
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -22338,7 +22413,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
22338
22413
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
22339
22414
|
return new Map(files.map((file) => {
|
|
22340
22415
|
try {
|
|
22341
|
-
const stat2 = fs6.statSync(
|
|
22416
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22342
22417
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
22343
22418
|
} catch {
|
|
22344
22419
|
return [file, `${file}:missing`];
|
|
@@ -22349,7 +22424,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
22349
22424
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
22350
22425
|
}
|
|
22351
22426
|
function getSavedHistoryIndexFilePath(dir) {
|
|
22352
|
-
return
|
|
22427
|
+
return path15.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
22353
22428
|
}
|
|
22354
22429
|
function getSavedHistoryIndexLockPath(dir) {
|
|
22355
22430
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -22451,7 +22526,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
22451
22526
|
}
|
|
22452
22527
|
for (const file of Array.from(currentEntries.keys())) {
|
|
22453
22528
|
if (incomingFiles.has(file)) continue;
|
|
22454
|
-
if (!fs6.existsSync(
|
|
22529
|
+
if (!fs6.existsSync(path15.join(dir, file))) {
|
|
22455
22530
|
currentEntries.delete(file);
|
|
22456
22531
|
}
|
|
22457
22532
|
}
|
|
@@ -22477,7 +22552,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
22477
22552
|
const indexStat = fs6.statSync(getSavedHistoryIndexFilePath(dir));
|
|
22478
22553
|
const files = listHistoryFiles(dir);
|
|
22479
22554
|
for (const file of files) {
|
|
22480
|
-
const stat2 = fs6.statSync(
|
|
22555
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22481
22556
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
22482
22557
|
}
|
|
22483
22558
|
return false;
|
|
@@ -22487,14 +22562,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
22487
22562
|
}
|
|
22488
22563
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
22489
22564
|
try {
|
|
22490
|
-
const stat2 = fs6.statSync(
|
|
22565
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22491
22566
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
22492
22567
|
} catch {
|
|
22493
22568
|
return `${file}:missing`;
|
|
22494
22569
|
}
|
|
22495
22570
|
}
|
|
22496
22571
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
22497
|
-
const filePath =
|
|
22572
|
+
const filePath = path15.join(dir, file);
|
|
22498
22573
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
22499
22574
|
const currentEntry = entries.get(file) || null;
|
|
22500
22575
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -22567,7 +22642,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
22567
22642
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
22568
22643
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
22569
22644
|
if (!historySessionId) return null;
|
|
22570
|
-
const filePath =
|
|
22645
|
+
const filePath = path15.join(dir, file);
|
|
22571
22646
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
22572
22647
|
const lines = content.split("\n").filter(Boolean);
|
|
22573
22648
|
let messageCount = 0;
|
|
@@ -22654,7 +22729,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
22654
22729
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
22655
22730
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
22656
22731
|
for (const file of files.slice().sort()) {
|
|
22657
|
-
const filePath =
|
|
22732
|
+
const filePath = path15.join(dir, file);
|
|
22658
22733
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
22659
22734
|
const cached3 = savedHistoryFileSummaryCache.get(filePath);
|
|
22660
22735
|
const persisted = persistedEntries.get(file);
|
|
@@ -22774,12 +22849,12 @@ var ChatHistoryWriter = class {
|
|
|
22774
22849
|
});
|
|
22775
22850
|
}
|
|
22776
22851
|
if (newMessages.length === 0) return;
|
|
22777
|
-
const dir =
|
|
22852
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22778
22853
|
fs6.mkdirSync(dir, { recursive: true });
|
|
22779
22854
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
22780
22855
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
22781
22856
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
22782
|
-
const filePath =
|
|
22857
|
+
const filePath = path15.join(dir, fileName);
|
|
22783
22858
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
22784
22859
|
fs6.appendFileSync(filePath, lines, "utf-8");
|
|
22785
22860
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -22870,11 +22945,11 @@ var ChatHistoryWriter = class {
|
|
|
22870
22945
|
const ws = String(workspace || "").trim();
|
|
22871
22946
|
if (!id || !ws) return;
|
|
22872
22947
|
try {
|
|
22873
|
-
const dir =
|
|
22948
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22874
22949
|
fs6.mkdirSync(dir, { recursive: true });
|
|
22875
22950
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
22876
22951
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
22877
|
-
const filePath =
|
|
22952
|
+
const filePath = path15.join(dir, fileName);
|
|
22878
22953
|
const record = {
|
|
22879
22954
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22880
22955
|
receivedAt: Date.now(),
|
|
@@ -22920,14 +22995,14 @@ var ChatHistoryWriter = class {
|
|
|
22920
22995
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
22921
22996
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
22922
22997
|
}
|
|
22923
|
-
const dir =
|
|
22998
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22924
22999
|
if (!fs6.existsSync(dir)) return;
|
|
22925
23000
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
22926
23001
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
22927
23002
|
const files = fs6.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
22928
23003
|
for (const file of files) {
|
|
22929
|
-
const sourcePath =
|
|
22930
|
-
const targetPath =
|
|
23004
|
+
const sourcePath = path15.join(dir, file);
|
|
23005
|
+
const targetPath = path15.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
22931
23006
|
const sourceLines = fs6.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
22932
23007
|
const rewritten = sourceLines.map((line) => {
|
|
22933
23008
|
try {
|
|
@@ -22961,13 +23036,13 @@ var ChatHistoryWriter = class {
|
|
|
22961
23036
|
const sessionId = String(historySessionId || "").trim();
|
|
22962
23037
|
if (!sessionId) return;
|
|
22963
23038
|
try {
|
|
22964
|
-
const dir =
|
|
23039
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
22965
23040
|
if (!fs6.existsSync(dir)) return;
|
|
22966
23041
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
22967
23042
|
const files = fs6.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
22968
23043
|
const seen = /* @__PURE__ */ new Set();
|
|
22969
23044
|
for (const file of files) {
|
|
22970
|
-
const filePath =
|
|
23045
|
+
const filePath = path15.join(dir, file);
|
|
22971
23046
|
const lines = fs6.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
22972
23047
|
const next = [];
|
|
22973
23048
|
for (const line of lines) {
|
|
@@ -23021,11 +23096,11 @@ var ChatHistoryWriter = class {
|
|
|
23021
23096
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
23022
23097
|
const agentDirs = fs6.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
23023
23098
|
for (const dir of agentDirs) {
|
|
23024
|
-
const dirPath =
|
|
23099
|
+
const dirPath = path15.join(HISTORY_DIR, dir.name);
|
|
23025
23100
|
const files = fs6.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
23026
23101
|
let removedAny = false;
|
|
23027
23102
|
for (const file of files) {
|
|
23028
|
-
const filePath =
|
|
23103
|
+
const filePath = path15.join(dirPath, file);
|
|
23029
23104
|
const stat2 = fs6.statSync(filePath);
|
|
23030
23105
|
if (stat2.mtimeMs < cutoff) {
|
|
23031
23106
|
fs6.unlinkSync(filePath);
|
|
@@ -23228,7 +23303,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
|
23228
23303
|
const seen = /* @__PURE__ */ new Set();
|
|
23229
23304
|
let readAllFiles = true;
|
|
23230
23305
|
for (let f = 0; f < files.length; f++) {
|
|
23231
|
-
const filePath =
|
|
23306
|
+
const filePath = path15.join(dir, files[f]);
|
|
23232
23307
|
const remaining = Math.max(0, needed - collected.length);
|
|
23233
23308
|
const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
|
|
23234
23309
|
const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
|
|
@@ -23261,7 +23336,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
|
23261
23336
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
23262
23337
|
try {
|
|
23263
23338
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
23264
|
-
const dir =
|
|
23339
|
+
const dir = path15.join(HISTORY_DIR, sanitized);
|
|
23265
23340
|
if (!fs6.existsSync(dir)) return { messages: [], hasMore: false };
|
|
23266
23341
|
const files = listHistoryFiles(dir, historySessionId);
|
|
23267
23342
|
const bounded = isBoundedTailRequest(limit, offset, excludeRecentCount);
|
|
@@ -23284,7 +23359,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
23284
23359
|
const allMessages = [];
|
|
23285
23360
|
const seen = /* @__PURE__ */ new Set();
|
|
23286
23361
|
for (const file of files) {
|
|
23287
|
-
const filePath =
|
|
23362
|
+
const filePath = path15.join(dir, file);
|
|
23288
23363
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
23289
23364
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
23290
23365
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -23308,7 +23383,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
23308
23383
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
23309
23384
|
try {
|
|
23310
23385
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
23311
|
-
const dir =
|
|
23386
|
+
const dir = path15.join(HISTORY_DIR, sanitized);
|
|
23312
23387
|
if (!fs6.existsSync(dir)) {
|
|
23313
23388
|
savedHistorySessionCache.delete(sanitized);
|
|
23314
23389
|
return { sessions: [], hasMore: false };
|
|
@@ -23369,11 +23444,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
23369
23444
|
}
|
|
23370
23445
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
23371
23446
|
try {
|
|
23372
|
-
const dir =
|
|
23447
|
+
const dir = path15.join(HISTORY_DIR, agentType);
|
|
23373
23448
|
if (!fs6.existsSync(dir)) return null;
|
|
23374
23449
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
23375
23450
|
for (const file of files) {
|
|
23376
|
-
const lines = fs6.readFileSync(
|
|
23451
|
+
const lines = fs6.readFileSync(path15.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
23377
23452
|
for (const line of lines) {
|
|
23378
23453
|
try {
|
|
23379
23454
|
const parsed = JSON.parse(line);
|
|
@@ -23393,16 +23468,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
23393
23468
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
23394
23469
|
if (records.length === 0) return false;
|
|
23395
23470
|
try {
|
|
23396
|
-
const dir =
|
|
23471
|
+
const dir = path15.join(HISTORY_DIR, agentType);
|
|
23397
23472
|
fs6.mkdirSync(dir, { recursive: true });
|
|
23398
23473
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
23399
23474
|
for (const file of fs6.readdirSync(dir)) {
|
|
23400
23475
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
23401
|
-
fs6.unlinkSync(
|
|
23476
|
+
fs6.unlinkSync(path15.join(dir, file));
|
|
23402
23477
|
}
|
|
23403
23478
|
}
|
|
23404
23479
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
23405
|
-
const filePath =
|
|
23480
|
+
const filePath = path15.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
23406
23481
|
fs6.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
23407
23482
|
`, "utf-8");
|
|
23408
23483
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -26008,7 +26083,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
26008
26083
|
init_contracts();
|
|
26009
26084
|
import * as fs7 from "fs";
|
|
26010
26085
|
import * as os9 from "os";
|
|
26011
|
-
import * as
|
|
26086
|
+
import * as path16 from "path";
|
|
26012
26087
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
26013
26088
|
init_logger();
|
|
26014
26089
|
|
|
@@ -27058,7 +27133,7 @@ function readExactRuntimeMirrorMessages(args) {
|
|
|
27058
27133
|
function normalizeComparableWorkspace(value) {
|
|
27059
27134
|
const text = typeof value === "string" ? value.trim() : "";
|
|
27060
27135
|
if (!text) return "";
|
|
27061
|
-
return
|
|
27136
|
+
return path16.resolve(text);
|
|
27062
27137
|
}
|
|
27063
27138
|
function isCurrentRuntimePtySafelyAttributed(args) {
|
|
27064
27139
|
if (args.adapter.cliType !== "codex-cli") return false;
|
|
@@ -27543,7 +27618,7 @@ function buildDebugBundleText(bundle) {
|
|
|
27543
27618
|
}
|
|
27544
27619
|
function getChatDebugBundleDir() {
|
|
27545
27620
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
27546
|
-
return override ||
|
|
27621
|
+
return override || path16.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
27547
27622
|
}
|
|
27548
27623
|
function safeBundleIdSegment(value, fallback) {
|
|
27549
27624
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -27600,7 +27675,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
27600
27675
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
27601
27676
|
const dir = getChatDebugBundleDir();
|
|
27602
27677
|
fs7.mkdirSync(dir, { recursive: true });
|
|
27603
|
-
const savedPath =
|
|
27678
|
+
const savedPath = path16.join(dir, `${bundleId}.json`);
|
|
27604
27679
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
27605
27680
|
`;
|
|
27606
27681
|
fs7.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -29164,7 +29239,7 @@ async function handleResolveAction(h, args) {
|
|
|
29164
29239
|
|
|
29165
29240
|
// src/commands/cdp-commands.ts
|
|
29166
29241
|
import * as fs8 from "fs";
|
|
29167
|
-
import * as
|
|
29242
|
+
import * as path17 from "path";
|
|
29168
29243
|
import * as os10 from "os";
|
|
29169
29244
|
var KEY_TO_VK = {
|
|
29170
29245
|
Backspace: 8,
|
|
@@ -29421,25 +29496,25 @@ function resolveSafePath(requestedPath) {
|
|
|
29421
29496
|
const inputPath = rawPath || ".";
|
|
29422
29497
|
const home = os10.homedir();
|
|
29423
29498
|
if (inputPath.startsWith("~")) {
|
|
29424
|
-
return
|
|
29499
|
+
return path17.resolve(path17.join(home, inputPath.slice(1)));
|
|
29425
29500
|
}
|
|
29426
29501
|
if (process.platform === "win32") {
|
|
29427
29502
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
29428
|
-
if (
|
|
29429
|
-
return
|
|
29503
|
+
if (path17.win32.isAbsolute(normalized)) {
|
|
29504
|
+
return path17.win32.normalize(normalized);
|
|
29430
29505
|
}
|
|
29431
|
-
return
|
|
29506
|
+
return path17.win32.resolve(normalized);
|
|
29432
29507
|
}
|
|
29433
|
-
if (
|
|
29434
|
-
return
|
|
29508
|
+
if (path17.isAbsolute(inputPath)) {
|
|
29509
|
+
return path17.normalize(inputPath);
|
|
29435
29510
|
}
|
|
29436
|
-
return
|
|
29511
|
+
return path17.resolve(inputPath);
|
|
29437
29512
|
}
|
|
29438
29513
|
function listDirectoryEntriesSafe(dirPath) {
|
|
29439
29514
|
const entries = fs8.readdirSync(dirPath, { withFileTypes: true });
|
|
29440
29515
|
const files = [];
|
|
29441
29516
|
for (const entry of entries) {
|
|
29442
|
-
const entryPath =
|
|
29517
|
+
const entryPath = path17.join(dirPath, entry.name);
|
|
29443
29518
|
try {
|
|
29444
29519
|
if (entry.isDirectory()) {
|
|
29445
29520
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -29493,7 +29568,7 @@ async function handleFileRead(h, args) {
|
|
|
29493
29568
|
async function handleFileWrite(h, args) {
|
|
29494
29569
|
try {
|
|
29495
29570
|
const filePath = resolveSafePath(args?.path);
|
|
29496
|
-
fs8.mkdirSync(
|
|
29571
|
+
fs8.mkdirSync(path17.dirname(filePath), { recursive: true });
|
|
29497
29572
|
fs8.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
29498
29573
|
return { success: true, path: filePath };
|
|
29499
29574
|
} catch (e) {
|
|
@@ -43306,6 +43381,7 @@ import { homedir as homedir26, hostname as osHostname } from "os";
|
|
|
43306
43381
|
import { basename as pathBasename, join as pathJoin, resolve as pathResolve2 } from "path";
|
|
43307
43382
|
import * as fs26 from "fs";
|
|
43308
43383
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
43384
|
+
init_resolve_executable();
|
|
43309
43385
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
43310
43386
|
var CHANNEL_SERVER_URL = {
|
|
43311
43387
|
stable: "https://api.adhf.dev",
|
|
@@ -44404,6 +44480,18 @@ function truncateValidationOutput(value) {
|
|
|
44404
44480
|
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
44405
44481
|
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
44406
44482
|
}
|
|
44483
|
+
function isSpawnResolutionError(error) {
|
|
44484
|
+
if (!error) return false;
|
|
44485
|
+
if (error.code === "ENOENT" && typeof error.syscall === "string" && error.syscall.startsWith("spawn")) return true;
|
|
44486
|
+
return error.code === "ENOENT" && (error.syscall === void 0 || String(error.syscall).startsWith("spawn"));
|
|
44487
|
+
}
|
|
44488
|
+
function describeSpawnError(error, command, spawnResolutionFailed) {
|
|
44489
|
+
if (spawnResolutionFailed) {
|
|
44490
|
+
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." : "";
|
|
44491
|
+
return `Could not resolve executable "${command}" (spawn ENOENT).${hint}`;
|
|
44492
|
+
}
|
|
44493
|
+
return String(error?.message || error);
|
|
44494
|
+
}
|
|
44407
44495
|
function recordMeshRefineStage(stages, stage, status, startedAt, details) {
|
|
44408
44496
|
stages.push({
|
|
44409
44497
|
stage,
|
|
@@ -45305,8 +45393,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45305
45393
|
const startedAt = Date.now();
|
|
45306
45394
|
const cwd = candidate.cwd ? pathResolve2(workspace, candidate.cwd) : workspace;
|
|
45307
45395
|
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
45396
|
+
const resolvedCommand = resolveWin32Executable(candidate.command);
|
|
45308
45397
|
try {
|
|
45309
|
-
const result = await execFileAsync4(
|
|
45398
|
+
const result = await execFileAsync4(resolvedCommand, candidate.args, {
|
|
45310
45399
|
cwd,
|
|
45311
45400
|
encoding: "utf8",
|
|
45312
45401
|
timeout,
|
|
@@ -45315,16 +45404,17 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45315
45404
|
});
|
|
45316
45405
|
summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
|
|
45317
45406
|
} catch (error) {
|
|
45407
|
+
const spawnResolutionFailed = isSpawnResolutionError(error);
|
|
45318
45408
|
summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
|
|
45319
45409
|
exitCode: typeof error?.code === "number" ? error.code : null,
|
|
45320
45410
|
signal: typeof error?.signal === "string" ? error.signal : null,
|
|
45321
45411
|
timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
|
|
45322
|
-
failureKind: "dependency_bootstrap_failed"
|
|
45412
|
+
...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : { failureKind: "dependency_bootstrap_failed" }
|
|
45323
45413
|
}));
|
|
45324
|
-
summary.bootstrap = { stage: "failed", error:
|
|
45414
|
+
summary.bootstrap = { stage: "failed", error: describeSpawnError(error, candidate.command, spawnResolutionFailed) };
|
|
45325
45415
|
summary.status = "failed";
|
|
45326
|
-
summary.failureKind = "dependency_bootstrap_failed";
|
|
45327
|
-
summary.failureCode = "dependency_bootstrap_failed";
|
|
45416
|
+
summary.failureKind = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
|
|
45417
|
+
summary.failureCode = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
|
|
45328
45418
|
return summary;
|
|
45329
45419
|
}
|
|
45330
45420
|
}
|
|
@@ -45347,8 +45437,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45347
45437
|
summary.failureCode = "missing_dependencies";
|
|
45348
45438
|
return summary;
|
|
45349
45439
|
}
|
|
45440
|
+
const resolvedCommand = resolveWin32Executable(candidate.command);
|
|
45350
45441
|
try {
|
|
45351
|
-
const result = await execFileAsync4(
|
|
45442
|
+
const result = await execFileAsync4(resolvedCommand, candidate.args, {
|
|
45352
45443
|
cwd,
|
|
45353
45444
|
encoding: "utf8",
|
|
45354
45445
|
timeout,
|
|
@@ -45357,16 +45448,21 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45357
45448
|
});
|
|
45358
45449
|
summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
|
|
45359
45450
|
} catch (error) {
|
|
45451
|
+
const spawnResolutionFailed = isSpawnResolutionError(error);
|
|
45360
45452
|
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);
|
|
45453
|
+
const missingDependencyFailure = !spawnResolutionFailed && /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
|
|
45362
45454
|
summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
|
|
45363
45455
|
exitCode: typeof error?.code === "number" ? error.code : null,
|
|
45364
45456
|
signal: typeof error?.signal === "string" ? error.signal : null,
|
|
45365
45457
|
timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
|
|
45366
|
-
...missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
|
|
45458
|
+
...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
|
|
45367
45459
|
}));
|
|
45368
45460
|
summary.status = "failed";
|
|
45369
|
-
if (
|
|
45461
|
+
if (spawnResolutionFailed) {
|
|
45462
|
+
summary.failureKind = "spawn_resolution_failed";
|
|
45463
|
+
summary.failureCode = "spawn_resolution_failed";
|
|
45464
|
+
summary.spawnResolutionError = describeSpawnError(error, candidate.command, true);
|
|
45465
|
+
} else if (missingDependencyFailure) {
|
|
45370
45466
|
summary.failureKind = "missing_dependencies";
|
|
45371
45467
|
summary.failureCode = "missing_dependencies";
|
|
45372
45468
|
}
|
|
@@ -46627,7 +46723,7 @@ var DaemonCommandRouter = class {
|
|
|
46627
46723
|
if (validationSummary.status === "failed") {
|
|
46628
46724
|
const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
|
|
46629
46725
|
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.";
|
|
46726
|
+
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
46727
|
if (!firstFailedCmd) return base;
|
|
46632
46728
|
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
46729
|
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
|