@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.js
CHANGED
|
@@ -316,10 +316,10 @@ function readInjected(value) {
|
|
|
316
316
|
}
|
|
317
317
|
function getDaemonBuildInfo() {
|
|
318
318
|
if (cached) return cached;
|
|
319
|
-
const commit = readInjected(true ? "
|
|
320
|
-
const commitShort = readInjected(true ? "
|
|
321
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
322
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
319
|
+
const commit = readInjected(true ? "e9e62c9770c0f4a419a90f5287125f3d3bb0fd95" : void 0) ?? "unknown";
|
|
320
|
+
const commitShort = readInjected(true ? "e9e62c97" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
321
|
+
const version = readInjected(true ? "0.9.82-rc.335" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
322
|
+
const builtAt = readInjected(true ? "2026-06-20T04:30:54.863Z" : void 0);
|
|
323
323
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
324
324
|
return cached;
|
|
325
325
|
}
|
|
@@ -3260,6 +3260,297 @@ var init_mesh_ledger = __esm({
|
|
|
3260
3260
|
}
|
|
3261
3261
|
});
|
|
3262
3262
|
|
|
3263
|
+
// src/logging/async-batch-writer.ts
|
|
3264
|
+
var fs3, AsyncBatchWriter;
|
|
3265
|
+
var init_async_batch_writer = __esm({
|
|
3266
|
+
"src/logging/async-batch-writer.ts"() {
|
|
3267
|
+
"use strict";
|
|
3268
|
+
fs3 = __toESM(require("fs"));
|
|
3269
|
+
AsyncBatchWriter = class {
|
|
3270
|
+
// Maps filePath -> string buffer
|
|
3271
|
+
static buffers = /* @__PURE__ */ new Map();
|
|
3272
|
+
static writePromises = /* @__PURE__ */ new Map();
|
|
3273
|
+
static flushTimer = null;
|
|
3274
|
+
/**
|
|
3275
|
+
* Queues data to be written to a file asynchronously in a batch.
|
|
3276
|
+
*/
|
|
3277
|
+
static write(filePath, data) {
|
|
3278
|
+
let buf = this.buffers.get(filePath);
|
|
3279
|
+
if (!buf) {
|
|
3280
|
+
buf = [];
|
|
3281
|
+
this.buffers.set(filePath, buf);
|
|
3282
|
+
}
|
|
3283
|
+
buf.push(data);
|
|
3284
|
+
if (!this.flushTimer) {
|
|
3285
|
+
this.flushTimer = setTimeout(() => {
|
|
3286
|
+
this.flushTimer = null;
|
|
3287
|
+
this.flushAll();
|
|
3288
|
+
}, 50);
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
static async flushAll() {
|
|
3292
|
+
const entries = Array.from(this.buffers.entries());
|
|
3293
|
+
this.buffers.clear();
|
|
3294
|
+
for (const [filePath, buffer] of entries) {
|
|
3295
|
+
const dataToWrite = buffer.join("");
|
|
3296
|
+
const doWrite = async () => {
|
|
3297
|
+
try {
|
|
3298
|
+
const prevPromise = this.writePromises.get(filePath);
|
|
3299
|
+
if (prevPromise) await prevPromise;
|
|
3300
|
+
await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
|
|
3301
|
+
} catch {
|
|
3302
|
+
}
|
|
3303
|
+
};
|
|
3304
|
+
const writePromise = doWrite();
|
|
3305
|
+
this.writePromises.set(filePath, writePromise);
|
|
3306
|
+
writePromise.finally(() => {
|
|
3307
|
+
if (this.writePromises.get(filePath) === writePromise) {
|
|
3308
|
+
this.writePromises.delete(filePath);
|
|
3309
|
+
}
|
|
3310
|
+
});
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
});
|
|
3316
|
+
|
|
3317
|
+
// src/logging/logger.ts
|
|
3318
|
+
var logger_exports = {};
|
|
3319
|
+
__export(logger_exports, {
|
|
3320
|
+
LOG: () => LOG,
|
|
3321
|
+
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
3322
|
+
LOG_PATH: () => LOG_PATH,
|
|
3323
|
+
daemonLog: () => daemonLog,
|
|
3324
|
+
getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
|
|
3325
|
+
getDaemonLogDir: () => getDaemonLogDir,
|
|
3326
|
+
getLogBufferSize: () => getLogBufferSize,
|
|
3327
|
+
getLogLevel: () => getLogLevel,
|
|
3328
|
+
getLogPath: () => getLogPath,
|
|
3329
|
+
getRecentLogs: () => getRecentLogs,
|
|
3330
|
+
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
3331
|
+
setLogLevel: () => setLogLevel
|
|
3332
|
+
});
|
|
3333
|
+
function setLogLevel(level) {
|
|
3334
|
+
currentLevel = level;
|
|
3335
|
+
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
3336
|
+
}
|
|
3337
|
+
function getLogLevel() {
|
|
3338
|
+
return currentLevel;
|
|
3339
|
+
}
|
|
3340
|
+
function getDateStr() {
|
|
3341
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3342
|
+
}
|
|
3343
|
+
function getDaemonLogDir() {
|
|
3344
|
+
return LOG_DIR;
|
|
3345
|
+
}
|
|
3346
|
+
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
3347
|
+
return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
3348
|
+
}
|
|
3349
|
+
function checkDateRotation() {
|
|
3350
|
+
const today = getDateStr();
|
|
3351
|
+
if (today !== currentDate) {
|
|
3352
|
+
currentDate = today;
|
|
3353
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
3354
|
+
cleanOldLogs();
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
function cleanOldLogs() {
|
|
3358
|
+
try {
|
|
3359
|
+
const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
3360
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
3361
|
+
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
3362
|
+
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
3363
|
+
for (const file of files) {
|
|
3364
|
+
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
3365
|
+
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
3366
|
+
try {
|
|
3367
|
+
fs4.unlinkSync(path9.join(LOG_DIR, file));
|
|
3368
|
+
} catch {
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
} catch {
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
function rotateSizeIfNeeded() {
|
|
3376
|
+
try {
|
|
3377
|
+
const stat2 = fs4.statSync(currentLogFile);
|
|
3378
|
+
if (stat2.size > MAX_LOG_SIZE) {
|
|
3379
|
+
const backup = currentLogFile.replace(".log", ".1.log");
|
|
3380
|
+
try {
|
|
3381
|
+
fs4.unlinkSync(backup);
|
|
3382
|
+
} catch {
|
|
3383
|
+
}
|
|
3384
|
+
fs4.renameSync(currentLogFile, backup);
|
|
3385
|
+
}
|
|
3386
|
+
} catch {
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
function writeToFile(line) {
|
|
3390
|
+
try {
|
|
3391
|
+
if (++writeCount % 1e3 === 0) {
|
|
3392
|
+
checkDateRotation();
|
|
3393
|
+
rotateSizeIfNeeded();
|
|
3394
|
+
}
|
|
3395
|
+
AsyncBatchWriter.write(currentLogFile, line + "\n");
|
|
3396
|
+
} catch {
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
function getRecentLogs(count = 50, minLevel = "info") {
|
|
3400
|
+
const minNum = LEVEL_NUM[minLevel];
|
|
3401
|
+
const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
|
|
3402
|
+
return filtered.slice(-count);
|
|
3403
|
+
}
|
|
3404
|
+
function getLogBufferSize() {
|
|
3405
|
+
return ringBuffer.length;
|
|
3406
|
+
}
|
|
3407
|
+
function ts() {
|
|
3408
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
3409
|
+
}
|
|
3410
|
+
function fullTs() {
|
|
3411
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3412
|
+
}
|
|
3413
|
+
function daemonLog(category, msg, level = "info") {
|
|
3414
|
+
const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
|
|
3415
|
+
const label = LEVEL_LABEL[level];
|
|
3416
|
+
const line = `[${ts()}] [${label}] [${category}] ${msg}`;
|
|
3417
|
+
if (!shouldOutput) return;
|
|
3418
|
+
writeToFile(line);
|
|
3419
|
+
ringBuffer.push({ ts: Date.now(), level, category, message: msg });
|
|
3420
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3421
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3422
|
+
}
|
|
3423
|
+
origConsoleLog(line);
|
|
3424
|
+
}
|
|
3425
|
+
function installGlobalInterceptor() {
|
|
3426
|
+
if (interceptorInstalled) return;
|
|
3427
|
+
interceptorInstalled = true;
|
|
3428
|
+
const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3429
|
+
const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
|
|
3430
|
+
console.log = (...args) => {
|
|
3431
|
+
origConsoleLog(...args);
|
|
3432
|
+
try {
|
|
3433
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
3434
|
+
const clean = stripAnsi4(msg);
|
|
3435
|
+
if (isDaemonLogLine(clean)) return;
|
|
3436
|
+
const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
|
|
3437
|
+
writeToFile(line);
|
|
3438
|
+
const catMatch = clean.match(/\[([^\]]+)\]/);
|
|
3439
|
+
ringBuffer.push({
|
|
3440
|
+
ts: Date.now(),
|
|
3441
|
+
level: "info",
|
|
3442
|
+
category: catMatch?.[1] || "System",
|
|
3443
|
+
message: clean
|
|
3444
|
+
});
|
|
3445
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3446
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3447
|
+
}
|
|
3448
|
+
} catch {
|
|
3449
|
+
}
|
|
3450
|
+
};
|
|
3451
|
+
console.error = (...args) => {
|
|
3452
|
+
origConsoleError(...args);
|
|
3453
|
+
try {
|
|
3454
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
3455
|
+
const clean = stripAnsi4(msg);
|
|
3456
|
+
if (isDaemonLogLine(clean)) return;
|
|
3457
|
+
const line = `[${fullTs()}] [ERROR] ${clean}`;
|
|
3458
|
+
writeToFile(line);
|
|
3459
|
+
ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
|
|
3460
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3461
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3462
|
+
}
|
|
3463
|
+
} catch {
|
|
3464
|
+
}
|
|
3465
|
+
};
|
|
3466
|
+
console.warn = (...args) => {
|
|
3467
|
+
origConsoleWarn(...args);
|
|
3468
|
+
try {
|
|
3469
|
+
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
3470
|
+
const clean = stripAnsi4(msg);
|
|
3471
|
+
if (isDaemonLogLine(clean)) return;
|
|
3472
|
+
const line = `[${fullTs()}] [WARN] ${clean}`;
|
|
3473
|
+
writeToFile(line);
|
|
3474
|
+
ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
|
|
3475
|
+
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
3476
|
+
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
3477
|
+
}
|
|
3478
|
+
} catch {
|
|
3479
|
+
}
|
|
3480
|
+
};
|
|
3481
|
+
writeToFile(`
|
|
3482
|
+
=== ADHDev Daemon started at ${fullTs()} ===`);
|
|
3483
|
+
writeToFile(`Log file: ${currentLogFile}`);
|
|
3484
|
+
writeToFile(`Log level: ${currentLevel}`);
|
|
3485
|
+
}
|
|
3486
|
+
function getLogPath() {
|
|
3487
|
+
return currentLogFile;
|
|
3488
|
+
}
|
|
3489
|
+
var fs4, path9, os3, 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;
|
|
3490
|
+
var init_logger = __esm({
|
|
3491
|
+
"src/logging/logger.ts"() {
|
|
3492
|
+
"use strict";
|
|
3493
|
+
fs4 = __toESM(require("fs"));
|
|
3494
|
+
path9 = __toESM(require("path"));
|
|
3495
|
+
os3 = __toESM(require("os"));
|
|
3496
|
+
init_async_batch_writer();
|
|
3497
|
+
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
3498
|
+
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
3499
|
+
currentLevel = "info";
|
|
3500
|
+
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");
|
|
3501
|
+
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
3502
|
+
MAX_LOG_DAYS = 7;
|
|
3503
|
+
try {
|
|
3504
|
+
fs4.mkdirSync(LOG_DIR, { recursive: true });
|
|
3505
|
+
} catch {
|
|
3506
|
+
}
|
|
3507
|
+
currentDate = getDateStr();
|
|
3508
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
3509
|
+
cleanOldLogs();
|
|
3510
|
+
try {
|
|
3511
|
+
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
3512
|
+
if (fs4.existsSync(oldLog)) {
|
|
3513
|
+
const stat2 = fs4.statSync(oldLog);
|
|
3514
|
+
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
3515
|
+
fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
3516
|
+
}
|
|
3517
|
+
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
3518
|
+
if (fs4.existsSync(oldLogBackup)) {
|
|
3519
|
+
fs4.unlinkSync(oldLogBackup);
|
|
3520
|
+
}
|
|
3521
|
+
} catch {
|
|
3522
|
+
}
|
|
3523
|
+
writeCount = 0;
|
|
3524
|
+
RING_BUFFER_SIZE = 200;
|
|
3525
|
+
ringBuffer = [];
|
|
3526
|
+
origConsoleLog = console.log.bind(console);
|
|
3527
|
+
origConsoleError = console.error.bind(console);
|
|
3528
|
+
origConsoleWarn = console.warn.bind(console);
|
|
3529
|
+
LOG = {
|
|
3530
|
+
debug: (category, msg) => daemonLog(category, msg, "debug"),
|
|
3531
|
+
info: (category, msg) => daemonLog(category, msg, "info"),
|
|
3532
|
+
warn: (category, msg) => daemonLog(category, msg, "warn"),
|
|
3533
|
+
error: (category, msg) => daemonLog(category, msg, "error"),
|
|
3534
|
+
/**
|
|
3535
|
+
* Create a scoped logger for a specific component.
|
|
3536
|
+
* Category is baked in so callers only pass the message.
|
|
3537
|
+
*/
|
|
3538
|
+
forComponent(category) {
|
|
3539
|
+
return {
|
|
3540
|
+
debug: (msg) => daemonLog(category, msg, "debug"),
|
|
3541
|
+
info: (msg) => daemonLog(category, msg, "info"),
|
|
3542
|
+
warn: (msg) => daemonLog(category, msg, "warn"),
|
|
3543
|
+
error: (msg) => daemonLog(category, msg, "error"),
|
|
3544
|
+
asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
};
|
|
3548
|
+
interceptorInstalled = false;
|
|
3549
|
+
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
3550
|
+
LOG_DIR_PATH = LOG_DIR;
|
|
3551
|
+
}
|
|
3552
|
+
});
|
|
3553
|
+
|
|
3263
3554
|
// src/mesh/mesh-work-queue.ts
|
|
3264
3555
|
var mesh_work_queue_exports = {};
|
|
3265
3556
|
__export(mesh_work_queue_exports, {
|
|
@@ -3724,11 +4015,18 @@ function requeueTask(meshId, taskId, opts) {
|
|
|
3724
4015
|
}
|
|
3725
4016
|
function updateSessionTaskStatus(meshId, sessionId, status, opts) {
|
|
3726
4017
|
return withQueueLock(meshId, () => {
|
|
4018
|
+
const store = MeshRuntimeStore.getInstance();
|
|
3727
4019
|
const occurredAtIso = opts?.occurredAt ? new Date(opts.occurredAt).toISOString() : void 0;
|
|
3728
|
-
const entry =
|
|
3729
|
-
if (!entry)
|
|
4020
|
+
const entry = store.findAssignedBySession(meshId, sessionId, occurredAtIso, opts?.taskId);
|
|
4021
|
+
if (!entry) {
|
|
4022
|
+
const assignedRows = store.getActiveAssignmentDetails(meshId).filter((r) => r.sessionId === sessionId);
|
|
4023
|
+
if (assignedRows.length > 0) {
|
|
4024
|
+
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(",")}`);
|
|
4025
|
+
}
|
|
4026
|
+
return null;
|
|
4027
|
+
}
|
|
3730
4028
|
entry.status = status;
|
|
3731
|
-
|
|
4029
|
+
store.updateQueueEntry(entry);
|
|
3732
4030
|
if (DEPENDENCY_FAILURE_TERMINALS.has(status)) propagateDependencyFailure(meshId, entry.id);
|
|
3733
4031
|
return entry;
|
|
3734
4032
|
});
|
|
@@ -3837,6 +4135,7 @@ var init_mesh_work_queue = __esm({
|
|
|
3837
4135
|
init_repo_mesh_types();
|
|
3838
4136
|
init_mesh_runtime_store();
|
|
3839
4137
|
init_mesh_config();
|
|
4138
|
+
init_logger();
|
|
3840
4139
|
ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
|
|
3841
4140
|
HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
|
|
3842
4141
|
MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
|
|
@@ -4495,12 +4794,51 @@ var init_mesh_runtime_store = __esm({
|
|
|
4495
4794
|
return { id, nodeId: r.assigned_node_id ?? void 0, sessionId: r.assigned_session_id ?? void 0, message };
|
|
4496
4795
|
});
|
|
4497
4796
|
}
|
|
4498
|
-
|
|
4797
|
+
/**
|
|
4798
|
+
* Resolve the `assigned` queue row a completion event belongs to.
|
|
4799
|
+
*
|
|
4800
|
+
* Clock-skew safety (C2): a completion event's `occurredAtIso` carries the
|
|
4801
|
+
* REMOTE WORKER's clock, while `updated_at` carries the COORDINATOR's clock
|
|
4802
|
+
* (set at assignment and re-bumped on every mutation). For a remote node,
|
|
4803
|
+
* coordinator-clock > worker-clock skew used to make an `updated_at <= occurredAt`
|
|
4804
|
+
* filter return nothing, stranding the finished task as `assigned` forever.
|
|
4805
|
+
*
|
|
4806
|
+
* We therefore NEVER filter completion-matching on the mutable `updated_at`:
|
|
4807
|
+
* 1. If `taskId` is given, match the exact `assigned` row by id (no time filter).
|
|
4808
|
+
* 2. Otherwise a session holds at most one `assigned` task — match it without a
|
|
4809
|
+
* time filter. If several exist (shouldn't normally), disambiguate by the
|
|
4810
|
+
* IMMUTABLE `dispatchTimestamp`: latest `dispatchTimestamp <= occurredAt`,
|
|
4811
|
+
* and if skew makes ALL of them later than `occurredAt`, fall back to the
|
|
4812
|
+
* most-recent `dispatchTimestamp` rather than returning null.
|
|
4813
|
+
*/
|
|
4814
|
+
findAssignedBySession(meshId, sessionId, occurredAtIso, taskId) {
|
|
4499
4815
|
this.ensureLegacyQueueMigrated(meshId);
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4816
|
+
if (taskId) {
|
|
4817
|
+
const row = this.db.prepare(
|
|
4818
|
+
`SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned' AND id = ? LIMIT 1`
|
|
4819
|
+
).get(meshId, sessionId, taskId);
|
|
4820
|
+
if (row) return JSON.parse(row.payload);
|
|
4821
|
+
}
|
|
4822
|
+
const rows = this.db.prepare(
|
|
4823
|
+
`SELECT payload FROM mesh_queue WHERE mesh_id = ? AND assigned_session_id = ? AND status = 'assigned'`
|
|
4824
|
+
).all(meshId, sessionId);
|
|
4825
|
+
if (rows.length === 0) return null;
|
|
4826
|
+
const entries = rows.map((r) => {
|
|
4827
|
+
try {
|
|
4828
|
+
return JSON.parse(r.payload);
|
|
4829
|
+
} catch {
|
|
4830
|
+
return null;
|
|
4831
|
+
}
|
|
4832
|
+
}).filter((e) => e !== null);
|
|
4833
|
+
if (entries.length === 0) return null;
|
|
4834
|
+
if (entries.length === 1) return entries[0];
|
|
4835
|
+
const orderKey = (e) => e.dispatchTimestamp ?? e.updatedAt ?? "";
|
|
4836
|
+
const byDispatchDesc = [...entries].sort((a, b) => orderKey(b).localeCompare(orderKey(a)));
|
|
4837
|
+
if (occurredAtIso) {
|
|
4838
|
+
const atOrBefore = byDispatchDesc.find((e) => orderKey(e) <= occurredAtIso);
|
|
4839
|
+
if (atOrBefore) return atOrBefore;
|
|
4840
|
+
}
|
|
4841
|
+
return byDispatchDesc[0];
|
|
4504
4842
|
}
|
|
4505
4843
|
toRow(entry) {
|
|
4506
4844
|
return {
|
|
@@ -5756,297 +6094,6 @@ var init_mesh_review_inbox = __esm({
|
|
|
5756
6094
|
}
|
|
5757
6095
|
});
|
|
5758
6096
|
|
|
5759
|
-
// src/logging/async-batch-writer.ts
|
|
5760
|
-
var fs3, AsyncBatchWriter;
|
|
5761
|
-
var init_async_batch_writer = __esm({
|
|
5762
|
-
"src/logging/async-batch-writer.ts"() {
|
|
5763
|
-
"use strict";
|
|
5764
|
-
fs3 = __toESM(require("fs"));
|
|
5765
|
-
AsyncBatchWriter = class {
|
|
5766
|
-
// Maps filePath -> string buffer
|
|
5767
|
-
static buffers = /* @__PURE__ */ new Map();
|
|
5768
|
-
static writePromises = /* @__PURE__ */ new Map();
|
|
5769
|
-
static flushTimer = null;
|
|
5770
|
-
/**
|
|
5771
|
-
* Queues data to be written to a file asynchronously in a batch.
|
|
5772
|
-
*/
|
|
5773
|
-
static write(filePath, data) {
|
|
5774
|
-
let buf = this.buffers.get(filePath);
|
|
5775
|
-
if (!buf) {
|
|
5776
|
-
buf = [];
|
|
5777
|
-
this.buffers.set(filePath, buf);
|
|
5778
|
-
}
|
|
5779
|
-
buf.push(data);
|
|
5780
|
-
if (!this.flushTimer) {
|
|
5781
|
-
this.flushTimer = setTimeout(() => {
|
|
5782
|
-
this.flushTimer = null;
|
|
5783
|
-
this.flushAll();
|
|
5784
|
-
}, 50);
|
|
5785
|
-
}
|
|
5786
|
-
}
|
|
5787
|
-
static async flushAll() {
|
|
5788
|
-
const entries = Array.from(this.buffers.entries());
|
|
5789
|
-
this.buffers.clear();
|
|
5790
|
-
for (const [filePath, buffer] of entries) {
|
|
5791
|
-
const dataToWrite = buffer.join("");
|
|
5792
|
-
const doWrite = async () => {
|
|
5793
|
-
try {
|
|
5794
|
-
const prevPromise = this.writePromises.get(filePath);
|
|
5795
|
-
if (prevPromise) await prevPromise;
|
|
5796
|
-
await fs3.promises.appendFile(filePath, dataToWrite, { encoding: "utf-8", mode: 384 });
|
|
5797
|
-
} catch {
|
|
5798
|
-
}
|
|
5799
|
-
};
|
|
5800
|
-
const writePromise = doWrite();
|
|
5801
|
-
this.writePromises.set(filePath, writePromise);
|
|
5802
|
-
writePromise.finally(() => {
|
|
5803
|
-
if (this.writePromises.get(filePath) === writePromise) {
|
|
5804
|
-
this.writePromises.delete(filePath);
|
|
5805
|
-
}
|
|
5806
|
-
});
|
|
5807
|
-
}
|
|
5808
|
-
}
|
|
5809
|
-
};
|
|
5810
|
-
}
|
|
5811
|
-
});
|
|
5812
|
-
|
|
5813
|
-
// src/logging/logger.ts
|
|
5814
|
-
var logger_exports = {};
|
|
5815
|
-
__export(logger_exports, {
|
|
5816
|
-
LOG: () => LOG,
|
|
5817
|
-
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
5818
|
-
LOG_PATH: () => LOG_PATH,
|
|
5819
|
-
daemonLog: () => daemonLog,
|
|
5820
|
-
getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
|
|
5821
|
-
getDaemonLogDir: () => getDaemonLogDir,
|
|
5822
|
-
getLogBufferSize: () => getLogBufferSize,
|
|
5823
|
-
getLogLevel: () => getLogLevel,
|
|
5824
|
-
getLogPath: () => getLogPath,
|
|
5825
|
-
getRecentLogs: () => getRecentLogs,
|
|
5826
|
-
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
5827
|
-
setLogLevel: () => setLogLevel
|
|
5828
|
-
});
|
|
5829
|
-
function setLogLevel(level) {
|
|
5830
|
-
currentLevel = level;
|
|
5831
|
-
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
5832
|
-
}
|
|
5833
|
-
function getLogLevel() {
|
|
5834
|
-
return currentLevel;
|
|
5835
|
-
}
|
|
5836
|
-
function getDateStr() {
|
|
5837
|
-
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
5838
|
-
}
|
|
5839
|
-
function getDaemonLogDir() {
|
|
5840
|
-
return LOG_DIR;
|
|
5841
|
-
}
|
|
5842
|
-
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
5843
|
-
return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
5844
|
-
}
|
|
5845
|
-
function checkDateRotation() {
|
|
5846
|
-
const today = getDateStr();
|
|
5847
|
-
if (today !== currentDate) {
|
|
5848
|
-
currentDate = today;
|
|
5849
|
-
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
5850
|
-
cleanOldLogs();
|
|
5851
|
-
}
|
|
5852
|
-
}
|
|
5853
|
-
function cleanOldLogs() {
|
|
5854
|
-
try {
|
|
5855
|
-
const files = fs4.readdirSync(LOG_DIR).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
5856
|
-
const cutoff = /* @__PURE__ */ new Date();
|
|
5857
|
-
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
5858
|
-
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
5859
|
-
for (const file of files) {
|
|
5860
|
-
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
5861
|
-
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
5862
|
-
try {
|
|
5863
|
-
fs4.unlinkSync(path9.join(LOG_DIR, file));
|
|
5864
|
-
} catch {
|
|
5865
|
-
}
|
|
5866
|
-
}
|
|
5867
|
-
}
|
|
5868
|
-
} catch {
|
|
5869
|
-
}
|
|
5870
|
-
}
|
|
5871
|
-
function rotateSizeIfNeeded() {
|
|
5872
|
-
try {
|
|
5873
|
-
const stat2 = fs4.statSync(currentLogFile);
|
|
5874
|
-
if (stat2.size > MAX_LOG_SIZE) {
|
|
5875
|
-
const backup = currentLogFile.replace(".log", ".1.log");
|
|
5876
|
-
try {
|
|
5877
|
-
fs4.unlinkSync(backup);
|
|
5878
|
-
} catch {
|
|
5879
|
-
}
|
|
5880
|
-
fs4.renameSync(currentLogFile, backup);
|
|
5881
|
-
}
|
|
5882
|
-
} catch {
|
|
5883
|
-
}
|
|
5884
|
-
}
|
|
5885
|
-
function writeToFile(line) {
|
|
5886
|
-
try {
|
|
5887
|
-
if (++writeCount % 1e3 === 0) {
|
|
5888
|
-
checkDateRotation();
|
|
5889
|
-
rotateSizeIfNeeded();
|
|
5890
|
-
}
|
|
5891
|
-
AsyncBatchWriter.write(currentLogFile, line + "\n");
|
|
5892
|
-
} catch {
|
|
5893
|
-
}
|
|
5894
|
-
}
|
|
5895
|
-
function getRecentLogs(count = 50, minLevel = "info") {
|
|
5896
|
-
const minNum = LEVEL_NUM[minLevel];
|
|
5897
|
-
const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
|
|
5898
|
-
return filtered.slice(-count);
|
|
5899
|
-
}
|
|
5900
|
-
function getLogBufferSize() {
|
|
5901
|
-
return ringBuffer.length;
|
|
5902
|
-
}
|
|
5903
|
-
function ts() {
|
|
5904
|
-
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
5905
|
-
}
|
|
5906
|
-
function fullTs() {
|
|
5907
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
5908
|
-
}
|
|
5909
|
-
function daemonLog(category, msg, level = "info") {
|
|
5910
|
-
const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
|
|
5911
|
-
const label = LEVEL_LABEL[level];
|
|
5912
|
-
const line = `[${ts()}] [${label}] [${category}] ${msg}`;
|
|
5913
|
-
if (!shouldOutput) return;
|
|
5914
|
-
writeToFile(line);
|
|
5915
|
-
ringBuffer.push({ ts: Date.now(), level, category, message: msg });
|
|
5916
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5917
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5918
|
-
}
|
|
5919
|
-
origConsoleLog(line);
|
|
5920
|
-
}
|
|
5921
|
-
function installGlobalInterceptor() {
|
|
5922
|
-
if (interceptorInstalled) return;
|
|
5923
|
-
interceptorInstalled = true;
|
|
5924
|
-
const stripAnsi4 = (str) => str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
5925
|
-
const isDaemonLogLine = (msg) => /\[(DBG|INF|WRN|ERR)\]/.test(msg);
|
|
5926
|
-
console.log = (...args) => {
|
|
5927
|
-
origConsoleLog(...args);
|
|
5928
|
-
try {
|
|
5929
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5930
|
-
const clean = stripAnsi4(msg);
|
|
5931
|
-
if (isDaemonLogLine(clean)) return;
|
|
5932
|
-
const line = clean.startsWith("[20") ? clean : `[${fullTs()}] ${clean}`;
|
|
5933
|
-
writeToFile(line);
|
|
5934
|
-
const catMatch = clean.match(/\[([^\]]+)\]/);
|
|
5935
|
-
ringBuffer.push({
|
|
5936
|
-
ts: Date.now(),
|
|
5937
|
-
level: "info",
|
|
5938
|
-
category: catMatch?.[1] || "System",
|
|
5939
|
-
message: clean
|
|
5940
|
-
});
|
|
5941
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5942
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5943
|
-
}
|
|
5944
|
-
} catch {
|
|
5945
|
-
}
|
|
5946
|
-
};
|
|
5947
|
-
console.error = (...args) => {
|
|
5948
|
-
origConsoleError(...args);
|
|
5949
|
-
try {
|
|
5950
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5951
|
-
const clean = stripAnsi4(msg);
|
|
5952
|
-
if (isDaemonLogLine(clean)) return;
|
|
5953
|
-
const line = `[${fullTs()}] [ERROR] ${clean}`;
|
|
5954
|
-
writeToFile(line);
|
|
5955
|
-
ringBuffer.push({ ts: Date.now(), level: "error", category: "System", message: clean });
|
|
5956
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5957
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5958
|
-
}
|
|
5959
|
-
} catch {
|
|
5960
|
-
}
|
|
5961
|
-
};
|
|
5962
|
-
console.warn = (...args) => {
|
|
5963
|
-
origConsoleWarn(...args);
|
|
5964
|
-
try {
|
|
5965
|
-
const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
5966
|
-
const clean = stripAnsi4(msg);
|
|
5967
|
-
if (isDaemonLogLine(clean)) return;
|
|
5968
|
-
const line = `[${fullTs()}] [WARN] ${clean}`;
|
|
5969
|
-
writeToFile(line);
|
|
5970
|
-
ringBuffer.push({ ts: Date.now(), level: "warn", category: "System", message: clean });
|
|
5971
|
-
if (ringBuffer.length > RING_BUFFER_SIZE) {
|
|
5972
|
-
ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
|
|
5973
|
-
}
|
|
5974
|
-
} catch {
|
|
5975
|
-
}
|
|
5976
|
-
};
|
|
5977
|
-
writeToFile(`
|
|
5978
|
-
=== ADHDev Daemon started at ${fullTs()} ===`);
|
|
5979
|
-
writeToFile(`Log file: ${currentLogFile}`);
|
|
5980
|
-
writeToFile(`Log level: ${currentLevel}`);
|
|
5981
|
-
}
|
|
5982
|
-
function getLogPath() {
|
|
5983
|
-
return currentLogFile;
|
|
5984
|
-
}
|
|
5985
|
-
var fs4, path9, os3, 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;
|
|
5986
|
-
var init_logger = __esm({
|
|
5987
|
-
"src/logging/logger.ts"() {
|
|
5988
|
-
"use strict";
|
|
5989
|
-
fs4 = __toESM(require("fs"));
|
|
5990
|
-
path9 = __toESM(require("path"));
|
|
5991
|
-
os3 = __toESM(require("os"));
|
|
5992
|
-
init_async_batch_writer();
|
|
5993
|
-
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
5994
|
-
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
5995
|
-
currentLevel = "info";
|
|
5996
|
-
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");
|
|
5997
|
-
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
5998
|
-
MAX_LOG_DAYS = 7;
|
|
5999
|
-
try {
|
|
6000
|
-
fs4.mkdirSync(LOG_DIR, { recursive: true });
|
|
6001
|
-
} catch {
|
|
6002
|
-
}
|
|
6003
|
-
currentDate = getDateStr();
|
|
6004
|
-
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
6005
|
-
cleanOldLogs();
|
|
6006
|
-
try {
|
|
6007
|
-
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
6008
|
-
if (fs4.existsSync(oldLog)) {
|
|
6009
|
-
const stat2 = fs4.statSync(oldLog);
|
|
6010
|
-
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
6011
|
-
fs4.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
6012
|
-
}
|
|
6013
|
-
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
6014
|
-
if (fs4.existsSync(oldLogBackup)) {
|
|
6015
|
-
fs4.unlinkSync(oldLogBackup);
|
|
6016
|
-
}
|
|
6017
|
-
} catch {
|
|
6018
|
-
}
|
|
6019
|
-
writeCount = 0;
|
|
6020
|
-
RING_BUFFER_SIZE = 200;
|
|
6021
|
-
ringBuffer = [];
|
|
6022
|
-
origConsoleLog = console.log.bind(console);
|
|
6023
|
-
origConsoleError = console.error.bind(console);
|
|
6024
|
-
origConsoleWarn = console.warn.bind(console);
|
|
6025
|
-
LOG = {
|
|
6026
|
-
debug: (category, msg) => daemonLog(category, msg, "debug"),
|
|
6027
|
-
info: (category, msg) => daemonLog(category, msg, "info"),
|
|
6028
|
-
warn: (category, msg) => daemonLog(category, msg, "warn"),
|
|
6029
|
-
error: (category, msg) => daemonLog(category, msg, "error"),
|
|
6030
|
-
/**
|
|
6031
|
-
* Create a scoped logger for a specific component.
|
|
6032
|
-
* Category is baked in so callers only pass the message.
|
|
6033
|
-
*/
|
|
6034
|
-
forComponent(category) {
|
|
6035
|
-
return {
|
|
6036
|
-
debug: (msg) => daemonLog(category, msg, "debug"),
|
|
6037
|
-
info: (msg) => daemonLog(category, msg, "info"),
|
|
6038
|
-
warn: (msg) => daemonLog(category, msg, "warn"),
|
|
6039
|
-
error: (msg) => daemonLog(category, msg, "error"),
|
|
6040
|
-
asLogFn: (level = "info") => (msg) => daemonLog(category, msg, level)
|
|
6041
|
-
};
|
|
6042
|
-
}
|
|
6043
|
-
};
|
|
6044
|
-
interceptorInstalled = false;
|
|
6045
|
-
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
6046
|
-
LOG_DIR_PATH = LOG_DIR;
|
|
6047
|
-
}
|
|
6048
|
-
});
|
|
6049
|
-
|
|
6050
6097
|
// src/commands/mesh-coordinator.ts
|
|
6051
6098
|
var mesh_coordinator_exports = {};
|
|
6052
6099
|
__export(mesh_coordinator_exports, {
|
|
@@ -6448,6 +6495,59 @@ var init_mesh_coordinator = __esm({
|
|
|
6448
6495
|
}
|
|
6449
6496
|
});
|
|
6450
6497
|
|
|
6498
|
+
// src/cli-adapters/resolve-executable.ts
|
|
6499
|
+
function resolveWin32GlobalBin(trimmed) {
|
|
6500
|
+
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
|
|
6501
|
+
return null;
|
|
6502
|
+
}
|
|
6503
|
+
const extraDirs = [];
|
|
6504
|
+
if (process.env.APPDATA) extraDirs.push(path10.join(process.env.APPDATA, "npm"));
|
|
6505
|
+
try {
|
|
6506
|
+
extraDirs.push(path10.dirname(process.execPath));
|
|
6507
|
+
} catch {
|
|
6508
|
+
}
|
|
6509
|
+
for (const dir of extraDirs) {
|
|
6510
|
+
if (!dir) continue;
|
|
6511
|
+
for (const ext of WIN_EXEC_EXT) {
|
|
6512
|
+
const full = path10.join(dir, trimmed + ext);
|
|
6513
|
+
if ((0, import_fs8.existsSync)(full)) return full;
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
return null;
|
|
6517
|
+
}
|
|
6518
|
+
function resolveWin32Executable(command) {
|
|
6519
|
+
if (process.platform !== "win32") return command;
|
|
6520
|
+
const trimmed = (command || "").trim();
|
|
6521
|
+
if (!trimmed) return command;
|
|
6522
|
+
if (path10.isAbsolute(trimmed) && (0, import_fs8.existsSync)(trimmed)) return trimmed;
|
|
6523
|
+
try {
|
|
6524
|
+
const out = (0, import_child_process.execFileSync)("where", [trimmed], {
|
|
6525
|
+
encoding: "utf8",
|
|
6526
|
+
windowsHide: true
|
|
6527
|
+
}).trim();
|
|
6528
|
+
if (out) {
|
|
6529
|
+
const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
6530
|
+
const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path10.extname(m).toLowerCase()));
|
|
6531
|
+
return direct || matches[0] || command;
|
|
6532
|
+
}
|
|
6533
|
+
} catch {
|
|
6534
|
+
}
|
|
6535
|
+
const globalBin = resolveWin32GlobalBin(trimmed);
|
|
6536
|
+
if (globalBin) return globalBin;
|
|
6537
|
+
return command;
|
|
6538
|
+
}
|
|
6539
|
+
var import_child_process, import_fs8, path10, DIRECT_EXEC_EXT, WIN_EXEC_EXT;
|
|
6540
|
+
var init_resolve_executable = __esm({
|
|
6541
|
+
"src/cli-adapters/resolve-executable.ts"() {
|
|
6542
|
+
"use strict";
|
|
6543
|
+
import_child_process = require("child_process");
|
|
6544
|
+
import_fs8 = require("fs");
|
|
6545
|
+
path10 = __toESM(require("path"));
|
|
6546
|
+
DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
|
|
6547
|
+
WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
|
|
6548
|
+
}
|
|
6549
|
+
});
|
|
6550
|
+
|
|
6451
6551
|
// src/mesh/mesh-fast-forward.ts
|
|
6452
6552
|
async function fastForwardMeshNode(args) {
|
|
6453
6553
|
const workspace = typeof args.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -7971,9 +8071,9 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
|
7971
8071
|
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
7972
8072
|
const events = [];
|
|
7973
8073
|
for (const path42 of paths) {
|
|
7974
|
-
if (!(0,
|
|
8074
|
+
if (!(0, import_fs10.existsSync)(path42)) continue;
|
|
7975
8075
|
try {
|
|
7976
|
-
const raw = (0,
|
|
8076
|
+
const raw = (0, import_fs10.readFileSync)(path42, "utf-8");
|
|
7977
8077
|
const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
7978
8078
|
try {
|
|
7979
8079
|
return [JSON.parse(line)];
|
|
@@ -8048,11 +8148,11 @@ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
|
|
|
8048
8148
|
}
|
|
8049
8149
|
function trimPendingEventsIfNeeded(path42) {
|
|
8050
8150
|
try {
|
|
8051
|
-
if (!(0,
|
|
8052
|
-
if ((0,
|
|
8053
|
-
const lines = (0,
|
|
8151
|
+
if (!(0, import_fs10.existsSync)(path42)) return;
|
|
8152
|
+
if ((0, import_fs10.statSync)(path42).size <= MAX_PENDING_EVENTS_BYTES) return;
|
|
8153
|
+
const lines = (0, import_fs10.readFileSync)(path42, "utf-8").split("\n").filter(Boolean);
|
|
8054
8154
|
if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
|
|
8055
|
-
(0,
|
|
8155
|
+
(0, import_fs10.writeFileSync)(path42, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
|
|
8056
8156
|
} catch {
|
|
8057
8157
|
}
|
|
8058
8158
|
}
|
|
@@ -8081,7 +8181,7 @@ function queuePendingMeshCoordinatorEvent(event) {
|
|
|
8081
8181
|
}
|
|
8082
8182
|
const path42 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
|
|
8083
8183
|
trimPendingEventsIfNeeded(path42);
|
|
8084
|
-
(0,
|
|
8184
|
+
(0, import_fs10.appendFileSync)(path42, JSON.stringify(event) + "\n", "utf-8");
|
|
8085
8185
|
return true;
|
|
8086
8186
|
} catch (e) {
|
|
8087
8187
|
LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
|
|
@@ -8091,20 +8191,20 @@ function queuePendingMeshCoordinatorEvent(event) {
|
|
|
8091
8191
|
function atomicDrainFile(path42) {
|
|
8092
8192
|
const tmpPath = `${path42}.draining`;
|
|
8093
8193
|
try {
|
|
8094
|
-
(0,
|
|
8194
|
+
(0, import_fs10.renameSync)(path42, tmpPath);
|
|
8095
8195
|
} catch {
|
|
8096
8196
|
return null;
|
|
8097
8197
|
}
|
|
8098
8198
|
try {
|
|
8099
|
-
const content = (0,
|
|
8199
|
+
const content = (0, import_fs10.readFileSync)(tmpPath, "utf-8");
|
|
8100
8200
|
try {
|
|
8101
|
-
(0,
|
|
8201
|
+
(0, import_fs10.unlinkSync)(tmpPath);
|
|
8102
8202
|
} catch {
|
|
8103
8203
|
}
|
|
8104
8204
|
return content;
|
|
8105
8205
|
} catch {
|
|
8106
8206
|
try {
|
|
8107
|
-
(0,
|
|
8207
|
+
(0, import_fs10.unlinkSync)(tmpPath);
|
|
8108
8208
|
} catch {
|
|
8109
8209
|
}
|
|
8110
8210
|
return null;
|
|
@@ -8113,16 +8213,16 @@ function atomicDrainFile(path42) {
|
|
|
8113
8213
|
function selectiveDrainFile(path42, predicate) {
|
|
8114
8214
|
const tmpPath = `${path42}.draining`;
|
|
8115
8215
|
try {
|
|
8116
|
-
(0,
|
|
8216
|
+
(0, import_fs10.renameSync)(path42, tmpPath);
|
|
8117
8217
|
} catch {
|
|
8118
8218
|
return [];
|
|
8119
8219
|
}
|
|
8120
8220
|
let content;
|
|
8121
8221
|
try {
|
|
8122
|
-
content = (0,
|
|
8222
|
+
content = (0, import_fs10.readFileSync)(tmpPath, "utf-8");
|
|
8123
8223
|
} catch {
|
|
8124
8224
|
try {
|
|
8125
|
-
(0,
|
|
8225
|
+
(0, import_fs10.unlinkSync)(tmpPath);
|
|
8126
8226
|
} catch {
|
|
8127
8227
|
}
|
|
8128
8228
|
return [];
|
|
@@ -8145,12 +8245,12 @@ function selectiveDrainFile(path42, predicate) {
|
|
|
8145
8245
|
}
|
|
8146
8246
|
try {
|
|
8147
8247
|
if (keptLines.length > 0) {
|
|
8148
|
-
(0,
|
|
8248
|
+
(0, import_fs10.writeFileSync)(path42, keptLines.join("\n") + "\n", "utf-8");
|
|
8149
8249
|
}
|
|
8150
|
-
(0,
|
|
8250
|
+
(0, import_fs10.unlinkSync)(tmpPath);
|
|
8151
8251
|
} catch {
|
|
8152
8252
|
try {
|
|
8153
|
-
if ((0,
|
|
8253
|
+
if ((0, import_fs10.existsSync)(tmpPath) && !(0, import_fs10.existsSync)(path42)) (0, import_fs10.renameSync)(tmpPath, path42);
|
|
8154
8254
|
} catch {
|
|
8155
8255
|
}
|
|
8156
8256
|
return [];
|
|
@@ -8244,17 +8344,17 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
8244
8344
|
}
|
|
8245
8345
|
const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
8246
8346
|
for (const path42 of paths) {
|
|
8247
|
-
if ((0,
|
|
8248
|
-
(0,
|
|
8347
|
+
if ((0, import_fs10.existsSync)(path42)) try {
|
|
8348
|
+
(0, import_fs10.unlinkSync)(path42);
|
|
8249
8349
|
} catch {
|
|
8250
8350
|
}
|
|
8251
8351
|
}
|
|
8252
8352
|
}
|
|
8253
|
-
var
|
|
8353
|
+
var import_fs10, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
|
|
8254
8354
|
var init_mesh_events_pending = __esm({
|
|
8255
8355
|
"src/mesh/mesh-events-pending.ts"() {
|
|
8256
8356
|
"use strict";
|
|
8257
|
-
|
|
8357
|
+
import_fs10 = require("fs");
|
|
8258
8358
|
import_path9 = require("path");
|
|
8259
8359
|
import_crypto7 = require("crypto");
|
|
8260
8360
|
init_logger();
|
|
@@ -8749,24 +8849,24 @@ function buildCliScreenSnapshot(text) {
|
|
|
8749
8849
|
function findBinary(name) {
|
|
8750
8850
|
const trimmed = String(name || "").trim();
|
|
8751
8851
|
if (!trimmed) return trimmed;
|
|
8752
|
-
const expanded = trimmed.startsWith("~") ?
|
|
8753
|
-
if (
|
|
8754
|
-
return
|
|
8852
|
+
const expanded = trimmed.startsWith("~") ? path11.join(os5.homedir(), trimmed.slice(1)) : trimmed;
|
|
8853
|
+
if (path11.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
8854
|
+
return path11.isAbsolute(expanded) ? expanded : path11.resolve(expanded);
|
|
8755
8855
|
}
|
|
8756
8856
|
const isWin = os5.platform() === "win32";
|
|
8757
|
-
const paths = (process.env.PATH || "").split(
|
|
8857
|
+
const paths = (process.env.PATH || "").split(path11.delimiter);
|
|
8758
8858
|
const extraDirs = [];
|
|
8759
8859
|
if (isWin) {
|
|
8760
|
-
if (process.env.APPDATA) extraDirs.push(
|
|
8860
|
+
if (process.env.APPDATA) extraDirs.push(path11.join(process.env.APPDATA, "npm"));
|
|
8761
8861
|
try {
|
|
8762
|
-
extraDirs.push(
|
|
8862
|
+
extraDirs.push(path11.dirname(process.execPath));
|
|
8763
8863
|
} catch {
|
|
8764
8864
|
}
|
|
8765
8865
|
} else {
|
|
8766
|
-
extraDirs.push(
|
|
8866
|
+
extraDirs.push(path11.join(os5.homedir(), ".npm-global", "bin"));
|
|
8767
8867
|
extraDirs.push("/usr/local/bin", "/opt/homebrew/bin");
|
|
8768
8868
|
try {
|
|
8769
|
-
extraDirs.push(
|
|
8869
|
+
extraDirs.push(path11.dirname(process.execPath));
|
|
8770
8870
|
} catch {
|
|
8771
8871
|
}
|
|
8772
8872
|
}
|
|
@@ -8775,7 +8875,7 @@ function findBinary(name) {
|
|
|
8775
8875
|
for (const p of searchDirs) {
|
|
8776
8876
|
if (!p) continue;
|
|
8777
8877
|
for (const ext of exes) {
|
|
8778
|
-
const fullPath =
|
|
8878
|
+
const fullPath = path11.join(p, trimmed + ext);
|
|
8779
8879
|
try {
|
|
8780
8880
|
const fs32 = require("fs");
|
|
8781
8881
|
if (fs32.existsSync(fullPath)) {
|
|
@@ -8791,7 +8891,7 @@ function findBinary(name) {
|
|
|
8791
8891
|
return isWin ? `${trimmed}.cmd` : trimmed;
|
|
8792
8892
|
}
|
|
8793
8893
|
function isScriptBinary(binaryPath) {
|
|
8794
|
-
if (!
|
|
8894
|
+
if (!path11.isAbsolute(binaryPath)) return false;
|
|
8795
8895
|
try {
|
|
8796
8896
|
const fs32 = require("fs");
|
|
8797
8897
|
const resolved = fs32.realpathSync(binaryPath);
|
|
@@ -8807,7 +8907,7 @@ function isScriptBinary(binaryPath) {
|
|
|
8807
8907
|
}
|
|
8808
8908
|
}
|
|
8809
8909
|
function looksLikeMachOOrElf(filePath) {
|
|
8810
|
-
if (!
|
|
8910
|
+
if (!path11.isAbsolute(filePath)) return false;
|
|
8811
8911
|
try {
|
|
8812
8912
|
const fs32 = require("fs");
|
|
8813
8913
|
const resolved = fs32.realpathSync(filePath);
|
|
@@ -8896,12 +8996,12 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
8896
8996
|
}
|
|
8897
8997
|
};
|
|
8898
8998
|
}
|
|
8899
|
-
var os5,
|
|
8999
|
+
var os5, path11, TerminalTranscriptAccumulator, buildCliSpawnEnv;
|
|
8900
9000
|
var init_provider_cli_shared = __esm({
|
|
8901
9001
|
"src/cli-adapters/provider-cli-shared.ts"() {
|
|
8902
9002
|
"use strict";
|
|
8903
9003
|
os5 = __toESM(require("os"));
|
|
8904
|
-
|
|
9004
|
+
path11 = __toESM(require("path"));
|
|
8905
9005
|
init_spawn_env();
|
|
8906
9006
|
TerminalTranscriptAccumulator = class {
|
|
8907
9007
|
lines = [[]];
|
|
@@ -9075,19 +9175,19 @@ function shellQuote(value) {
|
|
|
9075
9175
|
function expandHome(value) {
|
|
9076
9176
|
const trimmed = value.trim();
|
|
9077
9177
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
9078
|
-
return
|
|
9178
|
+
return path12.join(os6.homedir(), trimmed.slice(1));
|
|
9079
9179
|
}
|
|
9080
9180
|
function isExplicitCommandPath(command) {
|
|
9081
9181
|
const trimmed = command.trim();
|
|
9082
|
-
return
|
|
9182
|
+
return path12.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
9083
9183
|
}
|
|
9084
9184
|
function resolveCommandPath(command) {
|
|
9085
9185
|
const trimmed = command.trim();
|
|
9086
9186
|
if (!trimmed) return null;
|
|
9087
9187
|
if (isExplicitCommandPath(trimmed)) {
|
|
9088
9188
|
const expanded = expandHome(trimmed);
|
|
9089
|
-
const candidate =
|
|
9090
|
-
return (0,
|
|
9189
|
+
const candidate = path12.isAbsolute(expanded) ? expanded : path12.resolve(expanded);
|
|
9190
|
+
return (0, import_fs11.existsSync)(candidate) ? candidate : null;
|
|
9091
9191
|
}
|
|
9092
9192
|
return null;
|
|
9093
9193
|
}
|
|
@@ -9097,12 +9197,12 @@ async function resolveDetectionPath(command, whichCmd) {
|
|
|
9097
9197
|
const whichResult = await execAsync(`${whichCmd} ${shellQuote(command)}`);
|
|
9098
9198
|
if (whichResult) return whichResult.split("\n")[0];
|
|
9099
9199
|
const resolved = findBinary(command);
|
|
9100
|
-
if (
|
|
9200
|
+
if (path12.isAbsolute(resolved) && (0, import_fs11.existsSync)(resolved)) return resolved;
|
|
9101
9201
|
return null;
|
|
9102
9202
|
}
|
|
9103
9203
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
9104
9204
|
return new Promise((resolve24) => {
|
|
9105
|
-
const child = (0,
|
|
9205
|
+
const child = (0, import_child_process2.exec)(cmd, {
|
|
9106
9206
|
encoding: "utf-8",
|
|
9107
9207
|
timeout: timeoutMs,
|
|
9108
9208
|
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
@@ -9192,14 +9292,14 @@ async function detectCLI(cliId, providerLoader, options) {
|
|
|
9192
9292
|
const all = await detectCLIs(providerLoader, options);
|
|
9193
9293
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
9194
9294
|
}
|
|
9195
|
-
var
|
|
9295
|
+
var import_child_process2, os6, path12, import_fs11;
|
|
9196
9296
|
var init_cli_detector = __esm({
|
|
9197
9297
|
"src/detection/cli-detector.ts"() {
|
|
9198
9298
|
"use strict";
|
|
9199
|
-
|
|
9299
|
+
import_child_process2 = require("child_process");
|
|
9200
9300
|
os6 = __toESM(require("os"));
|
|
9201
|
-
|
|
9202
|
-
|
|
9301
|
+
path12 = __toESM(require("path"));
|
|
9302
|
+
import_fs11 = require("fs");
|
|
9203
9303
|
init_provider_cli_shared();
|
|
9204
9304
|
}
|
|
9205
9305
|
});
|
|
@@ -10234,7 +10334,7 @@ async function maybeAutoFastForwardIdleNode(components, args) {
|
|
|
10234
10334
|
const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
|
|
10235
10335
|
const workspace = readNonEmptyString2(node?.workspace);
|
|
10236
10336
|
if (!workspace) return;
|
|
10237
|
-
if (!(0,
|
|
10337
|
+
if (!(0, import_fs12.existsSync)(workspace)) return;
|
|
10238
10338
|
const policy = resolveAutoFastForwardPolicy(mesh);
|
|
10239
10339
|
if (!policy.enabled) return;
|
|
10240
10340
|
if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
|
|
@@ -10433,8 +10533,10 @@ function injectMeshSystemMessage(components, args) {
|
|
|
10433
10533
|
}
|
|
10434
10534
|
}
|
|
10435
10535
|
function markSessionTerminal(sessionId, outcome, occurredAtMs) {
|
|
10536
|
+
const eventTaskId = readNonEmptyString2(args.metadataEvent.taskId) || void 0;
|
|
10436
10537
|
const task = updateSessionTaskStatus(args.meshId, sessionId, outcome, {
|
|
10437
|
-
occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0
|
|
10538
|
+
occurredAt: occurredAtMs != null ? new Date(occurredAtMs).toISOString() : void 0,
|
|
10539
|
+
taskId: eventTaskId
|
|
10438
10540
|
});
|
|
10439
10541
|
updateDirectDispatchStatus(args.meshId, sessionId, outcome);
|
|
10440
10542
|
markSessionDeliveriesTerminal(args.meshId, sessionId, outcome);
|
|
@@ -10845,11 +10947,11 @@ function setupMeshEventForwarding(components) {
|
|
|
10845
10947
|
});
|
|
10846
10948
|
});
|
|
10847
10949
|
}
|
|
10848
|
-
var
|
|
10950
|
+
var import_fs12, REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, MESH_FORCE_INJECT_EVENTS;
|
|
10849
10951
|
var init_mesh_events_coordinator = __esm({
|
|
10850
10952
|
"src/mesh/mesh-events-coordinator.ts"() {
|
|
10851
10953
|
"use strict";
|
|
10852
|
-
|
|
10954
|
+
import_fs12 = require("fs");
|
|
10853
10955
|
init_config();
|
|
10854
10956
|
init_mesh_config();
|
|
10855
10957
|
init_cli_detector();
|
|
@@ -12731,16 +12833,16 @@ __export(external_sources_exports, {
|
|
|
12731
12833
|
sourcesProviding: () => sourcesProviding
|
|
12732
12834
|
});
|
|
12733
12835
|
function adhdevDir() {
|
|
12734
|
-
return
|
|
12836
|
+
return path18.join(os11.homedir(), ".adhdev");
|
|
12735
12837
|
}
|
|
12736
12838
|
function externalRoot() {
|
|
12737
|
-
return
|
|
12839
|
+
return path18.join(adhdevDir(), "external");
|
|
12738
12840
|
}
|
|
12739
12841
|
function sourcesFilePath() {
|
|
12740
|
-
return
|
|
12842
|
+
return path18.join(adhdevDir(), SOURCES_FILENAME);
|
|
12741
12843
|
}
|
|
12742
12844
|
function activeFilePath() {
|
|
12743
|
-
return
|
|
12845
|
+
return path18.join(adhdevDir(), ACTIVE_FILENAME);
|
|
12744
12846
|
}
|
|
12745
12847
|
function ensureAdhdevDir() {
|
|
12746
12848
|
const d = adhdevDir();
|
|
@@ -12807,7 +12909,7 @@ function inventoryExternalSources() {
|
|
|
12807
12909
|
for (const sourceEntry of entries) {
|
|
12808
12910
|
if (!sourceEntry.isDirectory()) continue;
|
|
12809
12911
|
const sourceName = sourceEntry.name;
|
|
12810
|
-
const sourceDir =
|
|
12912
|
+
const sourceDir = path18.join(root, sourceName);
|
|
12811
12913
|
const providers = {};
|
|
12812
12914
|
let categoryEntries;
|
|
12813
12915
|
try {
|
|
@@ -12818,7 +12920,7 @@ function inventoryExternalSources() {
|
|
|
12818
12920
|
for (const categoryEntry of categoryEntries) {
|
|
12819
12921
|
if (!categoryEntry.isDirectory()) continue;
|
|
12820
12922
|
const category = categoryEntry.name;
|
|
12821
|
-
const categoryDir =
|
|
12923
|
+
const categoryDir = path18.join(sourceDir, category);
|
|
12822
12924
|
let typeEntries;
|
|
12823
12925
|
try {
|
|
12824
12926
|
typeEntries = fs9.readdirSync(categoryDir, { withFileTypes: true });
|
|
@@ -12828,9 +12930,9 @@ function inventoryExternalSources() {
|
|
|
12828
12930
|
const types = [];
|
|
12829
12931
|
for (const typeEntry of typeEntries) {
|
|
12830
12932
|
if (!typeEntry.isDirectory()) continue;
|
|
12831
|
-
const typeDir =
|
|
12832
|
-
const hasV1 = fs9.existsSync(
|
|
12833
|
-
const hasV0 = fs9.existsSync(
|
|
12933
|
+
const typeDir = path18.join(categoryDir, typeEntry.name);
|
|
12934
|
+
const hasV1 = fs9.existsSync(path18.join(typeDir, "provider.v1.json"));
|
|
12935
|
+
const hasV0 = fs9.existsSync(path18.join(typeDir, "provider.json"));
|
|
12834
12936
|
if (hasV1 || hasV0) types.push(typeEntry.name);
|
|
12835
12937
|
}
|
|
12836
12938
|
if (types.length > 0) providers[category] = types;
|
|
@@ -12853,13 +12955,13 @@ function resolveActiveSource(category, type, activeFile) {
|
|
|
12853
12955
|
}
|
|
12854
12956
|
return { source: candidates[0], ambiguous: true, candidates };
|
|
12855
12957
|
}
|
|
12856
|
-
var fs9, os11,
|
|
12958
|
+
var fs9, os11, path18, SOURCES_FILENAME, ACTIVE_FILENAME;
|
|
12857
12959
|
var init_external_sources = __esm({
|
|
12858
12960
|
"src/providers/external-sources.ts"() {
|
|
12859
12961
|
"use strict";
|
|
12860
12962
|
fs9 = __toESM(require("fs"));
|
|
12861
12963
|
os11 = __toESM(require("os"));
|
|
12862
|
-
|
|
12964
|
+
path18 = __toESM(require("path"));
|
|
12863
12965
|
SOURCES_FILENAME = "providers-sources.json";
|
|
12864
12966
|
ACTIVE_FILENAME = "providers-active.json";
|
|
12865
12967
|
}
|
|
@@ -13037,59 +13139,6 @@ var init_terminal_screen = __esm({
|
|
|
13037
13139
|
}
|
|
13038
13140
|
});
|
|
13039
13141
|
|
|
13040
|
-
// src/cli-adapters/resolve-executable.ts
|
|
13041
|
-
function resolveWin32GlobalBin(trimmed) {
|
|
13042
|
-
if (path18.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\")) {
|
|
13043
|
-
return null;
|
|
13044
|
-
}
|
|
13045
|
-
const extraDirs = [];
|
|
13046
|
-
if (process.env.APPDATA) extraDirs.push(path18.join(process.env.APPDATA, "npm"));
|
|
13047
|
-
try {
|
|
13048
|
-
extraDirs.push(path18.dirname(process.execPath));
|
|
13049
|
-
} catch {
|
|
13050
|
-
}
|
|
13051
|
-
for (const dir of extraDirs) {
|
|
13052
|
-
if (!dir) continue;
|
|
13053
|
-
for (const ext of WIN_EXEC_EXT) {
|
|
13054
|
-
const full = path18.join(dir, trimmed + ext);
|
|
13055
|
-
if ((0, import_fs14.existsSync)(full)) return full;
|
|
13056
|
-
}
|
|
13057
|
-
}
|
|
13058
|
-
return null;
|
|
13059
|
-
}
|
|
13060
|
-
function resolveWin32Executable(command) {
|
|
13061
|
-
if (process.platform !== "win32") return command;
|
|
13062
|
-
const trimmed = (command || "").trim();
|
|
13063
|
-
if (!trimmed) return command;
|
|
13064
|
-
if (path18.isAbsolute(trimmed) && (0, import_fs14.existsSync)(trimmed)) return trimmed;
|
|
13065
|
-
try {
|
|
13066
|
-
const out = (0, import_child_process4.execFileSync)("where", [trimmed], {
|
|
13067
|
-
encoding: "utf8",
|
|
13068
|
-
windowsHide: true
|
|
13069
|
-
}).trim();
|
|
13070
|
-
if (out) {
|
|
13071
|
-
const matches = out.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
13072
|
-
const direct = matches.find((m) => DIRECT_EXEC_EXT.has(path18.extname(m).toLowerCase()));
|
|
13073
|
-
return direct || matches[0] || command;
|
|
13074
|
-
}
|
|
13075
|
-
} catch {
|
|
13076
|
-
}
|
|
13077
|
-
const globalBin = resolveWin32GlobalBin(trimmed);
|
|
13078
|
-
if (globalBin) return globalBin;
|
|
13079
|
-
return command;
|
|
13080
|
-
}
|
|
13081
|
-
var import_child_process4, import_fs14, path18, DIRECT_EXEC_EXT, WIN_EXEC_EXT;
|
|
13082
|
-
var init_resolve_executable = __esm({
|
|
13083
|
-
"src/cli-adapters/resolve-executable.ts"() {
|
|
13084
|
-
"use strict";
|
|
13085
|
-
import_child_process4 = require("child_process");
|
|
13086
|
-
import_fs14 = require("fs");
|
|
13087
|
-
path18 = __toESM(require("path"));
|
|
13088
|
-
DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
|
|
13089
|
-
WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
|
|
13090
|
-
}
|
|
13091
|
-
});
|
|
13092
|
-
|
|
13093
13142
|
// src/cli-adapters/pty-transport.ts
|
|
13094
13143
|
var pty_transport_exports = {};
|
|
13095
13144
|
__export(pty_transport_exports, {
|
|
@@ -15079,7 +15128,7 @@ function appendBoundedText(current, chunk, maxChars) {
|
|
|
15079
15128
|
if (current.length <= keepFromCurrent) return current + chunk;
|
|
15080
15129
|
return current.slice(-keepFromCurrent) + chunk;
|
|
15081
15130
|
}
|
|
15082
|
-
var os14, import_session_host_core5, ProviderCliAdapter;
|
|
15131
|
+
var os14, import_session_host_core5, FORCE_SUBMIT_SETTLE_MS, FORCE_SUBMIT_MAX_WAIT_MS, FORCE_SUBMIT_POLL_MS, ProviderCliAdapter;
|
|
15083
15132
|
var init_provider_cli_adapter = __esm({
|
|
15084
15133
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
15085
15134
|
"use strict";
|
|
@@ -15096,6 +15145,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
15096
15145
|
init_provider_cli_config();
|
|
15097
15146
|
init_provider_cli_runtime();
|
|
15098
15147
|
init_provider_cli_shared();
|
|
15148
|
+
FORCE_SUBMIT_SETTLE_MS = 150;
|
|
15149
|
+
FORCE_SUBMIT_MAX_WAIT_MS = 1500;
|
|
15150
|
+
FORCE_SUBMIT_POLL_MS = 50;
|
|
15099
15151
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
15100
15152
|
constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
|
|
15101
15153
|
this.extraArgs = extraArgs;
|
|
@@ -16024,9 +16076,23 @@ ${lastSnapshot}`;
|
|
|
16024
16076
|
return;
|
|
16025
16077
|
}
|
|
16026
16078
|
LOG.info("CLI", `[${this.cliType}] force-sending prompt while status=${this.engine.currentStatus}`);
|
|
16027
|
-
await this.writeToPty(content
|
|
16079
|
+
await this.writeToPty(content);
|
|
16080
|
+
await this.waitForForceSubmitSettle(content);
|
|
16081
|
+
await this.writeToPty(this.sendKey);
|
|
16028
16082
|
this.onStatusChange?.();
|
|
16029
16083
|
}
|
|
16084
|
+
async waitForForceSubmitSettle(content) {
|
|
16085
|
+
const startedAt = Date.now();
|
|
16086
|
+
const normalizedPromptSnippet = normalizePromptText(extractPromptRetrySnippet(content));
|
|
16087
|
+
await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_SETTLE_MS));
|
|
16088
|
+
if (!normalizedPromptSnippet) return;
|
|
16089
|
+
while (Date.now() - startedAt < FORCE_SUBMIT_MAX_WAIT_MS) {
|
|
16090
|
+
if (!this.ptyProcess) return;
|
|
16091
|
+
const screenText = this.terminalScreen.getText();
|
|
16092
|
+
if (promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
16093
|
+
await new Promise((resolve24) => setTimeout(resolve24, FORCE_SUBMIT_POLL_MS));
|
|
16094
|
+
}
|
|
16095
|
+
}
|
|
16030
16096
|
enqueuePendingOutboundMessage(text, reason) {
|
|
16031
16097
|
const content = String(text || "");
|
|
16032
16098
|
const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
|
|
@@ -19793,13 +19859,20 @@ var MESH_REFINE_CONFIG_SCHEMA = {
|
|
|
19793
19859
|
function isMeshConfigRecord(value) {
|
|
19794
19860
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
19795
19861
|
}
|
|
19862
|
+
var SHELL_METACHAR_RE = /[;&|<>`$\n\r'"]/;
|
|
19863
|
+
var SAFE_TOKEN_RE = /^[A-Za-z0-9_@./:=+-]+$/;
|
|
19864
|
+
var SAFE_WIN32_EXEC_TOKEN_RE = /^[A-Za-z0-9_@./:=+\\-]+$/;
|
|
19796
19865
|
function tokenizeCommandString(command) {
|
|
19797
19866
|
const trimmed = command.trim();
|
|
19798
19867
|
if (!trimmed) return null;
|
|
19799
|
-
if (
|
|
19868
|
+
if (SHELL_METACHAR_RE.test(trimmed)) return null;
|
|
19800
19869
|
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
19801
19870
|
if (!tokens.length) return null;
|
|
19802
|
-
|
|
19871
|
+
const isWin32 = process.platform === "win32";
|
|
19872
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
19873
|
+
const re = isWin32 && i === 0 ? SAFE_WIN32_EXEC_TOKEN_RE : SAFE_TOKEN_RE;
|
|
19874
|
+
if (!re.test(tokens[i])) return null;
|
|
19875
|
+
}
|
|
19803
19876
|
return tokens;
|
|
19804
19877
|
}
|
|
19805
19878
|
function validateCategory(value) {
|
|
@@ -20009,12 +20082,13 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
|
|
|
20009
20082
|
}
|
|
20010
20083
|
|
|
20011
20084
|
// src/mesh/worktree-bootstrap-config.ts
|
|
20012
|
-
var
|
|
20085
|
+
var import_fs9 = require("fs");
|
|
20013
20086
|
var import_path8 = require("path");
|
|
20014
20087
|
var import_node_child_process3 = require("child_process");
|
|
20015
20088
|
var import_node_crypto2 = require("crypto");
|
|
20016
20089
|
var import_node_util3 = require("util");
|
|
20017
20090
|
var yaml3 = __toESM(require("js-yaml"));
|
|
20091
|
+
init_resolve_executable();
|
|
20018
20092
|
var MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
|
|
20019
20093
|
".adhdev/worktree_bootstrap.json",
|
|
20020
20094
|
".adhdev/worktree_bootstrap.yaml",
|
|
@@ -20102,9 +20176,9 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
20102
20176
|
}
|
|
20103
20177
|
for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
|
|
20104
20178
|
const configPath = (0, import_path8.join)(workspace, relative5);
|
|
20105
|
-
if (!(0,
|
|
20179
|
+
if (!(0, import_fs9.existsSync)(configPath)) continue;
|
|
20106
20180
|
try {
|
|
20107
|
-
const parsed = parseConfigText3(configPath, (0,
|
|
20181
|
+
const parsed = parseConfigText3(configPath, (0, import_fs9.readFileSync)(configPath, "utf-8"));
|
|
20108
20182
|
const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
|
|
20109
20183
|
if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
|
|
20110
20184
|
return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
|
|
@@ -20119,7 +20193,7 @@ function computeStaleInputsDigest(workspace, staleInputs) {
|
|
|
20119
20193
|
for (const relative5 of staleInputs ?? []) {
|
|
20120
20194
|
const filePath = (0, import_path8.join)(workspace, relative5);
|
|
20121
20195
|
try {
|
|
20122
|
-
digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0,
|
|
20196
|
+
digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs9.readFileSync)(filePath)).digest("hex");
|
|
20123
20197
|
} catch {
|
|
20124
20198
|
digest[relative5] = "absent";
|
|
20125
20199
|
}
|
|
@@ -20189,10 +20263,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
20189
20263
|
staleInputs: loaded.config.staleInputs
|
|
20190
20264
|
};
|
|
20191
20265
|
const staleInputPaths = loaded.config.staleInputs ?? [];
|
|
20192
|
-
const initiallyAbsent = staleInputPaths.filter((p) => !(0,
|
|
20266
|
+
const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs9.existsSync)((0, import_path8.join)(workspace, p)));
|
|
20193
20267
|
for (const command of validation.commands) {
|
|
20194
20268
|
if (initiallyAbsent.length > 0) {
|
|
20195
|
-
const appearedNow = initiallyAbsent.filter((p) => (0,
|
|
20269
|
+
const appearedNow = initiallyAbsent.filter((p) => (0, import_fs9.existsSync)((0, import_path8.join)(workspace, p)));
|
|
20196
20270
|
if (appearedNow.length > 0) {
|
|
20197
20271
|
state.status = "stale";
|
|
20198
20272
|
state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -20203,8 +20277,9 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
20203
20277
|
const cwd = command.cwd ? (0, import_path8.resolve)(workspace, command.cwd) : workspace;
|
|
20204
20278
|
const startedAt = Date.now();
|
|
20205
20279
|
state.lastCommand = command.displayCommand;
|
|
20280
|
+
const resolvedCommand = resolveWin32Executable(command.command);
|
|
20206
20281
|
try {
|
|
20207
|
-
const result = await execFileAsync4(
|
|
20282
|
+
const result = await execFileAsync4(resolvedCommand, command.args, {
|
|
20208
20283
|
cwd,
|
|
20209
20284
|
encoding: "utf8",
|
|
20210
20285
|
timeout: command.timeoutMs || DEFAULT_TIMEOUT_MS2,
|
|
@@ -20439,7 +20514,7 @@ var P2pRelayFailureError = class extends Error {
|
|
|
20439
20514
|
};
|
|
20440
20515
|
|
|
20441
20516
|
// src/config/state-store.ts
|
|
20442
|
-
var
|
|
20517
|
+
var import_fs13 = require("fs");
|
|
20443
20518
|
var import_path10 = require("path");
|
|
20444
20519
|
init_config();
|
|
20445
20520
|
var DEFAULT_STATE = {
|
|
@@ -20490,11 +20565,11 @@ function normalizeState(raw) {
|
|
|
20490
20565
|
}
|
|
20491
20566
|
function loadState() {
|
|
20492
20567
|
const statePath = getStatePath();
|
|
20493
|
-
if (!(0,
|
|
20568
|
+
if (!(0, import_fs13.existsSync)(statePath)) {
|
|
20494
20569
|
return { ...DEFAULT_STATE };
|
|
20495
20570
|
}
|
|
20496
20571
|
try {
|
|
20497
|
-
const raw = (0,
|
|
20572
|
+
const raw = (0, import_fs13.readFileSync)(statePath, "utf-8");
|
|
20498
20573
|
return normalizeState(JSON.parse(raw));
|
|
20499
20574
|
} catch {
|
|
20500
20575
|
return { ...DEFAULT_STATE };
|
|
@@ -20503,28 +20578,28 @@ function loadState() {
|
|
|
20503
20578
|
function saveState(state) {
|
|
20504
20579
|
const statePath = getStatePath();
|
|
20505
20580
|
const normalized = normalizeState(state);
|
|
20506
|
-
(0,
|
|
20581
|
+
(0, import_fs13.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
20507
20582
|
}
|
|
20508
20583
|
function resetState() {
|
|
20509
20584
|
saveState({ ...DEFAULT_STATE });
|
|
20510
20585
|
}
|
|
20511
20586
|
|
|
20512
20587
|
// src/detection/ide-detector.ts
|
|
20513
|
-
var
|
|
20588
|
+
var import_child_process3 = require("child_process");
|
|
20514
20589
|
var import_util = require("util");
|
|
20515
|
-
var
|
|
20590
|
+
var import_fs14 = require("fs");
|
|
20516
20591
|
var import_os2 = require("os");
|
|
20517
|
-
var
|
|
20592
|
+
var path14 = __toESM(require("path"));
|
|
20518
20593
|
|
|
20519
20594
|
// src/detection/win32-ide-version.ts
|
|
20520
20595
|
var fs5 = __toESM(require("fs"));
|
|
20521
|
-
var
|
|
20596
|
+
var path13 = __toESM(require("path"));
|
|
20522
20597
|
function manifestCandidates(exeDir) {
|
|
20523
20598
|
return [
|
|
20524
|
-
|
|
20525
|
-
|
|
20599
|
+
path13.join(exeDir, "resources", "app", "product.json"),
|
|
20600
|
+
path13.join(exeDir, "resources", "app", "package.json"),
|
|
20526
20601
|
// Some packagings keep product.json one level up.
|
|
20527
|
-
|
|
20602
|
+
path13.join(exeDir, "product.json")
|
|
20528
20603
|
];
|
|
20529
20604
|
}
|
|
20530
20605
|
function parseVersionFromManifest(raw) {
|
|
@@ -20542,9 +20617,9 @@ function readWin32IdeVersionFromDisk(exePath) {
|
|
|
20542
20617
|
if (!exePath) return null;
|
|
20543
20618
|
let exeDir;
|
|
20544
20619
|
try {
|
|
20545
|
-
exeDir = fs5.statSync(exePath).isDirectory() ? exePath :
|
|
20620
|
+
exeDir = fs5.statSync(exePath).isDirectory() ? exePath : path13.dirname(exePath);
|
|
20546
20621
|
} catch {
|
|
20547
|
-
exeDir =
|
|
20622
|
+
exeDir = path13.dirname(exePath);
|
|
20548
20623
|
}
|
|
20549
20624
|
for (const candidate of manifestCandidates(exeDir)) {
|
|
20550
20625
|
try {
|
|
@@ -20558,7 +20633,7 @@ function readWin32IdeVersionFromDisk(exePath) {
|
|
|
20558
20633
|
}
|
|
20559
20634
|
function isKnownWin32GuiExe(binPath, win32ProcessNames) {
|
|
20560
20635
|
if (!binPath) return false;
|
|
20561
|
-
const base =
|
|
20636
|
+
const base = path13.win32.basename(binPath).toLowerCase();
|
|
20562
20637
|
if (!base.endsWith(".exe")) return false;
|
|
20563
20638
|
for (const names of Object.values(win32ProcessNames)) {
|
|
20564
20639
|
for (const name of names) {
|
|
@@ -20571,7 +20646,7 @@ function isKnownWin32GuiExe(binPath, win32ProcessNames) {
|
|
|
20571
20646
|
}
|
|
20572
20647
|
|
|
20573
20648
|
// src/detection/ide-detector.ts
|
|
20574
|
-
var execAsync2 = (0, import_util.promisify)(
|
|
20649
|
+
var execAsync2 = (0, import_util.promisify)(import_child_process3.exec);
|
|
20575
20650
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
20576
20651
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
20577
20652
|
function registerIDEDefinition(def) {
|
|
@@ -20590,10 +20665,10 @@ function getMergedDefinitions() {
|
|
|
20590
20665
|
function findCliCommand(command) {
|
|
20591
20666
|
const trimmed = String(command || "").trim();
|
|
20592
20667
|
if (!trimmed) return null;
|
|
20593
|
-
if (
|
|
20594
|
-
const candidate = trimmed.startsWith("~") ?
|
|
20595
|
-
const resolved =
|
|
20596
|
-
return (0,
|
|
20668
|
+
if (path14.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
20669
|
+
const candidate = trimmed.startsWith("~") ? path14.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
20670
|
+
const resolved = path14.isAbsolute(candidate) ? candidate : path14.resolve(candidate);
|
|
20671
|
+
return (0, import_fs14.existsSync)(resolved) ? resolved : null;
|
|
20597
20672
|
}
|
|
20598
20673
|
const isWin = (0, import_os2.platform)() === "win32";
|
|
20599
20674
|
const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
|
|
@@ -20601,10 +20676,10 @@ function findCliCommand(command) {
|
|
|
20601
20676
|
for (const p of paths) {
|
|
20602
20677
|
if (!p) continue;
|
|
20603
20678
|
for (const ext of exes) {
|
|
20604
|
-
const fullPath =
|
|
20679
|
+
const fullPath = path14.join(p, trimmed + ext);
|
|
20605
20680
|
try {
|
|
20606
|
-
if ((0,
|
|
20607
|
-
const stat2 = (0,
|
|
20681
|
+
if ((0, import_fs14.existsSync)(fullPath)) {
|
|
20682
|
+
const stat2 = (0, import_fs14.statSync)(fullPath);
|
|
20608
20683
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
20609
20684
|
return fullPath;
|
|
20610
20685
|
}
|
|
@@ -20618,13 +20693,13 @@ function findCliCommand(command) {
|
|
|
20618
20693
|
function checkPathExists(paths) {
|
|
20619
20694
|
const home = (0, import_os2.homedir)();
|
|
20620
20695
|
for (const p of paths) {
|
|
20621
|
-
const normalized = p.startsWith("~") ?
|
|
20696
|
+
const normalized = p.startsWith("~") ? path14.join(home, p.slice(1)) : p;
|
|
20622
20697
|
if (normalized.includes("*")) {
|
|
20623
20698
|
const username = home.split(/[\\/]/).pop() || "";
|
|
20624
20699
|
const resolved = normalized.replace("*", username);
|
|
20625
|
-
if ((0,
|
|
20700
|
+
if ((0, import_fs14.existsSync)(resolved)) return resolved;
|
|
20626
20701
|
} else {
|
|
20627
|
-
if ((0,
|
|
20702
|
+
if ((0, import_fs14.existsSync)(normalized)) return normalized;
|
|
20628
20703
|
}
|
|
20629
20704
|
}
|
|
20630
20705
|
return null;
|
|
@@ -20638,7 +20713,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20638
20713
|
let resolvedCli = cliPath;
|
|
20639
20714
|
if (!resolvedCli && appPath && os30 === "darwin") {
|
|
20640
20715
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
20641
|
-
if ((0,
|
|
20716
|
+
if ((0, import_fs14.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
20642
20717
|
}
|
|
20643
20718
|
if (!resolvedCli && appPath && os30 === "win32") {
|
|
20644
20719
|
const { dirname: dirname17 } = await import("path");
|
|
@@ -20651,7 +20726,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20651
20726
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
20652
20727
|
];
|
|
20653
20728
|
for (const c of candidates) {
|
|
20654
|
-
if ((0,
|
|
20729
|
+
if ((0, import_fs14.existsSync)(c)) {
|
|
20655
20730
|
resolvedCli = c;
|
|
20656
20731
|
break;
|
|
20657
20732
|
}
|
|
@@ -20678,9 +20753,9 @@ init_cli_detector();
|
|
|
20678
20753
|
|
|
20679
20754
|
// src/system/host-memory.ts
|
|
20680
20755
|
var os7 = __toESM(require("os"));
|
|
20681
|
-
var
|
|
20756
|
+
var import_child_process4 = require("child_process");
|
|
20682
20757
|
var import_util2 = require("util");
|
|
20683
|
-
var execAsync3 = (0, import_util2.promisify)(
|
|
20758
|
+
var execAsync3 = (0, import_util2.promisify)(import_child_process4.exec);
|
|
20684
20759
|
var cachedDarwinAvail = null;
|
|
20685
20760
|
var darwinMemoryInterval = null;
|
|
20686
20761
|
async function updateDarwinMemoryCache() {
|
|
@@ -22509,10 +22584,10 @@ ${cleanBody}`;
|
|
|
22509
22584
|
|
|
22510
22585
|
// src/config/chat-history.ts
|
|
22511
22586
|
var fs6 = __toESM(require("fs"));
|
|
22512
|
-
var
|
|
22587
|
+
var path15 = __toESM(require("path"));
|
|
22513
22588
|
var os8 = __toESM(require("os"));
|
|
22514
22589
|
init_chat_message_normalization();
|
|
22515
|
-
var HISTORY_DIR =
|
|
22590
|
+
var HISTORY_DIR = path15.join(os8.homedir(), ".adhdev", "history");
|
|
22516
22591
|
var RETAIN_DAYS = 30;
|
|
22517
22592
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
22518
22593
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -22698,7 +22773,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
22698
22773
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
22699
22774
|
return new Map(files.map((file) => {
|
|
22700
22775
|
try {
|
|
22701
|
-
const stat2 = fs6.statSync(
|
|
22776
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22702
22777
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
22703
22778
|
} catch {
|
|
22704
22779
|
return [file, `${file}:missing`];
|
|
@@ -22709,7 +22784,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
22709
22784
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
22710
22785
|
}
|
|
22711
22786
|
function getSavedHistoryIndexFilePath(dir) {
|
|
22712
|
-
return
|
|
22787
|
+
return path15.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
22713
22788
|
}
|
|
22714
22789
|
function getSavedHistoryIndexLockPath(dir) {
|
|
22715
22790
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -22811,7 +22886,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
22811
22886
|
}
|
|
22812
22887
|
for (const file of Array.from(currentEntries.keys())) {
|
|
22813
22888
|
if (incomingFiles.has(file)) continue;
|
|
22814
|
-
if (!fs6.existsSync(
|
|
22889
|
+
if (!fs6.existsSync(path15.join(dir, file))) {
|
|
22815
22890
|
currentEntries.delete(file);
|
|
22816
22891
|
}
|
|
22817
22892
|
}
|
|
@@ -22837,7 +22912,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
22837
22912
|
const indexStat = fs6.statSync(getSavedHistoryIndexFilePath(dir));
|
|
22838
22913
|
const files = listHistoryFiles(dir);
|
|
22839
22914
|
for (const file of files) {
|
|
22840
|
-
const stat2 = fs6.statSync(
|
|
22915
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22841
22916
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
22842
22917
|
}
|
|
22843
22918
|
return false;
|
|
@@ -22847,14 +22922,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
22847
22922
|
}
|
|
22848
22923
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
22849
22924
|
try {
|
|
22850
|
-
const stat2 = fs6.statSync(
|
|
22925
|
+
const stat2 = fs6.statSync(path15.join(dir, file));
|
|
22851
22926
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
22852
22927
|
} catch {
|
|
22853
22928
|
return `${file}:missing`;
|
|
22854
22929
|
}
|
|
22855
22930
|
}
|
|
22856
22931
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
22857
|
-
const filePath =
|
|
22932
|
+
const filePath = path15.join(dir, file);
|
|
22858
22933
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
22859
22934
|
const currentEntry = entries.get(file) || null;
|
|
22860
22935
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -22927,7 +23002,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
22927
23002
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
22928
23003
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
22929
23004
|
if (!historySessionId) return null;
|
|
22930
|
-
const filePath =
|
|
23005
|
+
const filePath = path15.join(dir, file);
|
|
22931
23006
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
22932
23007
|
const lines = content.split("\n").filter(Boolean);
|
|
22933
23008
|
let messageCount = 0;
|
|
@@ -23014,7 +23089,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
23014
23089
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
23015
23090
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
23016
23091
|
for (const file of files.slice().sort()) {
|
|
23017
|
-
const filePath =
|
|
23092
|
+
const filePath = path15.join(dir, file);
|
|
23018
23093
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
23019
23094
|
const cached3 = savedHistoryFileSummaryCache.get(filePath);
|
|
23020
23095
|
const persisted = persistedEntries.get(file);
|
|
@@ -23134,12 +23209,12 @@ var ChatHistoryWriter = class {
|
|
|
23134
23209
|
});
|
|
23135
23210
|
}
|
|
23136
23211
|
if (newMessages.length === 0) return;
|
|
23137
|
-
const dir =
|
|
23212
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
23138
23213
|
fs6.mkdirSync(dir, { recursive: true });
|
|
23139
23214
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
23140
23215
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
23141
23216
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
23142
|
-
const filePath =
|
|
23217
|
+
const filePath = path15.join(dir, fileName);
|
|
23143
23218
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
23144
23219
|
fs6.appendFileSync(filePath, lines, "utf-8");
|
|
23145
23220
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -23230,11 +23305,11 @@ var ChatHistoryWriter = class {
|
|
|
23230
23305
|
const ws = String(workspace || "").trim();
|
|
23231
23306
|
if (!id || !ws) return;
|
|
23232
23307
|
try {
|
|
23233
|
-
const dir =
|
|
23308
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
23234
23309
|
fs6.mkdirSync(dir, { recursive: true });
|
|
23235
23310
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
23236
23311
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
23237
|
-
const filePath =
|
|
23312
|
+
const filePath = path15.join(dir, fileName);
|
|
23238
23313
|
const record = {
|
|
23239
23314
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23240
23315
|
receivedAt: Date.now(),
|
|
@@ -23280,14 +23355,14 @@ var ChatHistoryWriter = class {
|
|
|
23280
23355
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
23281
23356
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
23282
23357
|
}
|
|
23283
|
-
const dir =
|
|
23358
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
23284
23359
|
if (!fs6.existsSync(dir)) return;
|
|
23285
23360
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
23286
23361
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
23287
23362
|
const files = fs6.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
23288
23363
|
for (const file of files) {
|
|
23289
|
-
const sourcePath =
|
|
23290
|
-
const targetPath =
|
|
23364
|
+
const sourcePath = path15.join(dir, file);
|
|
23365
|
+
const targetPath = path15.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
23291
23366
|
const sourceLines = fs6.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
23292
23367
|
const rewritten = sourceLines.map((line) => {
|
|
23293
23368
|
try {
|
|
@@ -23321,13 +23396,13 @@ var ChatHistoryWriter = class {
|
|
|
23321
23396
|
const sessionId = String(historySessionId || "").trim();
|
|
23322
23397
|
if (!sessionId) return;
|
|
23323
23398
|
try {
|
|
23324
|
-
const dir =
|
|
23399
|
+
const dir = path15.join(HISTORY_DIR, this.sanitize(agentType));
|
|
23325
23400
|
if (!fs6.existsSync(dir)) return;
|
|
23326
23401
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
23327
23402
|
const files = fs6.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
23328
23403
|
const seen = /* @__PURE__ */ new Set();
|
|
23329
23404
|
for (const file of files) {
|
|
23330
|
-
const filePath =
|
|
23405
|
+
const filePath = path15.join(dir, file);
|
|
23331
23406
|
const lines = fs6.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
23332
23407
|
const next = [];
|
|
23333
23408
|
for (const line of lines) {
|
|
@@ -23381,11 +23456,11 @@ var ChatHistoryWriter = class {
|
|
|
23381
23456
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
23382
23457
|
const agentDirs = fs6.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
23383
23458
|
for (const dir of agentDirs) {
|
|
23384
|
-
const dirPath =
|
|
23459
|
+
const dirPath = path15.join(HISTORY_DIR, dir.name);
|
|
23385
23460
|
const files = fs6.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
23386
23461
|
let removedAny = false;
|
|
23387
23462
|
for (const file of files) {
|
|
23388
|
-
const filePath =
|
|
23463
|
+
const filePath = path15.join(dirPath, file);
|
|
23389
23464
|
const stat2 = fs6.statSync(filePath);
|
|
23390
23465
|
if (stat2.mtimeMs < cutoff) {
|
|
23391
23466
|
fs6.unlinkSync(filePath);
|
|
@@ -23588,7 +23663,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
|
23588
23663
|
const seen = /* @__PURE__ */ new Set();
|
|
23589
23664
|
let readAllFiles = true;
|
|
23590
23665
|
for (let f = 0; f < files.length; f++) {
|
|
23591
|
-
const filePath =
|
|
23666
|
+
const filePath = path15.join(dir, files[f]);
|
|
23592
23667
|
const remaining = Math.max(0, needed - collected.length);
|
|
23593
23668
|
const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
|
|
23594
23669
|
const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
|
|
@@ -23621,7 +23696,7 @@ function readBoundedTailRecords(agentType, dir, files, needed) {
|
|
|
23621
23696
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
23622
23697
|
try {
|
|
23623
23698
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
23624
|
-
const dir =
|
|
23699
|
+
const dir = path15.join(HISTORY_DIR, sanitized);
|
|
23625
23700
|
if (!fs6.existsSync(dir)) return { messages: [], hasMore: false };
|
|
23626
23701
|
const files = listHistoryFiles(dir, historySessionId);
|
|
23627
23702
|
const bounded = isBoundedTailRequest(limit, offset, excludeRecentCount);
|
|
@@ -23644,7 +23719,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
23644
23719
|
const allMessages = [];
|
|
23645
23720
|
const seen = /* @__PURE__ */ new Set();
|
|
23646
23721
|
for (const file of files) {
|
|
23647
|
-
const filePath =
|
|
23722
|
+
const filePath = path15.join(dir, file);
|
|
23648
23723
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
23649
23724
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
23650
23725
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -23668,7 +23743,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
23668
23743
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
23669
23744
|
try {
|
|
23670
23745
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
23671
|
-
const dir =
|
|
23746
|
+
const dir = path15.join(HISTORY_DIR, sanitized);
|
|
23672
23747
|
if (!fs6.existsSync(dir)) {
|
|
23673
23748
|
savedHistorySessionCache.delete(sanitized);
|
|
23674
23749
|
return { sessions: [], hasMore: false };
|
|
@@ -23729,11 +23804,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
23729
23804
|
}
|
|
23730
23805
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
23731
23806
|
try {
|
|
23732
|
-
const dir =
|
|
23807
|
+
const dir = path15.join(HISTORY_DIR, agentType);
|
|
23733
23808
|
if (!fs6.existsSync(dir)) return null;
|
|
23734
23809
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
23735
23810
|
for (const file of files) {
|
|
23736
|
-
const lines = fs6.readFileSync(
|
|
23811
|
+
const lines = fs6.readFileSync(path15.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
23737
23812
|
for (const line of lines) {
|
|
23738
23813
|
try {
|
|
23739
23814
|
const parsed = JSON.parse(line);
|
|
@@ -23753,16 +23828,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
23753
23828
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
23754
23829
|
if (records.length === 0) return false;
|
|
23755
23830
|
try {
|
|
23756
|
-
const dir =
|
|
23831
|
+
const dir = path15.join(HISTORY_DIR, agentType);
|
|
23757
23832
|
fs6.mkdirSync(dir, { recursive: true });
|
|
23758
23833
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
23759
23834
|
for (const file of fs6.readdirSync(dir)) {
|
|
23760
23835
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
23761
|
-
fs6.unlinkSync(
|
|
23836
|
+
fs6.unlinkSync(path15.join(dir, file));
|
|
23762
23837
|
}
|
|
23763
23838
|
}
|
|
23764
23839
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
23765
|
-
const filePath =
|
|
23840
|
+
const filePath = path15.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
23766
23841
|
fs6.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
23767
23842
|
`, "utf-8");
|
|
23768
23843
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -26367,7 +26442,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
26367
26442
|
// src/commands/chat-commands.ts
|
|
26368
26443
|
var fs7 = __toESM(require("fs"));
|
|
26369
26444
|
var os9 = __toESM(require("os"));
|
|
26370
|
-
var
|
|
26445
|
+
var path16 = __toESM(require("path"));
|
|
26371
26446
|
var import_node_crypto3 = require("crypto");
|
|
26372
26447
|
init_contracts();
|
|
26373
26448
|
init_logger();
|
|
@@ -27418,7 +27493,7 @@ function readExactRuntimeMirrorMessages(args) {
|
|
|
27418
27493
|
function normalizeComparableWorkspace(value) {
|
|
27419
27494
|
const text = typeof value === "string" ? value.trim() : "";
|
|
27420
27495
|
if (!text) return "";
|
|
27421
|
-
return
|
|
27496
|
+
return path16.resolve(text);
|
|
27422
27497
|
}
|
|
27423
27498
|
function isCurrentRuntimePtySafelyAttributed(args) {
|
|
27424
27499
|
if (args.adapter.cliType !== "codex-cli") return false;
|
|
@@ -27903,7 +27978,7 @@ function buildDebugBundleText(bundle) {
|
|
|
27903
27978
|
}
|
|
27904
27979
|
function getChatDebugBundleDir() {
|
|
27905
27980
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
27906
|
-
return override ||
|
|
27981
|
+
return override || path16.join(os9.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
27907
27982
|
}
|
|
27908
27983
|
function safeBundleIdSegment(value, fallback) {
|
|
27909
27984
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -27960,7 +28035,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
27960
28035
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
27961
28036
|
const dir = getChatDebugBundleDir();
|
|
27962
28037
|
fs7.mkdirSync(dir, { recursive: true });
|
|
27963
|
-
const savedPath =
|
|
28038
|
+
const savedPath = path16.join(dir, `${bundleId}.json`);
|
|
27964
28039
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
27965
28040
|
`;
|
|
27966
28041
|
fs7.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -29524,7 +29599,7 @@ async function handleResolveAction(h, args) {
|
|
|
29524
29599
|
|
|
29525
29600
|
// src/commands/cdp-commands.ts
|
|
29526
29601
|
var fs8 = __toESM(require("fs"));
|
|
29527
|
-
var
|
|
29602
|
+
var path17 = __toESM(require("path"));
|
|
29528
29603
|
var os10 = __toESM(require("os"));
|
|
29529
29604
|
var KEY_TO_VK = {
|
|
29530
29605
|
Backspace: 8,
|
|
@@ -29781,25 +29856,25 @@ function resolveSafePath(requestedPath) {
|
|
|
29781
29856
|
const inputPath = rawPath || ".";
|
|
29782
29857
|
const home = os10.homedir();
|
|
29783
29858
|
if (inputPath.startsWith("~")) {
|
|
29784
|
-
return
|
|
29859
|
+
return path17.resolve(path17.join(home, inputPath.slice(1)));
|
|
29785
29860
|
}
|
|
29786
29861
|
if (process.platform === "win32") {
|
|
29787
29862
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
29788
|
-
if (
|
|
29789
|
-
return
|
|
29863
|
+
if (path17.win32.isAbsolute(normalized)) {
|
|
29864
|
+
return path17.win32.normalize(normalized);
|
|
29790
29865
|
}
|
|
29791
|
-
return
|
|
29866
|
+
return path17.win32.resolve(normalized);
|
|
29792
29867
|
}
|
|
29793
|
-
if (
|
|
29794
|
-
return
|
|
29868
|
+
if (path17.isAbsolute(inputPath)) {
|
|
29869
|
+
return path17.normalize(inputPath);
|
|
29795
29870
|
}
|
|
29796
|
-
return
|
|
29871
|
+
return path17.resolve(inputPath);
|
|
29797
29872
|
}
|
|
29798
29873
|
function listDirectoryEntriesSafe(dirPath) {
|
|
29799
29874
|
const entries = fs8.readdirSync(dirPath, { withFileTypes: true });
|
|
29800
29875
|
const files = [];
|
|
29801
29876
|
for (const entry of entries) {
|
|
29802
|
-
const entryPath =
|
|
29877
|
+
const entryPath = path17.join(dirPath, entry.name);
|
|
29803
29878
|
try {
|
|
29804
29879
|
if (entry.isDirectory()) {
|
|
29805
29880
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -29853,7 +29928,7 @@ async function handleFileRead(h, args) {
|
|
|
29853
29928
|
async function handleFileWrite(h, args) {
|
|
29854
29929
|
try {
|
|
29855
29930
|
const filePath = resolveSafePath(args?.path);
|
|
29856
|
-
fs8.mkdirSync(
|
|
29931
|
+
fs8.mkdirSync(path17.dirname(filePath), { recursive: true });
|
|
29857
29932
|
fs8.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
29858
29933
|
return { success: true, path: filePath };
|
|
29859
29934
|
} catch (e) {
|
|
@@ -43661,6 +43736,7 @@ var import_os3 = require("os");
|
|
|
43661
43736
|
var import_path12 = require("path");
|
|
43662
43737
|
var fs26 = __toESM(require("fs"));
|
|
43663
43738
|
var import_node_child_process6 = require("child_process");
|
|
43739
|
+
init_resolve_executable();
|
|
43664
43740
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
43665
43741
|
var CHANNEL_SERVER_URL = {
|
|
43666
43742
|
stable: "https://api.adhf.dev",
|
|
@@ -44759,6 +44835,18 @@ function truncateValidationOutput(value) {
|
|
|
44759
44835
|
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
44760
44836
|
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
44761
44837
|
}
|
|
44838
|
+
function isSpawnResolutionError(error) {
|
|
44839
|
+
if (!error) return false;
|
|
44840
|
+
if (error.code === "ENOENT" && typeof error.syscall === "string" && error.syscall.startsWith("spawn")) return true;
|
|
44841
|
+
return error.code === "ENOENT" && (error.syscall === void 0 || String(error.syscall).startsWith("spawn"));
|
|
44842
|
+
}
|
|
44843
|
+
function describeSpawnError(error, command, spawnResolutionFailed) {
|
|
44844
|
+
if (spawnResolutionFailed) {
|
|
44845
|
+
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." : "";
|
|
44846
|
+
return `Could not resolve executable "${command}" (spawn ENOENT).${hint}`;
|
|
44847
|
+
}
|
|
44848
|
+
return String(error?.message || error);
|
|
44849
|
+
}
|
|
44762
44850
|
function recordMeshRefineStage(stages, stage, status, startedAt, details) {
|
|
44763
44851
|
stages.push({
|
|
44764
44852
|
stage,
|
|
@@ -45660,8 +45748,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45660
45748
|
const startedAt = Date.now();
|
|
45661
45749
|
const cwd = candidate.cwd ? (0, import_path12.resolve)(workspace, candidate.cwd) : workspace;
|
|
45662
45750
|
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
45751
|
+
const resolvedCommand = resolveWin32Executable(candidate.command);
|
|
45663
45752
|
try {
|
|
45664
|
-
const result = await execFileAsync4(
|
|
45753
|
+
const result = await execFileAsync4(resolvedCommand, candidate.args, {
|
|
45665
45754
|
cwd,
|
|
45666
45755
|
encoding: "utf8",
|
|
45667
45756
|
timeout,
|
|
@@ -45670,16 +45759,17 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45670
45759
|
});
|
|
45671
45760
|
summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
|
|
45672
45761
|
} catch (error) {
|
|
45762
|
+
const spawnResolutionFailed = isSpawnResolutionError(error);
|
|
45673
45763
|
summary.bootstrapCommandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
|
|
45674
45764
|
exitCode: typeof error?.code === "number" ? error.code : null,
|
|
45675
45765
|
signal: typeof error?.signal === "string" ? error.signal : null,
|
|
45676
45766
|
timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
|
|
45677
|
-
failureKind: "dependency_bootstrap_failed"
|
|
45767
|
+
...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : { failureKind: "dependency_bootstrap_failed" }
|
|
45678
45768
|
}));
|
|
45679
|
-
summary.bootstrap = { stage: "failed", error:
|
|
45769
|
+
summary.bootstrap = { stage: "failed", error: describeSpawnError(error, candidate.command, spawnResolutionFailed) };
|
|
45680
45770
|
summary.status = "failed";
|
|
45681
|
-
summary.failureKind = "dependency_bootstrap_failed";
|
|
45682
|
-
summary.failureCode = "dependency_bootstrap_failed";
|
|
45771
|
+
summary.failureKind = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
|
|
45772
|
+
summary.failureCode = spawnResolutionFailed ? "spawn_resolution_failed" : "dependency_bootstrap_failed";
|
|
45683
45773
|
return summary;
|
|
45684
45774
|
}
|
|
45685
45775
|
}
|
|
@@ -45702,8 +45792,9 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45702
45792
|
summary.failureCode = "missing_dependencies";
|
|
45703
45793
|
return summary;
|
|
45704
45794
|
}
|
|
45795
|
+
const resolvedCommand = resolveWin32Executable(candidate.command);
|
|
45705
45796
|
try {
|
|
45706
|
-
const result = await execFileAsync4(
|
|
45797
|
+
const result = await execFileAsync4(resolvedCommand, candidate.args, {
|
|
45707
45798
|
cwd,
|
|
45708
45799
|
encoding: "utf8",
|
|
45709
45800
|
timeout,
|
|
@@ -45712,16 +45803,21 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45712
45803
|
});
|
|
45713
45804
|
summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, result, true, { exitCode: 0 }));
|
|
45714
45805
|
} catch (error) {
|
|
45806
|
+
const spawnResolutionFailed = isSpawnResolutionError(error);
|
|
45715
45807
|
const stderr = truncateValidationOutput(error?.stderr || error?.message);
|
|
45716
|
-
const missingDependencyFailure = /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
|
|
45808
|
+
const missingDependencyFailure = !spawnResolutionFailed && /Cannot find module|MODULE_NOT_FOUND|node_modules|command not found|not found/i.test(stderr);
|
|
45717
45809
|
summary.commandsRun.push(commandRecord(candidate, cwd, startedAt, error, false, {
|
|
45718
45810
|
exitCode: typeof error?.code === "number" ? error.code : null,
|
|
45719
45811
|
signal: typeof error?.signal === "string" ? error.signal : null,
|
|
45720
45812
|
timedOut: error?.killed === true || /timed out/i.test(String(error?.message || "")),
|
|
45721
|
-
...missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
|
|
45813
|
+
...spawnResolutionFailed ? { failureKind: "spawn_resolution_failed", resolvedCommand } : missingDependencyFailure ? { failureKind: "missing_dependencies" } : {}
|
|
45722
45814
|
}));
|
|
45723
45815
|
summary.status = "failed";
|
|
45724
|
-
if (
|
|
45816
|
+
if (spawnResolutionFailed) {
|
|
45817
|
+
summary.failureKind = "spawn_resolution_failed";
|
|
45818
|
+
summary.failureCode = "spawn_resolution_failed";
|
|
45819
|
+
summary.spawnResolutionError = describeSpawnError(error, candidate.command, true);
|
|
45820
|
+
} else if (missingDependencyFailure) {
|
|
45725
45821
|
summary.failureKind = "missing_dependencies";
|
|
45726
45822
|
summary.failureCode = "missing_dependencies";
|
|
45727
45823
|
}
|
|
@@ -46982,7 +47078,7 @@ var DaemonCommandRouter = class {
|
|
|
46982
47078
|
if (validationSummary.status === "failed") {
|
|
46983
47079
|
const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
|
|
46984
47080
|
const buildValidationFailedError = () => {
|
|
46985
|
-
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.";
|
|
47081
|
+
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.";
|
|
46986
47082
|
if (!firstFailedCmd) return base;
|
|
46987
47083
|
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 : "";
|
|
46988
47084
|
const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
|