@adhdev/daemon-core 0.9.82-rc.328 → 0.9.82-rc.329
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-shared.d.ts +1 -1
- package/dist/git/change-impact-config.d.ts +159 -0
- package/dist/git/git-status.d.ts +14 -0
- package/dist/git/index.d.ts +2 -0
- package/dist/index.js +647 -281
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +598 -238
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-stale.d.ts +1 -1
- package/dist/providers/status-monitor.d.ts +7 -7
- package/dist/shared-types.d.ts +1 -1
- package/package.json +2 -2
- package/src/agent-stream/provider-adapter.ts +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +2 -2
- package/src/cli-adapters/provider-cli-shared.ts +1 -1
- package/src/commands/chat-commands.ts +1 -1
- package/src/commands/cli-manager.ts +1 -1
- package/src/commands/router.ts +46 -0
- package/src/git/change-impact-config.ts +354 -0
- package/src/git/git-status.ts +182 -16
- package/src/git/index.ts +16 -0
- package/src/mesh/mesh-events-coordinator.ts +13 -12
- package/src/mesh/mesh-events-stale.ts +4 -4
- package/src/mesh/mesh-events-utils.ts +3 -3
- package/src/providers/acp-provider-instance.ts +6 -5
- package/src/providers/cli-provider-instance.ts +14 -10
- package/src/providers/extension-provider-instance.ts +7 -6
- package/src/providers/ide-provider-instance.ts +10 -6
- package/src/providers/read-chat-contract.ts +1 -1
- package/src/providers/status-monitor.d.ts +7 -7
- package/src/providers/status-monitor.ts +37 -22
- package/src/shared-types.ts +3 -0
- package/src/status/reporter.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -313,10 +313,10 @@ function readInjected(value) {
|
|
|
313
313
|
}
|
|
314
314
|
function getDaemonBuildInfo() {
|
|
315
315
|
if (cached) return cached;
|
|
316
|
-
const commit = readInjected(true ? "
|
|
317
|
-
const commitShort = readInjected(true ? "
|
|
318
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
319
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
316
|
+
const commit = readInjected(true ? "9277ba79593a0feae0e17de0204856825a199ebe" : void 0) ?? "unknown";
|
|
317
|
+
const commitShort = readInjected(true ? "9277ba79" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
318
|
+
const version = readInjected(true ? "0.9.82-rc.329" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
319
|
+
const builtAt = readInjected(true ? "2026-06-19T15:56:44.269Z" : void 0);
|
|
320
320
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
321
321
|
return cached;
|
|
322
322
|
}
|
|
@@ -327,6 +327,247 @@ var init_build_info = __esm({
|
|
|
327
327
|
}
|
|
328
328
|
});
|
|
329
329
|
|
|
330
|
+
// src/git/change-impact-config.ts
|
|
331
|
+
function isRecord(value) {
|
|
332
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
333
|
+
}
|
|
334
|
+
function isStringArray(value) {
|
|
335
|
+
return Array.isArray(value) && value.every((v) => typeof v === "string" && v.length > 0);
|
|
336
|
+
}
|
|
337
|
+
function validateTarget(value, key, errors) {
|
|
338
|
+
if (!isRecord(value)) {
|
|
339
|
+
errors.push(`impactTargets.${key} must be an object`);
|
|
340
|
+
return void 0;
|
|
341
|
+
}
|
|
342
|
+
const { recommendedCommand } = value;
|
|
343
|
+
if (typeof recommendedCommand !== "string" || !recommendedCommand.length) {
|
|
344
|
+
errors.push(`impactTargets.${key}.recommendedCommand must be a non-empty string`);
|
|
345
|
+
return void 0;
|
|
346
|
+
}
|
|
347
|
+
for (const k of Object.keys(value)) {
|
|
348
|
+
if (k !== "recommendedCommand") errors.push(`impactTargets.${key}.${k} is not a recognized field (only recommendedCommand)`);
|
|
349
|
+
}
|
|
350
|
+
return { recommendedCommand };
|
|
351
|
+
}
|
|
352
|
+
function validateChangeImpactConfig(raw, source = "inline") {
|
|
353
|
+
const errors = [];
|
|
354
|
+
if (!isRecord(raw)) {
|
|
355
|
+
return { valid: false, errors: [`${source}: config must be an object`] };
|
|
356
|
+
}
|
|
357
|
+
const config = {};
|
|
358
|
+
if (raw.daemonRuntimePackages !== void 0) {
|
|
359
|
+
if (isStringArray(raw.daemonRuntimePackages)) config.daemonRuntimePackages = [...raw.daemonRuntimePackages];
|
|
360
|
+
else errors.push("daemonRuntimePackages must be an array of non-empty strings");
|
|
361
|
+
}
|
|
362
|
+
if (raw.webOnlyPackages !== void 0) {
|
|
363
|
+
if (isStringArray(raw.webOnlyPackages)) config.webOnlyPackages = [...raw.webOnlyPackages];
|
|
364
|
+
else errors.push("webOnlyPackages must be an array of non-empty strings");
|
|
365
|
+
}
|
|
366
|
+
if (raw.nonRuntimeRootFilePatterns !== void 0) {
|
|
367
|
+
if (isStringArray(raw.nonRuntimeRootFilePatterns)) config.nonRuntimeRootFilePatterns = [...raw.nonRuntimeRootFilePatterns];
|
|
368
|
+
else errors.push("nonRuntimeRootFilePatterns must be an array of non-empty strings");
|
|
369
|
+
}
|
|
370
|
+
if (raw.impactTargets !== void 0) {
|
|
371
|
+
if (!isRecord(raw.impactTargets)) {
|
|
372
|
+
errors.push("impactTargets must be an object");
|
|
373
|
+
} else {
|
|
374
|
+
const targets = {};
|
|
375
|
+
for (const key of Object.keys(raw.impactTargets)) {
|
|
376
|
+
if (key !== "daemon" && key !== "web" && key !== "none") {
|
|
377
|
+
errors.push(`impactTargets.${key} is not a recognized impact kind (daemon|web|none)`);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const target = validateTarget(raw.impactTargets[key], key, errors);
|
|
381
|
+
if (target) targets[key] = target;
|
|
382
|
+
}
|
|
383
|
+
if (Object.keys(targets).length) config.impactTargets = targets;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
for (const key of Object.keys(raw)) {
|
|
387
|
+
if (!["daemonRuntimePackages", "webOnlyPackages", "nonRuntimeRootFilePatterns", "impactTargets"].includes(key)) {
|
|
388
|
+
errors.push(`unknown config key '${key}'`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return { valid: errors.length === 0, errors, config: errors.length === 0 ? config : void 0 };
|
|
392
|
+
}
|
|
393
|
+
function parseConfigText(path42, text) {
|
|
394
|
+
if (/\.json$/i.test(path42)) return JSON.parse(text);
|
|
395
|
+
return yaml.load(text);
|
|
396
|
+
}
|
|
397
|
+
function loadChangeImpactConfig(repoRoot) {
|
|
398
|
+
for (const relative5 of CHANGE_IMPACT_CONFIG_LOCATIONS) {
|
|
399
|
+
const configPath = (0, import_path.join)(repoRoot, relative5);
|
|
400
|
+
if (!(0, import_fs.existsSync)(configPath)) continue;
|
|
401
|
+
try {
|
|
402
|
+
const text = (0, import_fs.readFileSync)(configPath, "utf-8");
|
|
403
|
+
let mtimeMs = 0;
|
|
404
|
+
try {
|
|
405
|
+
mtimeMs = (0, import_fs.statSync)(configPath).mtimeMs;
|
|
406
|
+
} catch {
|
|
407
|
+
mtimeMs = text.length;
|
|
408
|
+
}
|
|
409
|
+
const parsed = parseConfigText(configPath, text);
|
|
410
|
+
const validation = validateChangeImpactConfig(parsed, relative5);
|
|
411
|
+
if (!validation.valid) {
|
|
412
|
+
return {
|
|
413
|
+
source: relative5,
|
|
414
|
+
sourceType: "invalid",
|
|
415
|
+
path: configPath,
|
|
416
|
+
error: validation.errors.join("; "),
|
|
417
|
+
sourceKey: `invalid:${configPath}:${mtimeMs}`
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
return {
|
|
421
|
+
config: validation.config,
|
|
422
|
+
source: relative5,
|
|
423
|
+
sourceType: "repo_file",
|
|
424
|
+
path: configPath,
|
|
425
|
+
sourceKey: `file:${configPath}:${mtimeMs}`
|
|
426
|
+
};
|
|
427
|
+
} catch (error) {
|
|
428
|
+
return {
|
|
429
|
+
source: relative5,
|
|
430
|
+
sourceType: "invalid",
|
|
431
|
+
path: configPath,
|
|
432
|
+
error: error?.message || String(error),
|
|
433
|
+
sourceKey: `error:${configPath}`
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return {
|
|
438
|
+
source: "unavailable",
|
|
439
|
+
sourceType: "unavailable",
|
|
440
|
+
error: `No change-impact config found. Checked: ${CHANGE_IMPACT_CONFIG_LOCATIONS.join(", ")}`,
|
|
441
|
+
sourceKey: "unavailable"
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
function globToRegExp(pattern) {
|
|
445
|
+
let out = "";
|
|
446
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
447
|
+
const ch = pattern[i];
|
|
448
|
+
if (ch === "*") {
|
|
449
|
+
if (pattern[i + 1] === "*") {
|
|
450
|
+
out += ".*";
|
|
451
|
+
i++;
|
|
452
|
+
if (pattern[i + 1] === "/") i++;
|
|
453
|
+
} else {
|
|
454
|
+
out += "[^/]*";
|
|
455
|
+
}
|
|
456
|
+
} else if (ch === "?") {
|
|
457
|
+
out += "[^/]";
|
|
458
|
+
} else if (".+^${}()|[]\\".includes(ch)) {
|
|
459
|
+
out += "\\" + ch;
|
|
460
|
+
} else {
|
|
461
|
+
out += ch;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return new RegExp(`^${out}$`);
|
|
465
|
+
}
|
|
466
|
+
function listPackageDirs(packagesRoot) {
|
|
467
|
+
try {
|
|
468
|
+
return (0, import_fs.readdirSync)(packagesRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
469
|
+
} catch {
|
|
470
|
+
return [];
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
function suggestChangeImpactConfig(repoRoot) {
|
|
474
|
+
const notes = [];
|
|
475
|
+
const daemon = /* @__PURE__ */ new Set();
|
|
476
|
+
const web = /* @__PURE__ */ new Set();
|
|
477
|
+
const unclassified = [];
|
|
478
|
+
const roots = ["packages", (0, import_path.join)("oss", "packages")];
|
|
479
|
+
for (const rel of roots) {
|
|
480
|
+
const packagesRoot = (0, import_path.join)(repoRoot, rel);
|
|
481
|
+
if (!(0, import_fs.existsSync)(packagesRoot)) continue;
|
|
482
|
+
for (const name of listPackageDirs(packagesRoot)) {
|
|
483
|
+
if (/(^web[-.]|[-.]web$)/i.test(name) || /dashboard|frontend|ui$/i.test(name)) {
|
|
484
|
+
web.add(name);
|
|
485
|
+
} else {
|
|
486
|
+
daemon.add(name);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
const daemonRuntimePackages = [...daemon].sort();
|
|
491
|
+
const webOnlyPackages = [...web].sort();
|
|
492
|
+
if (!daemonRuntimePackages.length && !webOnlyPackages.length) {
|
|
493
|
+
notes.push("No packages/ or oss/packages/ directories found \u2014 defaulting to an empty draft you should fill in by hand.");
|
|
494
|
+
} else {
|
|
495
|
+
if (daemonRuntimePackages.length) notes.push(`Classified ${daemonRuntimePackages.length} package(s) as daemon-runtime (change \u2192 rebuild/redeploy + restart).`);
|
|
496
|
+
if (webOnlyPackages.length) notes.push(`Classified ${webOnlyPackages.length} web-* package(s) as web-only (change \u2192 web redeploy, no daemon restart).`);
|
|
497
|
+
notes.push("Heuristic only: confirm each package actually matches its bucket before saving.");
|
|
498
|
+
}
|
|
499
|
+
const nonRuntimeRootFilePatterns = [
|
|
500
|
+
"*.md",
|
|
501
|
+
"docs/**",
|
|
502
|
+
"LICENSE",
|
|
503
|
+
"LICENSE.*",
|
|
504
|
+
".gitignore"
|
|
505
|
+
];
|
|
506
|
+
notes.push("nonRuntimeRootFilePatterns lists root files that demonstrably cannot change daemon runtime behavior; extend with your repo markers.");
|
|
507
|
+
const suggestedConfig = {
|
|
508
|
+
...daemonRuntimePackages.length ? { daemonRuntimePackages } : {},
|
|
509
|
+
...webOnlyPackages.length ? { webOnlyPackages } : {},
|
|
510
|
+
nonRuntimeRootFilePatterns,
|
|
511
|
+
impactTargets: {
|
|
512
|
+
daemon: { recommendedCommand: "rebuild + redeploy the daemon, then restart it" },
|
|
513
|
+
web: { recommendedCommand: "redeploy the web app (no daemon restart required)" },
|
|
514
|
+
none: { recommendedCommand: "no action required" }
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
return {
|
|
518
|
+
suggestedConfig,
|
|
519
|
+
notes,
|
|
520
|
+
discoveredPackages: { daemon: daemonRuntimePackages, web: webOnlyPackages, unclassified }
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
var import_fs, import_path, yaml, CHANGE_IMPACT_CONFIG_LOCATIONS, CHANGE_IMPACT_CONFIG_SCHEMA;
|
|
524
|
+
var init_change_impact_config = __esm({
|
|
525
|
+
"src/git/change-impact-config.ts"() {
|
|
526
|
+
"use strict";
|
|
527
|
+
import_fs = require("fs");
|
|
528
|
+
import_path = require("path");
|
|
529
|
+
yaml = __toESM(require("js-yaml"));
|
|
530
|
+
CHANGE_IMPACT_CONFIG_LOCATIONS = [
|
|
531
|
+
".adhdev/change-impact.json",
|
|
532
|
+
".adhdev/change-impact.yaml",
|
|
533
|
+
".adhdev/change-impact.yml",
|
|
534
|
+
".adhdev/repo-mesh-change-impact.json",
|
|
535
|
+
".adhdev/repo-mesh-change-impact.yaml",
|
|
536
|
+
".adhdev/repo-mesh-change-impact.yml"
|
|
537
|
+
];
|
|
538
|
+
CHANGE_IMPACT_CONFIG_SCHEMA = {
|
|
539
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
540
|
+
title: "ADHDev Change Impact Config",
|
|
541
|
+
type: "object",
|
|
542
|
+
additionalProperties: false,
|
|
543
|
+
properties: {
|
|
544
|
+
daemonRuntimePackages: { type: "array", items: { type: "string", minLength: 1 } },
|
|
545
|
+
webOnlyPackages: { type: "array", items: { type: "string", minLength: 1 } },
|
|
546
|
+
nonRuntimeRootFilePatterns: { type: "array", items: { type: "string", minLength: 1 } },
|
|
547
|
+
impactTargets: {
|
|
548
|
+
type: "object",
|
|
549
|
+
additionalProperties: false,
|
|
550
|
+
properties: {
|
|
551
|
+
daemon: { $ref: "#/$defs/target" },
|
|
552
|
+
web: { $ref: "#/$defs/target" },
|
|
553
|
+
none: { $ref: "#/$defs/target" }
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
$defs: {
|
|
558
|
+
target: {
|
|
559
|
+
type: "object",
|
|
560
|
+
additionalProperties: false,
|
|
561
|
+
required: ["recommendedCommand"],
|
|
562
|
+
properties: {
|
|
563
|
+
recommendedCommand: { type: "string", minLength: 1 }
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
|
|
330
571
|
// src/git/git-status.ts
|
|
331
572
|
function isTransientGitFailure(error) {
|
|
332
573
|
return error.reason === "timeout" || error.reason === "git_command_failed";
|
|
@@ -402,16 +643,34 @@ async function collectGitRepoStatus(repo, includeSubmodules, lastCheckedAt, opti
|
|
|
402
643
|
...daemonBuildBehind ? { daemonBuildBehind } : {}
|
|
403
644
|
};
|
|
404
645
|
}
|
|
405
|
-
function
|
|
646
|
+
function resolveChangeImpactPolicy(config) {
|
|
647
|
+
const daemonRuntimePackages = new Set(
|
|
648
|
+
config?.daemonRuntimePackages && config.daemonRuntimePackages.length ? config.daemonRuntimePackages : DEFAULT_DAEMON_RUNTIME_PACKAGES
|
|
649
|
+
);
|
|
650
|
+
const webOnlyPackages = new Set(
|
|
651
|
+
config?.webOnlyPackages && config.webOnlyPackages.length ? config.webOnlyPackages : DEFAULT_WEB_ONLY_PACKAGES
|
|
652
|
+
);
|
|
653
|
+
const nonRuntimeRootFilePatterns = (config?.nonRuntimeRootFilePatterns || []).map(globToRegExp);
|
|
654
|
+
const impactTargets = {
|
|
655
|
+
daemon: config?.impactTargets?.daemon ?? DEFAULT_IMPACT_TARGETS.daemon,
|
|
656
|
+
web: config?.impactTargets?.web ?? DEFAULT_IMPACT_TARGETS.web,
|
|
657
|
+
none: config?.impactTargets?.none ?? DEFAULT_IMPACT_TARGETS.none
|
|
658
|
+
};
|
|
659
|
+
return { daemonRuntimePackages, webOnlyPackages, nonRuntimeRootFilePatterns, impactTargets };
|
|
660
|
+
}
|
|
661
|
+
function isNonRuntimeRootFile(file, policy) {
|
|
406
662
|
const base = file.slice(file.lastIndexOf("/") + 1);
|
|
407
663
|
if (/^\.(?:verify|marker|converge|ff-verify|patch-equiv|live-verify)\b/i.test(base)) return true;
|
|
408
664
|
if (/(?:^|\/)docs\//i.test(file)) return true;
|
|
409
665
|
if (/^(?:README|CHANGELOG|LICENSE|NOTICE|AUTHORS|CONTRIBUTING|CODEOWNERS)(?:\.[A-Za-z0-9]+)?$/i.test(base)) {
|
|
410
666
|
return true;
|
|
411
667
|
}
|
|
668
|
+
for (const re of policy.nonRuntimeRootFilePatterns) {
|
|
669
|
+
if (re.test(file)) return true;
|
|
670
|
+
}
|
|
412
671
|
return false;
|
|
413
672
|
}
|
|
414
|
-
async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
|
|
673
|
+
async function classifyDaemonBuildChange(repoPath, buildCommit, options, policy) {
|
|
415
674
|
try {
|
|
416
675
|
const diff = await runGit(repoPath, ["diff", "--name-only", `${buildCommit}..HEAD`], options);
|
|
417
676
|
const files = diff.stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
@@ -423,21 +682,47 @@ async function classifyDaemonBuildChange(repoPath, buildCommit, options) {
|
|
|
423
682
|
for (const file of files) {
|
|
424
683
|
const match = file.match(/(?:^|\/)packages\/([^/]+)\//);
|
|
425
684
|
if (!match) {
|
|
426
|
-
if (!isNonRuntimeRootFile(file)) sawRuntimeAmbiguousNonPackage = true;
|
|
685
|
+
if (!isNonRuntimeRootFile(file, policy)) sawRuntimeAmbiguousNonPackage = true;
|
|
427
686
|
continue;
|
|
428
687
|
}
|
|
429
688
|
pkgs.add(match[1]);
|
|
430
689
|
}
|
|
431
690
|
const affectedPackages = [...pkgs].sort();
|
|
432
|
-
const allBenign = !sawRuntimeAmbiguousNonPackage && affectedPackages.every((p) =>
|
|
691
|
+
const allBenign = !sawRuntimeAmbiguousNonPackage && affectedPackages.every((p) => policy.webOnlyPackages.has(p) && !policy.daemonRuntimePackages.has(p));
|
|
433
692
|
return { isDaemonAffecting: !allBenign, affectedPackages };
|
|
434
693
|
} catch {
|
|
435
694
|
return { isDaemonAffecting: true, affectedPackages: [] };
|
|
436
695
|
}
|
|
437
696
|
}
|
|
697
|
+
function resolveChangeImpactConfigForRepo(repoRoot, options) {
|
|
698
|
+
if (options.changeImpactConfig === null) {
|
|
699
|
+
return { config: null, sourceKey: "forced-default" };
|
|
700
|
+
}
|
|
701
|
+
if (options.changeImpactConfig !== void 0) {
|
|
702
|
+
let key = "injected";
|
|
703
|
+
try {
|
|
704
|
+
key = `injected:${JSON.stringify(options.changeImpactConfig)}`;
|
|
705
|
+
} catch {
|
|
706
|
+
}
|
|
707
|
+
return { config: options.changeImpactConfig, sourceKey: key };
|
|
708
|
+
}
|
|
709
|
+
if (!repoRoot) {
|
|
710
|
+
return { config: null, sourceKey: "no-repo-root" };
|
|
711
|
+
}
|
|
712
|
+
const loaded = loadChangeImpactConfig(repoRoot);
|
|
713
|
+
const cached2 = changeImpactConfigCache.get(repoRoot);
|
|
714
|
+
if (cached2 && cached2.sourceKey === loaded.sourceKey) {
|
|
715
|
+
return { config: cached2.config, sourceKey: loaded.sourceKey };
|
|
716
|
+
}
|
|
717
|
+
const config = loaded.sourceType === "repo_file" ? loaded.config ?? null : null;
|
|
718
|
+
changeImpactConfigCache.set(repoRoot, { sourceKey: loaded.sourceKey, config });
|
|
719
|
+
return { config, sourceKey: loaded.sourceKey };
|
|
720
|
+
}
|
|
438
721
|
async function detectDaemonBuildBehind(repo, submodules, options) {
|
|
439
722
|
const build = options.daemonBuildInfo ?? getDaemonBuildInfo();
|
|
440
723
|
if (!build.commit || build.commit === "unknown") return void 0;
|
|
724
|
+
const { config, sourceKey: configKey } = resolveChangeImpactConfigForRepo(repo.repoRoot, options);
|
|
725
|
+
const policy = resolveChangeImpactPolicy(config);
|
|
441
726
|
const scopes = [
|
|
442
727
|
{ scope: "root", repoPath: repo.repoRoot || repo.workspace }
|
|
443
728
|
];
|
|
@@ -451,11 +736,15 @@ async function detectDaemonBuildBehind(repo, submodules, options) {
|
|
|
451
736
|
const head = headResult.stdout.trim();
|
|
452
737
|
if (!head || head === build.commit) continue;
|
|
453
738
|
await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
options
|
|
458
|
-
|
|
739
|
+
const evalKey = `${repoPath}\0${build.commit}\0${head}\0${configKey}`;
|
|
740
|
+
let evaluated = changeImpactEvalCache.get(evalKey);
|
|
741
|
+
if (!evaluated) {
|
|
742
|
+
evaluated = await classifyDaemonBuildChange(repoPath, build.commit, options, policy);
|
|
743
|
+
changeImpactEvalCache.set(evalKey, evaluated);
|
|
744
|
+
}
|
|
745
|
+
const { isDaemonAffecting, affectedPackages } = evaluated;
|
|
746
|
+
const kind = isDaemonAffecting ? "daemon" : affectedPackages.length > 0 ? "web" : "none";
|
|
747
|
+
const target = policy.impactTargets[kind];
|
|
459
748
|
const scopeLabel = scope === "root" ? "workspace" : scope;
|
|
460
749
|
const benignDetail = affectedPackages.length > 0 ? `only web packages changed (${affectedPackages.join(", ")})` : "only non-runtime files changed (markers/docs)";
|
|
461
750
|
const warning = isDaemonAffecting ? `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}. Merged code is NOT live until the daemon is rebuilt/redeployed and restarted \u2014 a local dist rebuild alone does not update a cloud daemon.` : `Live daemon was built from ${build.commitShort} which is behind ${scopeLabel} HEAD ${head.slice(0, 7)}, but ${benignDetail}. Daemon restart NOT required \u2014 redeploy the web app to reflect the change.`;
|
|
@@ -466,6 +755,8 @@ async function detectDaemonBuildBehind(repo, submodules, options) {
|
|
|
466
755
|
scope,
|
|
467
756
|
isDaemonAffecting,
|
|
468
757
|
...affectedPackages && affectedPackages.length > 0 ? { affectedPackages } : {},
|
|
758
|
+
recommendedAction: kind,
|
|
759
|
+
recommendedCommand: target.recommendedCommand,
|
|
469
760
|
warning
|
|
470
761
|
};
|
|
471
762
|
} catch {
|
|
@@ -729,14 +1020,17 @@ async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
|
|
|
729
1020
|
submodule.error = formatGitError(error);
|
|
730
1021
|
}
|
|
731
1022
|
}
|
|
732
|
-
var lastKnownGoodStatus,
|
|
1023
|
+
var lastKnownGoodStatus, changeImpactEvalCache, changeImpactConfigCache, DEFAULT_DAEMON_RUNTIME_PACKAGES, DEFAULT_WEB_ONLY_PACKAGES, DEFAULT_IMPACT_TARGETS;
|
|
733
1024
|
var init_git_status = __esm({
|
|
734
1025
|
"src/git/git-status.ts"() {
|
|
735
1026
|
"use strict";
|
|
736
1027
|
init_git_executor();
|
|
737
1028
|
init_build_info();
|
|
1029
|
+
init_change_impact_config();
|
|
738
1030
|
lastKnownGoodStatus = /* @__PURE__ */ new Map();
|
|
739
|
-
|
|
1031
|
+
changeImpactEvalCache = /* @__PURE__ */ new Map();
|
|
1032
|
+
changeImpactConfigCache = /* @__PURE__ */ new Map();
|
|
1033
|
+
DEFAULT_DAEMON_RUNTIME_PACKAGES = [
|
|
740
1034
|
"daemon-core",
|
|
741
1035
|
"daemon-standalone",
|
|
742
1036
|
"session-host-core",
|
|
@@ -746,13 +1040,24 @@ var init_git_status = __esm({
|
|
|
746
1040
|
"terminal-mux-cli",
|
|
747
1041
|
"ghostty-vt-node",
|
|
748
1042
|
"mcp-server"
|
|
749
|
-
]
|
|
750
|
-
|
|
1043
|
+
];
|
|
1044
|
+
DEFAULT_WEB_ONLY_PACKAGES = [
|
|
751
1045
|
"web-core",
|
|
752
1046
|
"web-standalone",
|
|
753
1047
|
"web-devconsole",
|
|
754
1048
|
"terminal-render-web"
|
|
755
|
-
]
|
|
1049
|
+
];
|
|
1050
|
+
DEFAULT_IMPACT_TARGETS = {
|
|
1051
|
+
daemon: {
|
|
1052
|
+
recommendedCommand: "Redeploy + restart the daemon (a local dist rebuild alone does not update a cloud daemon)."
|
|
1053
|
+
},
|
|
1054
|
+
web: {
|
|
1055
|
+
recommendedCommand: "Redeploy the web app (no daemon restart required)."
|
|
1056
|
+
},
|
|
1057
|
+
none: {
|
|
1058
|
+
recommendedCommand: "No action required."
|
|
1059
|
+
}
|
|
1060
|
+
};
|
|
756
1061
|
}
|
|
757
1062
|
});
|
|
758
1063
|
|
|
@@ -1311,25 +1616,25 @@ function ensureMachineId(config) {
|
|
|
1311
1616
|
}
|
|
1312
1617
|
function getConfigDir() {
|
|
1313
1618
|
const override = process.env.ADHDEV_CONFIG_DIR;
|
|
1314
|
-
const dir = override && override.trim() ? override.trim() : (0,
|
|
1315
|
-
if (!(0,
|
|
1316
|
-
(0,
|
|
1619
|
+
const dir = override && override.trim() ? override.trim() : (0, import_path2.join)((0, import_os.homedir)(), ".adhdev");
|
|
1620
|
+
if (!(0, import_fs2.existsSync)(dir)) {
|
|
1621
|
+
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
1317
1622
|
}
|
|
1318
1623
|
return dir;
|
|
1319
1624
|
}
|
|
1320
1625
|
function getDaemonDataDir() {
|
|
1321
|
-
const dir = (0,
|
|
1322
|
-
if (!(0,
|
|
1323
|
-
(0,
|
|
1626
|
+
const dir = (0, import_path2.join)(getConfigDir(), "daemon");
|
|
1627
|
+
if (!(0, import_fs2.existsSync)(dir)) {
|
|
1628
|
+
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
1324
1629
|
}
|
|
1325
1630
|
return dir;
|
|
1326
1631
|
}
|
|
1327
1632
|
function getConfigPath() {
|
|
1328
|
-
return (0,
|
|
1633
|
+
return (0, import_path2.join)(getConfigDir(), "config.json");
|
|
1329
1634
|
}
|
|
1330
1635
|
function migrateStateToStateFile(raw) {
|
|
1331
|
-
const statePath = (0,
|
|
1332
|
-
if ((0,
|
|
1636
|
+
const statePath = (0, import_path2.join)(getConfigDir(), "state.json");
|
|
1637
|
+
if ((0, import_fs2.existsSync)(statePath)) return;
|
|
1333
1638
|
const recentActivity = Array.isArray(raw.recentActivity) ? raw.recentActivity : [];
|
|
1334
1639
|
const savedProviderSessions = Array.isArray(raw.savedProviderSessions) ? raw.savedProviderSessions : [];
|
|
1335
1640
|
const legacySessionReads = isPlainObject(raw.recentSessionReads) ? raw.recentSessionReads : {};
|
|
@@ -1349,11 +1654,11 @@ function migrateStateToStateFile(raw) {
|
|
|
1349
1654
|
sessionReads: mergedReads,
|
|
1350
1655
|
sessionReadMarkers: cleanedMarkers
|
|
1351
1656
|
};
|
|
1352
|
-
(0,
|
|
1657
|
+
(0, import_fs2.writeFileSync)(statePath, JSON.stringify(state, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1353
1658
|
}
|
|
1354
1659
|
function loadConfig() {
|
|
1355
1660
|
const configPath = getConfigPath();
|
|
1356
|
-
if (!(0,
|
|
1661
|
+
if (!(0, import_fs2.existsSync)(configPath)) {
|
|
1357
1662
|
const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
|
|
1358
1663
|
try {
|
|
1359
1664
|
saveConfig(initialized.config);
|
|
@@ -1362,7 +1667,7 @@ function loadConfig() {
|
|
|
1362
1667
|
return initialized.config;
|
|
1363
1668
|
}
|
|
1364
1669
|
try {
|
|
1365
|
-
const raw = (0,
|
|
1670
|
+
const raw = (0, import_fs2.readFileSync)(configPath, "utf-8");
|
|
1366
1671
|
const parsed = JSON.parse(raw);
|
|
1367
1672
|
migrateStateToStateFile(parsed);
|
|
1368
1673
|
const normalizedInput = normalizeConfig(parsed);
|
|
@@ -1384,12 +1689,12 @@ function saveConfig(config) {
|
|
|
1384
1689
|
const configPath = getConfigPath();
|
|
1385
1690
|
const dir = getConfigDir();
|
|
1386
1691
|
const normalized = normalizeConfig(config);
|
|
1387
|
-
if (!(0,
|
|
1388
|
-
(0,
|
|
1692
|
+
if (!(0, import_fs2.existsSync)(dir)) {
|
|
1693
|
+
(0, import_fs2.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
1389
1694
|
}
|
|
1390
|
-
(0,
|
|
1695
|
+
(0, import_fs2.writeFileSync)(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1391
1696
|
try {
|
|
1392
|
-
(0,
|
|
1697
|
+
(0, import_fs2.chmodSync)(configPath, 384);
|
|
1393
1698
|
} catch {
|
|
1394
1699
|
}
|
|
1395
1700
|
}
|
|
@@ -1416,13 +1721,13 @@ function isSetupComplete() {
|
|
|
1416
1721
|
function resetConfig() {
|
|
1417
1722
|
saveConfig({ ...DEFAULT_CONFIG });
|
|
1418
1723
|
}
|
|
1419
|
-
var import_os,
|
|
1724
|
+
var import_os, import_path2, import_fs2, import_crypto, DEFAULT_CONFIG, MACHINE_ID_PREFIX;
|
|
1420
1725
|
var init_config = __esm({
|
|
1421
1726
|
"src/config/config.ts"() {
|
|
1422
1727
|
"use strict";
|
|
1423
1728
|
import_os = require("os");
|
|
1424
|
-
|
|
1425
|
-
|
|
1729
|
+
import_path2 = require("path");
|
|
1730
|
+
import_fs2 = require("fs");
|
|
1426
1731
|
import_crypto = require("crypto");
|
|
1427
1732
|
DEFAULT_CONFIG = {
|
|
1428
1733
|
serverUrl: "https://api.adhf.dev",
|
|
@@ -1541,13 +1846,13 @@ __export(mesh_config_exports, {
|
|
|
1541
1846
|
updateNode: () => updateNode
|
|
1542
1847
|
});
|
|
1543
1848
|
function getMeshConfigPath() {
|
|
1544
|
-
return (0,
|
|
1849
|
+
return (0, import_path3.join)(getConfigDir(), "meshes.json");
|
|
1545
1850
|
}
|
|
1546
1851
|
function loadMeshConfig() {
|
|
1547
1852
|
const path42 = getMeshConfigPath();
|
|
1548
|
-
if (!(0,
|
|
1853
|
+
if (!(0, import_fs3.existsSync)(path42)) return { meshes: [] };
|
|
1549
1854
|
try {
|
|
1550
|
-
const raw = JSON.parse((0,
|
|
1855
|
+
const raw = JSON.parse((0, import_fs3.readFileSync)(path42, "utf-8"));
|
|
1551
1856
|
if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
|
|
1552
1857
|
const config = raw;
|
|
1553
1858
|
const migrated = migrateLoadedMeshConfig(config);
|
|
@@ -1597,7 +1902,7 @@ function normalizeCapabilityTags(value) {
|
|
|
1597
1902
|
}
|
|
1598
1903
|
function saveMeshConfig(config) {
|
|
1599
1904
|
const path42 = getMeshConfigPath();
|
|
1600
|
-
(0,
|
|
1905
|
+
(0, import_fs3.writeFileSync)(path42, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
|
|
1601
1906
|
}
|
|
1602
1907
|
function normalizeRepoIdentity(remoteUrl) {
|
|
1603
1908
|
let identity = remoteUrl.trim();
|
|
@@ -1957,12 +2262,12 @@ function updateNode(meshId, nodeId, opts) {
|
|
|
1957
2262
|
saveMeshConfig(config);
|
|
1958
2263
|
return node;
|
|
1959
2264
|
}
|
|
1960
|
-
var
|
|
2265
|
+
var import_fs3, import_path3, import_crypto3, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES;
|
|
1961
2266
|
var init_mesh_config = __esm({
|
|
1962
2267
|
"src/config/mesh-config.ts"() {
|
|
1963
2268
|
"use strict";
|
|
1964
|
-
|
|
1965
|
-
|
|
2269
|
+
import_fs3 = require("fs");
|
|
2270
|
+
import_path3 = require("path");
|
|
1966
2271
|
import_crypto3 = require("crypto");
|
|
1967
2272
|
init_config();
|
|
1968
2273
|
init_repo_mesh_types();
|
|
@@ -2259,41 +2564,41 @@ function isIntentionalCleanupStopEntry(entry) {
|
|
|
2259
2564
|
return payload.intentional === true && (payload.reason === "operator_cleanup" || payload.intentionalStopReason === "operator_cleanup" || payload.source === "mesh_cleanup_sessions" || payload.source === "mesh_remove_node");
|
|
2260
2565
|
}
|
|
2261
2566
|
function getLedgerDir() {
|
|
2262
|
-
const dir = (0,
|
|
2263
|
-
if (!(0,
|
|
2264
|
-
(0,
|
|
2567
|
+
const dir = (0, import_path4.join)(getConfigDir(), LEDGER_DIR_NAME);
|
|
2568
|
+
if (!(0, import_fs4.existsSync)(dir)) {
|
|
2569
|
+
(0, import_fs4.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
2265
2570
|
}
|
|
2266
2571
|
return dir;
|
|
2267
2572
|
}
|
|
2268
2573
|
function getLedgerPath(meshId) {
|
|
2269
2574
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2270
|
-
return (0,
|
|
2575
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.jsonl`);
|
|
2271
2576
|
}
|
|
2272
2577
|
function getRotatedPath(meshId, index) {
|
|
2273
2578
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2274
|
-
return (0,
|
|
2579
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.${index}.jsonl`);
|
|
2275
2580
|
}
|
|
2276
2581
|
function getArchivePath(meshId) {
|
|
2277
2582
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2278
|
-
return (0,
|
|
2583
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.archive.jsonl`);
|
|
2279
2584
|
}
|
|
2280
2585
|
function getRotatedArchivePath(meshId, index) {
|
|
2281
2586
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2282
|
-
return (0,
|
|
2587
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.archive.${index}.jsonl`);
|
|
2283
2588
|
}
|
|
2284
2589
|
function getArchivedCountsPath(meshId) {
|
|
2285
2590
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2286
|
-
return (0,
|
|
2591
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.archived-counts.json`);
|
|
2287
2592
|
}
|
|
2288
2593
|
function rotateArchiveFile(meshId, archivePath) {
|
|
2289
2594
|
let index = 1;
|
|
2290
|
-
while ((0,
|
|
2595
|
+
while ((0, import_fs4.existsSync)(getRotatedArchivePath(meshId, index))) {
|
|
2291
2596
|
index++;
|
|
2292
2597
|
if (index > 5) break;
|
|
2293
2598
|
}
|
|
2294
2599
|
if (index > 5) index = 5;
|
|
2295
2600
|
try {
|
|
2296
|
-
(0,
|
|
2601
|
+
(0, import_fs4.renameSync)(archivePath, getRotatedArchivePath(meshId, index));
|
|
2297
2602
|
} catch (e) {
|
|
2298
2603
|
process.stderr.write(`[adhdev-mesh] Archive rotation failed for mesh ${meshId}: ${e?.message || e}
|
|
2299
2604
|
`);
|
|
@@ -2301,9 +2606,9 @@ function rotateArchiveFile(meshId, archivePath) {
|
|
|
2301
2606
|
}
|
|
2302
2607
|
function readArchivedCounts(meshId) {
|
|
2303
2608
|
const path42 = getArchivedCountsPath(meshId);
|
|
2304
|
-
if (!(0,
|
|
2609
|
+
if (!(0, import_fs4.existsSync)(path42)) return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
|
|
2305
2610
|
try {
|
|
2306
|
-
return JSON.parse((0,
|
|
2611
|
+
return JSON.parse((0, import_fs4.readFileSync)(path42, "utf-8"));
|
|
2307
2612
|
} catch {
|
|
2308
2613
|
return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
|
|
2309
2614
|
}
|
|
@@ -2319,7 +2624,7 @@ function updateArchivedCounts(meshId, archived) {
|
|
|
2319
2624
|
counts.totalArchived += archived.length;
|
|
2320
2625
|
counts.lastArchivedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2321
2626
|
try {
|
|
2322
|
-
(0,
|
|
2627
|
+
(0, import_fs4.writeFileSync)(getArchivedCountsPath(meshId), JSON.stringify(counts), { encoding: "utf-8", mode: 384 });
|
|
2323
2628
|
} catch {
|
|
2324
2629
|
}
|
|
2325
2630
|
}
|
|
@@ -2342,7 +2647,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
2342
2647
|
}
|
|
2343
2648
|
function compactLedger(meshId) {
|
|
2344
2649
|
const filePath = getLedgerPath(meshId);
|
|
2345
|
-
if (!(0,
|
|
2650
|
+
if (!(0, import_fs4.existsSync)(filePath)) return { archivedCount: 0, retainedCount: 0 };
|
|
2346
2651
|
const cutoff = Date.now() - ARCHIVE_TERMINAL_OLDER_THAN_MS;
|
|
2347
2652
|
const entries = readLedgerEntries(meshId);
|
|
2348
2653
|
const keep = [];
|
|
@@ -2357,11 +2662,11 @@ function compactLedger(meshId) {
|
|
|
2357
2662
|
if (archive.length === 0) return { archivedCount: 0, retainedCount: keep.length };
|
|
2358
2663
|
const archivePath = getArchivePath(meshId);
|
|
2359
2664
|
try {
|
|
2360
|
-
if ((0,
|
|
2665
|
+
if ((0, import_fs4.existsSync)(archivePath) && (0, import_fs4.statSync)(archivePath).size > 50 * 1024 * 1024) {
|
|
2361
2666
|
rotateArchiveFile(meshId, archivePath);
|
|
2362
2667
|
}
|
|
2363
2668
|
const archiveLines = archive.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
2364
|
-
(0,
|
|
2669
|
+
(0, import_fs4.appendFileSync)(archivePath, archiveLines, { encoding: "utf-8", mode: 384 });
|
|
2365
2670
|
updateArchivedCounts(meshId, archive);
|
|
2366
2671
|
} catch (e) {
|
|
2367
2672
|
process.stderr.write(`[adhdev-mesh] Ledger archive write failed for mesh ${meshId}: ${e?.message || e}
|
|
@@ -2370,7 +2675,7 @@ function compactLedger(meshId) {
|
|
|
2370
2675
|
}
|
|
2371
2676
|
try {
|
|
2372
2677
|
const keepLines = keep.length ? keep.map((e) => JSON.stringify(e)).join("\n") + "\n" : "";
|
|
2373
|
-
(0,
|
|
2678
|
+
(0, import_fs4.writeFileSync)(filePath, keepLines, { encoding: "utf-8", mode: 384 });
|
|
2374
2679
|
invalidateLedgerCache(meshId);
|
|
2375
2680
|
} catch (e) {
|
|
2376
2681
|
process.stderr.write(`[adhdev-mesh] Ledger compaction rewrite failed for mesh ${meshId}: ${e?.message || e}
|
|
@@ -2507,9 +2812,9 @@ function appendLedgerEntry(meshId, partial) {
|
|
|
2507
2812
|
...partial
|
|
2508
2813
|
};
|
|
2509
2814
|
const filePath = getLedgerPath(meshId);
|
|
2510
|
-
if ((0,
|
|
2815
|
+
if ((0, import_fs4.existsSync)(filePath)) {
|
|
2511
2816
|
try {
|
|
2512
|
-
const stat2 = (0,
|
|
2817
|
+
const stat2 = (0, import_fs4.statSync)(filePath);
|
|
2513
2818
|
if (stat2.size >= MAX_FILE_SIZE_BYTES) {
|
|
2514
2819
|
rotateLedgerFile(meshId, filePath);
|
|
2515
2820
|
} else if (stat2.size >= COMPACT_THRESHOLD_BYTES) {
|
|
@@ -2534,7 +2839,7 @@ function appendLedgerEntry(meshId, partial) {
|
|
|
2534
2839
|
}
|
|
2535
2840
|
try {
|
|
2536
2841
|
const line = JSON.stringify(entry) + "\n";
|
|
2537
|
-
(0,
|
|
2842
|
+
(0, import_fs4.appendFileSync)(filePath, line, { encoding: "utf-8", mode: 384 });
|
|
2538
2843
|
invalidateLedgerCache(meshId);
|
|
2539
2844
|
meshLedgerEvents.emit("append", meshId, entry);
|
|
2540
2845
|
return entry;
|
|
@@ -2593,7 +2898,7 @@ function appendRemoteLedgerEntries(meshId, entries) {
|
|
|
2593
2898
|
}
|
|
2594
2899
|
try {
|
|
2595
2900
|
const lines = validEntries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
2596
|
-
(0,
|
|
2901
|
+
(0, import_fs4.appendFileSync)(ledgerPath, lines, { encoding: "utf-8", mode: 384 });
|
|
2597
2902
|
invalidateLedgerCache(meshId);
|
|
2598
2903
|
for (const entry of validEntries) {
|
|
2599
2904
|
meshLedgerEvents.emit("append", meshId, entry);
|
|
@@ -2605,10 +2910,10 @@ function appendRemoteLedgerEntries(meshId, entries) {
|
|
|
2605
2910
|
}
|
|
2606
2911
|
function readLedgerFile(meshId) {
|
|
2607
2912
|
const filePath = getLedgerPath(meshId);
|
|
2608
|
-
if (!(0,
|
|
2913
|
+
if (!(0, import_fs4.existsSync)(filePath)) return [];
|
|
2609
2914
|
let content;
|
|
2610
2915
|
try {
|
|
2611
|
-
content = (0,
|
|
2916
|
+
content = (0, import_fs4.readFileSync)(filePath, "utf-8");
|
|
2612
2917
|
} catch {
|
|
2613
2918
|
return [];
|
|
2614
2919
|
}
|
|
@@ -2869,24 +3174,24 @@ function getSessionRecoveryContext(meshId, opts) {
|
|
|
2869
3174
|
}
|
|
2870
3175
|
function rotateLedgerFile(meshId, currentPath) {
|
|
2871
3176
|
let index = 1;
|
|
2872
|
-
while ((0,
|
|
3177
|
+
while ((0, import_fs4.existsSync)(getRotatedPath(meshId, index))) {
|
|
2873
3178
|
index++;
|
|
2874
3179
|
if (index > 10) break;
|
|
2875
3180
|
}
|
|
2876
3181
|
if (index > 10) index = 10;
|
|
2877
3182
|
try {
|
|
2878
|
-
(0,
|
|
3183
|
+
(0, import_fs4.renameSync)(currentPath, getRotatedPath(meshId, index));
|
|
2879
3184
|
} catch (e) {
|
|
2880
3185
|
process.stderr.write(`[adhdev-mesh] Ledger rotation failed for mesh ${meshId}: ${e?.message || e}. File will continue to grow.
|
|
2881
3186
|
`);
|
|
2882
3187
|
}
|
|
2883
3188
|
}
|
|
2884
|
-
var
|
|
3189
|
+
var import_fs4, import_path4, import_crypto4, import_events, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, COMPACT_THRESHOLD_BYTES, ARCHIVE_TERMINAL_OLDER_THAN_MS, RECENT_FAILURE_WINDOW_MS, ARCHIVABLE_KINDS, DEFAULT_LEDGER_SLICE_LIMIT, MAX_LEDGER_SLICE_LIMIT, meshLedgerEvents, ledgerReadCache, LEDGER_CACHE_TTL_MS, ledgerImportStoreRef, ledgerImportDone;
|
|
2885
3190
|
var init_mesh_ledger = __esm({
|
|
2886
3191
|
"src/mesh/mesh-ledger.ts"() {
|
|
2887
3192
|
"use strict";
|
|
2888
|
-
|
|
2889
|
-
|
|
3193
|
+
import_fs4 = require("fs");
|
|
3194
|
+
import_path4 = require("path");
|
|
2890
3195
|
import_crypto4 = require("crypto");
|
|
2891
3196
|
init_config();
|
|
2892
3197
|
import_events = require("events");
|
|
@@ -3554,32 +3859,32 @@ function safeMeshId(meshId) {
|
|
|
3554
3859
|
return meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3555
3860
|
}
|
|
3556
3861
|
function legacyQueuePath(meshId) {
|
|
3557
|
-
return (0,
|
|
3862
|
+
return (0, import_path5.join)(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
|
|
3558
3863
|
}
|
|
3559
3864
|
function meshRuntimeStorePath() {
|
|
3560
3865
|
const dir = getLedgerDir();
|
|
3561
|
-
const nextPath = (0,
|
|
3562
|
-
if ((0,
|
|
3563
|
-
const legacyPath = (0,
|
|
3564
|
-
if (!(0,
|
|
3866
|
+
const nextPath = (0, import_path5.join)(dir, "mesh-runtime.db");
|
|
3867
|
+
if ((0, import_fs5.existsSync)(nextPath)) return nextPath;
|
|
3868
|
+
const legacyPath = (0, import_path5.join)(dir, "beads.db");
|
|
3869
|
+
if (!(0, import_fs5.existsSync)(legacyPath)) return nextPath;
|
|
3565
3870
|
try {
|
|
3566
|
-
(0,
|
|
3871
|
+
(0, import_fs5.renameSync)(legacyPath, nextPath);
|
|
3567
3872
|
for (const suffix of ["-wal", "-shm"]) {
|
|
3568
3873
|
const legacyCompanion = `${legacyPath}${suffix}`;
|
|
3569
|
-
if ((0,
|
|
3570
|
-
(0,
|
|
3874
|
+
if ((0, import_fs5.existsSync)(legacyCompanion)) {
|
|
3875
|
+
(0, import_fs5.renameSync)(legacyCompanion, `${nextPath}${suffix}`);
|
|
3571
3876
|
}
|
|
3572
3877
|
}
|
|
3573
3878
|
} catch {
|
|
3574
3879
|
}
|
|
3575
3880
|
return nextPath;
|
|
3576
3881
|
}
|
|
3577
|
-
var
|
|
3882
|
+
var import_fs5, import_path5, import_module, import_meta, DatabaseCtor, MeshRuntimeStore;
|
|
3578
3883
|
var init_mesh_runtime_store = __esm({
|
|
3579
3884
|
"src/mesh/mesh-runtime-store.ts"() {
|
|
3580
3885
|
"use strict";
|
|
3581
|
-
|
|
3582
|
-
|
|
3886
|
+
import_fs5 = require("fs");
|
|
3887
|
+
import_path5 = require("path");
|
|
3583
3888
|
import_module = require("module");
|
|
3584
3889
|
init_mesh_ledger();
|
|
3585
3890
|
init_mesh_work_queue();
|
|
@@ -3595,8 +3900,8 @@ var init_mesh_runtime_store = __esm({
|
|
|
3595
3900
|
static WAL_MAX_BYTES = 50 * 1024 * 1024;
|
|
3596
3901
|
// 50 MB
|
|
3597
3902
|
constructor(dbPath) {
|
|
3598
|
-
const dir = (0,
|
|
3599
|
-
if (!(0,
|
|
3903
|
+
const dir = (0, import_path5.dirname)(dbPath);
|
|
3904
|
+
if (!(0, import_fs5.existsSync)(dir)) (0, import_fs5.mkdirSync)(dir, { recursive: true });
|
|
3600
3905
|
this.dbPath = dbPath;
|
|
3601
3906
|
this.db = new (loadDatabaseCtor())(dbPath);
|
|
3602
3907
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -3851,8 +4156,8 @@ var init_mesh_runtime_store = __esm({
|
|
|
3851
4156
|
this.walWriteCounter = 0;
|
|
3852
4157
|
try {
|
|
3853
4158
|
const walPath = `${this.dbPath}-wal`;
|
|
3854
|
-
if (!(0,
|
|
3855
|
-
const size = (0,
|
|
4159
|
+
if (!(0, import_fs5.existsSync)(walPath)) return;
|
|
4160
|
+
const size = (0, import_fs5.statSync)(walPath).size;
|
|
3856
4161
|
if (size < _MeshRuntimeStore.WAL_MAX_BYTES) return;
|
|
3857
4162
|
process.stderr.write(
|
|
3858
4163
|
`[adhdev-mesh] WAL file ${Math.round(size / 1024 / 1024)}MB exceeds threshold; forcing checkpoint
|
|
@@ -3868,9 +4173,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
3868
4173
|
const count = this.db.prepare("SELECT COUNT(*) AS count FROM mesh_queue WHERE mesh_id = ?").get(meshId);
|
|
3869
4174
|
if (count.count > 0) return;
|
|
3870
4175
|
const path42 = legacyQueuePath(meshId);
|
|
3871
|
-
if (!(0,
|
|
4176
|
+
if (!(0, import_fs5.existsSync)(path42)) return;
|
|
3872
4177
|
try {
|
|
3873
|
-
const entries = JSON.parse((0,
|
|
4178
|
+
const entries = JSON.parse((0, import_fs5.readFileSync)(path42, "utf-8"));
|
|
3874
4179
|
if (!Array.isArray(entries)) return;
|
|
3875
4180
|
const insert = this.db.prepare(`
|
|
3876
4181
|
INSERT OR REPLACE INTO mesh_queue (
|
|
@@ -7434,8 +7739,8 @@ function formatCompletionMetadata(event) {
|
|
|
7434
7739
|
function buildMeshSystemMessage(args) {
|
|
7435
7740
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
7436
7741
|
if (args.event === "agent:generating_completed") {
|
|
7437
|
-
if (args.metadataEvent.source === "
|
|
7438
|
-
return `[System] ${args.nodeLabel} already has completion evidence${metadata}. The
|
|
7742
|
+
if (args.metadataEvent.source === "no_progress_reconciliation") {
|
|
7743
|
+
return `[System] ${args.nodeLabel} already has completion evidence${metadata}. The no-progress monitor reconciled the terminal handoff and marked the session complete; wait for the queued completion event/status refresh before doing any manual transcript check.`;
|
|
7439
7744
|
}
|
|
7440
7745
|
const reviewNote = args.metadataEvent.reviewRecommended === true ? " Completion evidence is insufficient \u2014 verify via git status or provider_session_id before assuming the task is done. Use mesh_read_chat once if needed, but do not poll repeatedly." : " Use mesh_read_chat once to review its final progress, but do not poll repeatedly.";
|
|
7441
7746
|
return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. This completion came from the agent status event path;${reviewNote}`;
|
|
@@ -7474,7 +7779,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
|
|
|
7474
7779
|
}
|
|
7475
7780
|
return `[System] ${args.nodeLabel} has stopped${metadata}. Use mesh_read_chat once if you need to inspect its last output.`;
|
|
7476
7781
|
}
|
|
7477
|
-
if (args.event === "monitor:
|
|
7782
|
+
if (args.event === "monitor:no_progress") {
|
|
7478
7783
|
return `[System] ${args.nodeLabel} is still reported as generating after a long interval${metadata}. Wait for pendingCoordinatorEvents or a completion/status event; if the user explicitly asks for status, make one bounded status check and then wait again.`;
|
|
7479
7784
|
}
|
|
7480
7785
|
if (args.event === "worktree_bootstrap_complete") {
|
|
@@ -7613,9 +7918,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
|
|
|
7613
7918
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7614
7919
|
if (coordinatorDaemonId) {
|
|
7615
7920
|
const safeDaemon = coordinatorDaemonId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7616
|
-
return (0,
|
|
7921
|
+
return (0, import_path9.join)(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
|
|
7617
7922
|
}
|
|
7618
|
-
return (0,
|
|
7923
|
+
return (0, import_path9.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
|
|
7619
7924
|
}
|
|
7620
7925
|
function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
7621
7926
|
if (!meshId) return [];
|
|
@@ -7624,9 +7929,9 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
|
|
|
7624
7929
|
const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
7625
7930
|
const events = [];
|
|
7626
7931
|
for (const path42 of paths) {
|
|
7627
|
-
if (!(0,
|
|
7932
|
+
if (!(0, import_fs9.existsSync)(path42)) continue;
|
|
7628
7933
|
try {
|
|
7629
|
-
const raw = (0,
|
|
7934
|
+
const raw = (0, import_fs9.readFileSync)(path42, "utf-8");
|
|
7630
7935
|
const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
7631
7936
|
try {
|
|
7632
7937
|
return [JSON.parse(line)];
|
|
@@ -7701,11 +8006,11 @@ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
|
|
|
7701
8006
|
}
|
|
7702
8007
|
function trimPendingEventsIfNeeded(path42) {
|
|
7703
8008
|
try {
|
|
7704
|
-
if (!(0,
|
|
7705
|
-
if ((0,
|
|
7706
|
-
const lines = (0,
|
|
8009
|
+
if (!(0, import_fs9.existsSync)(path42)) return;
|
|
8010
|
+
if ((0, import_fs9.statSync)(path42).size <= MAX_PENDING_EVENTS_BYTES) return;
|
|
8011
|
+
const lines = (0, import_fs9.readFileSync)(path42, "utf-8").split("\n").filter(Boolean);
|
|
7707
8012
|
if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
|
|
7708
|
-
(0,
|
|
8013
|
+
(0, import_fs9.writeFileSync)(path42, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
|
|
7709
8014
|
} catch {
|
|
7710
8015
|
}
|
|
7711
8016
|
}
|
|
@@ -7734,7 +8039,7 @@ function queuePendingMeshCoordinatorEvent(event) {
|
|
|
7734
8039
|
}
|
|
7735
8040
|
const path42 = getPendingEventsPath(event.meshId, event.targetCoordinatorDaemonId);
|
|
7736
8041
|
trimPendingEventsIfNeeded(path42);
|
|
7737
|
-
(0,
|
|
8042
|
+
(0, import_fs9.appendFileSync)(path42, JSON.stringify(event) + "\n", "utf-8");
|
|
7738
8043
|
return true;
|
|
7739
8044
|
} catch (e) {
|
|
7740
8045
|
LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
|
|
@@ -7744,20 +8049,20 @@ function queuePendingMeshCoordinatorEvent(event) {
|
|
|
7744
8049
|
function atomicDrainFile(path42) {
|
|
7745
8050
|
const tmpPath = `${path42}.draining`;
|
|
7746
8051
|
try {
|
|
7747
|
-
(0,
|
|
8052
|
+
(0, import_fs9.renameSync)(path42, tmpPath);
|
|
7748
8053
|
} catch {
|
|
7749
8054
|
return null;
|
|
7750
8055
|
}
|
|
7751
8056
|
try {
|
|
7752
|
-
const content = (0,
|
|
8057
|
+
const content = (0, import_fs9.readFileSync)(tmpPath, "utf-8");
|
|
7753
8058
|
try {
|
|
7754
|
-
(0,
|
|
8059
|
+
(0, import_fs9.unlinkSync)(tmpPath);
|
|
7755
8060
|
} catch {
|
|
7756
8061
|
}
|
|
7757
8062
|
return content;
|
|
7758
8063
|
} catch {
|
|
7759
8064
|
try {
|
|
7760
|
-
(0,
|
|
8065
|
+
(0, import_fs9.unlinkSync)(tmpPath);
|
|
7761
8066
|
} catch {
|
|
7762
8067
|
}
|
|
7763
8068
|
return null;
|
|
@@ -7766,16 +8071,16 @@ function atomicDrainFile(path42) {
|
|
|
7766
8071
|
function selectiveDrainFile(path42, predicate) {
|
|
7767
8072
|
const tmpPath = `${path42}.draining`;
|
|
7768
8073
|
try {
|
|
7769
|
-
(0,
|
|
8074
|
+
(0, import_fs9.renameSync)(path42, tmpPath);
|
|
7770
8075
|
} catch {
|
|
7771
8076
|
return [];
|
|
7772
8077
|
}
|
|
7773
8078
|
let content;
|
|
7774
8079
|
try {
|
|
7775
|
-
content = (0,
|
|
8080
|
+
content = (0, import_fs9.readFileSync)(tmpPath, "utf-8");
|
|
7776
8081
|
} catch {
|
|
7777
8082
|
try {
|
|
7778
|
-
(0,
|
|
8083
|
+
(0, import_fs9.unlinkSync)(tmpPath);
|
|
7779
8084
|
} catch {
|
|
7780
8085
|
}
|
|
7781
8086
|
return [];
|
|
@@ -7798,12 +8103,12 @@ function selectiveDrainFile(path42, predicate) {
|
|
|
7798
8103
|
}
|
|
7799
8104
|
try {
|
|
7800
8105
|
if (keptLines.length > 0) {
|
|
7801
|
-
(0,
|
|
8106
|
+
(0, import_fs9.writeFileSync)(path42, keptLines.join("\n") + "\n", "utf-8");
|
|
7802
8107
|
}
|
|
7803
|
-
(0,
|
|
8108
|
+
(0, import_fs9.unlinkSync)(tmpPath);
|
|
7804
8109
|
} catch {
|
|
7805
8110
|
try {
|
|
7806
|
-
if ((0,
|
|
8111
|
+
if ((0, import_fs9.existsSync)(tmpPath) && !(0, import_fs9.existsSync)(path42)) (0, import_fs9.renameSync)(tmpPath, path42);
|
|
7807
8112
|
} catch {
|
|
7808
8113
|
}
|
|
7809
8114
|
return [];
|
|
@@ -7897,18 +8202,18 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
|
|
|
7897
8202
|
}
|
|
7898
8203
|
const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
|
|
7899
8204
|
for (const path42 of paths) {
|
|
7900
|
-
if ((0,
|
|
7901
|
-
(0,
|
|
8205
|
+
if ((0, import_fs9.existsSync)(path42)) try {
|
|
8206
|
+
(0, import_fs9.unlinkSync)(path42);
|
|
7902
8207
|
} catch {
|
|
7903
8208
|
}
|
|
7904
8209
|
}
|
|
7905
8210
|
}
|
|
7906
|
-
var
|
|
8211
|
+
var import_fs9, import_path9, import_crypto7, REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
|
|
7907
8212
|
var init_mesh_events_pending = __esm({
|
|
7908
8213
|
"src/mesh/mesh-events-pending.ts"() {
|
|
7909
8214
|
"use strict";
|
|
7910
|
-
|
|
7911
|
-
|
|
8215
|
+
import_fs9 = require("fs");
|
|
8216
|
+
import_path9 = require("path");
|
|
7912
8217
|
import_crypto7 = require("crypto");
|
|
7913
8218
|
init_logger();
|
|
7914
8219
|
init_mesh_ledger();
|
|
@@ -8264,7 +8569,7 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
|
|
|
8264
8569
|
});
|
|
8265
8570
|
return { reconciled: true, kind, workerResult, ledgerEntryId: entry.id };
|
|
8266
8571
|
}
|
|
8267
|
-
function
|
|
8572
|
+
function buildNoProgressCompletionReconciliation(args) {
|
|
8268
8573
|
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
8269
8574
|
const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
|
|
8270
8575
|
const providerType = readNonEmptyString2(args.metadataEvent.providerType);
|
|
@@ -8283,8 +8588,8 @@ function buildLongGeneratingCompletionReconciliation(args) {
|
|
|
8283
8588
|
providerType,
|
|
8284
8589
|
providerSessionId,
|
|
8285
8590
|
finalSummary,
|
|
8286
|
-
source: "
|
|
8287
|
-
reconciledFromEvent: "monitor:
|
|
8591
|
+
source: "no_progress_reconciliation",
|
|
8592
|
+
reconciledFromEvent: "monitor:no_progress",
|
|
8288
8593
|
timestamp: args.metadataEvent.timestamp ?? Date.now(),
|
|
8289
8594
|
completionDiagnostic: {
|
|
8290
8595
|
...completionDiagnostic || {},
|
|
@@ -8300,7 +8605,7 @@ function buildLongGeneratingCompletionReconciliation(args) {
|
|
|
8300
8605
|
if (!terminal) return null;
|
|
8301
8606
|
return {
|
|
8302
8607
|
...args.metadataEvent,
|
|
8303
|
-
source: "
|
|
8608
|
+
source: "no_progress_terminal_ledger_suppression",
|
|
8304
8609
|
terminalLedgerKind: terminal.kind,
|
|
8305
8610
|
terminalLedgerAt: terminal.timestamp
|
|
8306
8611
|
};
|
|
@@ -8740,7 +9045,7 @@ function resolveCommandPath(command) {
|
|
|
8740
9045
|
if (isExplicitCommandPath(trimmed)) {
|
|
8741
9046
|
const expanded = expandHome(trimmed);
|
|
8742
9047
|
const candidate = path11.isAbsolute(expanded) ? expanded : path11.resolve(expanded);
|
|
8743
|
-
return (0,
|
|
9048
|
+
return (0, import_fs10.existsSync)(candidate) ? candidate : null;
|
|
8744
9049
|
}
|
|
8745
9050
|
return null;
|
|
8746
9051
|
}
|
|
@@ -8750,7 +9055,7 @@ async function resolveDetectionPath(command, whichCmd) {
|
|
|
8750
9055
|
const whichResult = await execAsync(`${whichCmd} ${shellQuote(command)}`);
|
|
8751
9056
|
if (whichResult) return whichResult.split("\n")[0];
|
|
8752
9057
|
const resolved = findBinary(command);
|
|
8753
|
-
if (path11.isAbsolute(resolved) && (0,
|
|
9058
|
+
if (path11.isAbsolute(resolved) && (0, import_fs10.existsSync)(resolved)) return resolved;
|
|
8754
9059
|
return null;
|
|
8755
9060
|
}
|
|
8756
9061
|
function execAsync(cmd, timeoutMs = 5e3) {
|
|
@@ -8845,14 +9150,14 @@ async function detectCLI(cliId, providerLoader, options) {
|
|
|
8845
9150
|
const all = await detectCLIs(providerLoader, options);
|
|
8846
9151
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
8847
9152
|
}
|
|
8848
|
-
var import_child_process, os6, path11,
|
|
9153
|
+
var import_child_process, os6, path11, import_fs10;
|
|
8849
9154
|
var init_cli_detector = __esm({
|
|
8850
9155
|
"src/detection/cli-detector.ts"() {
|
|
8851
9156
|
"use strict";
|
|
8852
9157
|
import_child_process = require("child_process");
|
|
8853
9158
|
os6 = __toESM(require("os"));
|
|
8854
9159
|
path11 = __toESM(require("path"));
|
|
8855
|
-
|
|
9160
|
+
import_fs10 = require("fs");
|
|
8856
9161
|
init_provider_cli_shared();
|
|
8857
9162
|
}
|
|
8858
9163
|
});
|
|
@@ -9151,7 +9456,7 @@ function hasRecentIntentionalCleanupStop(meshId, sessionId, nodeId) {
|
|
|
9151
9456
|
return false;
|
|
9152
9457
|
}
|
|
9153
9458
|
function shouldSuppressIntentionalCleanupStop(args) {
|
|
9154
|
-
if (args.event !== "agent:stopped" && args.event !== "monitor:
|
|
9459
|
+
if (args.event !== "agent:stopped" && args.event !== "monitor:no_progress") return false;
|
|
9155
9460
|
if (isIntentionalCleanupStopMetadata(args.metadataEvent)) return true;
|
|
9156
9461
|
return hasRecentIntentionalCleanupStop(args.meshId, args.sessionId, args.nodeId);
|
|
9157
9462
|
}
|
|
@@ -9367,7 +9672,7 @@ function resolveAutoFastForwardPolicy(mesh) {
|
|
|
9367
9672
|
function sessionStateLooksActive(state) {
|
|
9368
9673
|
const status = readNonEmptyString2(state?.status).toLowerCase();
|
|
9369
9674
|
const chatStatus = readNonEmptyString2(state?.activeChat?.status).toLowerCase();
|
|
9370
|
-
const active = /* @__PURE__ */ new Set(["generating", "streaming", "long_generating", "working", "starting", "waiting_approval"]);
|
|
9675
|
+
const active = /* @__PURE__ */ new Set(["generating", "streaming", "no_progress", "long_generating", "working", "starting", "waiting_approval"]);
|
|
9371
9676
|
return active.has(status) || active.has(chatStatus);
|
|
9372
9677
|
}
|
|
9373
9678
|
function nodeHasActiveMeshWork(components, meshId, nodeId, currentSessionId) {
|
|
@@ -9887,7 +10192,7 @@ async function maybeAutoFastForwardIdleNode(components, args) {
|
|
|
9887
10192
|
const node = mesh?.nodes?.find((candidate) => meshNodeIdMatches(candidate, args.nodeId));
|
|
9888
10193
|
const workspace = readNonEmptyString2(node?.workspace);
|
|
9889
10194
|
if (!workspace) return;
|
|
9890
|
-
if (!(0,
|
|
10195
|
+
if (!(0, import_fs11.existsSync)(workspace)) return;
|
|
9891
10196
|
const policy = resolveAutoFastForwardPolicy(mesh);
|
|
9892
10197
|
if (!policy.enabled) return;
|
|
9893
10198
|
if (nodeHasActiveMeshWork(components, args.meshId, args.nodeId, args.sessionId)) return;
|
|
@@ -9981,24 +10286,24 @@ function injectMeshSystemMessage(components, args) {
|
|
|
9981
10286
|
LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
|
|
9982
10287
|
return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
|
|
9983
10288
|
}
|
|
9984
|
-
if (args.event === "monitor:
|
|
9985
|
-
const reconciledCompletion =
|
|
10289
|
+
if (args.event === "monitor:no_progress") {
|
|
10290
|
+
const reconciledCompletion = buildNoProgressCompletionReconciliation({
|
|
9986
10291
|
meshId: args.meshId,
|
|
9987
10292
|
nodeId: args.nodeId,
|
|
9988
10293
|
nodeLabel: args.nodeLabel,
|
|
9989
10294
|
metadataEvent: args.metadataEvent,
|
|
9990
10295
|
sourceInstanceId: args.sourceInstanceId
|
|
9991
10296
|
});
|
|
9992
|
-
if (reconciledCompletion?.source === "
|
|
9993
|
-
LOG.info("MeshEvents", `Reconciled
|
|
10297
|
+
if (reconciledCompletion?.source === "no_progress_reconciliation") {
|
|
10298
|
+
LOG.info("MeshEvents", `Reconciled no-progress monitor to completion for session ${eventSessionId || "(unknown session)"}`);
|
|
9994
10299
|
return injectMeshSystemMessage(components, {
|
|
9995
10300
|
...args,
|
|
9996
10301
|
event: "agent:generating_completed",
|
|
9997
10302
|
metadataEvent: reconciledCompletion
|
|
9998
10303
|
});
|
|
9999
10304
|
}
|
|
10000
|
-
if (reconciledCompletion?.source === "
|
|
10001
|
-
LOG.info("MeshEvents", `Suppressed
|
|
10305
|
+
if (reconciledCompletion?.source === "no_progress_terminal_ledger_suppression") {
|
|
10306
|
+
LOG.info("MeshEvents", `Suppressed no-progress monitor because terminal ledger evidence already exists for session ${eventSessionId || "(unknown session)"}`);
|
|
10002
10307
|
return {
|
|
10003
10308
|
success: true,
|
|
10004
10309
|
forwarded: 0,
|
|
@@ -10040,7 +10345,7 @@ function injectMeshSystemMessage(components, args) {
|
|
|
10040
10345
|
const terminalFinalSummary = readNonEmptyString2(terminal.payload.finalSummary);
|
|
10041
10346
|
const eventProviderSessionId = readNonEmptyString2(args.metadataEvent.providerSessionId);
|
|
10042
10347
|
const eventFinalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
|
|
10043
|
-
if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "
|
|
10348
|
+
if (terminalProviderSessionId && terminalProviderSessionId === eventProviderSessionId || terminalFinalSummary && terminalFinalSummary === eventFinalSummary || args.metadataEvent.source === "no_progress_reconciliation") {
|
|
10044
10349
|
LOG.info("MeshEvents", `Suppressed duplicate completion with existing terminal ledger evidence for mesh ${args.meshId} session ${eventSessionId}`);
|
|
10045
10350
|
return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true, terminalLedgerEvidence: true };
|
|
10046
10351
|
}
|
|
@@ -10479,11 +10784,11 @@ function setupMeshEventForwarding(components) {
|
|
|
10479
10784
|
});
|
|
10480
10785
|
});
|
|
10481
10786
|
}
|
|
10482
|
-
var
|
|
10787
|
+
var import_fs11, 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;
|
|
10483
10788
|
var init_mesh_events_coordinator = __esm({
|
|
10484
10789
|
"src/mesh/mesh-events-coordinator.ts"() {
|
|
10485
10790
|
"use strict";
|
|
10486
|
-
|
|
10791
|
+
import_fs11 = require("fs");
|
|
10487
10792
|
init_config();
|
|
10488
10793
|
init_mesh_config();
|
|
10489
10794
|
init_cli_detector();
|
|
@@ -10519,7 +10824,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
10519
10824
|
"agent:waiting_approval",
|
|
10520
10825
|
"agent:stopped",
|
|
10521
10826
|
"agent:ready",
|
|
10522
|
-
"monitor:
|
|
10827
|
+
"monitor:no_progress",
|
|
10523
10828
|
"refine:accepted",
|
|
10524
10829
|
"refine:completed",
|
|
10525
10830
|
"refine:failed",
|
|
@@ -10530,7 +10835,7 @@ var init_mesh_events_coordinator = __esm({
|
|
|
10530
10835
|
"agent:generating_completed": "task_completed",
|
|
10531
10836
|
"agent:waiting_approval": "task_approval_needed",
|
|
10532
10837
|
"agent:stopped": "task_failed",
|
|
10533
|
-
"monitor:
|
|
10838
|
+
"monitor:no_progress": "task_stalled"
|
|
10534
10839
|
};
|
|
10535
10840
|
MESH_FORCE_INJECT_EVENTS = /* @__PURE__ */ new Set([
|
|
10536
10841
|
"agent:generating_completed",
|
|
@@ -12678,7 +12983,7 @@ function resolveWin32GlobalBin(trimmed) {
|
|
|
12678
12983
|
if (!dir) continue;
|
|
12679
12984
|
for (const ext of WIN_EXEC_EXT) {
|
|
12680
12985
|
const full = path18.join(dir, trimmed + ext);
|
|
12681
|
-
if ((0,
|
|
12986
|
+
if ((0, import_fs14.existsSync)(full)) return full;
|
|
12682
12987
|
}
|
|
12683
12988
|
}
|
|
12684
12989
|
return null;
|
|
@@ -12687,7 +12992,7 @@ function resolveWin32Executable(command) {
|
|
|
12687
12992
|
if (process.platform !== "win32") return command;
|
|
12688
12993
|
const trimmed = (command || "").trim();
|
|
12689
12994
|
if (!trimmed) return command;
|
|
12690
|
-
if (path18.isAbsolute(trimmed) && (0,
|
|
12995
|
+
if (path18.isAbsolute(trimmed) && (0, import_fs14.existsSync)(trimmed)) return trimmed;
|
|
12691
12996
|
try {
|
|
12692
12997
|
const out = (0, import_child_process4.execFileSync)("where", [trimmed], {
|
|
12693
12998
|
encoding: "utf8",
|
|
@@ -12704,12 +13009,12 @@ function resolveWin32Executable(command) {
|
|
|
12704
13009
|
if (globalBin) return globalBin;
|
|
12705
13010
|
return command;
|
|
12706
13011
|
}
|
|
12707
|
-
var import_child_process4,
|
|
13012
|
+
var import_child_process4, import_fs14, path18, DIRECT_EXEC_EXT, WIN_EXEC_EXT;
|
|
12708
13013
|
var init_resolve_executable = __esm({
|
|
12709
13014
|
"src/cli-adapters/resolve-executable.ts"() {
|
|
12710
13015
|
"use strict";
|
|
12711
13016
|
import_child_process4 = require("child_process");
|
|
12712
|
-
|
|
13017
|
+
import_fs14 = require("fs");
|
|
12713
13018
|
path18 = __toESM(require("path"));
|
|
12714
13019
|
DIRECT_EXEC_EXT = /* @__PURE__ */ new Set([".exe", ".com"]);
|
|
12715
13020
|
WIN_EXEC_EXT = [".exe", ".com", ".cmd", ".bat"];
|
|
@@ -15677,7 +15982,7 @@ ${lastSnapshot}`;
|
|
|
15677
15982
|
};
|
|
15678
15983
|
if (parsedSessionStatus === "idle" && hasFinalAssistant(parsedStatusBeforeSend)) return null;
|
|
15679
15984
|
if (this.engine.currentStatus === "generating") return "current_status_generating";
|
|
15680
|
-
if (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating") {
|
|
15985
|
+
if (parsedSessionStatus === "generating" || parsedSessionStatus === "no_progress" || parsedSessionStatus === "long_generating") {
|
|
15681
15986
|
const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
|
|
15682
15987
|
const parsedHasActionableModal = Boolean(
|
|
15683
15988
|
parsedModal && Array.isArray(parsedModal.buttons) && parsedModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim())
|
|
@@ -15754,7 +16059,7 @@ ${lastSnapshot}`;
|
|
|
15754
16059
|
}
|
|
15755
16060
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.engine.currentStatus})`);
|
|
15756
16061
|
const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
|
|
15757
|
-
if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
|
|
16062
|
+
if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "no_progress" || parsedSessionStatus === "long_generating")) {
|
|
15758
16063
|
const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
|
|
15759
16064
|
const parsedHasActionableModal = Boolean(
|
|
15760
16065
|
parsedModal && Array.isArray(parsedModal.buttons) && parsedModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim())
|
|
@@ -17264,6 +17569,8 @@ __export(index_exports, {
|
|
|
17264
17569
|
AcpProviderInstance: () => AcpProviderInstance,
|
|
17265
17570
|
AgentStreamPoller: () => AgentStreamPoller,
|
|
17266
17571
|
BUILTIN_CHAT_MESSAGE_KINDS: () => BUILTIN_CHAT_MESSAGE_KINDS,
|
|
17572
|
+
CHANGE_IMPACT_CONFIG_LOCATIONS: () => CHANGE_IMPACT_CONFIG_LOCATIONS,
|
|
17573
|
+
CHANGE_IMPACT_CONFIG_SCHEMA: () => CHANGE_IMPACT_CONFIG_SCHEMA,
|
|
17267
17574
|
CHAT_MESSAGE_ACTIVITY_SOURCES: () => CHAT_MESSAGE_ACTIVITY_SOURCES,
|
|
17268
17575
|
CHAT_MESSAGE_AUDIENCES: () => CHAT_MESSAGE_AUDIENCES,
|
|
17269
17576
|
CHAT_MESSAGE_INTERNAL_SOURCES: () => CHAT_MESSAGE_INTERNAL_SOURCES,
|
|
@@ -17454,6 +17761,7 @@ __export(index_exports, {
|
|
|
17454
17761
|
getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
|
|
17455
17762
|
getSessionRecoveryContext: () => getSessionRecoveryContext,
|
|
17456
17763
|
getWorkspaceState: () => getWorkspaceState,
|
|
17764
|
+
globToRegExp: () => globToRegExp,
|
|
17457
17765
|
handleGitCommand: () => handleGitCommand,
|
|
17458
17766
|
hasCdpManager: () => hasCdpManager,
|
|
17459
17767
|
hasPendingDependents: () => hasPendingDependents,
|
|
@@ -17487,6 +17795,7 @@ __export(index_exports, {
|
|
|
17487
17795
|
listMeshMissionSummaries: () => listMeshMissionSummaries,
|
|
17488
17796
|
listMeshes: () => listMeshes,
|
|
17489
17797
|
listWorktrees: () => listWorktrees,
|
|
17798
|
+
loadChangeImpactConfig: () => loadChangeImpactConfig,
|
|
17490
17799
|
loadConfig: () => loadConfig,
|
|
17491
17800
|
loadMeshCoordinatorRegistry: () => loadMeshCoordinatorRegistry,
|
|
17492
17801
|
loadMeshRefineConfig: () => loadMeshRefineConfig,
|
|
@@ -17581,6 +17890,7 @@ __export(index_exports, {
|
|
|
17581
17890
|
spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
|
|
17582
17891
|
startDaemonDevSupport: () => startDaemonDevSupport,
|
|
17583
17892
|
startLocalIpcServer: () => startLocalIpcServer,
|
|
17893
|
+
suggestChangeImpactConfig: () => suggestChangeImpactConfig,
|
|
17584
17894
|
suggestMeshRefineConfig: () => suggestMeshRefineConfig,
|
|
17585
17895
|
summarizeGitStatus: () => summarizeGitStatus,
|
|
17586
17896
|
summarizeMeshAsyncRefineJobs: () => summarizeMeshAsyncRefineJobs,
|
|
@@ -17597,6 +17907,7 @@ __export(index_exports, {
|
|
|
17597
17907
|
updateTaskStatus: () => updateTaskStatus,
|
|
17598
17908
|
upsertMeshMission: () => upsertMeshMission,
|
|
17599
17909
|
upsertSavedProviderSession: () => upsertSavedProviderSession,
|
|
17910
|
+
validateChangeImpactConfig: () => validateChangeImpactConfig,
|
|
17600
17911
|
validateCliProviderManifest: () => validateCliProviderManifest,
|
|
17601
17912
|
validateFsmSpec: () => validateFsmSpec,
|
|
17602
17913
|
validateMeshRefineConfig: () => validateMeshRefineConfig,
|
|
@@ -17966,6 +18277,7 @@ init_repo_mesh_types();
|
|
|
17966
18277
|
// src/git/index.ts
|
|
17967
18278
|
init_git_executor();
|
|
17968
18279
|
init_git_status();
|
|
18280
|
+
init_change_impact_config();
|
|
17969
18281
|
init_git_diff();
|
|
17970
18282
|
|
|
17971
18283
|
// src/git/git-summary.ts
|
|
@@ -19259,18 +19571,18 @@ init_mesh_task_stats();
|
|
|
19259
19571
|
init_mesh_review_inbox();
|
|
19260
19572
|
|
|
19261
19573
|
// src/mesh/coordinator-registry.ts
|
|
19262
|
-
var
|
|
19263
|
-
var
|
|
19574
|
+
var import_path6 = require("path");
|
|
19575
|
+
var import_fs6 = require("fs");
|
|
19264
19576
|
init_config();
|
|
19265
19577
|
var _registry = /* @__PURE__ */ new Map();
|
|
19266
19578
|
function getRegistryPath() {
|
|
19267
|
-
return (0,
|
|
19579
|
+
return (0, import_path6.join)(getDaemonDataDir(), "mesh-coordinators.json");
|
|
19268
19580
|
}
|
|
19269
19581
|
function loadMeshCoordinatorRegistry() {
|
|
19270
19582
|
const path42 = getRegistryPath();
|
|
19271
|
-
if (!(0,
|
|
19583
|
+
if (!(0, import_fs6.existsSync)(path42)) return;
|
|
19272
19584
|
try {
|
|
19273
|
-
const raw = JSON.parse((0,
|
|
19585
|
+
const raw = JSON.parse((0, import_fs6.readFileSync)(path42, "utf-8"));
|
|
19274
19586
|
if (!Array.isArray(raw)) return;
|
|
19275
19587
|
_registry.clear();
|
|
19276
19588
|
for (const entry of raw) {
|
|
@@ -19283,7 +19595,7 @@ function loadMeshCoordinatorRegistry() {
|
|
|
19283
19595
|
}
|
|
19284
19596
|
function saveRegistry() {
|
|
19285
19597
|
try {
|
|
19286
|
-
(0,
|
|
19598
|
+
(0, import_fs6.writeFileSync)(
|
|
19287
19599
|
getRegistryPath(),
|
|
19288
19600
|
JSON.stringify([..._registry.values()], null, 2),
|
|
19289
19601
|
{ encoding: "utf-8", mode: 384 }
|
|
@@ -19318,9 +19630,9 @@ function listCoordinatorsForWorkspace(workspace) {
|
|
|
19318
19630
|
}
|
|
19319
19631
|
|
|
19320
19632
|
// src/mesh/refine-config.ts
|
|
19321
|
-
var
|
|
19322
|
-
var
|
|
19323
|
-
var
|
|
19633
|
+
var import_fs7 = require("fs");
|
|
19634
|
+
var import_path7 = require("path");
|
|
19635
|
+
var yaml2 = __toESM(require("js-yaml"));
|
|
19324
19636
|
var MESH_REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
|
|
19325
19637
|
var MESH_REFINE_CONFIG_LOCATIONS = [
|
|
19326
19638
|
".adhdev/refine.json",
|
|
@@ -19461,7 +19773,7 @@ function normalizeMeshCommandConfig(entry, source) {
|
|
|
19461
19773
|
}
|
|
19462
19774
|
};
|
|
19463
19775
|
}
|
|
19464
|
-
var
|
|
19776
|
+
var isRecord2 = isMeshConfigRecord;
|
|
19465
19777
|
function validateMeshRefineConfig(config, source = "inline") {
|
|
19466
19778
|
const errors = [];
|
|
19467
19779
|
const bootstrapCommands = [];
|
|
@@ -19469,14 +19781,14 @@ function validateMeshRefineConfig(config, source = "inline") {
|
|
|
19469
19781
|
const rejectedCommands = [];
|
|
19470
19782
|
const deprecationWarnings = [];
|
|
19471
19783
|
let bootstrapMode = "inherit";
|
|
19472
|
-
if (!
|
|
19784
|
+
if (!isRecord2(config)) return { valid: false, errors: ["config must be an object"], bootstrapCommands, commands, rejectedCommands, bootstrapMode, deprecationWarnings };
|
|
19473
19785
|
if (config.version !== 1) errors.push("version must be 1");
|
|
19474
19786
|
if (config.allowAutoPublishSubmoduleMainCommits !== void 0 && typeof config.allowAutoPublishSubmoduleMainCommits !== "boolean") {
|
|
19475
19787
|
errors.push("allowAutoPublishSubmoduleMainCommits must be a boolean when provided");
|
|
19476
19788
|
}
|
|
19477
19789
|
const validation = config.validation;
|
|
19478
|
-
if (validation !== void 0 && !
|
|
19479
|
-
const rawBootstrapMode =
|
|
19790
|
+
if (validation !== void 0 && !isRecord2(validation)) errors.push("validation must be an object");
|
|
19791
|
+
const rawBootstrapMode = isRecord2(validation) ? validation.bootstrap : void 0;
|
|
19480
19792
|
if (rawBootstrapMode !== void 0) {
|
|
19481
19793
|
if (rawBootstrapMode === "inherit" || rawBootstrapMode === "skip") {
|
|
19482
19794
|
bootstrapMode = rawBootstrapMode;
|
|
@@ -19484,8 +19796,8 @@ function validateMeshRefineConfig(config, source = "inline") {
|
|
|
19484
19796
|
errors.push("validation.bootstrap must be 'inherit' or 'skip' when provided");
|
|
19485
19797
|
}
|
|
19486
19798
|
}
|
|
19487
|
-
const rawCommands =
|
|
19488
|
-
const rawBootstrapCommands =
|
|
19799
|
+
const rawCommands = isRecord2(validation) ? validation.commands : void 0;
|
|
19800
|
+
const rawBootstrapCommands = isRecord2(validation) ? validation.bootstrapCommands : void 0;
|
|
19489
19801
|
if (rawCommands !== void 0 && !Array.isArray(rawCommands)) errors.push("validation.commands must be an array");
|
|
19490
19802
|
if (rawBootstrapCommands !== void 0 && !Array.isArray(rawBootstrapCommands)) errors.push("validation.bootstrapCommands must be an array");
|
|
19491
19803
|
if (Array.isArray(rawBootstrapCommands) && rawBootstrapCommands.length > 0) {
|
|
@@ -19508,9 +19820,9 @@ function validateMeshRefineConfig(config, source = "inline") {
|
|
|
19508
19820
|
if (rejectedCommands.length) errors.push("one or more validation commands are invalid");
|
|
19509
19821
|
return { valid: errors.length === 0, errors, bootstrapCommands, commands, rejectedCommands, bootstrapMode, deprecationWarnings };
|
|
19510
19822
|
}
|
|
19511
|
-
function
|
|
19823
|
+
function parseConfigText2(path42, text) {
|
|
19512
19824
|
if (/\.json$/i.test(path42)) return JSON.parse(text);
|
|
19513
|
-
return
|
|
19825
|
+
return yaml2.load(text);
|
|
19514
19826
|
}
|
|
19515
19827
|
function loadMeshRefineConfig(mesh, workspace) {
|
|
19516
19828
|
const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
|
|
@@ -19521,10 +19833,10 @@ function loadMeshRefineConfig(mesh, workspace) {
|
|
|
19521
19833
|
return { config: inline, source: "mesh.policy.refineConfig", sourceType: "mesh_policy" };
|
|
19522
19834
|
}
|
|
19523
19835
|
for (const relative5 of MESH_REFINE_CONFIG_LOCATIONS) {
|
|
19524
|
-
const configPath = (0,
|
|
19525
|
-
if (!(0,
|
|
19836
|
+
const configPath = (0, import_path7.join)(workspace, relative5);
|
|
19837
|
+
if (!(0, import_fs7.existsSync)(configPath)) continue;
|
|
19526
19838
|
try {
|
|
19527
|
-
const parsed =
|
|
19839
|
+
const parsed = parseConfigText2(configPath, (0, import_fs7.readFileSync)(configPath, "utf-8"));
|
|
19528
19840
|
const validation = validateMeshRefineConfig(parsed, relative5);
|
|
19529
19841
|
if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
|
|
19530
19842
|
return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
|
|
@@ -19540,20 +19852,20 @@ function loadMeshRefineConfig(mesh, workspace) {
|
|
|
19540
19852
|
}
|
|
19541
19853
|
function readPackageScripts(workspace) {
|
|
19542
19854
|
try {
|
|
19543
|
-
const parsed = JSON.parse((0,
|
|
19544
|
-
return
|
|
19855
|
+
const parsed = JSON.parse((0, import_fs7.readFileSync)((0, import_path7.join)(workspace, "package.json"), "utf-8"));
|
|
19856
|
+
return isRecord2(parsed?.scripts) ? parsed.scripts : {};
|
|
19545
19857
|
} catch {
|
|
19546
19858
|
return {};
|
|
19547
19859
|
}
|
|
19548
19860
|
}
|
|
19549
19861
|
function collectProjectContextSuggestions(mesh) {
|
|
19550
19862
|
const commands = mesh?.projectContext?.commands;
|
|
19551
|
-
if (!
|
|
19863
|
+
if (!isRecord2(commands)) return [];
|
|
19552
19864
|
const suggestions = [];
|
|
19553
19865
|
for (const category of MESH_REFINE_VALIDATION_CATEGORIES) {
|
|
19554
19866
|
const entries = Array.isArray(commands[category]) ? commands[category] : [];
|
|
19555
19867
|
for (const entry of entries) {
|
|
19556
|
-
if (
|
|
19868
|
+
if (isRecord2(entry) && typeof entry.command === "string") suggestions.push({ command: entry.command, category });
|
|
19557
19869
|
}
|
|
19558
19870
|
}
|
|
19559
19871
|
return suggestions;
|
|
@@ -19617,12 +19929,12 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
|
|
|
19617
19929
|
}
|
|
19618
19930
|
|
|
19619
19931
|
// src/mesh/worktree-bootstrap-config.ts
|
|
19620
|
-
var
|
|
19621
|
-
var
|
|
19932
|
+
var import_fs8 = require("fs");
|
|
19933
|
+
var import_path8 = require("path");
|
|
19622
19934
|
var import_node_child_process3 = require("child_process");
|
|
19623
19935
|
var import_node_crypto2 = require("crypto");
|
|
19624
19936
|
var import_node_util3 = require("util");
|
|
19625
|
-
var
|
|
19937
|
+
var yaml3 = __toESM(require("js-yaml"));
|
|
19626
19938
|
var MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
|
|
19627
19939
|
".adhdev/worktree_bootstrap.json",
|
|
19628
19940
|
".adhdev/worktree_bootstrap.yaml",
|
|
@@ -19667,9 +19979,9 @@ var MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA = {
|
|
|
19667
19979
|
var DEFAULT_TIMEOUT_MS2 = 12e4;
|
|
19668
19980
|
var DEFAULT_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
19669
19981
|
var OUTPUT_SUMMARY_CHARS = 2e3;
|
|
19670
|
-
function
|
|
19982
|
+
function parseConfigText3(path42, text) {
|
|
19671
19983
|
if (/\.json$/i.test(path42)) return JSON.parse(text);
|
|
19672
|
-
return
|
|
19984
|
+
return yaml3.load(text);
|
|
19673
19985
|
}
|
|
19674
19986
|
function truncateOutput(value) {
|
|
19675
19987
|
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
@@ -19709,10 +20021,10 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
19709
20021
|
return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
|
|
19710
20022
|
}
|
|
19711
20023
|
for (const relative5 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
|
|
19712
|
-
const configPath = (0,
|
|
19713
|
-
if (!(0,
|
|
20024
|
+
const configPath = (0, import_path8.join)(workspace, relative5);
|
|
20025
|
+
if (!(0, import_fs8.existsSync)(configPath)) continue;
|
|
19714
20026
|
try {
|
|
19715
|
-
const parsed =
|
|
20027
|
+
const parsed = parseConfigText3(configPath, (0, import_fs8.readFileSync)(configPath, "utf-8"));
|
|
19716
20028
|
const validation = validateMeshWorktreeBootstrapConfig(parsed, relative5);
|
|
19717
20029
|
if (!validation.valid) return { source: relative5, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
|
|
19718
20030
|
return { config: parsed, source: relative5, sourceType: "repo_file", path: configPath };
|
|
@@ -19725,9 +20037,9 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
|
|
|
19725
20037
|
function computeStaleInputsDigest(workspace, staleInputs) {
|
|
19726
20038
|
const digest = {};
|
|
19727
20039
|
for (const relative5 of staleInputs ?? []) {
|
|
19728
|
-
const filePath = (0,
|
|
20040
|
+
const filePath = (0, import_path8.join)(workspace, relative5);
|
|
19729
20041
|
try {
|
|
19730
|
-
digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0,
|
|
20042
|
+
digest[relative5] = (0, import_node_crypto2.createHash)("sha256").update((0, import_fs8.readFileSync)(filePath)).digest("hex");
|
|
19731
20043
|
} catch {
|
|
19732
20044
|
digest[relative5] = "absent";
|
|
19733
20045
|
}
|
|
@@ -19797,10 +20109,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
19797
20109
|
staleInputs: loaded.config.staleInputs
|
|
19798
20110
|
};
|
|
19799
20111
|
const staleInputPaths = loaded.config.staleInputs ?? [];
|
|
19800
|
-
const initiallyAbsent = staleInputPaths.filter((p) => !(0,
|
|
20112
|
+
const initiallyAbsent = staleInputPaths.filter((p) => !(0, import_fs8.existsSync)((0, import_path8.join)(workspace, p)));
|
|
19801
20113
|
for (const command of validation.commands) {
|
|
19802
20114
|
if (initiallyAbsent.length > 0) {
|
|
19803
|
-
const appearedNow = initiallyAbsent.filter((p) => (0,
|
|
20115
|
+
const appearedNow = initiallyAbsent.filter((p) => (0, import_fs8.existsSync)((0, import_path8.join)(workspace, p)));
|
|
19804
20116
|
if (appearedNow.length > 0) {
|
|
19805
20117
|
state.status = "stale";
|
|
19806
20118
|
state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -19808,7 +20120,7 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
|
|
|
19808
20120
|
return state;
|
|
19809
20121
|
}
|
|
19810
20122
|
}
|
|
19811
|
-
const cwd = command.cwd ? (0,
|
|
20123
|
+
const cwd = command.cwd ? (0, import_path8.resolve)(workspace, command.cwd) : workspace;
|
|
19812
20124
|
const startedAt = Date.now();
|
|
19813
20125
|
state.lastCommand = command.displayCommand;
|
|
19814
20126
|
try {
|
|
@@ -20047,8 +20359,8 @@ var P2pRelayFailureError = class extends Error {
|
|
|
20047
20359
|
};
|
|
20048
20360
|
|
|
20049
20361
|
// src/config/state-store.ts
|
|
20050
|
-
var
|
|
20051
|
-
var
|
|
20362
|
+
var import_fs12 = require("fs");
|
|
20363
|
+
var import_path10 = require("path");
|
|
20052
20364
|
init_config();
|
|
20053
20365
|
var DEFAULT_STATE = {
|
|
20054
20366
|
recentActivity: [],
|
|
@@ -20062,7 +20374,7 @@ function isPlainObject2(value) {
|
|
|
20062
20374
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
20063
20375
|
}
|
|
20064
20376
|
function getStatePath() {
|
|
20065
|
-
return (0,
|
|
20377
|
+
return (0, import_path10.join)(getConfigDir(), "state.json");
|
|
20066
20378
|
}
|
|
20067
20379
|
function normalizeState(raw) {
|
|
20068
20380
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -20098,11 +20410,11 @@ function normalizeState(raw) {
|
|
|
20098
20410
|
}
|
|
20099
20411
|
function loadState() {
|
|
20100
20412
|
const statePath = getStatePath();
|
|
20101
|
-
if (!(0,
|
|
20413
|
+
if (!(0, import_fs12.existsSync)(statePath)) {
|
|
20102
20414
|
return { ...DEFAULT_STATE };
|
|
20103
20415
|
}
|
|
20104
20416
|
try {
|
|
20105
|
-
const raw = (0,
|
|
20417
|
+
const raw = (0, import_fs12.readFileSync)(statePath, "utf-8");
|
|
20106
20418
|
return normalizeState(JSON.parse(raw));
|
|
20107
20419
|
} catch {
|
|
20108
20420
|
return { ...DEFAULT_STATE };
|
|
@@ -20111,7 +20423,7 @@ function loadState() {
|
|
|
20111
20423
|
function saveState(state) {
|
|
20112
20424
|
const statePath = getStatePath();
|
|
20113
20425
|
const normalized = normalizeState(state);
|
|
20114
|
-
(0,
|
|
20426
|
+
(0, import_fs12.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
20115
20427
|
}
|
|
20116
20428
|
function resetState() {
|
|
20117
20429
|
saveState({ ...DEFAULT_STATE });
|
|
@@ -20120,7 +20432,7 @@ function resetState() {
|
|
|
20120
20432
|
// src/detection/ide-detector.ts
|
|
20121
20433
|
var import_child_process2 = require("child_process");
|
|
20122
20434
|
var import_util = require("util");
|
|
20123
|
-
var
|
|
20435
|
+
var import_fs13 = require("fs");
|
|
20124
20436
|
var import_os2 = require("os");
|
|
20125
20437
|
var path13 = __toESM(require("path"));
|
|
20126
20438
|
|
|
@@ -20201,7 +20513,7 @@ function findCliCommand(command) {
|
|
|
20201
20513
|
if (path13.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
20202
20514
|
const candidate = trimmed.startsWith("~") ? path13.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
20203
20515
|
const resolved = path13.isAbsolute(candidate) ? candidate : path13.resolve(candidate);
|
|
20204
|
-
return (0,
|
|
20516
|
+
return (0, import_fs13.existsSync)(resolved) ? resolved : null;
|
|
20205
20517
|
}
|
|
20206
20518
|
const isWin = (0, import_os2.platform)() === "win32";
|
|
20207
20519
|
const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
|
|
@@ -20211,8 +20523,8 @@ function findCliCommand(command) {
|
|
|
20211
20523
|
for (const ext of exes) {
|
|
20212
20524
|
const fullPath = path13.join(p, trimmed + ext);
|
|
20213
20525
|
try {
|
|
20214
|
-
if ((0,
|
|
20215
|
-
const stat2 = (0,
|
|
20526
|
+
if ((0, import_fs13.existsSync)(fullPath)) {
|
|
20527
|
+
const stat2 = (0, import_fs13.statSync)(fullPath);
|
|
20216
20528
|
if (stat2.isFile() && (isWin || stat2.mode & 73)) {
|
|
20217
20529
|
return fullPath;
|
|
20218
20530
|
}
|
|
@@ -20230,9 +20542,9 @@ function checkPathExists(paths) {
|
|
|
20230
20542
|
if (normalized.includes("*")) {
|
|
20231
20543
|
const username = home.split(/[\\/]/).pop() || "";
|
|
20232
20544
|
const resolved = normalized.replace("*", username);
|
|
20233
|
-
if ((0,
|
|
20545
|
+
if ((0, import_fs13.existsSync)(resolved)) return resolved;
|
|
20234
20546
|
} else {
|
|
20235
|
-
if ((0,
|
|
20547
|
+
if ((0, import_fs13.existsSync)(normalized)) return normalized;
|
|
20236
20548
|
}
|
|
20237
20549
|
}
|
|
20238
20550
|
return null;
|
|
@@ -20246,7 +20558,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20246
20558
|
let resolvedCli = cliPath;
|
|
20247
20559
|
if (!resolvedCli && appPath && os30 === "darwin") {
|
|
20248
20560
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
20249
|
-
if ((0,
|
|
20561
|
+
if ((0, import_fs13.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
20250
20562
|
}
|
|
20251
20563
|
if (!resolvedCli && appPath && os30 === "win32") {
|
|
20252
20564
|
const { dirname: dirname17 } = await import("path");
|
|
@@ -20259,7 +20571,7 @@ async function detectIDEs(providerLoader) {
|
|
|
20259
20571
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
20260
20572
|
];
|
|
20261
20573
|
for (const c of candidates) {
|
|
20262
|
-
if ((0,
|
|
20574
|
+
if ((0, import_fs13.existsSync)(c)) {
|
|
20263
20575
|
resolvedCli = c;
|
|
20264
20576
|
break;
|
|
20265
20577
|
}
|
|
@@ -21804,8 +22116,8 @@ init_contracts();
|
|
|
21804
22116
|
// src/providers/status-monitor.ts
|
|
21805
22117
|
var DEFAULT_MONITOR_CONFIG = {
|
|
21806
22118
|
approvalAlert: true,
|
|
21807
|
-
|
|
21808
|
-
|
|
22119
|
+
noProgressAlert: true,
|
|
22120
|
+
noProgressThresholdSec: 180,
|
|
21809
22121
|
// 3 minutes
|
|
21810
22122
|
alertCooldownSec: 60
|
|
21811
22123
|
// 1 minute cooldown
|
|
@@ -21814,7 +22126,7 @@ var StatusMonitor = class {
|
|
|
21814
22126
|
config;
|
|
21815
22127
|
lastAlertTime = /* @__PURE__ */ new Map();
|
|
21816
22128
|
generatingStartTimes = /* @__PURE__ */ new Map();
|
|
21817
|
-
|
|
22129
|
+
noProgressAlerted = /* @__PURE__ */ new Map();
|
|
21818
22130
|
lastProgressFingerprint = /* @__PURE__ */ new Map();
|
|
21819
22131
|
lastProgressChangeAt = /* @__PURE__ */ new Map();
|
|
21820
22132
|
constructor(config) {
|
|
@@ -21832,7 +22144,7 @@ var StatusMonitor = class {
|
|
|
21832
22144
|
* Check status transition → return notification event array.
|
|
21833
22145
|
* Called from each onTick() or detectStatusTransition().
|
|
21834
22146
|
*/
|
|
21835
|
-
check(agentKey, status, now, progressFingerprint) {
|
|
22147
|
+
check(agentKey, status, now, progressFingerprint, approvalPending) {
|
|
21836
22148
|
const events = [];
|
|
21837
22149
|
if (this.config.approvalAlert && status === "waiting_approval") {
|
|
21838
22150
|
if (this.shouldAlert(agentKey + ":approval", now)) {
|
|
@@ -21845,9 +22157,16 @@ var StatusMonitor = class {
|
|
|
21845
22157
|
}
|
|
21846
22158
|
}
|
|
21847
22159
|
if (status === "generating" || status === "streaming") {
|
|
22160
|
+
if (approvalPending) {
|
|
22161
|
+
this.generatingStartTimes.set(agentKey, now);
|
|
22162
|
+
this.lastProgressFingerprint.set(agentKey, progressFingerprint ?? "");
|
|
22163
|
+
this.lastProgressChangeAt.set(agentKey, now);
|
|
22164
|
+
this.noProgressAlerted.set(agentKey, false);
|
|
22165
|
+
return events;
|
|
22166
|
+
}
|
|
21848
22167
|
if (!this.generatingStartTimes.has(agentKey)) {
|
|
21849
22168
|
this.generatingStartTimes.set(agentKey, now);
|
|
21850
|
-
this.
|
|
22169
|
+
this.noProgressAlerted.set(agentKey, false);
|
|
21851
22170
|
const initialFingerprint = progressFingerprint ?? "";
|
|
21852
22171
|
this.lastProgressFingerprint.set(agentKey, initialFingerprint);
|
|
21853
22172
|
this.lastProgressChangeAt.set(agentKey, now);
|
|
@@ -21857,17 +22176,17 @@ var StatusMonitor = class {
|
|
|
21857
22176
|
if (previousFingerprint !== currentFingerprint) {
|
|
21858
22177
|
this.lastProgressFingerprint.set(agentKey, currentFingerprint);
|
|
21859
22178
|
this.lastProgressChangeAt.set(agentKey, now);
|
|
21860
|
-
this.
|
|
22179
|
+
this.noProgressAlerted.set(agentKey, false);
|
|
21861
22180
|
}
|
|
21862
|
-
if (this.config.
|
|
22181
|
+
if (this.config.noProgressAlert) {
|
|
21863
22182
|
const progressChangedAt = this.lastProgressChangeAt.get(agentKey) || this.generatingStartTimes.get(agentKey);
|
|
21864
22183
|
const elapsedSec = Math.round((now - progressChangedAt) / 1e3);
|
|
21865
|
-
const alreadyAlerted = this.
|
|
21866
|
-
if (elapsedSec > this.config.
|
|
21867
|
-
if (this.shouldAlert(agentKey + ":
|
|
21868
|
-
this.
|
|
22184
|
+
const alreadyAlerted = this.noProgressAlerted.get(agentKey) === true;
|
|
22185
|
+
if (elapsedSec > this.config.noProgressThresholdSec && !alreadyAlerted) {
|
|
22186
|
+
if (this.shouldAlert(agentKey + ":no_progress", now)) {
|
|
22187
|
+
this.noProgressAlerted.set(agentKey, true);
|
|
21869
22188
|
events.push({
|
|
21870
|
-
type: "monitor:
|
|
22189
|
+
type: "monitor:no_progress",
|
|
21871
22190
|
agentKey,
|
|
21872
22191
|
elapsedSec,
|
|
21873
22192
|
timestamp: now,
|
|
@@ -21878,7 +22197,7 @@ var StatusMonitor = class {
|
|
|
21878
22197
|
}
|
|
21879
22198
|
} else {
|
|
21880
22199
|
this.generatingStartTimes.delete(agentKey);
|
|
21881
|
-
this.
|
|
22200
|
+
this.noProgressAlerted.delete(agentKey);
|
|
21882
22201
|
this.lastProgressFingerprint.delete(agentKey);
|
|
21883
22202
|
this.lastProgressChangeAt.delete(agentKey);
|
|
21884
22203
|
}
|
|
@@ -21897,7 +22216,7 @@ var StatusMonitor = class {
|
|
|
21897
22216
|
reset(agentKey) {
|
|
21898
22217
|
if (agentKey) {
|
|
21899
22218
|
this.generatingStartTimes.delete(agentKey);
|
|
21900
|
-
this.
|
|
22219
|
+
this.noProgressAlerted.delete(agentKey);
|
|
21901
22220
|
this.lastProgressFingerprint.delete(agentKey);
|
|
21902
22221
|
this.lastProgressChangeAt.delete(agentKey);
|
|
21903
22222
|
for (const k of this.lastAlertTime.keys()) {
|
|
@@ -21905,7 +22224,7 @@ var StatusMonitor = class {
|
|
|
21905
22224
|
}
|
|
21906
22225
|
} else {
|
|
21907
22226
|
this.generatingStartTimes.clear();
|
|
21908
|
-
this.
|
|
22227
|
+
this.noProgressAlerted.clear();
|
|
21909
22228
|
this.lastProgressFingerprint.clear();
|
|
21910
22229
|
this.lastProgressChangeAt.clear();
|
|
21911
22230
|
this.lastAlertTime.clear();
|
|
@@ -23728,8 +24047,8 @@ var ExtensionProviderInstance = class {
|
|
|
23728
24047
|
this.settings = context.settings || {};
|
|
23729
24048
|
this.monitor.updateConfig({
|
|
23730
24049
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
23731
|
-
|
|
23732
|
-
|
|
24050
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
24051
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
23733
24052
|
});
|
|
23734
24053
|
}
|
|
23735
24054
|
async onTick() {
|
|
@@ -23820,8 +24139,8 @@ var ExtensionProviderInstance = class {
|
|
|
23820
24139
|
this.settings = { ...this.settings, ...newSettings };
|
|
23821
24140
|
this.monitor.updateConfig({
|
|
23822
24141
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
23823
|
-
|
|
23824
|
-
|
|
24142
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
24143
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
23825
24144
|
});
|
|
23826
24145
|
}
|
|
23827
24146
|
/** Query UUID instanceId */
|
|
@@ -23881,7 +24200,8 @@ var ExtensionProviderInstance = class {
|
|
|
23881
24200
|
phase: agentStatus === "idle" && (previousStatus === "generating" || previousStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
23882
24201
|
});
|
|
23883
24202
|
const agentKey = `${this.type}:ext`;
|
|
23884
|
-
const
|
|
24203
|
+
const approvalPending = agentStatus === "waiting_approval";
|
|
24204
|
+
const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint, approvalPending);
|
|
23885
24205
|
for (const me of monitorEvents) {
|
|
23886
24206
|
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
23887
24207
|
}
|
|
@@ -24096,7 +24416,7 @@ init_contracts();
|
|
|
24096
24416
|
var CHAT_CONTRACT_VERSION_V1 = "1.0";
|
|
24097
24417
|
|
|
24098
24418
|
// src/providers/read-chat-contract.ts
|
|
24099
|
-
var VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "starting", "streaming", "long_generating"];
|
|
24419
|
+
var VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "starting", "streaming", "no_progress", "long_generating"];
|
|
24100
24420
|
var VALID_ROLES = ["user", "assistant", "system", "human"];
|
|
24101
24421
|
var VALID_BUBBLE_STATES = ["draft", "streaming", "final", "removed"];
|
|
24102
24422
|
var VALID_TURN_STATUSES = ["open", "waiting_approval", "complete", "error"];
|
|
@@ -24363,8 +24683,8 @@ var IdeProviderInstance = class {
|
|
|
24363
24683
|
this.settings = context.settings || {};
|
|
24364
24684
|
this.monitor.updateConfig({
|
|
24365
24685
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
24366
|
-
|
|
24367
|
-
|
|
24686
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
24687
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
24368
24688
|
});
|
|
24369
24689
|
}
|
|
24370
24690
|
async onTick() {
|
|
@@ -24491,8 +24811,8 @@ var IdeProviderInstance = class {
|
|
|
24491
24811
|
this.settings = { ...this.settings, ...newSettings };
|
|
24492
24812
|
this.monitor.updateConfig({
|
|
24493
24813
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
24494
|
-
|
|
24495
|
-
|
|
24814
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
24815
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
24496
24816
|
});
|
|
24497
24817
|
}
|
|
24498
24818
|
// ─── Extension manage ─────────────────────────────
|
|
@@ -24623,7 +24943,7 @@ var IdeProviderInstance = class {
|
|
|
24623
24943
|
const persistedMessages = chat.messages || messages;
|
|
24624
24944
|
if (persistedMessages.length > 0) {
|
|
24625
24945
|
let toSave = persistedMessages;
|
|
24626
|
-
if (chat.status === "generating" || chat.status === "long_generating") {
|
|
24946
|
+
if (chat.status === "generating" || chat.status === "no_progress" || chat.status === "long_generating") {
|
|
24627
24947
|
const lastIdx = toSave.length - 1;
|
|
24628
24948
|
if (lastIdx >= 0 && toSave[lastIdx].role === "assistant") {
|
|
24629
24949
|
toSave = toSave.slice(0, lastIdx);
|
|
@@ -24693,7 +25013,8 @@ var IdeProviderInstance = class {
|
|
|
24693
25013
|
if (rawAgentStatus === "waiting_approval" && autoApproveActive && !this.autoApproveBusy) {
|
|
24694
25014
|
this.autoApproveViaScript(chatData);
|
|
24695
25015
|
}
|
|
24696
|
-
const
|
|
25016
|
+
const approvalPending = rawAgentStatus === "waiting_approval";
|
|
25017
|
+
const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint, approvalPending);
|
|
24697
25018
|
for (const me of monitorEvents) {
|
|
24698
25019
|
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
24699
25020
|
}
|
|
@@ -27250,7 +27571,7 @@ function normalizeReadChatCommandStatus(status, activeModal) {
|
|
|
27250
27571
|
}
|
|
27251
27572
|
}
|
|
27252
27573
|
function isGeneratingLikeStatus(status) {
|
|
27253
|
-
return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
|
|
27574
|
+
return status === "generating" || status === "streaming" || status === "no_progress" || status === "long_generating" || status === "starting";
|
|
27254
27575
|
}
|
|
27255
27576
|
function hasVisibleAssistantMessage(messages) {
|
|
27256
27577
|
if (!Array.isArray(messages)) return false;
|
|
@@ -31283,7 +31604,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
31283
31604
|
var os19 = __toESM(require("os"));
|
|
31284
31605
|
var path26 = __toESM(require("path"));
|
|
31285
31606
|
var crypto5 = __toESM(require("crypto"));
|
|
31286
|
-
var
|
|
31607
|
+
var import_fs15 = require("fs");
|
|
31287
31608
|
var import_child_process6 = require("child_process");
|
|
31288
31609
|
var import_chalk = __toESM(require("chalk"));
|
|
31289
31610
|
init_provider_cli_adapter();
|
|
@@ -33928,7 +34249,7 @@ function hasNonEmptyCliModalButtons(activeModal) {
|
|
|
33928
34249
|
return Array.isArray(buttons) && buttons.some((button) => String(button || "").trim().length > 0);
|
|
33929
34250
|
}
|
|
33930
34251
|
function isCliGeneratingLikeStatus(status) {
|
|
33931
|
-
return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
|
|
34252
|
+
return status === "generating" || status === "streaming" || status === "no_progress" || status === "long_generating" || status === "starting";
|
|
33932
34253
|
}
|
|
33933
34254
|
function buildCliStructuredInputPrompt(input, options = {}) {
|
|
33934
34255
|
const promptParts = [];
|
|
@@ -34130,8 +34451,8 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
34130
34451
|
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
34131
34452
|
this.monitor.updateConfig({
|
|
34132
34453
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
34133
|
-
|
|
34134
|
-
|
|
34454
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
34455
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
34135
34456
|
});
|
|
34136
34457
|
if (context.serverConn) {
|
|
34137
34458
|
this.adapter.setServerConn(context.serverConn);
|
|
@@ -34278,7 +34599,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
34278
34599
|
if (parsedMessages.length > 0) {
|
|
34279
34600
|
const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
|
|
34280
34601
|
let messagesToSave = parsedMessages;
|
|
34281
|
-
if (!suppressStaleParsedBusyStatus && (parsedChatStatus === "generating" || parsedChatStatus === "long_generating")) {
|
|
34602
|
+
if (!suppressStaleParsedBusyStatus && (parsedChatStatus === "generating" || parsedChatStatus === "no_progress" || parsedChatStatus === "long_generating")) {
|
|
34282
34603
|
const lastIdx = messagesToSave.length - 1;
|
|
34283
34604
|
if (lastIdx >= 0 && messagesToSave[lastIdx]?.role === "assistant") {
|
|
34284
34605
|
messagesToSave = messagesToSave.slice(0, lastIdx);
|
|
@@ -34406,8 +34727,8 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
34406
34727
|
this.adapter.updateRuntimeSettings?.(this.settings);
|
|
34407
34728
|
this.monitor.updateConfig({
|
|
34408
34729
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
34409
|
-
|
|
34410
|
-
|
|
34730
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
34731
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
34411
34732
|
});
|
|
34412
34733
|
}
|
|
34413
34734
|
/**
|
|
@@ -35139,10 +35460,11 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35139
35460
|
phase: newStatus === "idle" && (previousStatus === "generating" || previousStatus === "waiting_approval") ? "turn_completed" : "immediate"
|
|
35140
35461
|
});
|
|
35141
35462
|
const agentKey = `${this.type}:cli`;
|
|
35142
|
-
const
|
|
35463
|
+
const approvalPending = rawStatus === "waiting_approval";
|
|
35464
|
+
const monitorEvents = this.monitor.check(agentKey, newStatus, now, progressFingerprint, approvalPending);
|
|
35143
35465
|
const monitorParsedStatus = parsedStatus;
|
|
35144
35466
|
for (const me of monitorEvents) {
|
|
35145
|
-
if (me.type === "monitor:
|
|
35467
|
+
if (me.type === "monitor:no_progress" && this.completionHasFinalAssistantMessage(monitorParsedStatus?.messages) && !this.hasAdapterPendingResponse() && !hasNonEmptyCliModalButtons(monitorParsedStatus?.activeModal ?? monitorParsedStatus?.modal)) {
|
|
35146
35468
|
this.pushEvent({
|
|
35147
35469
|
event: "agent:generating_completed",
|
|
35148
35470
|
chatTitle,
|
|
@@ -35153,7 +35475,7 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
35153
35475
|
providerType: this.type,
|
|
35154
35476
|
sessionId: this.instanceId,
|
|
35155
35477
|
providerSessionId: this.providerSessionId || null,
|
|
35156
|
-
reconciliationReason: "
|
|
35478
|
+
reconciliationReason: "no_progress_monitor_final_summary",
|
|
35157
35479
|
finalAssistantPresent: true
|
|
35158
35480
|
}
|
|
35159
35481
|
});
|
|
@@ -35830,8 +36152,8 @@ var AcpProviderInstance = class {
|
|
|
35830
36152
|
this.settings = context.settings || {};
|
|
35831
36153
|
this.monitor.updateConfig({
|
|
35832
36154
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
35833
|
-
|
|
35834
|
-
|
|
36155
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
36156
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
35835
36157
|
});
|
|
35836
36158
|
await this.spawnAgent();
|
|
35837
36159
|
}
|
|
@@ -36127,8 +36449,8 @@ var AcpProviderInstance = class {
|
|
|
36127
36449
|
this.settings = { ...this.settings, ...newSettings };
|
|
36128
36450
|
this.monitor.updateConfig({
|
|
36129
36451
|
approvalAlert: this.settings.approvalAlert !== false,
|
|
36130
|
-
|
|
36131
|
-
|
|
36452
|
+
noProgressAlert: (this.settings.noProgressAlert ?? this.settings.longGeneratingAlert) !== false,
|
|
36453
|
+
noProgressThresholdSec: this.settings.noProgressThresholdSec ?? this.settings.longGeneratingThresholdSec ?? 180
|
|
36132
36454
|
});
|
|
36133
36455
|
this.log.info(`[${this.type}] Settings updated: ${Object.keys(newSettings).join(", ")}`);
|
|
36134
36456
|
}
|
|
@@ -36835,7 +37157,8 @@ ${rawInput}` : rawInput;
|
|
|
36835
37157
|
this.lastStatus = newStatus;
|
|
36836
37158
|
}
|
|
36837
37159
|
const agentKey = `${this.type}:acp`;
|
|
36838
|
-
const
|
|
37160
|
+
const approvalPending = newStatus === "waiting_approval";
|
|
37161
|
+
const monitorEvents = this.monitor.check(agentKey, newStatus, now, progressFingerprint, approvalPending);
|
|
36839
37162
|
for (const me of monitorEvents) {
|
|
36840
37163
|
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
36841
37164
|
}
|
|
@@ -36897,7 +37220,7 @@ function commandExists(command) {
|
|
|
36897
37220
|
const trimmed = command.trim();
|
|
36898
37221
|
if (!trimmed) return false;
|
|
36899
37222
|
if (isExplicitCommand(trimmed)) {
|
|
36900
|
-
return (0,
|
|
37223
|
+
return (0, import_fs15.existsSync)(expandExecutable(trimmed));
|
|
36901
37224
|
}
|
|
36902
37225
|
try {
|
|
36903
37226
|
(0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -36909,7 +37232,7 @@ function commandExists(command) {
|
|
|
36909
37232
|
return false;
|
|
36910
37233
|
}
|
|
36911
37234
|
}
|
|
36912
|
-
var BUSY_AGENT_STATUSES = /* @__PURE__ */ new Set(["generating", "running", "streaming", "starting", "busy", "waiting", "waiting_approval", "long_generating"]);
|
|
37235
|
+
var BUSY_AGENT_STATUSES = /* @__PURE__ */ new Set(["generating", "running", "streaming", "starting", "busy", "waiting", "waiting_approval", "no_progress", "long_generating"]);
|
|
36913
37236
|
var ZERO_MESSAGE_STARTING_SEND_WAIT_MS = 2e3;
|
|
36914
37237
|
function normalizeAgentStatus(value) {
|
|
36915
37238
|
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
@@ -37033,10 +37356,10 @@ function hasConfigOverride(args, key) {
|
|
|
37033
37356
|
}
|
|
37034
37357
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
37035
37358
|
const baseDir = path26.join(os19.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
37036
|
-
(0,
|
|
37359
|
+
(0, import_fs15.mkdirSync)(baseDir, { recursive: true });
|
|
37037
37360
|
const workspaceHash = crypto5.createHash("sha256").update(path26.resolve(workspace || os19.tmpdir())).digest("hex").slice(0, 16);
|
|
37038
37361
|
const filePath = path26.join(baseDir, `${workspaceHash}.json`);
|
|
37039
|
-
(0,
|
|
37362
|
+
(0, import_fs15.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
37040
37363
|
return filePath;
|
|
37041
37364
|
}
|
|
37042
37365
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
@@ -41774,6 +42097,7 @@ function getAvailableIdeIds() {
|
|
|
41774
42097
|
init_config();
|
|
41775
42098
|
init_cli_detector();
|
|
41776
42099
|
init_git_status();
|
|
42100
|
+
init_change_impact_config();
|
|
41777
42101
|
init_dist();
|
|
41778
42102
|
init_logger();
|
|
41779
42103
|
|
|
@@ -41922,7 +42246,7 @@ function getRecentCommands(count = 50) {
|
|
|
41922
42246
|
cleanOldFiles();
|
|
41923
42247
|
|
|
41924
42248
|
// src/commands/router.ts
|
|
41925
|
-
var
|
|
42249
|
+
var yaml4 = __toESM(require("js-yaml"));
|
|
41926
42250
|
init_logger();
|
|
41927
42251
|
|
|
41928
42252
|
// src/logging/log-tail-reader.ts
|
|
@@ -42308,8 +42632,8 @@ function buildPreviewFreshness(repoRoot) {
|
|
|
42308
42632
|
init_mesh_refine_status();
|
|
42309
42633
|
|
|
42310
42634
|
// src/mesh/mesh-init.ts
|
|
42311
|
-
var
|
|
42312
|
-
var
|
|
42635
|
+
var import_fs16 = require("fs");
|
|
42636
|
+
var import_path11 = require("path");
|
|
42313
42637
|
var MESH_INIT_REFINE_CONFIG_PATH = MESH_REFINE_CONFIG_LOCATIONS[0];
|
|
42314
42638
|
var MESH_INIT_WORKTREE_BOOTSTRAP_CONFIG_PATH = MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS[0];
|
|
42315
42639
|
var CANDIDATE_STALE_INPUTS = [
|
|
@@ -42323,22 +42647,22 @@ var CANDIDATE_STALE_INPUTS = [
|
|
|
42323
42647
|
"requirements.txt"
|
|
42324
42648
|
];
|
|
42325
42649
|
function writeConfigFile(workspace, relativePath, config) {
|
|
42326
|
-
const target = (0,
|
|
42327
|
-
(0,
|
|
42328
|
-
(0,
|
|
42650
|
+
const target = (0, import_path11.join)(workspace, relativePath);
|
|
42651
|
+
(0, import_fs16.mkdirSync)((0, import_path11.dirname)(target), { recursive: true });
|
|
42652
|
+
(0, import_fs16.writeFileSync)(target, `${JSON.stringify(config, null, 2)}
|
|
42329
42653
|
`, "utf-8");
|
|
42330
42654
|
return target;
|
|
42331
42655
|
}
|
|
42332
42656
|
function suggestMeshWorktreeBootstrapConfig(workspace) {
|
|
42333
42657
|
const commands = [];
|
|
42334
|
-
const hasPackageJson = (0,
|
|
42335
|
-
const hasNpmLock = (0,
|
|
42658
|
+
const hasPackageJson = (0, import_fs16.existsSync)((0, import_path11.join)(workspace, "package.json"));
|
|
42659
|
+
const hasNpmLock = (0, import_fs16.existsSync)((0, import_path11.join)(workspace, "package-lock.json"));
|
|
42336
42660
|
if (hasPackageJson) {
|
|
42337
42661
|
commands.push(
|
|
42338
42662
|
hasNpmLock ? { command: "npm", args: ["ci"] } : { command: "npm", args: ["install"] }
|
|
42339
42663
|
);
|
|
42340
42664
|
}
|
|
42341
|
-
const staleInputs = CANDIDATE_STALE_INPUTS.filter((relative5) => (0,
|
|
42665
|
+
const staleInputs = CANDIDATE_STALE_INPUTS.filter((relative5) => (0, import_fs16.existsSync)((0, import_path11.join)(workspace, relative5)));
|
|
42342
42666
|
if (!commands.length) {
|
|
42343
42667
|
return { commands, staleInputs };
|
|
42344
42668
|
}
|
|
@@ -42406,7 +42730,7 @@ function runMeshInit(mesh, workspace, detected, options = {}) {
|
|
|
42406
42730
|
}
|
|
42407
42731
|
function applyConfigSuggestion(input) {
|
|
42408
42732
|
const { workspace, relativePath, existing, suggestedConfig, validate, write, overwrite } = input;
|
|
42409
|
-
const absolute = (0,
|
|
42733
|
+
const absolute = (0, import_path11.join)(workspace, relativePath);
|
|
42410
42734
|
if (existing !== void 0 && !overwrite) {
|
|
42411
42735
|
return { path: absolute, relativePath, written: false, skippedReason: "already_exists", config: existing };
|
|
42412
42736
|
}
|
|
@@ -43131,7 +43455,7 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
|
|
|
43131
43455
|
init_mesh_work_queue();
|
|
43132
43456
|
init_repo_mesh_types();
|
|
43133
43457
|
var import_os3 = require("os");
|
|
43134
|
-
var
|
|
43458
|
+
var import_path12 = require("path");
|
|
43135
43459
|
var fs26 = __toESM(require("fs"));
|
|
43136
43460
|
var import_node_child_process6 = require("child_process");
|
|
43137
43461
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
@@ -44604,14 +44928,14 @@ function collectFastForwardGitlinkPaths(repoRoot, baseHead, branchHead) {
|
|
|
44604
44928
|
const baseCommit = readTreeObject(repoRoot, baseHead, path42);
|
|
44605
44929
|
const branchCommit = readTreeObject(repoRoot, branchHead, path42);
|
|
44606
44930
|
if (!baseCommit || !branchCommit) return false;
|
|
44607
|
-
return isSubmoduleFastForward((0,
|
|
44931
|
+
return isSubmoduleFastForward((0, import_path12.resolve)(repoRoot, path42), baseCommit, branchCommit);
|
|
44608
44932
|
});
|
|
44609
44933
|
}
|
|
44610
44934
|
function evaluateGitlinkTrivialFastForward(repoRoot, baseHead, branchHead) {
|
|
44611
44935
|
const changedGitlinks = readChangedGitlinkPaths(repoRoot, baseHead, branchHead).map((path42) => {
|
|
44612
44936
|
const baseCommit = readTreeObject(repoRoot, baseHead, path42);
|
|
44613
44937
|
const branchCommit = readTreeObject(repoRoot, branchHead, path42);
|
|
44614
|
-
const submoduleRepoPath = (0,
|
|
44938
|
+
const submoduleRepoPath = (0, import_path12.resolve)(repoRoot, path42);
|
|
44615
44939
|
const fastForward = !!baseCommit && !!branchCommit && isSubmoduleFastForward(submoduleRepoPath, baseCommit, branchCommit);
|
|
44616
44940
|
return { path: path42, baseCommit, branchCommit, fastForward };
|
|
44617
44941
|
});
|
|
@@ -44666,7 +44990,7 @@ function buildTreeWithGitlinksEqualized(repoRoot, commitish, paths, placeholderC
|
|
|
44666
44990
|
if (!tree) return void 0;
|
|
44667
44991
|
const updates = paths.map((path42) => `160000 commit ${placeholderCommit} ${path42}`).join("\n");
|
|
44668
44992
|
if (!updates) return tree;
|
|
44669
|
-
const tmpIndex = (0,
|
|
44993
|
+
const tmpIndex = (0, import_path12.join)(resolveGitDir(repoRoot), `adhdev-refine-eq-${commitish.slice(0, 12)}.index`);
|
|
44670
44994
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
44671
44995
|
try {
|
|
44672
44996
|
(0, import_node_child_process6.execFileSync)("git", ["read-tree", tree], { cwd: repoRoot, env, stdio: "ignore" });
|
|
@@ -44741,7 +45065,7 @@ function synthesizeTrivialFastForwardMergeTree(repoRoot, baseHead, branchHead, g
|
|
|
44741
45065
|
if (!contentTree) return void 0;
|
|
44742
45066
|
const updates = branchGitlinks.map((entry) => `160000 commit ${entry.branchCommit} ${entry.path}`).join("\n");
|
|
44743
45067
|
if (!updates) return contentTree;
|
|
44744
|
-
const tmpIndex = (0,
|
|
45068
|
+
const tmpIndex = (0, import_path12.join)(resolveGitDir(repoRoot), `adhdev-refine-ff-${baseHead.slice(0, 12)}-${branchHead.slice(0, 12)}.index`);
|
|
44745
45069
|
const env = { ...process.env, GIT_INDEX_FILE: tmpIndex };
|
|
44746
45070
|
try {
|
|
44747
45071
|
(0, import_node_child_process6.execFileSync)("git", ["read-tree", contentTree], { cwd: repoRoot, env, stdio: "ignore" });
|
|
@@ -44879,7 +45203,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
|
|
|
44879
45203
|
return match ? { commit: match[1], path: match[2] } : null;
|
|
44880
45204
|
}).filter((entry) => !!entry);
|
|
44881
45205
|
for (const gitlink of gitlinks) {
|
|
44882
|
-
const submodulePath = (0,
|
|
45206
|
+
const submodulePath = (0, import_path12.resolve)(repoRoot, gitlink.path);
|
|
44883
45207
|
const entry = {
|
|
44884
45208
|
path: gitlink.path,
|
|
44885
45209
|
commit: gitlink.commit,
|
|
@@ -44907,7 +45231,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
|
|
|
44907
45231
|
try {
|
|
44908
45232
|
const imported = await importCommitFromWorktreeSubmodule(
|
|
44909
45233
|
submodulePath,
|
|
44910
|
-
(0,
|
|
45234
|
+
(0, import_path12.resolve)(options.worktreeRoot, gitlink.path),
|
|
44911
45235
|
gitlink.commit
|
|
44912
45236
|
);
|
|
44913
45237
|
if (imported) {
|
|
@@ -45119,19 +45443,19 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45119
45443
|
...extras
|
|
45120
45444
|
});
|
|
45121
45445
|
const isPackageManagerValidation = (candidate) => {
|
|
45122
|
-
const command = (0,
|
|
45446
|
+
const command = (0, import_path12.basename)(candidate.command).replace(/\.(?:cmd|exe)$/i, "");
|
|
45123
45447
|
return ["npm", "pnpm", "yarn", "bun"].includes(command) && candidate.args.some((arg) => arg === "run" || arg === "test" || arg === "exec");
|
|
45124
45448
|
};
|
|
45125
45449
|
const dependenciesLikelyMissing = (cwd) => {
|
|
45126
|
-
if (!fs26.existsSync((0,
|
|
45127
|
-
if (fs26.existsSync((0,
|
|
45128
|
-
return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) => fs26.existsSync((0,
|
|
45450
|
+
if (!fs26.existsSync((0, import_path12.join)(cwd, "package.json"))) return false;
|
|
45451
|
+
if (fs26.existsSync((0, import_path12.join)(cwd, "node_modules"))) return false;
|
|
45452
|
+
return ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock"].some((lock) => fs26.existsSync((0, import_path12.join)(cwd, lock)));
|
|
45129
45453
|
};
|
|
45130
45454
|
if (runLegacyBootstrapCommands) {
|
|
45131
45455
|
summary.bootstrap = { stage: "legacy" };
|
|
45132
45456
|
for (const candidate of selection.bootstrapCommands) {
|
|
45133
45457
|
const startedAt = Date.now();
|
|
45134
|
-
const cwd = candidate.cwd ? (0,
|
|
45458
|
+
const cwd = candidate.cwd ? (0, import_path12.resolve)(workspace, candidate.cwd) : workspace;
|
|
45135
45459
|
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
45136
45460
|
try {
|
|
45137
45461
|
const result = await execFileAsync4(candidate.command, candidate.args, {
|
|
@@ -45159,7 +45483,7 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45159
45483
|
}
|
|
45160
45484
|
for (const candidate of selection.commands) {
|
|
45161
45485
|
const startedAt = Date.now();
|
|
45162
|
-
const cwd = candidate.cwd ? (0,
|
|
45486
|
+
const cwd = candidate.cwd ? (0, import_path12.resolve)(workspace, candidate.cwd) : workspace;
|
|
45163
45487
|
const timeout = candidate.timeoutMs || REFINE_VALIDATION_TIMEOUT_MS;
|
|
45164
45488
|
const bootstrapProvidedDependencies = summary.bootstrap?.stage === "cached" || summary.bootstrap?.stage === "ran" || summary.bootstrap?.stage === "legacy";
|
|
45165
45489
|
if (!bootstrapProvidedDependencies && isPackageManagerValidation(candidate) && dependenciesLikelyMissing(cwd)) {
|
|
@@ -45205,7 +45529,7 @@ async function runMeshRefineValidationGate(mesh, workspace, opts) {
|
|
|
45205
45529
|
return summary;
|
|
45206
45530
|
}
|
|
45207
45531
|
function loadYamlModule() {
|
|
45208
|
-
return
|
|
45532
|
+
return yaml4;
|
|
45209
45533
|
}
|
|
45210
45534
|
function getMcpServersKey(format) {
|
|
45211
45535
|
return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
|
|
@@ -45222,13 +45546,13 @@ function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
|
45222
45546
|
}
|
|
45223
45547
|
function resolveHermesUserHome() {
|
|
45224
45548
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
45225
|
-
return explicitHome || (0,
|
|
45549
|
+
return explicitHome || (0, import_path12.join)((0, import_os3.homedir)(), ".hermes");
|
|
45226
45550
|
}
|
|
45227
45551
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
45228
45552
|
const sourceHome = resolveHermesUserHome();
|
|
45229
|
-
const sourceConfigPath = (0,
|
|
45553
|
+
const sourceConfigPath = (0, import_path12.join)(sourceHome, "config.yaml");
|
|
45230
45554
|
if (!fs26.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
45231
|
-
if ((0,
|
|
45555
|
+
if ((0, import_path12.resolve)(sourceConfigPath) === (0, import_path12.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
45232
45556
|
const parsed = parseMeshCoordinatorMcpConfig(fs26.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
45233
45557
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
45234
45558
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
@@ -45262,10 +45586,10 @@ function stripHermesCoordinatorTempModelProviderOverrides(config) {
|
|
|
45262
45586
|
return sanitized;
|
|
45263
45587
|
}
|
|
45264
45588
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
45265
|
-
if ((0,
|
|
45589
|
+
if ((0, import_path12.resolve)(sourceHome) === (0, import_path12.resolve)(targetHome)) return;
|
|
45266
45590
|
for (const fileName of [".env", "auth.json"]) {
|
|
45267
|
-
const sourcePath = (0,
|
|
45268
|
-
const targetPath = (0,
|
|
45591
|
+
const sourcePath = (0, import_path12.join)(sourceHome, fileName);
|
|
45592
|
+
const targetPath = (0, import_path12.join)(targetHome, fileName);
|
|
45269
45593
|
if (!fs26.existsSync(sourcePath)) continue;
|
|
45270
45594
|
try {
|
|
45271
45595
|
fs26.copyFileSync(sourcePath, targetPath);
|
|
@@ -45767,7 +46091,7 @@ var DaemonCommandRouter = class {
|
|
|
45767
46091
|
}
|
|
45768
46092
|
const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
45769
46093
|
const normalizePath = (value) => {
|
|
45770
|
-
const resolved = (0,
|
|
46094
|
+
const resolved = (0, import_path12.resolve)(value);
|
|
45771
46095
|
try {
|
|
45772
46096
|
return fs26.realpathSync(resolved);
|
|
45773
46097
|
} catch {
|
|
@@ -48947,6 +49271,42 @@ ${hintLines.join("\n")}` : "",
|
|
|
48947
49271
|
note: "Suggestions are heuristic scaffold only; Refinery will not execute them until saved into repo mesh/refine config."
|
|
48948
49272
|
};
|
|
48949
49273
|
}
|
|
49274
|
+
case "get_mesh_change_impact_config_schema": {
|
|
49275
|
+
return {
|
|
49276
|
+
success: true,
|
|
49277
|
+
schema: CHANGE_IMPACT_CONFIG_SCHEMA,
|
|
49278
|
+
locations: CHANGE_IMPACT_CONFIG_LOCATIONS,
|
|
49279
|
+
sourceOfTruth: "repo change-impact config",
|
|
49280
|
+
heuristicRole: "suggestions_only_not_execution_path",
|
|
49281
|
+
note: "Declarative config only \u2014 JSON/YAML are parsed but never executed. Defines which package/file changes require a daemon rebuild/restart vs. a web-only redeploy vs. nothing."
|
|
49282
|
+
};
|
|
49283
|
+
}
|
|
49284
|
+
case "validate_mesh_change_impact_config": {
|
|
49285
|
+
const workspace = typeof args?.workspace === "string" ? args.workspace : process.cwd();
|
|
49286
|
+
if (args?.config !== void 0) {
|
|
49287
|
+
const validation = validateChangeImpactConfig(args.config, "inline");
|
|
49288
|
+
return { success: validation.valid, source: "inline", sourceType: "mesh_policy", ...validation };
|
|
49289
|
+
}
|
|
49290
|
+
const loaded = loadChangeImpactConfig(workspace);
|
|
49291
|
+
if (loaded.sourceType === "repo_file") {
|
|
49292
|
+
const validation = validateChangeImpactConfig(loaded.config, loaded.source);
|
|
49293
|
+
return { success: validation.valid, ...loaded, ...validation };
|
|
49294
|
+
}
|
|
49295
|
+
return {
|
|
49296
|
+
success: false,
|
|
49297
|
+
...loaded,
|
|
49298
|
+
valid: false,
|
|
49299
|
+
errors: [loaded.error || "repo change-impact config unavailable"]
|
|
49300
|
+
};
|
|
49301
|
+
}
|
|
49302
|
+
case "suggest_mesh_change_impact_config": {
|
|
49303
|
+
const workspace = typeof args?.workspace === "string" ? args.workspace : process.cwd();
|
|
49304
|
+
return {
|
|
49305
|
+
success: true,
|
|
49306
|
+
...suggestChangeImpactConfig(workspace),
|
|
49307
|
+
note: "Suggestions are heuristic scaffold only; the draft must be reviewed and saved into repo change-impact config before it takes effect. Nothing is executed."
|
|
49308
|
+
};
|
|
49309
|
+
}
|
|
48950
49310
|
case "mesh_init": {
|
|
48951
49311
|
const workspace = typeof args?.workspace === "string" && args.workspace.trim() ? args.workspace.trim() : process.cwd();
|
|
48952
49312
|
const mesh = args?.inlineMesh || {};
|
|
@@ -49738,7 +50098,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
49738
50098
|
};
|
|
49739
50099
|
}
|
|
49740
50100
|
if (cliType === "codex-cli") {
|
|
49741
|
-
const repoMcpConfigPath = (0,
|
|
50101
|
+
const repoMcpConfigPath = (0, import_path12.join)(workspace, ".mcp.json");
|
|
49742
50102
|
if (fs26.existsSync(repoMcpConfigPath)) {
|
|
49743
50103
|
try {
|
|
49744
50104
|
const repoMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
@@ -49863,7 +50223,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
49863
50223
|
workspace
|
|
49864
50224
|
};
|
|
49865
50225
|
}
|
|
49866
|
-
const { existsSync:
|
|
50226
|
+
const { existsSync: existsSync46, readFileSync: readFileSync37, writeFileSync: writeFileSync23, copyFileSync: copyFileSync4, mkdirSync: mkdirSync21 } = await import("fs");
|
|
49867
50227
|
const { dirname: dirname17 } = await import("path");
|
|
49868
50228
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
49869
50229
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -49906,14 +50266,14 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
49906
50266
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
49907
50267
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
49908
50268
|
}
|
|
49909
|
-
const hadExistingMcpConfig =
|
|
50269
|
+
const hadExistingMcpConfig = existsSync46(mcpConfigPath);
|
|
49910
50270
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
49911
50271
|
if (hermesBaseConfig) {
|
|
49912
50272
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname17(mcpConfigPath));
|
|
49913
50273
|
}
|
|
49914
50274
|
if (hadExistingMcpConfig) {
|
|
49915
50275
|
try {
|
|
49916
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
50276
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync37(mcpConfigPath, "utf-8"), configFormat);
|
|
49917
50277
|
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
49918
50278
|
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
49919
50279
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
@@ -50412,7 +50772,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
50412
50772
|
const { deriveMeshReviewInboxItems: deriveMeshReviewInboxItems2 } = await Promise.resolve().then(() => (init_mesh_review_inbox(), mesh_review_inbox_exports));
|
|
50413
50773
|
const { readLedgerEntries: readLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
50414
50774
|
const { getGitDiffSummary: getGitDiffSummary2 } = await Promise.resolve().then(() => (init_git_diff(), git_diff_exports));
|
|
50415
|
-
const { existsSync:
|
|
50775
|
+
const { existsSync: existsSync46 } = await import("fs");
|
|
50416
50776
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
50417
50777
|
const mesh = meshRecord?.mesh;
|
|
50418
50778
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
@@ -50431,7 +50791,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
50431
50791
|
const derivation = deriveMeshReviewInboxItems2({ nodes: nodeStatuses, ledgerEntries });
|
|
50432
50792
|
for (const item of derivation.items) {
|
|
50433
50793
|
const workspace = item.workspace;
|
|
50434
|
-
if (!workspace || !
|
|
50794
|
+
if (!workspace || !existsSync46(workspace)) continue;
|
|
50435
50795
|
const baseRef = item.defaultBranch ? `origin/${item.defaultBranch}` : "origin/main";
|
|
50436
50796
|
try {
|
|
50437
50797
|
const diffResult = await getGitDiffSummary2(workspace, { baseRef, maxFiles: 100 });
|
|
@@ -50605,7 +50965,7 @@ var DaemonStatusReporter = class {
|
|
|
50605
50965
|
case "agent:waiting_approval":
|
|
50606
50966
|
case "agent:generating_completed":
|
|
50607
50967
|
case "agent:stopped":
|
|
50608
|
-
case "monitor:
|
|
50968
|
+
case "monitor:no_progress":
|
|
50609
50969
|
return value;
|
|
50610
50970
|
default:
|
|
50611
50971
|
return null;
|
|
@@ -51150,7 +51510,7 @@ var ProviderStreamAdapter = class {
|
|
|
51150
51510
|
}
|
|
51151
51511
|
const validated = validateReadChatResultPayload(data, `${this.agentType} readChat`);
|
|
51152
51512
|
const validatedStatus = validated.status;
|
|
51153
|
-
const streamStatus = validatedStatus === "generating" || validatedStatus === "long_generating" ? "streaming" : validatedStatus;
|
|
51513
|
+
const streamStatus = validatedStatus === "generating" || validatedStatus === "no_progress" || validatedStatus === "long_generating" ? "streaming" : validatedStatus;
|
|
51154
51514
|
const state = {
|
|
51155
51515
|
agentType: this.agentType,
|
|
51156
51516
|
agentName: this.agentName,
|
|
@@ -59069,6 +59429,8 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
59069
59429
|
AcpProviderInstance,
|
|
59070
59430
|
AgentStreamPoller,
|
|
59071
59431
|
BUILTIN_CHAT_MESSAGE_KINDS,
|
|
59432
|
+
CHANGE_IMPACT_CONFIG_LOCATIONS,
|
|
59433
|
+
CHANGE_IMPACT_CONFIG_SCHEMA,
|
|
59072
59434
|
CHAT_MESSAGE_ACTIVITY_SOURCES,
|
|
59073
59435
|
CHAT_MESSAGE_AUDIENCES,
|
|
59074
59436
|
CHAT_MESSAGE_INTERNAL_SOURCES,
|
|
@@ -59259,6 +59621,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
59259
59621
|
getSessionHostSurfaceKind,
|
|
59260
59622
|
getSessionRecoveryContext,
|
|
59261
59623
|
getWorkspaceState,
|
|
59624
|
+
globToRegExp,
|
|
59262
59625
|
handleGitCommand,
|
|
59263
59626
|
hasCdpManager,
|
|
59264
59627
|
hasPendingDependents,
|
|
@@ -59292,6 +59655,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
59292
59655
|
listMeshMissionSummaries,
|
|
59293
59656
|
listMeshes,
|
|
59294
59657
|
listWorktrees,
|
|
59658
|
+
loadChangeImpactConfig,
|
|
59295
59659
|
loadConfig,
|
|
59296
59660
|
loadMeshCoordinatorRegistry,
|
|
59297
59661
|
loadMeshRefineConfig,
|
|
@@ -59386,6 +59750,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
59386
59750
|
spawnDetachedDaemonUpgradeHelper,
|
|
59387
59751
|
startDaemonDevSupport,
|
|
59388
59752
|
startLocalIpcServer,
|
|
59753
|
+
suggestChangeImpactConfig,
|
|
59389
59754
|
suggestMeshRefineConfig,
|
|
59390
59755
|
summarizeGitStatus,
|
|
59391
59756
|
summarizeMeshAsyncRefineJobs,
|
|
@@ -59402,6 +59767,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
|
|
|
59402
59767
|
updateTaskStatus,
|
|
59403
59768
|
upsertMeshMission,
|
|
59404
59769
|
upsertSavedProviderSession,
|
|
59770
|
+
validateChangeImpactConfig,
|
|
59405
59771
|
validateCliProviderManifest,
|
|
59406
59772
|
validateFsmSpec,
|
|
59407
59773
|
validateMeshRefineConfig,
|