@adhdev/daemon-standalone 1.0.29 → 1.0.30-rc.2
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/index.js +562 -94
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/{index-CymiuPZJ.js → index-NkLGCvUY.js} +3 -3
- package/public/assets/{terminal-BZj_X5zy.js → terminal-DiXj2eIR.js} +1 -1
- package/public/assets/{vendor-cL4V2vaO.js → vendor-DyCWA2YZ.js} +57 -49
- package/public/index.html +2 -2
- package/vendor/mcp-server/index.js +277 -2
- package/vendor/mcp-server/index.js.map +1 -1
- package/vendor/session-host-daemon/index.d.mts +5 -0
- package/vendor/session-host-daemon/index.d.ts +5 -0
- package/vendor/session-host-daemon/index.js +24 -3
- package/vendor/session-host-daemon/index.js.map +1 -1
- package/vendor/session-host-daemon/index.mjs +26 -4
- package/vendor/session-host-daemon/index.mjs.map +1 -1
package/dist/index.js
CHANGED
|
@@ -2887,6 +2887,7 @@ var require_dist = __commonJS({
|
|
|
2887
2887
|
isDefaultInstanceConfigDir: () => isDefaultInstanceConfigDir,
|
|
2888
2888
|
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime2,
|
|
2889
2889
|
isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot2,
|
|
2890
|
+
isTerminalRecord: () => isTerminalRecord,
|
|
2890
2891
|
partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions2,
|
|
2891
2892
|
partitionSessionHostRecords: () => partitionSessionHostRecords2,
|
|
2892
2893
|
resolveAttachableRuntimeRecord: () => resolveAttachableRuntimeRecord,
|
|
@@ -3062,10 +3063,17 @@ var require_dist = __commonJS({
|
|
|
3062
3063
|
return candidate;
|
|
3063
3064
|
}
|
|
3064
3065
|
var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
3066
|
+
var TERMINAL_LIFECYCLES = /* @__PURE__ */ new Set(["stopped", "failed"]);
|
|
3067
|
+
function isTerminalRecord(record2) {
|
|
3068
|
+
if (!record2) return false;
|
|
3069
|
+
if (record2.termination) return true;
|
|
3070
|
+
return TERMINAL_LIFECYCLES.has(String(record2.lifecycle || "").trim());
|
|
3071
|
+
}
|
|
3065
3072
|
function isSessionHostLiveRuntime2(record2) {
|
|
3066
3073
|
if (!record2) return false;
|
|
3067
3074
|
if (record2.surfaceKind === "live_runtime") return true;
|
|
3068
3075
|
if (record2.surfaceKind === "recovery_snapshot" || record2.surfaceKind === "inactive_record") return false;
|
|
3076
|
+
if (record2.termination) return false;
|
|
3069
3077
|
const lifecycle = String(record2.lifecycle || "").trim();
|
|
3070
3078
|
return LIVE_LIFECYCLES.has(lifecycle);
|
|
3071
3079
|
}
|
|
@@ -33311,10 +33319,10 @@ var require_dist3 = __commonJS({
|
|
|
33311
33319
|
}
|
|
33312
33320
|
function getDaemonBuildInfo() {
|
|
33313
33321
|
if (cached2) return cached2;
|
|
33314
|
-
const commit = readInjected(true ? "
|
|
33315
|
-
const commitShort = readInjected(true ? "
|
|
33316
|
-
const version2 = readInjected(true ? "1.0.
|
|
33317
|
-
const builtAt = readInjected(true ? "2026-08-
|
|
33322
|
+
const commit = readInjected(true ? "db8aa7a995a36bb687757d1ebcac1e394ee764a6" : void 0) ?? "unknown";
|
|
33323
|
+
const commitShort = readInjected(true ? "db8aa7a9" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
33324
|
+
const version2 = readInjected(true ? "1.0.30-rc.2" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
33325
|
+
const builtAt = readInjected(true ? "2026-08-03T02:08:19.187Z" : void 0);
|
|
33318
33326
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
33319
33327
|
return cached2;
|
|
33320
33328
|
}
|
|
@@ -35574,11 +35582,15 @@ ${error48.message || ""}`;
|
|
|
35574
35582
|
__export2(dist_exports, {
|
|
35575
35583
|
CANONICAL_MESH_TOOL_COUNT: () => CANONICAL_MESH_TOOL_COUNT,
|
|
35576
35584
|
CANONICAL_MESH_TOOL_NAMES: () => CANONICAL_MESH_TOOL_NAMES,
|
|
35585
|
+
CLI_SLOT_RECIPES: () => CLI_SLOT_RECIPES,
|
|
35577
35586
|
DEFAULT_DIFFICULTY_BRAINS: () => DEFAULT_DIFFICULTY_BRAINS,
|
|
35578
35587
|
MAGI_RAW_ANSWER_CAP: () => MAGI_RAW_ANSWER_CAP,
|
|
35579
35588
|
MESH_TASK_DIFFICULTIES: () => MESH_TASK_DIFFICULTIES,
|
|
35580
35589
|
STATUS_PROBE_ARG_KEY: () => STATUS_PROBE_ARG_KEY,
|
|
35590
|
+
UNKNOWN_CLI_SLOT_RECIPE: () => UNKNOWN_CLI_SLOT_RECIPE,
|
|
35581
35591
|
argsCarryStatusProbeMarker: () => argsCarryStatusProbeMarker,
|
|
35592
|
+
buildMagiPanelProposal: () => buildMagiPanelProposal,
|
|
35593
|
+
buildSlotProposal: () => buildSlotProposal,
|
|
35582
35594
|
canonicalDaemonId: () => canonicalDaemonId,
|
|
35583
35595
|
daemonIdsEquivalent: () => daemonIdsEquivalent,
|
|
35584
35596
|
deriveSlotsFromLegacy: () => deriveSlotsFromLegacy,
|
|
@@ -36033,6 +36045,93 @@ ${error48.message || ""}`;
|
|
|
36033
36045
|
};
|
|
36034
36046
|
});
|
|
36035
36047
|
}
|
|
36048
|
+
function slotKey(slot) {
|
|
36049
|
+
return [
|
|
36050
|
+
slot.provider,
|
|
36051
|
+
slot.model ?? "",
|
|
36052
|
+
slot.thinkingLevel ?? "",
|
|
36053
|
+
[...slot.difficulty ?? []].sort().join("|"),
|
|
36054
|
+
[...slot.capability ?? []].sort().join("|"),
|
|
36055
|
+
slot.maxParallel ?? ""
|
|
36056
|
+
].join("\0");
|
|
36057
|
+
}
|
|
36058
|
+
function dedupeDetected(detected) {
|
|
36059
|
+
const seen = /* @__PURE__ */ new Set();
|
|
36060
|
+
const out = [];
|
|
36061
|
+
for (const d of detected) {
|
|
36062
|
+
const type2 = typeof d?.type === "string" ? d.type.trim() : "";
|
|
36063
|
+
if (!type2 || seen.has(type2)) continue;
|
|
36064
|
+
seen.add(type2);
|
|
36065
|
+
out.push({ ...d, type: type2 });
|
|
36066
|
+
}
|
|
36067
|
+
return out;
|
|
36068
|
+
}
|
|
36069
|
+
function buildSlotProposal(detected, currentSlots = []) {
|
|
36070
|
+
const providers = dedupeDetected(detected ?? []);
|
|
36071
|
+
const proposedSlots = [];
|
|
36072
|
+
const entries = [];
|
|
36073
|
+
const unknownProviders = [];
|
|
36074
|
+
const provisionalProviders = [];
|
|
36075
|
+
for (const provider of providers) {
|
|
36076
|
+
const known = CLI_SLOT_RECIPES[provider.type];
|
|
36077
|
+
const recipes = known ?? [UNKNOWN_CLI_SLOT_RECIPE];
|
|
36078
|
+
const isUnknown = !known;
|
|
36079
|
+
if (isUnknown) unknownProviders.push(provider.type);
|
|
36080
|
+
let providerProvisional = false;
|
|
36081
|
+
for (const recipe of recipes) {
|
|
36082
|
+
const slot = normalizeNodeCapabilitySlot({
|
|
36083
|
+
provider: provider.type,
|
|
36084
|
+
model: recipe.model,
|
|
36085
|
+
thinkingLevel: recipe.thinkingLevel,
|
|
36086
|
+
difficulty: recipe.difficulty,
|
|
36087
|
+
maxParallel: recipe.maxParallel
|
|
36088
|
+
});
|
|
36089
|
+
if (!slot) continue;
|
|
36090
|
+
const provisional = recipe.provisional === true;
|
|
36091
|
+
if (provisional) providerProvisional = true;
|
|
36092
|
+
proposedSlots.push(slot);
|
|
36093
|
+
entries.push({
|
|
36094
|
+
slot,
|
|
36095
|
+
unknownProvider: isUnknown,
|
|
36096
|
+
provisional,
|
|
36097
|
+
...recipe.rationale ? { rationale: recipe.rationale } : {}
|
|
36098
|
+
});
|
|
36099
|
+
}
|
|
36100
|
+
if (providerProvisional) provisionalProviders.push(provider.type);
|
|
36101
|
+
}
|
|
36102
|
+
const proposedKeys = new Set(proposedSlots.map(slotKey));
|
|
36103
|
+
const droppedSlots = currentSlots.filter((slot) => !proposedKeys.has(slotKey(slot)));
|
|
36104
|
+
const proposedProviders = new Set(proposedSlots.map((s2) => s2.provider));
|
|
36105
|
+
const droppedProviders = [...new Set(
|
|
36106
|
+
droppedSlots.map((s2) => s2.provider).filter((p) => !proposedProviders.has(p))
|
|
36107
|
+
)];
|
|
36108
|
+
return {
|
|
36109
|
+
proposedSlots,
|
|
36110
|
+
entries,
|
|
36111
|
+
unknownProviders,
|
|
36112
|
+
provisionalProviders,
|
|
36113
|
+
droppedSlots,
|
|
36114
|
+
droppedProviders,
|
|
36115
|
+
destructive: droppedSlots.length > 0
|
|
36116
|
+
};
|
|
36117
|
+
}
|
|
36118
|
+
function buildMagiPanelProposal(detected, opts = {}) {
|
|
36119
|
+
const providers = dedupeDetected(detected ?? []);
|
|
36120
|
+
const tableOrder = Object.keys(CLI_SLOT_RECIPES);
|
|
36121
|
+
const rank = (type2) => {
|
|
36122
|
+
const i = tableOrder.indexOf(type2);
|
|
36123
|
+
return i === -1 ? Number.MAX_SAFE_INTEGER : i;
|
|
36124
|
+
};
|
|
36125
|
+
const ordered = [...providers].sort((a, b) => rank(a.type) - rank(b.type));
|
|
36126
|
+
const limit = Number.isFinite(opts.maxSlots) && opts.maxSlots > 0 ? Math.floor(opts.maxSlots) : ordered.length;
|
|
36127
|
+
return ordered.slice(0, limit).map((p) => ({
|
|
36128
|
+
...opts.nodeId ? { nodeId: opts.nodeId } : {},
|
|
36129
|
+
provider: p.type
|
|
36130
|
+
// A model is intentionally NOT pinned: the panel's job is cross-provider
|
|
36131
|
+
// independence, and pinning models here would silently couple the panel
|
|
36132
|
+
// to this table's cost assumptions rather than to review quality.
|
|
36133
|
+
}));
|
|
36134
|
+
}
|
|
36036
36135
|
function interpolateArgs(args, context) {
|
|
36037
36136
|
const result = {};
|
|
36038
36137
|
for (const [k, v] of Object.entries(args)) {
|
|
@@ -36061,6 +36160,8 @@ ${error48.message || ""}`;
|
|
|
36061
36160
|
var MAGI_RAW_ANSWER_CAP;
|
|
36062
36161
|
var MESH_TASK_DIFFICULTIES;
|
|
36063
36162
|
var DEFAULT_DIFFICULTY_BRAINS;
|
|
36163
|
+
var CLI_SLOT_RECIPES;
|
|
36164
|
+
var UNKNOWN_CLI_SLOT_RECIPE;
|
|
36064
36165
|
var CANONICAL_MESH_TOOL_NAMES;
|
|
36065
36166
|
var CANONICAL_MESH_TOOL_COUNT;
|
|
36066
36167
|
var STATUS_PROBE_ARG_KEY;
|
|
@@ -36075,6 +36176,73 @@ ${error48.message || ""}`;
|
|
|
36075
36176
|
medium: { model: "sonnet", thinkingLevel: "medium" },
|
|
36076
36177
|
difficult: { model: "opus", thinkingLevel: "high" }
|
|
36077
36178
|
};
|
|
36179
|
+
CLI_SLOT_RECIPES = Object.freeze({
|
|
36180
|
+
"claude-cli": [
|
|
36181
|
+
{
|
|
36182
|
+
model: "sonnet",
|
|
36183
|
+
thinkingLevel: "high",
|
|
36184
|
+
difficulty: ["medium", "easy"],
|
|
36185
|
+
maxParallel: 5,
|
|
36186
|
+
rationale: "Primary workhorse \u2014 widest parallelism for routine work."
|
|
36187
|
+
},
|
|
36188
|
+
{
|
|
36189
|
+
model: "opus",
|
|
36190
|
+
thinkingLevel: "high",
|
|
36191
|
+
difficulty: ["difficult"],
|
|
36192
|
+
maxParallel: 1,
|
|
36193
|
+
rationale: "Reserved for hard tasks; capped at 1 to bound cost."
|
|
36194
|
+
}
|
|
36195
|
+
],
|
|
36196
|
+
"kimi": [
|
|
36197
|
+
{
|
|
36198
|
+
model: "kimi-code/k3",
|
|
36199
|
+
difficulty: ["medium", "difficult"],
|
|
36200
|
+
maxParallel: 2,
|
|
36201
|
+
rationale: "Independent second opinion on mid/hard work."
|
|
36202
|
+
}
|
|
36203
|
+
],
|
|
36204
|
+
"codex-cli": [
|
|
36205
|
+
{
|
|
36206
|
+
difficulty: ["medium", "difficult", "freeform"],
|
|
36207
|
+
maxParallel: 2,
|
|
36208
|
+
rationale: "Broad range including freeform; no model pin."
|
|
36209
|
+
}
|
|
36210
|
+
],
|
|
36211
|
+
"antigravity-cli": [
|
|
36212
|
+
{
|
|
36213
|
+
model: "Gemini 3.1 Pro (High)",
|
|
36214
|
+
difficulty: ["easy"],
|
|
36215
|
+
maxParallel: 2,
|
|
36216
|
+
rationale: "Cheap capacity for easy tasks."
|
|
36217
|
+
}
|
|
36218
|
+
],
|
|
36219
|
+
"cursor-cli": [
|
|
36220
|
+
{
|
|
36221
|
+
model: "auto",
|
|
36222
|
+
difficulty: ["easy"],
|
|
36223
|
+
maxParallel: 1,
|
|
36224
|
+
rationale: "Easy tasks only; auto model selection."
|
|
36225
|
+
}
|
|
36226
|
+
],
|
|
36227
|
+
"hermes-cli": [
|
|
36228
|
+
{
|
|
36229
|
+
difficulty: ["medium"],
|
|
36230
|
+
maxParallel: 2,
|
|
36231
|
+
provisional: true,
|
|
36232
|
+
// NOTE: ESTIMATE, NOT OBSERVED. hermes-cli is absent from the live
|
|
36233
|
+
// slot configuration this table was seeded from, so `medium` is a
|
|
36234
|
+
// conservative placement rather than a transcription. Revisit once
|
|
36235
|
+
// it has real usage data.
|
|
36236
|
+
rationale: "ESTIMATE \u2014 no live slot to transcribe; conservative mid placement. Adjust after real use."
|
|
36237
|
+
}
|
|
36238
|
+
]
|
|
36239
|
+
});
|
|
36240
|
+
UNKNOWN_CLI_SLOT_RECIPE = Object.freeze({
|
|
36241
|
+
difficulty: ["medium"],
|
|
36242
|
+
maxParallel: 1,
|
|
36243
|
+
provisional: true,
|
|
36244
|
+
rationale: "Unrecognized provider \u2014 conservative default (medium, maxParallel 1). Review before relying on it."
|
|
36245
|
+
});
|
|
36078
36246
|
CANONICAL_MESH_TOOL_NAMES = [
|
|
36079
36247
|
"mesh_status",
|
|
36080
36248
|
"mesh_list_nodes",
|
|
@@ -36126,7 +36294,8 @@ ${error48.message || ""}`;
|
|
|
36126
36294
|
"mesh_magi_kind_panel_set",
|
|
36127
36295
|
"mesh_magi_kind_panel_list",
|
|
36128
36296
|
"mesh_node_slots_set",
|
|
36129
|
-
"mesh_node_slots_list"
|
|
36297
|
+
"mesh_node_slots_list",
|
|
36298
|
+
"mesh_node_slots_propose"
|
|
36130
36299
|
];
|
|
36131
36300
|
CANONICAL_MESH_TOOL_COUNT = CANONICAL_MESH_TOOL_NAMES.length;
|
|
36132
36301
|
STATUS_PROBE_ARG_KEY = "_statusProbe";
|
|
@@ -37438,26 +37607,48 @@ Next step: ${nextStep}`;
|
|
|
37438
37607
|
function getLogLevel() {
|
|
37439
37608
|
return currentLevel;
|
|
37440
37609
|
}
|
|
37610
|
+
function resolveLogDir() {
|
|
37611
|
+
const override = process.env.ADHDEV_CONFIG_DIR;
|
|
37612
|
+
const home = override && override.trim() ? override.trim() : path9.join(os42.homedir(), ".adhdev");
|
|
37613
|
+
return path9.join(home, "logs");
|
|
37614
|
+
}
|
|
37615
|
+
function ensureLogDir(dir) {
|
|
37616
|
+
try {
|
|
37617
|
+
fs32.mkdirSync(dir, { recursive: true });
|
|
37618
|
+
} catch {
|
|
37619
|
+
}
|
|
37620
|
+
}
|
|
37441
37621
|
function getDateStr() {
|
|
37442
37622
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
37443
37623
|
}
|
|
37444
37624
|
function getDaemonLogDir() {
|
|
37445
|
-
|
|
37625
|
+
const dir = resolveLogDir();
|
|
37626
|
+
prepareLogDirOnce(dir);
|
|
37627
|
+
return dir;
|
|
37446
37628
|
}
|
|
37447
37629
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
37448
|
-
return path9.join(
|
|
37630
|
+
return path9.join(getDaemonLogDir(), `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
37449
37631
|
}
|
|
37450
|
-
function
|
|
37632
|
+
function refreshCurrentLogFile() {
|
|
37451
37633
|
const today = getDateStr();
|
|
37452
|
-
|
|
37453
|
-
|
|
37454
|
-
|
|
37455
|
-
|
|
37456
|
-
|
|
37634
|
+
const dir = resolveLogDir();
|
|
37635
|
+
const dateChanged = today !== currentDate;
|
|
37636
|
+
const dirChanged = dir !== currentLogDir;
|
|
37637
|
+
if (!dateChanged && !dirChanged) return false;
|
|
37638
|
+
currentDate = today;
|
|
37639
|
+
currentLogDir = dir;
|
|
37640
|
+
currentLogDirEnv = process.env.ADHDEV_CONFIG_DIR;
|
|
37641
|
+
currentLogFile = path9.join(dir, `daemon-${today}.log`);
|
|
37642
|
+
if (dirChanged) prepareLogDirOnce(dir);
|
|
37643
|
+
else if (dateChanged) cleanOldLogs(dir);
|
|
37644
|
+
return true;
|
|
37457
37645
|
}
|
|
37458
|
-
function
|
|
37646
|
+
function checkDateRotation() {
|
|
37647
|
+
refreshCurrentLogFile();
|
|
37648
|
+
}
|
|
37649
|
+
function cleanOldLogs(logDir) {
|
|
37459
37650
|
try {
|
|
37460
|
-
const files = fs32.readdirSync(
|
|
37651
|
+
const files = fs32.readdirSync(logDir).filter((f) => f.startsWith("daemon-") && f.endsWith(".log"));
|
|
37461
37652
|
const cutoff = /* @__PURE__ */ new Date();
|
|
37462
37653
|
cutoff.setDate(cutoff.getDate() - MAX_LOG_DAYS);
|
|
37463
37654
|
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
@@ -37465,7 +37656,7 @@ Next step: ${nextStep}`;
|
|
|
37465
37656
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
37466
37657
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
37467
37658
|
try {
|
|
37468
|
-
fs32.unlinkSync(path9.join(
|
|
37659
|
+
fs32.unlinkSync(path9.join(logDir, file2));
|
|
37469
37660
|
} catch {
|
|
37470
37661
|
}
|
|
37471
37662
|
}
|
|
@@ -37502,12 +37693,35 @@ Next step: ${nextStep}`;
|
|
|
37502
37693
|
} catch {
|
|
37503
37694
|
}
|
|
37504
37695
|
}
|
|
37696
|
+
function prepareLogDirOnce(dir) {
|
|
37697
|
+
if (preparedLogDirs.has(dir)) return;
|
|
37698
|
+
preparedLogDirs.add(dir);
|
|
37699
|
+
ensureLogDir(dir);
|
|
37700
|
+
cleanOldLogs(dir);
|
|
37701
|
+
try {
|
|
37702
|
+
const oldLog = path9.join(dir, "daemon.log");
|
|
37703
|
+
if (fs32.existsSync(oldLog)) {
|
|
37704
|
+
const stat2 = fs32.statSync(oldLog);
|
|
37705
|
+
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
37706
|
+
fs32.renameSync(oldLog, path9.join(dir, `daemon-${oldDate}.log`));
|
|
37707
|
+
}
|
|
37708
|
+
const oldLogBackup = path9.join(dir, "daemon.log.old");
|
|
37709
|
+
if (fs32.existsSync(oldLogBackup)) {
|
|
37710
|
+
fs32.unlinkSync(oldLogBackup);
|
|
37711
|
+
}
|
|
37712
|
+
} catch {
|
|
37713
|
+
}
|
|
37714
|
+
}
|
|
37505
37715
|
function writeToFile(line) {
|
|
37506
37716
|
try {
|
|
37507
37717
|
if (++writeCount % 1e3 === 0) {
|
|
37508
37718
|
checkDateRotation();
|
|
37509
37719
|
rotateSizeIfNeeded();
|
|
37720
|
+
} else if (process.env.ADHDEV_CONFIG_DIR !== currentLogDirEnv) {
|
|
37721
|
+
currentLogDirEnv = process.env.ADHDEV_CONFIG_DIR;
|
|
37722
|
+
refreshCurrentLogFile();
|
|
37510
37723
|
}
|
|
37724
|
+
prepareLogDirOnce(currentLogDir);
|
|
37511
37725
|
AsyncBatchWriter.write(currentLogFile, line + "\n");
|
|
37512
37726
|
} catch {
|
|
37513
37727
|
}
|
|
@@ -37602,14 +37816,15 @@ Next step: ${nextStep}`;
|
|
|
37602
37816
|
var LEVEL_NUM;
|
|
37603
37817
|
var LEVEL_LABEL;
|
|
37604
37818
|
var currentLevel;
|
|
37605
|
-
var ADHDEV_HOME;
|
|
37606
|
-
var LOG_DIR;
|
|
37607
37819
|
var MAX_LOG_SIZE;
|
|
37608
37820
|
var MAX_LOG_DAYS;
|
|
37609
37821
|
var MAX_SIZE_ROTATION_GENERATIONS;
|
|
37610
37822
|
var currentDate;
|
|
37823
|
+
var currentLogDir;
|
|
37611
37824
|
var currentLogFile;
|
|
37825
|
+
var preparedLogDirs;
|
|
37612
37826
|
var writeCount;
|
|
37827
|
+
var currentLogDirEnv;
|
|
37613
37828
|
var RING_BUFFER_SIZE;
|
|
37614
37829
|
var ringBuffer;
|
|
37615
37830
|
var origConsoleLog;
|
|
@@ -37617,7 +37832,6 @@ Next step: ${nextStep}`;
|
|
|
37617
37832
|
var origConsoleWarn;
|
|
37618
37833
|
var LOG2;
|
|
37619
37834
|
var interceptorInstalled;
|
|
37620
|
-
var LOG_PATH;
|
|
37621
37835
|
var init_logger = __esm2({
|
|
37622
37836
|
"src/logging/logger.ts"() {
|
|
37623
37837
|
"use strict";
|
|
@@ -37628,32 +37842,15 @@ Next step: ${nextStep}`;
|
|
|
37628
37842
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
37629
37843
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
37630
37844
|
currentLevel = "info";
|
|
37631
|
-
ADHDEV_HOME = process.env.ADHDEV_CONFIG_DIR && process.env.ADHDEV_CONFIG_DIR.trim() ? process.env.ADHDEV_CONFIG_DIR.trim() : path9.join(os42.homedir(), ".adhdev");
|
|
37632
|
-
LOG_DIR = path9.join(ADHDEV_HOME, "logs");
|
|
37633
37845
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
37634
37846
|
MAX_LOG_DAYS = 7;
|
|
37635
37847
|
MAX_SIZE_ROTATION_GENERATIONS = 3;
|
|
37636
|
-
try {
|
|
37637
|
-
fs32.mkdirSync(LOG_DIR, { recursive: true });
|
|
37638
|
-
} catch {
|
|
37639
|
-
}
|
|
37640
37848
|
currentDate = getDateStr();
|
|
37641
|
-
|
|
37642
|
-
|
|
37643
|
-
|
|
37644
|
-
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
37645
|
-
if (fs32.existsSync(oldLog)) {
|
|
37646
|
-
const stat2 = fs32.statSync(oldLog);
|
|
37647
|
-
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
37648
|
-
fs32.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
37649
|
-
}
|
|
37650
|
-
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
37651
|
-
if (fs32.existsSync(oldLogBackup)) {
|
|
37652
|
-
fs32.unlinkSync(oldLogBackup);
|
|
37653
|
-
}
|
|
37654
|
-
} catch {
|
|
37655
|
-
}
|
|
37849
|
+
currentLogDir = resolveLogDir();
|
|
37850
|
+
currentLogFile = path9.join(currentLogDir, `daemon-${currentDate}.log`);
|
|
37851
|
+
preparedLogDirs = /* @__PURE__ */ new Set();
|
|
37656
37852
|
writeCount = 0;
|
|
37853
|
+
currentLogDirEnv = process.env.ADHDEV_CONFIG_DIR;
|
|
37657
37854
|
RING_BUFFER_SIZE = 200;
|
|
37658
37855
|
ringBuffer = [];
|
|
37659
37856
|
origConsoleLog = console.log.bind(console);
|
|
@@ -37679,7 +37876,6 @@ Next step: ${nextStep}`;
|
|
|
37679
37876
|
}
|
|
37680
37877
|
};
|
|
37681
37878
|
interceptorInstalled = false;
|
|
37682
|
-
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
37683
37879
|
}
|
|
37684
37880
|
});
|
|
37685
37881
|
function loadBetterSqlite3() {
|
|
@@ -45689,6 +45885,7 @@ ${rules.join("\n")}`;
|
|
|
45689
45885
|
- **Worktree affinity.** A worktree is a durable per-branch workspace; keep all of a branch's code_change/fix/review work on its worktree node by targeting \`required_tags: ["worktree=<branch>"]\` or \`target_node_id\`. Get the id/branch from the \`mesh_clone_node\` result or a live \`mesh_status\` \u2014 the Configured Nodes snapshot won't list a worktree cloned after launch. Untargeted same-branch follow-ups drift to the base node. Only \`convergence\` (merge/push) runs on the base, never pinned to the worktree.
|
|
45690
45886
|
- **Classify task difficulty to save tokens.** For each task you enqueue, judge its execution difficulty and pass \`difficulty\`: \`easy\` (extraction, renames, doc tweaks, trivial fixes), \`medium\` (ordinary feature/bugfix work), \`difficult\` (architecture, tricky debugging, multi-file refactors, subtle reasoning), or \`freeform\`. The mesh's per-difficulty brain preset then runs easy tasks on a cheaper model at low reasoning effort and hard tasks on a stronger model at high effort \u2014 real token savings on simple work. The current presets are shown in the "Brain presets" section below. You may still pass an explicit \`model\`/\`thinkingLevel\` to override the preset for one task.
|
|
45691
45887
|
- **Retune node profiles when routing is a poor fit \u2014 but only with approval.** A node's capability slots (its provider/model/thinking + difficulty range + capability tags, seen via \`mesh_node_slots_list\`) are what task\u2192node fitness routing matches against. If you notice a persistent mismatch \u2014 e.g. every \`difficult\` task lands on a node whose only slot is a cheap model, or a capability a node clearly has isn't declared \u2014 you MAY propose a slot change with \`mesh_node_slots_set\` (write=false). That returns current-vs-proposed; present that diff to the user with a one-line reason and apply (write=true) ONLY after they approve. It is a WHOLESALE replacement of the node's slots, so include the slots you want to keep. Never rewrite a node's profile silently or without a clear routing reason.
|
|
45888
|
+
- **Bootstrap a node's slots from what's actually installed.** When a node has NO slots configured (routing then falls back to "first available provider"), or CLI agents were newly installed on it, call \`mesh_node_slots_propose({ node_id })\` instead of hand-writing a profile. It detects the node's installed CLI agents and drafts a slot list from them \u2014 read-only, it never writes. Present its \`proposedSlots\` with the \`droppedSlots\` / \`destructive\` fields it reports (a wholesale write would delete any existing hand-tuned slot the draft doesn't reproduce, including providers not currently on PATH), then apply with \`mesh_node_slots_set({ slots: proposedSlots, write: true })\` after approval. It flags \`unknownProvider\` / \`provisional\` slots whose placement is a conservative guess rather than an attested one \u2014 call those out rather than presenting them as settled.
|
|
45692
45889
|
- **Respect explicit provider requests.** Map: Hermes \u2192 \`hermes-cli\`, Claude/Claude Code \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute the coordinator's own runtime.
|
|
45693
45890
|
- **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
|
|
45694
45891
|
- **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
|
|
@@ -45707,10 +45904,8 @@ ${rules.join("\n")}`;
|
|
|
45707
45904
|
|
|
45708
45905
|
### Task Messaging Requirements
|
|
45709
45906
|
|
|
45710
|
-
When you compose the task message you dispatch to a node, include
|
|
45907
|
+
When you compose the task message you dispatch to a node, include this requirement so the worker's completion report is verifiable:
|
|
45711
45908
|
|
|
45712
|
-
- **OSS English commits.** If a task commits anything under \`oss/\` (an AGPL public repo whose history external contributors read), tell the worker explicitly that commit messages in \`oss/\` MUST be English. Root-level commits (proprietary packages) may use any language.
|
|
45713
|
-
- **Scoped test runs.** For a validation or code-change task, instruct the worker to run only the tests covering the changed files (\`vitest run <path>\` or \`-t <name>\`), not the whole suite. Run the full suite only when the task is explicitly a full-suite gate \u2014 a broad daemon-core run is minutes of wall-clock and the biggest source of worker slowness.
|
|
45714
45909
|
- **Branch convergence state.** For a worktree task, require the completion report to classify the touched branch into exactly one final state: \`merged_to_main\`, \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\`. A task that ends on a non-main branch is not complete unless the report names that state and the next step.`;
|
|
45715
45910
|
}
|
|
45716
45911
|
var fs42;
|
|
@@ -45792,7 +45987,8 @@ When you compose the task message you dispatch to a node, include these requirem
|
|
|
45792
45987
|
| \`mesh_magi_kind_panel_set\` | Bind a task_kind \u2192 MAGI kind-panel slots (the SOLE MAGI panel-resolution surface; machine-local, wholesale replacement \u2014 approve current-vs-new first) |
|
|
45793
45988
|
| \`mesh_magi_kind_panel_list\` | List configured task_kind \u2192 MAGI kind-panel slot bindings (machine-local, read-only) |
|
|
45794
45989
|
| \`mesh_node_slots_list\` | List a node's capability slots (its AI-tool profile: provider/model/thinking + difficulty range + capability tags), read-only |
|
|
45795
|
-
| \`mesh_node_slots_set\` | PROPOSE (dry-run) or APPLY a node's capability slots \u2014 how you autonomously retune a node's tool profile; WHOLESALE replacement, present current-vs-proposed and get user approval before write=true
|
|
45990
|
+
| \`mesh_node_slots_set\` | PROPOSE (dry-run) or APPLY a node's capability slots \u2014 how you autonomously retune a node's tool profile; WHOLESALE replacement, present current-vs-proposed and get user approval before write=true |
|
|
45991
|
+
| \`mesh_node_slots_propose\` | AUTO-DETECT a node's installed CLI agents and DRAFT a slot profile from them (read-only, never writes) \u2014 use when a node has no slots yet or new CLIs were installed; reports droppedSlots (what a wholesale write would destroy), then apply via mesh_node_slots_set write=true after approval |`;
|
|
45796
45992
|
TOOL_EXPOSURE_PREFLIGHT_SECTION = `## Tool Exposure Preflight
|
|
45797
45993
|
|
|
45798
45994
|
Before doing any coordinator work, confirm that the actual callable tool list includes \`mesh_status\` and the other \`mesh_*\` tools from the table above. If this Repo Mesh coordinator prompt is present but the callable \`mesh_*\` tools are missing, the MCP server/tool manifest is stale or not injected yet. Do not substitute terminal/file/git tools, do not inspect or edit the repository directly, and do not continue as a non-mesh local coding agent. Stop immediately and tell the user to run \`/reload-mcp\` or start a fresh coordinator session so ADHDev can reconnect \`adhdev-mesh\`.`;
|
|
@@ -51552,10 +51748,15 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
51552
51748
|
}
|
|
51553
51749
|
function findRecentTerminalLedgerEvidence(args) {
|
|
51554
51750
|
if (!args.sessionId && !args.nodeId) return null;
|
|
51751
|
+
const notBefore = typeof args.notBeforeMs === "number" && Number.isFinite(args.notBeforeMs) ? args.notBeforeMs : null;
|
|
51555
51752
|
const entries = readLedgerEntries(args.meshId, { tail: 200 });
|
|
51556
51753
|
for (let i = entries.length - 1; i >= 0; i--) {
|
|
51557
51754
|
const entry = entries[i];
|
|
51558
51755
|
if (entry.kind !== "task_completed" && entry.kind !== "task_failed" && entry.kind !== "task_stalled") continue;
|
|
51756
|
+
if (notBefore !== null) {
|
|
51757
|
+
const entryTime = new Date(entry.timestamp).getTime();
|
|
51758
|
+
if (!Number.isFinite(entryTime) || entryTime < notBefore) continue;
|
|
51759
|
+
}
|
|
51559
51760
|
if (args.sessionId && sessionIdsEquivalent(entry.sessionId, args.sessionId)) {
|
|
51560
51761
|
return { id: entry.id, kind: entry.kind, payload: entry.payload || {}, timestamp: entry.timestamp };
|
|
51561
51762
|
}
|
|
@@ -51819,19 +52020,44 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
51819
52020
|
}
|
|
51820
52021
|
};
|
|
51821
52022
|
}
|
|
51822
|
-
const
|
|
52023
|
+
const taskId = readNonEmptyString(args.metadataEvent.taskId);
|
|
52024
|
+
const terminal = taskId ? findTerminalLedgerEvidenceForTask({
|
|
51823
52025
|
meshId: args.meshId,
|
|
52026
|
+
taskId,
|
|
51824
52027
|
sessionId: sessionId || void 0,
|
|
51825
52028
|
nodeId: nodeId || void 0
|
|
51826
|
-
})
|
|
52029
|
+
}) : (() => {
|
|
52030
|
+
const notBeforeMs = resolveNoProgressEvidenceFloor(args.metadataEvent);
|
|
52031
|
+
if (notBeforeMs === null) return null;
|
|
52032
|
+
return findRecentTerminalLedgerEvidence({
|
|
52033
|
+
meshId: args.meshId,
|
|
52034
|
+
sessionId: sessionId || void 0,
|
|
52035
|
+
nodeId: nodeId || void 0,
|
|
52036
|
+
notBeforeMs
|
|
52037
|
+
});
|
|
52038
|
+
})();
|
|
51827
52039
|
if (!terminal) return null;
|
|
51828
52040
|
return {
|
|
51829
52041
|
...args.metadataEvent,
|
|
51830
52042
|
source: "no_progress_terminal_ledger_suppression",
|
|
51831
52043
|
terminalLedgerKind: terminal.kind,
|
|
51832
|
-
terminalLedgerAt: terminal.timestamp
|
|
52044
|
+
terminalLedgerAt: terminal.timestamp,
|
|
52045
|
+
terminalLedgerScope: taskId ? "task" : "session_recency_bounded"
|
|
51833
52046
|
};
|
|
51834
52047
|
}
|
|
52048
|
+
function resolveNoProgressEvidenceFloor(metadataEvent) {
|
|
52049
|
+
const lastOutputAt = readFiniteNumber(metadataEvent.lastOutputAt);
|
|
52050
|
+
if (lastOutputAt !== null && lastOutputAt > 0) return lastOutputAt;
|
|
52051
|
+
const stalledMs = readFiniteNumber(metadataEvent.stalledMs);
|
|
52052
|
+
const timestamp2 = readFiniteNumber(metadataEvent.timestamp);
|
|
52053
|
+
if (stalledMs !== null && stalledMs >= 0 && timestamp2 !== null && timestamp2 > 0) {
|
|
52054
|
+
return timestamp2 - stalledMs;
|
|
52055
|
+
}
|
|
52056
|
+
return null;
|
|
52057
|
+
}
|
|
52058
|
+
function readFiniteNumber(value) {
|
|
52059
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
52060
|
+
}
|
|
51835
52061
|
var DIRECT_DISPATCH_RECONCILE_GRACE_MS;
|
|
51836
52062
|
var DIRECT_DISPATCH_IDLE_SESSION_RECONCILE_GRACE_MS;
|
|
51837
52063
|
var init_mesh_events_stale = __esm2({
|
|
@@ -58161,7 +58387,7 @@ ${cleanBody}`;
|
|
|
58161
58387
|
function readRecord6(value) {
|
|
58162
58388
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
58163
58389
|
}
|
|
58164
|
-
function
|
|
58390
|
+
function readFiniteNumber2(value) {
|
|
58165
58391
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
58166
58392
|
}
|
|
58167
58393
|
function identitiesMatch(metadataEvent, evidence, attempt, eventSessionId) {
|
|
@@ -58170,8 +58396,8 @@ ${cleanBody}`;
|
|
|
58170
58396
|
const evidenceTaskId = readNonEmptyString(evidence.taskId);
|
|
58171
58397
|
const evidenceAttemptId = readNonEmptyString(evidence.attemptId);
|
|
58172
58398
|
const evidenceSessionId = readNonEmptyString(evidence.sessionId);
|
|
58173
|
-
const eventNonce =
|
|
58174
|
-
const evidenceNonce =
|
|
58399
|
+
const eventNonce = readFiniteNumber2(metadataEvent.dispatchNonce);
|
|
58400
|
+
const evidenceNonce = readFiniteNumber2(evidence.dispatchNonce);
|
|
58175
58401
|
if (!taskId || !attemptId || !eventSessionId) return false;
|
|
58176
58402
|
if (taskId !== attempt.taskId || attemptId !== attempt.attemptId) return false;
|
|
58177
58403
|
if (evidenceTaskId !== taskId || evidenceAttemptId !== attemptId) return false;
|
|
@@ -58207,16 +58433,16 @@ ${cleanBody}`;
|
|
|
58207
58433
|
return { authoritative: false, reason: "evidence_source_profile_mismatch" };
|
|
58208
58434
|
}
|
|
58209
58435
|
const finalSummary = readNonEmptyString(metadataEvent.finalSummary);
|
|
58210
|
-
const finalContentLength =
|
|
58436
|
+
const finalContentLength = readFiniteNumber2(evidence.finalContentLength) ?? 0;
|
|
58211
58437
|
if (!finalSummary || finalContentLength <= 0) {
|
|
58212
58438
|
return { authoritative: false, reason: "empty_final_content" };
|
|
58213
58439
|
}
|
|
58214
58440
|
if (!identitiesMatch(metadataEvent, evidence, attempt, eventSessionId)) {
|
|
58215
58441
|
return { authoritative: false, reason: "causal_identity_mismatch" };
|
|
58216
58442
|
}
|
|
58217
|
-
const observedAt =
|
|
58218
|
-
const eventTimestamp =
|
|
58219
|
-
const turnStartedAt =
|
|
58443
|
+
const observedAt = readFiniteNumber2(evidence.observedAt);
|
|
58444
|
+
const eventTimestamp = readFiniteNumber2(metadataEvent.timestamp);
|
|
58445
|
+
const turnStartedAt = readFiniteNumber2(evidence.turnStartedAt);
|
|
58220
58446
|
const acceptedAt = Date.parse(attempt.acceptedAt || attempt.createdAt);
|
|
58221
58447
|
if (!observedAt || !eventTimestamp || !turnStartedAt) {
|
|
58222
58448
|
return { authoritative: false, reason: "missing_evidence_timestamp" };
|
|
@@ -58258,11 +58484,11 @@ ${cleanBody}`;
|
|
|
58258
58484
|
if (!attempt || attempt.terminalOutcome || isTerminalTurnStage(attempt.stage)) return false;
|
|
58259
58485
|
const taskId = readNonEmptyString(metadataEvent.taskId);
|
|
58260
58486
|
const attemptId = readNonEmptyString(metadataEvent.attemptId);
|
|
58261
|
-
const nonce =
|
|
58487
|
+
const nonce = readFiniteNumber2(metadataEvent.dispatchNonce);
|
|
58262
58488
|
if (!taskId || taskId !== attempt.taskId || attemptId !== attempt.attemptId) return false;
|
|
58263
58489
|
if (!attempt.sessionId || !sessionIdsEquivalent(attempt.sessionId, eventSessionId)) return false;
|
|
58264
58490
|
if (typeof attempt.dispatchNonce !== "number" || nonce !== attempt.dispatchNonce) return false;
|
|
58265
|
-
const eventTimestamp =
|
|
58491
|
+
const eventTimestamp = readFiniteNumber2(metadataEvent.timestamp);
|
|
58266
58492
|
const acceptedAt = Date.parse(attempt.acceptedAt || attempt.createdAt);
|
|
58267
58493
|
if (!eventTimestamp || eventTimestamp > nowMs + 2e3 || nowMs - eventTimestamp > AUTHORITATIVE_COMPLETION_MAX_AGE_MS) return false;
|
|
58268
58494
|
if (Number.isFinite(acceptedAt) && eventTimestamp < acceptedAt - 2e3) return false;
|
|
@@ -71432,6 +71658,7 @@ ${lastSnapshot}`;
|
|
|
71432
71658
|
DEFAULT_ACTIVE_CHAT_POLL_STATUSES: () => DEFAULT_ACTIVE_CHAT_POLL_STATUSES,
|
|
71433
71659
|
DEFAULT_CDP_DISCOVERY_INTERVAL_MS: () => DEFAULT_CDP_DISCOVERY_INTERVAL_MS,
|
|
71434
71660
|
DEFAULT_CDP_SCAN_INTERVAL_MS: () => DEFAULT_CDP_SCAN_INTERVAL_MS,
|
|
71661
|
+
DEFAULT_CHAT_TAIL_MISSING_SESSION_POLICY: () => DEFAULT_CHAT_TAIL_MISSING_SESSION_POLICY,
|
|
71435
71662
|
DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS: () => DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS2,
|
|
71436
71663
|
DEFAULT_DAEMON_PORT: () => DEFAULT_DAEMON_PORT2,
|
|
71437
71664
|
DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
|
|
@@ -71598,6 +71825,7 @@ ${lastSnapshot}`;
|
|
|
71598
71825
|
createSessionDelivery: () => createSessionDelivery,
|
|
71599
71826
|
createWorktree: () => createWorktree,
|
|
71600
71827
|
daemonIdsEquivalent: () => daemonIdsEquivalent,
|
|
71828
|
+
decideMissingSessionAttempt: () => decideMissingSessionAttempt2,
|
|
71601
71829
|
delegatedWorkerAutoApproveSettings: () => delegatedWorkerAutoApproveSettings,
|
|
71602
71830
|
deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
|
|
71603
71831
|
deleteMesh: () => deleteMesh,
|
|
@@ -71695,6 +71923,7 @@ ${lastSnapshot}`;
|
|
|
71695
71923
|
isManagedStatusWorking: () => isManagedStatusWorking,
|
|
71696
71924
|
isMeshHostOwner: () => isMeshHostOwner,
|
|
71697
71925
|
isMeshNodeHealthLaunchable: () => isMeshNodeHealthLaunchable,
|
|
71926
|
+
isMissingLiveSessionResult: () => isMissingLiveSessionResult2,
|
|
71698
71927
|
isOperatingNoteTombstoned: () => isOperatingNoteTombstoned,
|
|
71699
71928
|
isP2pRelayTransportFailure: () => isP2pRelayTransportFailure,
|
|
71700
71929
|
isPathInside: () => isPathInside,
|
|
@@ -71797,6 +72026,7 @@ ${lastSnapshot}`;
|
|
|
71797
72026
|
recordDebugTrace: () => recordDebugTrace,
|
|
71798
72027
|
recordDirectDispatchTask: () => recordDirectDispatchTask,
|
|
71799
72028
|
recordMeshToolCall: () => recordMeshToolCall,
|
|
72029
|
+
recordMissingSessionAttempt: () => recordMissingSessionAttempt2,
|
|
71800
72030
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
71801
72031
|
registerMeshCoordinator: () => registerMeshCoordinator,
|
|
71802
72032
|
removeMagiKindPanel: () => removeMagiKindPanel,
|
|
@@ -71811,6 +72041,7 @@ ${lastSnapshot}`;
|
|
|
71811
72041
|
resetState: () => resetState,
|
|
71812
72042
|
resolveAllowSendKeysDestructive: () => resolveAllowSendKeysDestructive,
|
|
71813
72043
|
resolveAutoConvergeCodeChange: () => resolveAutoConvergeCodeChange,
|
|
72044
|
+
resolveBackoffMs: () => resolveBackoffMs,
|
|
71814
72045
|
resolveChatMessageKind: () => resolveChatMessageKind,
|
|
71815
72046
|
resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
|
|
71816
72047
|
resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
|
|
@@ -71856,6 +72087,7 @@ ${lastSnapshot}`;
|
|
|
71856
72087
|
shouldAutoRestoreHostedSessionsOnStartup: () => shouldAutoRestoreHostedSessionsOnStartup2,
|
|
71857
72088
|
shouldCollectTraceCategory: () => shouldCollectTraceCategory,
|
|
71858
72089
|
shouldFireIdleReminder: () => shouldFireIdleReminder,
|
|
72090
|
+
shouldWarnForMissingSession: () => shouldWarnForMissingSession2,
|
|
71859
72091
|
shutdownDaemonComponents: () => shutdownDaemonComponents2,
|
|
71860
72092
|
spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
|
|
71861
72093
|
startDaemonDevSupport: () => startDaemonDevSupport2,
|
|
@@ -73532,6 +73764,12 @@ ${lastSnapshot}`;
|
|
|
73532
73764
|
ambiguous: identities.length > 1 || !!remotes.find((remote) => remote.identities.length > 1)
|
|
73533
73765
|
};
|
|
73534
73766
|
}
|
|
73767
|
+
async function deriveLocalRepoIdentity(repoRoot) {
|
|
73768
|
+
const raw = await git(repoRoot, ["rev-list", "--max-parents=0", "HEAD"], true);
|
|
73769
|
+
const roots = raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => /^[0-9a-f]{40}$/i.test(line)).sort();
|
|
73770
|
+
const root = roots[0];
|
|
73771
|
+
return root ? `local/${root.toLowerCase()}` : "";
|
|
73772
|
+
}
|
|
73535
73773
|
async function resolveDefaultBranch(repoRoot, remoteName, currentBranch) {
|
|
73536
73774
|
const symbolic = await git(repoRoot, ["symbolic-ref", "--quiet", "--short", `refs/remotes/${remoteName}/HEAD`], true);
|
|
73537
73775
|
if (symbolic.startsWith(`${remoteName}/`)) return symbolic.slice(remoteName.length + 1);
|
|
@@ -73619,12 +73857,34 @@ ${lastSnapshot}`;
|
|
|
73619
73857
|
);
|
|
73620
73858
|
}
|
|
73621
73859
|
const remoteDiscovery = await discoverRemotes(repoRoot, currentBranch);
|
|
73622
|
-
if (!remoteDiscovery.remotes.length
|
|
73860
|
+
if (!remoteDiscovery.remotes.length) {
|
|
73861
|
+
const localIdentity = await deriveLocalRepoIdentity(repoRoot);
|
|
73862
|
+
if (!localIdentity) {
|
|
73863
|
+
return failure2(
|
|
73864
|
+
"no_commits_for_local_identity",
|
|
73865
|
+
"This repository has no remote and no commits, so a stable repository identity cannot be derived.",
|
|
73866
|
+
"Create at least one commit (the root commit becomes the local identity), or pass an explicit repo identity when creating the mesh.",
|
|
73867
|
+
{ discovery: partial2 }
|
|
73868
|
+
);
|
|
73869
|
+
}
|
|
73870
|
+
const localDefaultBranch = await resolveDefaultBranch(repoRoot, "", currentBranch);
|
|
73871
|
+
return {
|
|
73872
|
+
...partial2,
|
|
73873
|
+
remotes: [],
|
|
73874
|
+
origin: void 0,
|
|
73875
|
+
upstream: void 0,
|
|
73876
|
+
selectedRemote: "",
|
|
73877
|
+
repoIdentity: localIdentity,
|
|
73878
|
+
defaultBranch: localDefaultBranch
|
|
73879
|
+
};
|
|
73880
|
+
}
|
|
73881
|
+
if (!remoteDiscovery.selectedRemote) {
|
|
73882
|
+
const detail = remoteDiscovery.remotes.map((remote) => remote.name).join(", ");
|
|
73623
73883
|
return failure2(
|
|
73624
|
-
"
|
|
73625
|
-
|
|
73626
|
-
"
|
|
73627
|
-
{ discovery: partial2 }
|
|
73884
|
+
"remote_not_selected",
|
|
73885
|
+
`No canonical remote could be selected among multiple remotes (${detail}).`,
|
|
73886
|
+
"Name one of them origin or upstream, set the current branch to track one of them, or pass an explicit repo identity when creating the mesh.",
|
|
73887
|
+
{ discovery: { ...partial2, remotes: remoteDiscovery.remotes, origin: remoteDiscovery.origin, upstream: remoteDiscovery.upstream } }
|
|
73628
73888
|
);
|
|
73629
73889
|
}
|
|
73630
73890
|
if (remoteDiscovery.ambiguous) {
|
|
@@ -83789,8 +84049,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
83789
84049
|
if (sinceTs > 0) {
|
|
83790
84050
|
return { success: true, logs: [], totalBuffered: 0 };
|
|
83791
84051
|
}
|
|
83792
|
-
|
|
83793
|
-
|
|
84052
|
+
const logPath = getCurrentDaemonLogPath();
|
|
84053
|
+
if (fs14.existsSync(logPath)) {
|
|
84054
|
+
const content = fs14.readFileSync(logPath, "utf-8");
|
|
83794
84055
|
const allLines = content.split("\n");
|
|
83795
84056
|
const recent = allLines.slice(-count).join("\n");
|
|
83796
84057
|
return { success: true, logs: recent, totalLines: allLines.length };
|
|
@@ -84099,11 +84360,17 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
84099
84360
|
var http2 = __toESM2(require("http"));
|
|
84100
84361
|
var path21 = __toESM2(require("path"));
|
|
84101
84362
|
var import_child_process6 = require("child_process");
|
|
84363
|
+
init_logger();
|
|
84364
|
+
function errorText(error48) {
|
|
84365
|
+
return error48 instanceof Error ? error48.message : String(error48);
|
|
84366
|
+
}
|
|
84367
|
+
var warnedCommandLineFailures = /* @__PURE__ */ new Set();
|
|
84102
84368
|
function defaultExecFileSync() {
|
|
84103
84369
|
return import_child_process6.execFileSync;
|
|
84104
84370
|
}
|
|
84105
84371
|
function getWindowsProcessCommandLine(pid, exec7) {
|
|
84106
84372
|
const pidFilter = `ProcessId=${pid}`;
|
|
84373
|
+
const failures = [];
|
|
84107
84374
|
try {
|
|
84108
84375
|
const psOut = exec7("powershell.exe", [
|
|
84109
84376
|
"-NoProfile",
|
|
@@ -84115,7 +84382,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
84115
84382
|
], { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
|
|
84116
84383
|
const text = String(psOut).trim();
|
|
84117
84384
|
if (text) return text;
|
|
84118
|
-
|
|
84385
|
+
failures.push("powershell Get-CimInstance returned no CommandLine");
|
|
84386
|
+
} catch (error48) {
|
|
84387
|
+
failures.push(`powershell Get-CimInstance failed: ${errorText(error48)}`);
|
|
84119
84388
|
}
|
|
84120
84389
|
try {
|
|
84121
84390
|
const wmicOut = exec7("wmic", [
|
|
@@ -84127,7 +84396,19 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
84127
84396
|
], { encoding: "utf8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
|
|
84128
84397
|
const text = String(wmicOut).trim();
|
|
84129
84398
|
if (text) return text;
|
|
84130
|
-
|
|
84399
|
+
failures.push("wmic returned no CommandLine");
|
|
84400
|
+
} catch (error48) {
|
|
84401
|
+
failures.push(`wmic failed: ${errorText(error48)}`);
|
|
84402
|
+
}
|
|
84403
|
+
const signature = failures.join("; ");
|
|
84404
|
+
if (!warnedCommandLineFailures.has(signature)) {
|
|
84405
|
+
warnedCommandLineFailures.add(signature);
|
|
84406
|
+
LOG2.warn(
|
|
84407
|
+
"ProcessLifecycle",
|
|
84408
|
+
`Could not read a process command line (pid ${pid}): ${signature}. Process-identity checks that depend on it will fail safe. This is logged once per distinct cause.`
|
|
84409
|
+
);
|
|
84410
|
+
} else {
|
|
84411
|
+
LOG2.debug("ProcessLifecycle", `Could not read the command line of pid ${pid}: ${signature}`);
|
|
84131
84412
|
}
|
|
84132
84413
|
return null;
|
|
84133
84414
|
}
|
|
@@ -84145,7 +84426,8 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
84145
84426
|
stdio: ["ignore", "pipe", "ignore"]
|
|
84146
84427
|
})).trim();
|
|
84147
84428
|
return text || null;
|
|
84148
|
-
} catch {
|
|
84429
|
+
} catch (error48) {
|
|
84430
|
+
LOG2.debug("ProcessLifecycle", `ps lookup failed for pid ${pid}: ${errorText(error48)}`);
|
|
84149
84431
|
return null;
|
|
84150
84432
|
}
|
|
84151
84433
|
}
|
|
@@ -84370,7 +84652,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
84370
84652
|
function packageRootForPrefix(prefix, packageName) {
|
|
84371
84653
|
return path21.join(prefix, "node_modules", ...packageName.split("/"));
|
|
84372
84654
|
}
|
|
84373
|
-
var
|
|
84655
|
+
var CONPTY_PREBUILD_NESTED_RELATIVE_PATH = path21.join(
|
|
84374
84656
|
"node_modules",
|
|
84375
84657
|
"adhdev",
|
|
84376
84658
|
"node_modules",
|
|
@@ -84379,16 +84661,28 @@ ${formatManifestValidationIssues2(validation.issues)}`,
|
|
|
84379
84661
|
"win32-x64",
|
|
84380
84662
|
"conpty.node"
|
|
84381
84663
|
);
|
|
84382
|
-
|
|
84383
|
-
|
|
84664
|
+
var CONPTY_PREBUILD_HOISTED_RELATIVE_PATH = path21.join(
|
|
84665
|
+
"node_modules",
|
|
84666
|
+
"node-pty",
|
|
84667
|
+
"prebuilds",
|
|
84668
|
+
"win32-x64",
|
|
84669
|
+
"conpty.node"
|
|
84670
|
+
);
|
|
84671
|
+
function resolveConptyPrebuildCandidates(prefix) {
|
|
84672
|
+
return [
|
|
84673
|
+
path21.join(prefix, CONPTY_PREBUILD_NESTED_RELATIVE_PATH),
|
|
84674
|
+
path21.join(prefix, CONPTY_PREBUILD_HOISTED_RELATIVE_PATH)
|
|
84675
|
+
];
|
|
84384
84676
|
}
|
|
84385
|
-
function verifyStagedConptyPrebuild(stagedPrefix) {
|
|
84386
|
-
const
|
|
84387
|
-
|
|
84677
|
+
function verifyStagedConptyPrebuild(stagedPrefix, log) {
|
|
84678
|
+
const candidates = resolveConptyPrebuildCandidates(stagedPrefix);
|
|
84679
|
+
const found = candidates.find((candidate) => fs15.existsSync(candidate));
|
|
84680
|
+
if (!found) {
|
|
84388
84681
|
throw new Error(
|
|
84389
|
-
`Staged install is missing required native addon: ${
|
|
84682
|
+
`Staged install is missing required native addon: node-pty's conpty.node prebuild (checked: ${candidates.join(", ")}). Aborting activation to prevent a daemon boot crash.`
|
|
84390
84683
|
);
|
|
84391
84684
|
}
|
|
84685
|
+
log?.(`conpty prebuild verified at ${found}`);
|
|
84392
84686
|
}
|
|
84393
84687
|
function readPackageCliEntry(prefix, packageName, targetVersion) {
|
|
84394
84688
|
const packageRoot = packageRootForPrefix(prefix, packageName);
|
|
@@ -84544,6 +84838,29 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
84544
84838
|
}
|
|
84545
84839
|
atomicWrite(layout.pointerPath, versionName, "ascii");
|
|
84546
84840
|
}
|
|
84841
|
+
function removeFailedStagedPrefix(stagedPrefix, layout, log) {
|
|
84842
|
+
try {
|
|
84843
|
+
const staged = normalizeForCompare(stagedPrefix);
|
|
84844
|
+
const protectedPrefixes = [layout.activePrefix, layout.stablePrefix, layout.installRoot];
|
|
84845
|
+
if (protectedPrefixes.some((candidate) => normalizeForCompare(candidate) === staged)) {
|
|
84846
|
+
log(`Refusing to clean up ${stagedPrefix}: it is the active/stable install, not a staged prefix`);
|
|
84847
|
+
return;
|
|
84848
|
+
}
|
|
84849
|
+
if (normalizeForCompare(path21.dirname(stagedPrefix)) !== normalizeForCompare(layout.installRoot) || !path21.basename(stagedPrefix).startsWith("version-")) {
|
|
84850
|
+
log(`Refusing to clean up ${stagedPrefix}: not a version-* prefix under ${layout.installRoot}`);
|
|
84851
|
+
return;
|
|
84852
|
+
}
|
|
84853
|
+
if (!fs15.existsSync(stagedPrefix)) return;
|
|
84854
|
+
removeInactivePrefix(stagedPrefix, log);
|
|
84855
|
+
if (fs15.existsSync(stagedPrefix)) {
|
|
84856
|
+
log(`Failed staged prefix ${stagedPrefix} could not be fully removed; a future update will retry`);
|
|
84857
|
+
} else {
|
|
84858
|
+
log(`Cleaned up failed staged prefix ${stagedPrefix}`);
|
|
84859
|
+
}
|
|
84860
|
+
} catch (error48) {
|
|
84861
|
+
log(`Failed staged-prefix cleanup errored for ${stagedPrefix}: ${error48?.message || String(error48)}`);
|
|
84862
|
+
}
|
|
84863
|
+
}
|
|
84547
84864
|
async function performWindowsAtomicUpgrade(options) {
|
|
84548
84865
|
const { layout, packageName, targetVersion, portableNode, hooks } = options;
|
|
84549
84866
|
const versionName = `version-${Date.now()}-${process.pid}-${Math.random().toString(16).slice(2)}`;
|
|
@@ -84555,7 +84872,7 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
84555
84872
|
try {
|
|
84556
84873
|
hooks.log(`Installing ${packageName}@${targetVersion} into inactive prefix ${stagedPrefix}`);
|
|
84557
84874
|
await hooks.install(stagedPrefix, portableNode);
|
|
84558
|
-
verifyStagedConptyPrebuild(stagedPrefix);
|
|
84875
|
+
verifyStagedConptyPrebuild(stagedPrefix, hooks.log);
|
|
84559
84876
|
const stagedCliEntry = readPackageCliEntry(stagedPrefix, packageName, targetVersion);
|
|
84560
84877
|
pinStagedShims(stagedPrefix, portableNode, stagedCliEntry);
|
|
84561
84878
|
validateStagedCli(portableNode, stagedCliEntry, targetVersion);
|
|
@@ -84599,6 +84916,7 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
84599
84916
|
} catch {
|
|
84600
84917
|
hooks.log("Failed to restart the previous daemon during rollback");
|
|
84601
84918
|
}
|
|
84919
|
+
removeFailedStagedPrefix(stagedPrefix, layout, hooks.log);
|
|
84602
84920
|
try {
|
|
84603
84921
|
await hooks.cleanup(layout, layout.activePrefix);
|
|
84604
84922
|
} catch {
|
|
@@ -84882,6 +85200,8 @@ exec "${portableNode}" "${cliEntry}" "$@"
|
|
|
84882
85200
|
const current = env2[pathKey] || "";
|
|
84883
85201
|
env2[pathKey] = current ? `${nodeBinDir};${current}` : nodeBinDir;
|
|
84884
85202
|
env2.ADHDEV_BOOTSTRAP = "1";
|
|
85203
|
+
env2.npm_config_build_from_source = "false";
|
|
85204
|
+
env2["npm_config_build-from-source"] = "false";
|
|
84885
85205
|
return env2;
|
|
84886
85206
|
}
|
|
84887
85207
|
function getNpmExecOptions(platform10 = process.platform) {
|
|
@@ -85233,6 +85553,21 @@ ${body}
|
|
|
85233
85553
|
if (installOutput.trim()) {
|
|
85234
85554
|
appendUpgradeLog(installOutput.trim());
|
|
85235
85555
|
}
|
|
85556
|
+
if (process.platform === "win32" && installCommand.surface.installPrefix) {
|
|
85557
|
+
try {
|
|
85558
|
+
verifyStagedConptyPrebuild(installCommand.surface.installPrefix, appendUpgradeLog);
|
|
85559
|
+
} catch (error48) {
|
|
85560
|
+
appendUpgradeLog(`Post-install conpty verification failed: ${error48?.message || String(error48)}`);
|
|
85561
|
+
emitUpgradeFailureNotice([
|
|
85562
|
+
`adhdev ${spec} installed but is missing node-pty's native addon (conpty.node).`,
|
|
85563
|
+
'Starting it would break every session with "Failed to load native module: conpty.node",',
|
|
85564
|
+
"so the running daemon was left on its previous version and was NOT restarted.",
|
|
85565
|
+
"To recover, reinstall (this forces the shipped prebuild instead of a source rebuild):",
|
|
85566
|
+
` ${buildManualRecoveryCommand(installCommand)}`
|
|
85567
|
+
]);
|
|
85568
|
+
throw error48;
|
|
85569
|
+
}
|
|
85570
|
+
}
|
|
85236
85571
|
if (process.platform === "win32") {
|
|
85237
85572
|
await new Promise((resolve29) => setTimeout(resolve29, 500));
|
|
85238
85573
|
cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
|
|
@@ -86321,6 +86656,7 @@ ${body}
|
|
|
86321
86656
|
return n;
|
|
86322
86657
|
}
|
|
86323
86658
|
var SUBMIT_DELAY_FLOOR_MS = 200;
|
|
86659
|
+
var fsmDriverSeq = 0;
|
|
86324
86660
|
var WIN32_SUBMIT_RESEND_GAP_MS = 350;
|
|
86325
86661
|
var WIN32_SUBMIT_MAX_RESENDS = 14;
|
|
86326
86662
|
var WIN32_SUBMIT_SETTLE_MS = 500;
|
|
@@ -86353,6 +86689,8 @@ ${body}
|
|
|
86353
86689
|
var FsmDriver = class {
|
|
86354
86690
|
constructor(opts) {
|
|
86355
86691
|
this.opts = opts;
|
|
86692
|
+
const sessionId = typeof opts.sessionId === "string" ? opts.sessionId.trim() : "";
|
|
86693
|
+
this.sessionTag = sessionId ? sessionId.slice(0, 8) : `d${++fsmDriverSeq}`;
|
|
86356
86694
|
this.loadSpecOrThrow();
|
|
86357
86695
|
this.adapter = new TerminalAdapter(
|
|
86358
86696
|
this.buildAdapterOpts(),
|
|
@@ -86442,6 +86780,8 @@ ${body}
|
|
|
86442
86780
|
* the shadow verdict currently disagrees with the real one), so the
|
|
86443
86781
|
* shadow log emits on FLIP only, not every frame. */
|
|
86444
86782
|
shadowDivergenceLast = /* @__PURE__ */ new Map();
|
|
86783
|
+
/** FSMLOG-SESSION-ATTRIBUTION (D3): session segment of every log line's prefix. */
|
|
86784
|
+
sessionTag;
|
|
86445
86785
|
subscribe(listener) {
|
|
86446
86786
|
this.listeners.add(listener);
|
|
86447
86787
|
return () => {
|
|
@@ -87405,8 +87745,16 @@ ${body}
|
|
|
87405
87745
|
});
|
|
87406
87746
|
if (this.stateHistory.length > 50) this.stateHistory.shift();
|
|
87407
87747
|
}
|
|
87748
|
+
/**
|
|
87749
|
+
* FSMLOG-SESSION-ATTRIBUTION (D3): log prefix identifying BOTH the spec being driven and the
|
|
87750
|
+
* session driving it. Previously spec-only, which made every concurrent session of the same
|
|
87751
|
+
* provider log under an identical tag. The session segment is the owning instance's session id
|
|
87752
|
+
* (short form — the leading 8 chars are what mesh ledger/trace lines carry, so logs grep-join
|
|
87753
|
+
* against them), or a per-driver `d<n>` fallback when no session id was supplied.
|
|
87754
|
+
*/
|
|
87408
87755
|
specTag() {
|
|
87409
|
-
|
|
87756
|
+
const spec = this.opts.specPath.split(/[/\\]/).slice(-3).join("/");
|
|
87757
|
+
return `${spec}|${this.sessionTag}`;
|
|
87410
87758
|
}
|
|
87411
87759
|
emit(ev) {
|
|
87412
87760
|
for (const l of this.listeners) {
|
|
@@ -87583,7 +87931,7 @@ ${body}
|
|
|
87583
87931
|
* cli-state-engine's lastApprovalResolvedAt for the spec-driven adapter path
|
|
87584
87932
|
* (claude-cli specs/4.0.json), which previously stubbed the method to false. */
|
|
87585
87933
|
lastApprovalResolvedAt = 0;
|
|
87586
|
-
constructor(specPath, workingDir, cliArgs, extraEnv, transportFactory) {
|
|
87934
|
+
constructor(specPath, workingDir, cliArgs, extraEnv, transportFactory, sessionId) {
|
|
87587
87935
|
const raw = JSON.parse(fs222.readFileSync(specPath, "utf8"));
|
|
87588
87936
|
this.spec = {
|
|
87589
87937
|
id: raw.id,
|
|
@@ -87602,7 +87950,8 @@ ${body}
|
|
|
87602
87950
|
hotReload: true,
|
|
87603
87951
|
emitTrace: false,
|
|
87604
87952
|
transportFactory,
|
|
87605
|
-
extraCliArgs: cliArgs
|
|
87953
|
+
extraCliArgs: cliArgs,
|
|
87954
|
+
sessionId
|
|
87606
87955
|
});
|
|
87607
87956
|
this.driver.subscribe((ev) => this.handleEvent(ev));
|
|
87608
87957
|
}
|
|
@@ -88592,7 +88941,7 @@ ${body}
|
|
|
88592
88941
|
}
|
|
88593
88942
|
};
|
|
88594
88943
|
init_logger();
|
|
88595
|
-
function createCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFactory) {
|
|
88944
|
+
function createCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFactory, sessionId) {
|
|
88596
88945
|
const resolvedSpecPath = provider._resolvedSpecPath;
|
|
88597
88946
|
const dir = provider._resolvedProviderDir;
|
|
88598
88947
|
let specPath = resolvedSpecPath && fs23.existsSync(resolvedSpecPath) ? resolvedSpecPath : void 0;
|
|
@@ -88603,7 +88952,7 @@ ${body}
|
|
|
88603
88952
|
if (specPath) {
|
|
88604
88953
|
try {
|
|
88605
88954
|
LOG2.info("spec-route", `[${provider.type}] routing through SpecCliAdapter (${path27.relative(dir || "", specPath) || specPath})`);
|
|
88606
|
-
return new SpecCliAdapter(specPath, workingDir, cliArgs, extraEnv, transportFactory);
|
|
88955
|
+
return new SpecCliAdapter(specPath, workingDir, cliArgs, extraEnv, transportFactory, sessionId);
|
|
88607
88956
|
} catch (err) {
|
|
88608
88957
|
LOG2.warn("spec-route", `[${provider.type}] spec invalid, falling back to ProviderCliAdapter: ${err.message}`);
|
|
88609
88958
|
}
|
|
@@ -89005,7 +89354,7 @@ ${body}
|
|
|
89005
89354
|
this.launchMode = options?.launchMode || "new";
|
|
89006
89355
|
this.initialThinkingLevel = options?.initialThinkingLevel;
|
|
89007
89356
|
this.onProviderSessionResolved = options?.onProviderSessionResolved;
|
|
89008
|
-
this.adapter = createCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
|
|
89357
|
+
this.adapter = createCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory, this.instanceId);
|
|
89009
89358
|
if (this.providerSessionId) {
|
|
89010
89359
|
this.adapter.updateRuntimeMeta({ providerSessionId: this.providerSessionId });
|
|
89011
89360
|
}
|
|
@@ -99126,19 +99475,37 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
99126
99475
|
* Resolve provider type by alias
|
|
99127
99476
|
* 'claude' → 'claude-cli', 'codex' → 'codex-cli' etc
|
|
99128
99477
|
* Returns input as-is if no match found.
|
|
99478
|
+
*
|
|
99479
|
+
* `categories` narrows resolution to the given provider categories. Without it
|
|
99480
|
+
* the resolution order is unchanged (direct type match first, then alias scan)
|
|
99481
|
+
* — every existing caller keeps its exact behaviour.
|
|
99482
|
+
*
|
|
99483
|
+
* The hint exists because provider types and aliases share one namespace across
|
|
99484
|
+
* categories, so a direct match can shadow an alias that a category-scoped
|
|
99485
|
+
* caller actually wants. Concretely: `extension/codex` declares `type: 'codex'`
|
|
99486
|
+
* while `cli/codex-cli` declares `aliases: ['codex']`, so unscoped
|
|
99487
|
+
* `resolveAlias('codex')` returns the IDE-webview provider. `adhdev launch`
|
|
99488
|
+
* only ever starts a cli/acp session, so it passes `['cli', 'acp']` and gets
|
|
99489
|
+
* `codex-cli`. Within a scope the direct-match-first order still holds.
|
|
99129
99490
|
*/
|
|
99130
|
-
resolveAlias(input) {
|
|
99131
|
-
|
|
99491
|
+
resolveAlias(input, categories) {
|
|
99492
|
+
const inScope = (p) => !!p && (!categories || categories.includes(p.category));
|
|
99493
|
+
const direct = this.providers.get(input);
|
|
99494
|
+
if (inScope(direct)) return input;
|
|
99132
99495
|
for (const p of this.providers.values()) {
|
|
99133
|
-
if (p.aliases?.includes(input)) return p.type;
|
|
99496
|
+
if (p.aliases?.includes(input) && inScope(p)) return p.type;
|
|
99134
99497
|
}
|
|
99135
99498
|
return input;
|
|
99136
99499
|
}
|
|
99137
99500
|
/**
|
|
99138
99501
|
* Get provider with alias resolution (get + alias fallback)
|
|
99502
|
+
* `categories` narrows resolution the same way as `resolveAlias`, and also
|
|
99503
|
+
* filters the returned module so an out-of-scope provider is never handed back.
|
|
99139
99504
|
*/
|
|
99140
|
-
getByAlias(input) {
|
|
99141
|
-
|
|
99505
|
+
getByAlias(input, categories) {
|
|
99506
|
+
const resolved = this.providers.get(this.resolveAlias(input, categories));
|
|
99507
|
+
if (resolved && categories && !categories.includes(resolved.category)) return void 0;
|
|
99508
|
+
return resolved;
|
|
99142
99509
|
}
|
|
99143
99510
|
/**
|
|
99144
99511
|
* Build CLI/ACP detection list (replaces cli-detector)
|
|
@@ -104744,12 +105111,12 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
104744
105111
|
var fs37 = __toESM2(require("fs"));
|
|
104745
105112
|
var path43 = __toESM2(require("path"));
|
|
104746
105113
|
var os26 = __toESM2(require("os"));
|
|
104747
|
-
var
|
|
104748
|
-
var
|
|
105114
|
+
var ADHDEV_HOME = process.env.ADHDEV_CONFIG_DIR && process.env.ADHDEV_CONFIG_DIR.trim() ? process.env.ADHDEV_CONFIG_DIR.trim() : path43.join(os26.homedir(), ".adhdev");
|
|
105115
|
+
var LOG_DIR = path43.join(ADHDEV_HOME, "logs");
|
|
104749
105116
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
104750
105117
|
var MAX_DAYS = 7;
|
|
104751
105118
|
try {
|
|
104752
|
-
fs37.mkdirSync(
|
|
105119
|
+
fs37.mkdirSync(LOG_DIR, { recursive: true });
|
|
104753
105120
|
} catch {
|
|
104754
105121
|
}
|
|
104755
105122
|
var SENSITIVE_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -104783,19 +105150,19 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
104783
105150
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
104784
105151
|
}
|
|
104785
105152
|
var currentDate2 = getDateStr2();
|
|
104786
|
-
var currentFile = path43.join(
|
|
105153
|
+
var currentFile = path43.join(LOG_DIR, `commands-${currentDate2}.jsonl`);
|
|
104787
105154
|
var writeCount2 = 0;
|
|
104788
105155
|
function checkRotation() {
|
|
104789
105156
|
const today = getDateStr2();
|
|
104790
105157
|
if (today !== currentDate2) {
|
|
104791
105158
|
currentDate2 = today;
|
|
104792
|
-
currentFile = path43.join(
|
|
105159
|
+
currentFile = path43.join(LOG_DIR, `commands-${currentDate2}.jsonl`);
|
|
104793
105160
|
cleanOldFiles();
|
|
104794
105161
|
}
|
|
104795
105162
|
}
|
|
104796
105163
|
function cleanOldFiles() {
|
|
104797
105164
|
try {
|
|
104798
|
-
const files = fs37.readdirSync(
|
|
105165
|
+
const files = fs37.readdirSync(LOG_DIR).filter((f) => f.startsWith("commands-") && f.endsWith(".jsonl"));
|
|
104799
105166
|
const cutoff = /* @__PURE__ */ new Date();
|
|
104800
105167
|
cutoff.setDate(cutoff.getDate() - MAX_DAYS);
|
|
104801
105168
|
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
@@ -104803,7 +105170,7 @@ ${ptyResult.output.slice(-2e3)}`);
|
|
|
104803
105170
|
const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
104804
105171
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
104805
105172
|
try {
|
|
104806
|
-
fs37.unlinkSync(path43.join(
|
|
105173
|
+
fs37.unlinkSync(path43.join(LOG_DIR, file2));
|
|
104807
105174
|
} catch {
|
|
104808
105175
|
}
|
|
104809
105176
|
}
|
|
@@ -110323,6 +110690,53 @@ ${e?.stderr || ""}`;
|
|
|
110323
110690
|
});
|
|
110324
110691
|
await Promise.all(runners);
|
|
110325
110692
|
}
|
|
110693
|
+
var DEFAULT_CHAT_TAIL_MISSING_SESSION_POLICY = {
|
|
110694
|
+
// 10s of normal-cadence retries: comfortably longer than a session-registry
|
|
110695
|
+
// attach, short enough that a genuinely dead session starts backing off well
|
|
110696
|
+
// before it can produce a meaningful number of warns.
|
|
110697
|
+
graceMs: 1e4,
|
|
110698
|
+
initialBackoffMs: 1e3,
|
|
110699
|
+
// 30s ceiling — matches the idle status heartbeat, so a lingering
|
|
110700
|
+
// subscription costs at most one read per heartbeat instead of ~20/sec.
|
|
110701
|
+
maxBackoffMs: 3e4,
|
|
110702
|
+
// 5 min. Past this the session is not coming back under this subscription;
|
|
110703
|
+
// the dashboard re-subscribes on reopen if it ever does.
|
|
110704
|
+
giveUpAfterMs: 5 * 6e4
|
|
110705
|
+
};
|
|
110706
|
+
function decideMissingSessionAttempt2(state, now, policy = DEFAULT_CHAT_TAIL_MISSING_SESSION_POLICY) {
|
|
110707
|
+
if (!state) return { action: "attempt" };
|
|
110708
|
+
const missingFor = now - state.firstMissingAt;
|
|
110709
|
+
if (missingFor >= policy.giveUpAfterMs) return { action: "drop" };
|
|
110710
|
+
if (missingFor < policy.graceMs) return { action: "attempt" };
|
|
110711
|
+
const sinceLastAttempt = now - state.lastAttemptAt;
|
|
110712
|
+
return sinceLastAttempt >= resolveBackoffMs(state, policy) ? { action: "attempt" } : { action: "skip" };
|
|
110713
|
+
}
|
|
110714
|
+
function resolveBackoffMs(state, policy = DEFAULT_CHAT_TAIL_MISSING_SESSION_POLICY) {
|
|
110715
|
+
const stepsIntoBackoff = Math.max(0, state.consecutiveMisses - 1);
|
|
110716
|
+
const boundedExponent = Math.min(stepsIntoBackoff, 20);
|
|
110717
|
+
const scaled = policy.initialBackoffMs * Math.pow(2, boundedExponent);
|
|
110718
|
+
return Math.min(scaled, policy.maxBackoffMs);
|
|
110719
|
+
}
|
|
110720
|
+
function recordMissingSessionAttempt2(state, now) {
|
|
110721
|
+
if (!state) {
|
|
110722
|
+
return { firstMissingAt: now, lastAttemptAt: now, consecutiveMisses: 1, warned: false };
|
|
110723
|
+
}
|
|
110724
|
+
return {
|
|
110725
|
+
firstMissingAt: state.firstMissingAt,
|
|
110726
|
+
lastAttemptAt: now,
|
|
110727
|
+
consecutiveMisses: state.consecutiveMisses + 1,
|
|
110728
|
+
warned: state.warned
|
|
110729
|
+
};
|
|
110730
|
+
}
|
|
110731
|
+
function shouldWarnForMissingSession2(state) {
|
|
110732
|
+
return !state.warned;
|
|
110733
|
+
}
|
|
110734
|
+
function isMissingLiveSessionResult2(result) {
|
|
110735
|
+
if (!result || typeof result !== "object") return false;
|
|
110736
|
+
const { success: success2, error: error48 } = result;
|
|
110737
|
+
if (success2 !== false || typeof error48 !== "string") return false;
|
|
110738
|
+
return error48.startsWith("Live session not found for targetSessionId:");
|
|
110739
|
+
}
|
|
110326
110740
|
init_control_effects();
|
|
110327
110741
|
init_provider_patch_state();
|
|
110328
110742
|
init_chat_message_normalization();
|
|
@@ -117151,6 +117565,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
117151
117565
|
const appName = options.appName;
|
|
117152
117566
|
const timeoutMs = options.timeoutMs ?? DEFAULT_SESSION_HOST_READY_TIMEOUT_MS2;
|
|
117153
117567
|
const isManagedPid = options.isManagedPid ?? (() => true);
|
|
117568
|
+
let unverifiedStopPid = null;
|
|
117154
117569
|
const instance = () => getProcessInstanceContext();
|
|
117155
117570
|
const getEndpoint = () => (0, import_session_host_core15.getDefaultSessionHostEndpoint)(appName, { ipcKey: instance().ipcKey });
|
|
117156
117571
|
function buildEnv(baseEnv) {
|
|
@@ -117228,8 +117643,25 @@ data: ${JSON.stringify(msg.data)}
|
|
|
117228
117643
|
);
|
|
117229
117644
|
return process.execPath;
|
|
117230
117645
|
}
|
|
117646
|
+
function verifyConptyPrebuildBeforeSpawn(entry) {
|
|
117647
|
+
if (process.platform !== "win32") return;
|
|
117648
|
+
const normalized = entry.replace(/\\/g, "/");
|
|
117649
|
+
const marker = "/node_modules/adhdev/vendor/session-host-daemon/";
|
|
117650
|
+
const markerIndex = normalized.lastIndexOf(marker);
|
|
117651
|
+
if (markerIndex === -1) return;
|
|
117652
|
+
const activePrefix = entry.slice(0, markerIndex);
|
|
117653
|
+
const candidates = resolveConptyPrebuildCandidates(activePrefix);
|
|
117654
|
+
const found = candidates.find((candidate) => fs47.existsSync(candidate));
|
|
117655
|
+
if (!found) {
|
|
117656
|
+
throw new Error(
|
|
117657
|
+
`conpty.node missing at boot despite passing the install-time gate \u2014 likely deleted post-install (checked: ${candidates.join(", ")}). Every session-host spawn would crash requiring node-pty; refusing to spawn.`
|
|
117658
|
+
);
|
|
117659
|
+
}
|
|
117660
|
+
LOG2.info("SessionHost", `conpty prebuild verified before spawn at ${found}`);
|
|
117661
|
+
}
|
|
117231
117662
|
function spawnHost() {
|
|
117232
117663
|
const entry = resolveEntry();
|
|
117664
|
+
verifyConptyPrebuildBeforeSpawn(entry);
|
|
117233
117665
|
const nodeExecutable = resolveSessionHostNode();
|
|
117234
117666
|
let stdio = "ignore";
|
|
117235
117667
|
let logFd = null;
|
|
@@ -117282,7 +117714,21 @@ data: ${JSON.stringify(msg.data)}
|
|
|
117282
117714
|
if (existingPid !== null) {
|
|
117283
117715
|
const runningPath = getRunningSessionHostScriptPath(existingPid);
|
|
117284
117716
|
const currentEntry = resolveEntry();
|
|
117285
|
-
if (runningPath
|
|
117717
|
+
if (runningPath === null) {
|
|
117718
|
+
if (unverifiedStopPid !== existingPid) {
|
|
117719
|
+
unverifiedStopPid = existingPid;
|
|
117720
|
+
LOG2.warn(
|
|
117721
|
+
"SessionHost",
|
|
117722
|
+
`Could not read the command line of host pid ${existingPid}; cannot prove it runs from ${currentEntry}. Stopping it once and respawning rather than risking reuse of a stale-prefix host.`
|
|
117723
|
+
);
|
|
117724
|
+
stopManagedSessionHostProcess();
|
|
117725
|
+
} else {
|
|
117726
|
+
LOG2.warn(
|
|
117727
|
+
"SessionHost",
|
|
117728
|
+
`Host pid ${existingPid} is still unverifiable; leaving it alone (already restarted once this process) to avoid a kill/respawn loop.`
|
|
117729
|
+
);
|
|
117730
|
+
}
|
|
117731
|
+
} else if (!pathsEquivalent(runningPath, currentEntry)) {
|
|
117286
117732
|
LOG2.warn(
|
|
117287
117733
|
"SessionHost",
|
|
117288
117734
|
`Detected stale host pid ${existingPid} running from ${runningPath}; restarting from ${currentEntry}`
|
|
@@ -120524,6 +120970,20 @@ var StandaloneServer = class {
|
|
|
120524
120970
|
...request.historySessionId ? { historySessionId: request.historySessionId } : {},
|
|
120525
120971
|
...state.cursor.tailLimit > 0 ? { tailLimit: state.cursor.tailLimit } : {}
|
|
120526
120972
|
});
|
|
120973
|
+
if ((0, import_daemon_core2.isMissingLiveSessionResult)(result)) {
|
|
120974
|
+
const now = Date.now();
|
|
120975
|
+
const missing = (0, import_daemon_core2.recordMissingSessionAttempt)(state.missingSession, now);
|
|
120976
|
+
state.missingSession = missing;
|
|
120977
|
+
const message = `[chat_tail] session ${request.targetSessionId} is not in the live registry`;
|
|
120978
|
+
if ((0, import_daemon_core2.shouldWarnForMissingSession)(missing)) {
|
|
120979
|
+
missing.warned = true;
|
|
120980
|
+
import_daemon_core2.LOG.warn("Standalone", `${message} \u2014 backing off, and dropping the subscription if it stays absent`);
|
|
120981
|
+
} else {
|
|
120982
|
+
import_daemon_core2.LOG.debug("Standalone", `${message} (miss #${missing.consecutiveMisses})`);
|
|
120983
|
+
}
|
|
120984
|
+
return null;
|
|
120985
|
+
}
|
|
120986
|
+
if (state.missingSession) state.missingSession = void 0;
|
|
120527
120987
|
const prepared = (0, import_daemon_core2.prepareSessionChatTailUpdate)({
|
|
120528
120988
|
key,
|
|
120529
120989
|
sessionId: request.targetSessionId,
|
|
@@ -120687,6 +121147,7 @@ var StandaloneServer = class {
|
|
|
120687
121147
|
const targets = targetWs ? [targetWs] : Array.from(this.clients);
|
|
120688
121148
|
const hotSessionIds = options.onlyActive ? this.getHotChatSessionIdsForWsFlush() : null;
|
|
120689
121149
|
const forceSessionIds = options.forceSessionIds ?? null;
|
|
121150
|
+
const now = Date.now();
|
|
120690
121151
|
const tasks = [];
|
|
120691
121152
|
for (const ws of targets) {
|
|
120692
121153
|
if (ws.readyState !== import_ws.WebSocket.OPEN) continue;
|
|
@@ -120694,6 +121155,13 @@ var StandaloneServer = class {
|
|
|
120694
121155
|
if (!subs || subs.size === 0) continue;
|
|
120695
121156
|
for (const [key, sub] of subs.entries()) {
|
|
120696
121157
|
const targetSessionId = sub.request.params.targetSessionId;
|
|
121158
|
+
const decision = (0, import_daemon_core2.decideMissingSessionAttempt)(sub.missingSession, now);
|
|
121159
|
+
if (decision.action === "skip") continue;
|
|
121160
|
+
if (decision.action === "drop") {
|
|
121161
|
+
subs.delete(key);
|
|
121162
|
+
import_daemon_core2.LOG.info("Standalone", `[chat_tail] subscription dropped: session=${targetSessionId} key=${key} \u2014 live session absent for ${Math.round((now - (sub.missingSession?.firstMissingAt ?? now)) / 1e3)}s`);
|
|
121163
|
+
continue;
|
|
121164
|
+
}
|
|
120697
121165
|
const isForced = forceSessionIds?.has(targetSessionId) === true;
|
|
120698
121166
|
if (!isForced && hotSessionIds && !hotSessionIds.active.has(targetSessionId) && !hotSessionIds.finalizing.has(targetSessionId)) {
|
|
120699
121167
|
continue;
|