@adhdev/daemon-standalone 0.9.77-rc.44 → 0.9.77-rc.45
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 +925 -172
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +995 -187
- package/vendor/mcp-server/index.js.map +1 -1
|
@@ -25094,6 +25094,7 @@ __export(dist_exports, {
|
|
|
25094
25094
|
MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
|
|
25095
25095
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
|
|
25096
25096
|
NodePtyTransportFactory: () => NodePtyTransportFactory,
|
|
25097
|
+
P2pRelayFailureError: () => P2pRelayFailureError,
|
|
25097
25098
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
25098
25099
|
ProviderInstanceManager: () => ProviderInstanceManager,
|
|
25099
25100
|
ProviderLoader: () => ProviderLoader,
|
|
@@ -25110,6 +25111,7 @@ __export(dist_exports, {
|
|
|
25110
25111
|
buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
|
|
25111
25112
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
|
|
25112
25113
|
buildMachineInfo: () => buildMachineInfo,
|
|
25114
|
+
buildP2pRelayFailurePayload: () => buildP2pRelayFailurePayload,
|
|
25113
25115
|
buildPinnedGlobalInstallCommand: () => buildPinnedGlobalInstallCommand,
|
|
25114
25116
|
buildRuntimeSystemChatMessage: () => buildRuntimeSystemChatMessage,
|
|
25115
25117
|
buildSessionEntries: () => buildSessionEntries,
|
|
@@ -25124,6 +25126,7 @@ __export(dist_exports, {
|
|
|
25124
25126
|
claimNextTask: () => claimNextTask,
|
|
25125
25127
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
25126
25128
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
|
|
25129
|
+
classifyP2pRelayFailure: () => classifyP2pRelayFailure,
|
|
25127
25130
|
clearDebugTrace: () => clearDebugTrace,
|
|
25128
25131
|
compareGitSnapshots: () => compareGitSnapshots,
|
|
25129
25132
|
configureDebugTraceStore: () => configureDebugTraceStore,
|
|
@@ -25191,6 +25194,7 @@ __export(dist_exports, {
|
|
|
25191
25194
|
isInternalChatMessage: () => isInternalChatMessage,
|
|
25192
25195
|
isManagedStatusWaiting: () => isManagedStatusWaiting,
|
|
25193
25196
|
isManagedStatusWorking: () => isManagedStatusWorking,
|
|
25197
|
+
isP2pRelayTransportFailure: () => isP2pRelayTransportFailure,
|
|
25194
25198
|
isPathInside: () => isPathInside,
|
|
25195
25199
|
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
|
|
25196
25200
|
isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
|
|
@@ -25331,7 +25335,33 @@ async function removeWorktree(repoRoot, worktreePath, opts = {}) {
|
|
|
25331
25335
|
});
|
|
25332
25336
|
} catch (error48) {
|
|
25333
25337
|
const stderr = typeof error48.stderr === "string" ? error48.stderr : "";
|
|
25334
|
-
|
|
25338
|
+
const stdout = typeof error48.stdout === "string" ? error48.stdout : "";
|
|
25339
|
+
const detail = `${stderr}
|
|
25340
|
+
${stdout}
|
|
25341
|
+
${error48.message || ""}`;
|
|
25342
|
+
if (opts.allowSubmoduleForceFallback && SUBMODULE_WORKTREE_REMOVE_RE.test(detail)) {
|
|
25343
|
+
try {
|
|
25344
|
+
await execFileAsync2("git", ["worktree", "remove", "--force", worktreePath], {
|
|
25345
|
+
cwd: repoRoot,
|
|
25346
|
+
encoding: "utf8",
|
|
25347
|
+
timeout: GIT_TIMEOUT_MS,
|
|
25348
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
25349
|
+
windowsHide: true
|
|
25350
|
+
});
|
|
25351
|
+
} catch (forceError) {
|
|
25352
|
+
const forceStderr = typeof forceError.stderr === "string" ? forceError.stderr : "";
|
|
25353
|
+
const forceStdout = typeof forceError.stdout === "string" ? forceError.stdout : "";
|
|
25354
|
+
throw new Error(`git worktree remove --force fallback failed: ${forceStderr.trim() || forceStdout.trim() || forceError.message}`);
|
|
25355
|
+
}
|
|
25356
|
+
return {
|
|
25357
|
+
success: true,
|
|
25358
|
+
removedPath: worktreePath,
|
|
25359
|
+
fallback: "git_worktree_remove_force_submodule",
|
|
25360
|
+
forced: true,
|
|
25361
|
+
reason: "working_trees_containing_submodules"
|
|
25362
|
+
};
|
|
25363
|
+
}
|
|
25364
|
+
throw new Error(`git worktree remove failed: ${stderr.trim() || stdout.trim() || error48.message}`);
|
|
25335
25365
|
}
|
|
25336
25366
|
return { success: true, removedPath: worktreePath };
|
|
25337
25367
|
}
|
|
@@ -26092,6 +26122,19 @@ function updateTaskStatus(meshId, taskId, status) {
|
|
|
26092
26122
|
writeQueue(meshId, queue);
|
|
26093
26123
|
return queue[idx];
|
|
26094
26124
|
}
|
|
26125
|
+
function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
|
|
26126
|
+
const queue = readQueue(meshId);
|
|
26127
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
26128
|
+
if (idx === -1) return null;
|
|
26129
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26130
|
+
queue[idx].autoLaunch = {
|
|
26131
|
+
...autoLaunch,
|
|
26132
|
+
updatedAt: now
|
|
26133
|
+
};
|
|
26134
|
+
queue[idx].updatedAt = now;
|
|
26135
|
+
writeQueue(meshId, queue);
|
|
26136
|
+
return queue[idx];
|
|
26137
|
+
}
|
|
26095
26138
|
function cancelTask(meshId, taskId, opts) {
|
|
26096
26139
|
const queue = readQueue(meshId);
|
|
26097
26140
|
const idx = queue.findIndex((q) => q.id === taskId);
|
|
@@ -26154,6 +26197,129 @@ function getMeshQueueStats(meshId) {
|
|
|
26154
26197
|
}))
|
|
26155
26198
|
};
|
|
26156
26199
|
}
|
|
26200
|
+
function parseVersion(raw) {
|
|
26201
|
+
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
26202
|
+
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
26203
|
+
}
|
|
26204
|
+
function shellQuote(value) {
|
|
26205
|
+
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
26206
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
26207
|
+
}
|
|
26208
|
+
function expandHome(value) {
|
|
26209
|
+
const trimmed = value.trim();
|
|
26210
|
+
if (!trimmed.startsWith("~")) return trimmed;
|
|
26211
|
+
return path8.join(os22.homedir(), trimmed.slice(1));
|
|
26212
|
+
}
|
|
26213
|
+
function isExplicitCommandPath(command) {
|
|
26214
|
+
const trimmed = command.trim();
|
|
26215
|
+
return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
26216
|
+
}
|
|
26217
|
+
function resolveCommandPath(command) {
|
|
26218
|
+
const trimmed = command.trim();
|
|
26219
|
+
if (!trimmed) return null;
|
|
26220
|
+
if (isExplicitCommandPath(trimmed)) {
|
|
26221
|
+
const expanded = expandHome(trimmed);
|
|
26222
|
+
const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
|
|
26223
|
+
return (0, import_fs8.existsSync)(candidate) ? candidate : null;
|
|
26224
|
+
}
|
|
26225
|
+
return null;
|
|
26226
|
+
}
|
|
26227
|
+
function execAsync(cmd, timeoutMs = 5e3) {
|
|
26228
|
+
return new Promise((resolve162) => {
|
|
26229
|
+
const child = (0, import_child_process2.exec)(cmd, {
|
|
26230
|
+
encoding: "utf-8",
|
|
26231
|
+
timeout: timeoutMs,
|
|
26232
|
+
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
26233
|
+
}, (err, stdout) => {
|
|
26234
|
+
if (err || !stdout?.trim()) {
|
|
26235
|
+
resolve162(null);
|
|
26236
|
+
} else {
|
|
26237
|
+
resolve162(stdout.trim());
|
|
26238
|
+
}
|
|
26239
|
+
});
|
|
26240
|
+
child.on("error", () => resolve162(null));
|
|
26241
|
+
});
|
|
26242
|
+
}
|
|
26243
|
+
async function detectCLIs(providerLoader, options) {
|
|
26244
|
+
const platform10 = os22.platform();
|
|
26245
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
26246
|
+
const includeVersion = options?.includeVersion !== false;
|
|
26247
|
+
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
26248
|
+
const results = await Promise.all(
|
|
26249
|
+
cliList.map(async (cli) => {
|
|
26250
|
+
try {
|
|
26251
|
+
const explicitPath = resolveCommandPath(cli.command);
|
|
26252
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
26253
|
+
if (!pathResult) return { ...cli, installed: false };
|
|
26254
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
26255
|
+
let version2;
|
|
26256
|
+
if (includeVersion) {
|
|
26257
|
+
const versionCommands = [
|
|
26258
|
+
`"${firstPath}" --version`,
|
|
26259
|
+
`"${firstPath}" -V`,
|
|
26260
|
+
`"${firstPath}" -v`,
|
|
26261
|
+
cli.versionCommand
|
|
26262
|
+
].filter((v) => !!v);
|
|
26263
|
+
try {
|
|
26264
|
+
for (const versionCommand of versionCommands) {
|
|
26265
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
26266
|
+
if (versionResult) {
|
|
26267
|
+
version2 = parseVersion(versionResult);
|
|
26268
|
+
break;
|
|
26269
|
+
}
|
|
26270
|
+
}
|
|
26271
|
+
} catch {
|
|
26272
|
+
}
|
|
26273
|
+
}
|
|
26274
|
+
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
26275
|
+
} catch {
|
|
26276
|
+
return { ...cli, installed: false };
|
|
26277
|
+
}
|
|
26278
|
+
})
|
|
26279
|
+
);
|
|
26280
|
+
return results;
|
|
26281
|
+
}
|
|
26282
|
+
async function detectCLI(cliId, providerLoader, options) {
|
|
26283
|
+
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
26284
|
+
if (providerLoader) {
|
|
26285
|
+
const cliList = providerLoader.getCliDetectionList();
|
|
26286
|
+
const target = cliList.find((c) => c.id === resolvedId);
|
|
26287
|
+
if (target) {
|
|
26288
|
+
const platform10 = os22.platform();
|
|
26289
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
26290
|
+
try {
|
|
26291
|
+
const explicitPath = resolveCommandPath(target.command);
|
|
26292
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
26293
|
+
if (!pathResult) return null;
|
|
26294
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
26295
|
+
let version2;
|
|
26296
|
+
if (options?.includeVersion !== false) {
|
|
26297
|
+
const versionCommands = [
|
|
26298
|
+
`"${firstPath}" --version`,
|
|
26299
|
+
`"${firstPath}" -V`,
|
|
26300
|
+
`"${firstPath}" -v`,
|
|
26301
|
+
target.versionCommand
|
|
26302
|
+
].filter((v) => !!v);
|
|
26303
|
+
try {
|
|
26304
|
+
for (const versionCommand of versionCommands) {
|
|
26305
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
26306
|
+
if (versionResult) {
|
|
26307
|
+
version2 = parseVersion(versionResult);
|
|
26308
|
+
break;
|
|
26309
|
+
}
|
|
26310
|
+
}
|
|
26311
|
+
} catch {
|
|
26312
|
+
}
|
|
26313
|
+
}
|
|
26314
|
+
return { ...target, installed: true, version: version2, path: firstPath };
|
|
26315
|
+
} catch {
|
|
26316
|
+
return null;
|
|
26317
|
+
}
|
|
26318
|
+
}
|
|
26319
|
+
}
|
|
26320
|
+
const all = await detectCLIs(providerLoader, options);
|
|
26321
|
+
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
26322
|
+
}
|
|
26157
26323
|
function setLogLevel(level) {
|
|
26158
26324
|
currentLevel = level;
|
|
26159
26325
|
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
@@ -26168,13 +26334,13 @@ function getDaemonLogDir() {
|
|
|
26168
26334
|
return LOG_DIR;
|
|
26169
26335
|
}
|
|
26170
26336
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
26171
|
-
return
|
|
26337
|
+
return path9.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
26172
26338
|
}
|
|
26173
26339
|
function checkDateRotation() {
|
|
26174
26340
|
const today = getDateStr();
|
|
26175
26341
|
if (today !== currentDate) {
|
|
26176
26342
|
currentDate = today;
|
|
26177
|
-
currentLogFile =
|
|
26343
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
26178
26344
|
cleanOldLogs();
|
|
26179
26345
|
}
|
|
26180
26346
|
}
|
|
@@ -26188,7 +26354,7 @@ function cleanOldLogs() {
|
|
|
26188
26354
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
26189
26355
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
26190
26356
|
try {
|
|
26191
|
-
fs2.unlinkSync(
|
|
26357
|
+
fs2.unlinkSync(path9.join(LOG_DIR, file2));
|
|
26192
26358
|
} catch {
|
|
26193
26359
|
}
|
|
26194
26360
|
}
|
|
@@ -26363,7 +26529,235 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
26363
26529
|
});
|
|
26364
26530
|
return true;
|
|
26365
26531
|
}
|
|
26366
|
-
function
|
|
26532
|
+
function normalizeProviderPriority(policy) {
|
|
26533
|
+
const raw = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerPriority : void 0;
|
|
26534
|
+
if (!Array.isArray(raw)) return [];
|
|
26535
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26536
|
+
return raw.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean).filter((type2) => {
|
|
26537
|
+
if (seen.has(type2)) return false;
|
|
26538
|
+
seen.add(type2);
|
|
26539
|
+
return true;
|
|
26540
|
+
});
|
|
26541
|
+
}
|
|
26542
|
+
function isTerminalSessionStatus(status) {
|
|
26543
|
+
return ["stopped", "failed", "terminated", "exited", "closed"].includes(status);
|
|
26544
|
+
}
|
|
26545
|
+
function isIdleSessionState(state) {
|
|
26546
|
+
const status = readNonEmptyString(state?.status).toLowerCase();
|
|
26547
|
+
if (isTerminalSessionStatus(status)) return false;
|
|
26548
|
+
return status === "idle" || state?.activeChat?.status === "waiting_input";
|
|
26549
|
+
}
|
|
26550
|
+
function isDirtyNode(node) {
|
|
26551
|
+
return node?.health === "dirty" || node?.git?.dirty === true;
|
|
26552
|
+
}
|
|
26553
|
+
function isLaunchableNode(node) {
|
|
26554
|
+
if (!node || node.status === "disabled" || node.status === "removed") return false;
|
|
26555
|
+
const health = readNonEmptyString(node.health).toLowerCase();
|
|
26556
|
+
if (!health) return true;
|
|
26557
|
+
return health === "online" || health === "unknown";
|
|
26558
|
+
}
|
|
26559
|
+
function localAutoLaunchSkipReason(node) {
|
|
26560
|
+
const daemonId = readNonEmptyString(node?.daemonId);
|
|
26561
|
+
const machineId = readNonEmptyString(node?.machineId);
|
|
26562
|
+
const appConfig = loadConfig();
|
|
26563
|
+
const localMachineId = readNonEmptyString(appConfig.machineId) || readNonEmptyString(appConfig.registeredMachineId);
|
|
26564
|
+
const cloudDaemonId = localMachineId ? `daemon_${localMachineId}` : "";
|
|
26565
|
+
const standaloneDaemonId = localMachineId ? `standalone_${localMachineId}` : "";
|
|
26566
|
+
const daemonMatchesLocal = !daemonId || daemonId === cloudDaemonId || daemonId === standaloneDaemonId;
|
|
26567
|
+
const machineMatchesLocal = !machineId || localMachineId && machineId === localMachineId;
|
|
26568
|
+
if (node?.isLocalWorktree === true) {
|
|
26569
|
+
return daemonMatchesLocal && machineMatchesLocal ? null : "remote_auto_launch_unsupported";
|
|
26570
|
+
}
|
|
26571
|
+
if (daemonId || machineId) {
|
|
26572
|
+
return daemonMatchesLocal && machineMatchesLocal ? null : "remote_auto_launch_unsupported";
|
|
26573
|
+
}
|
|
26574
|
+
return null;
|
|
26575
|
+
}
|
|
26576
|
+
function activeAssignedCount(meshId) {
|
|
26577
|
+
return getQueue(meshId, { status: ["assigned"] }).length;
|
|
26578
|
+
}
|
|
26579
|
+
function nodeHasActiveAssignment(meshId, nodeId) {
|
|
26580
|
+
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
26581
|
+
}
|
|
26582
|
+
function liveSessionCountForNode(components, meshId, nodeId) {
|
|
26583
|
+
return components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
26584
|
+
const state = inst.getState();
|
|
26585
|
+
const settings = state.settings || {};
|
|
26586
|
+
if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
|
|
26587
|
+
const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
26588
|
+
if (instNodeId !== nodeId) return false;
|
|
26589
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
26590
|
+
return !isTerminalSessionStatus(status);
|
|
26591
|
+
}).length;
|
|
26592
|
+
}
|
|
26593
|
+
function recordAutoLaunchEvent(meshId, args) {
|
|
26594
|
+
try {
|
|
26595
|
+
appendLedgerEntry(meshId, {
|
|
26596
|
+
kind: "session_auto_launch",
|
|
26597
|
+
nodeId: args.nodeId,
|
|
26598
|
+
sessionId: args.sessionId,
|
|
26599
|
+
providerType: args.providerType,
|
|
26600
|
+
payload: {
|
|
26601
|
+
phase: args.phase,
|
|
26602
|
+
taskId: args.taskId,
|
|
26603
|
+
reason: args.reason,
|
|
26604
|
+
error: args.error
|
|
26605
|
+
}
|
|
26606
|
+
});
|
|
26607
|
+
} catch (e) {
|
|
26608
|
+
LOG.warn("MeshQueue", `Failed to record auto-launch ledger event: ${e?.message || e}`);
|
|
26609
|
+
}
|
|
26610
|
+
}
|
|
26611
|
+
function markAutoLaunch(meshId, taskId, args) {
|
|
26612
|
+
recordTaskAutoLaunch(meshId, taskId, {
|
|
26613
|
+
status: args.status,
|
|
26614
|
+
reason: args.reason || args.error,
|
|
26615
|
+
nodeId: args.nodeId,
|
|
26616
|
+
providerType: args.providerType,
|
|
26617
|
+
sessionId: args.sessionId
|
|
26618
|
+
});
|
|
26619
|
+
recordAutoLaunchEvent(meshId, {
|
|
26620
|
+
phase: args.status,
|
|
26621
|
+
taskId,
|
|
26622
|
+
nodeId: args.nodeId,
|
|
26623
|
+
providerType: args.providerType,
|
|
26624
|
+
sessionId: args.sessionId,
|
|
26625
|
+
reason: args.reason,
|
|
26626
|
+
error: args.error
|
|
26627
|
+
});
|
|
26628
|
+
}
|
|
26629
|
+
async function resolveUsableProvider(components, nodeId, node) {
|
|
26630
|
+
const providerPriority = normalizeProviderPriority(node?.policy);
|
|
26631
|
+
if (!providerPriority.length) return { reason: "missing_provider_priority" };
|
|
26632
|
+
const providerLoader = components.providerLoader;
|
|
26633
|
+
if (!providerLoader) return { reason: "provider_loader_unavailable" };
|
|
26634
|
+
const failed = [];
|
|
26635
|
+
for (const requestedType of providerPriority) {
|
|
26636
|
+
const normalizedType = typeof providerLoader.resolveAlias === "function" ? providerLoader.resolveAlias(requestedType) : requestedType;
|
|
26637
|
+
if (typeof providerLoader.isMachineProviderEnabled === "function" && !providerLoader.isMachineProviderEnabled(normalizedType)) {
|
|
26638
|
+
failed.push(`${requestedType}: disabled`);
|
|
26639
|
+
continue;
|
|
26640
|
+
}
|
|
26641
|
+
let detected;
|
|
26642
|
+
try {
|
|
26643
|
+
detected = await detectCLI(normalizedType, providerLoader, { includeVersion: false });
|
|
26644
|
+
} catch (e) {
|
|
26645
|
+
failed.push(`${requestedType}: detect failed: ${e?.message || e}`);
|
|
26646
|
+
continue;
|
|
26647
|
+
}
|
|
26648
|
+
if (typeof providerLoader.setCliDetectionResults === "function") {
|
|
26649
|
+
providerLoader.setCliDetectionResults([{
|
|
26650
|
+
id: normalizedType,
|
|
26651
|
+
installed: !!detected,
|
|
26652
|
+
path: detected?.path
|
|
26653
|
+
}], false);
|
|
26654
|
+
}
|
|
26655
|
+
components.onStatusChange?.();
|
|
26656
|
+
if (detected) return { providerType: normalizedType };
|
|
26657
|
+
failed.push(`${requestedType}: not detected`);
|
|
26658
|
+
}
|
|
26659
|
+
return { reason: `provider_priority_unusable: ${failed.join("; ") || nodeId}` };
|
|
26660
|
+
}
|
|
26661
|
+
async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
26662
|
+
const queue = getQueue(meshId);
|
|
26663
|
+
const pending = queue.filter((task) => task.status === "pending");
|
|
26664
|
+
if (!pending.length) return false;
|
|
26665
|
+
const maxParallelTasks = Math.max(1, Math.floor(Number(mesh?.policy?.maxParallelTasks) || 2));
|
|
26666
|
+
for (const task of pending) {
|
|
26667
|
+
if (activeAssignedCount(meshId) >= maxParallelTasks) {
|
|
26668
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_parallel_tasks_reached" });
|
|
26669
|
+
return false;
|
|
26670
|
+
}
|
|
26671
|
+
if (task.targetSessionId) {
|
|
26672
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_constraint" });
|
|
26673
|
+
continue;
|
|
26674
|
+
}
|
|
26675
|
+
const candidateNodes = Array.isArray(mesh?.nodes) ? mesh.nodes.filter((node) => task.targetNodeId ? node?.id === task.targetNodeId : true) : [];
|
|
26676
|
+
if (!candidateNodes.length) {
|
|
26677
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "no_matching_node", nodeId: task.targetNodeId });
|
|
26678
|
+
continue;
|
|
26679
|
+
}
|
|
26680
|
+
for (const node of candidateNodes) {
|
|
26681
|
+
const nodeId = readNonEmptyString(node?.id);
|
|
26682
|
+
if (!nodeId) continue;
|
|
26683
|
+
const launchKey = `${meshId}:${nodeId}`;
|
|
26684
|
+
const cooldownUntil = autoLaunchCooldownUntil.get(launchKey) || 0;
|
|
26685
|
+
if (autoLaunchInProgress.has(launchKey)) {
|
|
26686
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_in_progress", nodeId });
|
|
26687
|
+
continue;
|
|
26688
|
+
}
|
|
26689
|
+
if (Date.now() < cooldownUntil) {
|
|
26690
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_cooldown", nodeId });
|
|
26691
|
+
continue;
|
|
26692
|
+
}
|
|
26693
|
+
if (isDirtyNode(node)) {
|
|
26694
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "dirty_workspace", nodeId });
|
|
26695
|
+
continue;
|
|
26696
|
+
}
|
|
26697
|
+
if (!isLaunchableNode(node)) {
|
|
26698
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_not_launch_ready", nodeId });
|
|
26699
|
+
continue;
|
|
26700
|
+
}
|
|
26701
|
+
const localSkipReason = localAutoLaunchSkipReason(node);
|
|
26702
|
+
if (localSkipReason) {
|
|
26703
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: localSkipReason, nodeId });
|
|
26704
|
+
continue;
|
|
26705
|
+
}
|
|
26706
|
+
if (nodeHasActiveAssignment(meshId, nodeId)) {
|
|
26707
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
|
|
26708
|
+
continue;
|
|
26709
|
+
}
|
|
26710
|
+
const maxConcurrentSessions = Number(node?.policy?.maxConcurrentSessions);
|
|
26711
|
+
if (Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0 && liveSessionCountForNode(components, meshId, nodeId) >= maxConcurrentSessions) {
|
|
26712
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_concurrent_sessions_reached", nodeId });
|
|
26713
|
+
continue;
|
|
26714
|
+
}
|
|
26715
|
+
autoLaunchInProgress.add(launchKey);
|
|
26716
|
+
try {
|
|
26717
|
+
const resolved = await resolveUsableProvider(components, nodeId, node);
|
|
26718
|
+
if (!resolved.providerType) {
|
|
26719
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: resolved.reason || "provider_unusable", nodeId });
|
|
26720
|
+
continue;
|
|
26721
|
+
}
|
|
26722
|
+
markAutoLaunch(meshId, task.id, { status: "started", nodeId, providerType: resolved.providerType });
|
|
26723
|
+
const launchResult = await components.cliManager.handleCliCommand("launch_cli", {
|
|
26724
|
+
cliType: resolved.providerType,
|
|
26725
|
+
dir: node.workspace,
|
|
26726
|
+
settings: {
|
|
26727
|
+
meshNodeFor: meshId,
|
|
26728
|
+
meshNodeId: nodeId,
|
|
26729
|
+
spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
|
|
26730
|
+
launchedByCoordinator: true,
|
|
26731
|
+
autoLaunchedForQueueTaskId: task.id
|
|
26732
|
+
}
|
|
26733
|
+
});
|
|
26734
|
+
if (!launchResult?.success) {
|
|
26735
|
+
const reason = launchResult?.error || "launch_cli_failed";
|
|
26736
|
+
markAutoLaunch(meshId, task.id, { status: "failed", reason, nodeId, providerType: resolved.providerType });
|
|
26737
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
26738
|
+
return false;
|
|
26739
|
+
}
|
|
26740
|
+
const sessionId = readNonEmptyString(launchResult.sessionId) || readNonEmptyString(launchResult.id) || readNonEmptyString(launchResult.runtimeSessionId);
|
|
26741
|
+
if (!sessionId) {
|
|
26742
|
+
markAutoLaunch(meshId, task.id, { status: "failed", reason: "launch_missing_session_id", nodeId, providerType: resolved.providerType });
|
|
26743
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
26744
|
+
return false;
|
|
26745
|
+
}
|
|
26746
|
+
markAutoLaunch(meshId, task.id, { status: "completed", nodeId, providerType: resolved.providerType, sessionId });
|
|
26747
|
+
tryAssignQueueTask(components, meshId, nodeId, sessionId, resolved.providerType);
|
|
26748
|
+
return true;
|
|
26749
|
+
} catch (e) {
|
|
26750
|
+
markAutoLaunch(meshId, task.id, { status: "failed", error: e?.message || String(e), nodeId });
|
|
26751
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
26752
|
+
return false;
|
|
26753
|
+
} finally {
|
|
26754
|
+
autoLaunchInProgress.delete(launchKey);
|
|
26755
|
+
}
|
|
26756
|
+
}
|
|
26757
|
+
}
|
|
26758
|
+
return false;
|
|
26759
|
+
}
|
|
26760
|
+
async function triggerMeshQueue(components, meshId) {
|
|
26367
26761
|
const mesh = getMeshWithCache(components, meshId);
|
|
26368
26762
|
if (!mesh) return;
|
|
26369
26763
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
@@ -26374,9 +26768,7 @@ function triggerMeshQueue(components, meshId) {
|
|
|
26374
26768
|
if (instMeshId !== meshId) continue;
|
|
26375
26769
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
26376
26770
|
if (!nodeId) continue;
|
|
26377
|
-
|
|
26378
|
-
if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
|
|
26379
|
-
if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
|
|
26771
|
+
if (!isIdleSessionState(state)) continue;
|
|
26380
26772
|
const sessionId = state.instanceId;
|
|
26381
26773
|
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
26382
26774
|
if (providerType) {
|
|
@@ -26392,6 +26784,7 @@ function triggerMeshQueue(components, meshId) {
|
|
|
26392
26784
|
}
|
|
26393
26785
|
}
|
|
26394
26786
|
}
|
|
26787
|
+
await maybeAutoLaunchOneQueueSession(components, meshId, mesh);
|
|
26395
26788
|
}
|
|
26396
26789
|
function buildMeshSystemMessage(args) {
|
|
26397
26790
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
@@ -26899,7 +27292,7 @@ function findBinary(name) {
|
|
|
26899
27292
|
const isWin = os9.platform() === "win32";
|
|
26900
27293
|
try {
|
|
26901
27294
|
const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
|
|
26902
|
-
return (0,
|
|
27295
|
+
return (0, import_child_process3.execSync)(cmd, {
|
|
26903
27296
|
encoding: "utf-8",
|
|
26904
27297
|
timeout: 5e3,
|
|
26905
27298
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -27274,7 +27667,7 @@ async function validateWorkspace(workspace) {
|
|
|
27274
27667
|
cwd: normalizedWorkspace
|
|
27275
27668
|
});
|
|
27276
27669
|
}
|
|
27277
|
-
await (0, import_promises5.access)(normalizedWorkspace,
|
|
27670
|
+
await (0, import_promises5.access)(normalizedWorkspace, import_fs9.constants.R_OK);
|
|
27278
27671
|
} catch (error48) {
|
|
27279
27672
|
if (error48 instanceof GitCommandError) throw error48;
|
|
27280
27673
|
throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
|
|
@@ -28787,6 +29180,86 @@ async function syncMeshLedger(meshId, transport) {
|
|
|
28787
29180
|
appendRemoteLedgerEntries2(meshId, res.missingEntries);
|
|
28788
29181
|
}
|
|
28789
29182
|
}
|
|
29183
|
+
function messageFromError(error48) {
|
|
29184
|
+
if (error48 instanceof Error) return error48.message;
|
|
29185
|
+
if (typeof error48 === "string") return error48;
|
|
29186
|
+
if (error48 && typeof error48 === "object") {
|
|
29187
|
+
const candidate = error48.error ?? error48.message ?? error48.reason;
|
|
29188
|
+
if (typeof candidate === "string") return candidate;
|
|
29189
|
+
}
|
|
29190
|
+
return String(error48 || "mesh relay command failed");
|
|
29191
|
+
}
|
|
29192
|
+
function classifyP2pRelayFailure(error48, _context = {}) {
|
|
29193
|
+
const message = messageFromError(error48);
|
|
29194
|
+
const lower = message.toLowerCase();
|
|
29195
|
+
const hasP2pSignal = /p2p|datachannel|node-datachannel|webrtc|ice|mesh_relay_command|daemon_mesh_p2p_transport/i.test(message);
|
|
29196
|
+
const hasFailureSignal = /unavailable|missing|failed|failure|timeout|timed out|not connected|closed|disconnected|offline|no route|route unavailable|cannot send|cannot establish/i.test(message);
|
|
29197
|
+
if (/requires targetdaemonid and command|providerpriority|no inference provider|permission denied|read-only|not a member/i.test(message)) {
|
|
29198
|
+
return {
|
|
29199
|
+
code: "mesh_logic_or_provider_failure",
|
|
29200
|
+
reason: "mesh_logic_or_provider_failure",
|
|
29201
|
+
transport: "unknown",
|
|
29202
|
+
recoverable: false,
|
|
29203
|
+
retryRecommended: false,
|
|
29204
|
+
nextAction: NON_P2P_NEXT_ACTION,
|
|
29205
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29206
|
+
};
|
|
29207
|
+
}
|
|
29208
|
+
let code = null;
|
|
29209
|
+
let reason = "";
|
|
29210
|
+
if (/timeout|timed out/i.test(message) && (hasP2pSignal || /mesh transport/i.test(message))) {
|
|
29211
|
+
code = "p2p_timeout";
|
|
29212
|
+
reason = "daemon_mesh_p2p_timeout";
|
|
29213
|
+
} else if (/no route|route unavailable/i.test(message)) {
|
|
29214
|
+
code = "p2p_no_route";
|
|
29215
|
+
reason = "daemon_mesh_p2p_no_route";
|
|
29216
|
+
} else if (/offline|not owned|not found|not connected to server/i.test(message) && /daemon|peer|target/i.test(message)) {
|
|
29217
|
+
code = "p2p_daemon_offline";
|
|
29218
|
+
reason = "daemon_mesh_target_offline";
|
|
29219
|
+
} else if (/closed|disconnected/i.test(message) && (hasP2pSignal || /state changed/i.test(message))) {
|
|
29220
|
+
code = "p2p_datachannel_closed";
|
|
29221
|
+
reason = "daemon_mesh_p2p_datachannel_closed";
|
|
29222
|
+
} else if (/not connected|cannot send|cannot establish/i.test(message) && hasP2pSignal) {
|
|
29223
|
+
code = "p2p_not_connected";
|
|
29224
|
+
reason = "daemon_mesh_p2p_not_connected";
|
|
29225
|
+
} else if (hasP2pSignal && hasFailureSignal) {
|
|
29226
|
+
code = "p2p_unavailable";
|
|
29227
|
+
reason = "daemon_mesh_p2p_transport_unavailable";
|
|
29228
|
+
}
|
|
29229
|
+
if (!code) {
|
|
29230
|
+
return {
|
|
29231
|
+
code: "mesh_logic_or_provider_failure",
|
|
29232
|
+
reason: "mesh_logic_or_provider_failure",
|
|
29233
|
+
transport: "unknown",
|
|
29234
|
+
recoverable: false,
|
|
29235
|
+
retryRecommended: false,
|
|
29236
|
+
nextAction: NON_P2P_NEXT_ACTION,
|
|
29237
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29238
|
+
};
|
|
29239
|
+
}
|
|
29240
|
+
return {
|
|
29241
|
+
code,
|
|
29242
|
+
reason,
|
|
29243
|
+
transport: "p2p",
|
|
29244
|
+
recoverable: true,
|
|
29245
|
+
retryRecommended: true,
|
|
29246
|
+
nextAction: P2P_NEXT_ACTION,
|
|
29247
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29248
|
+
};
|
|
29249
|
+
}
|
|
29250
|
+
function isP2pRelayTransportFailure(error48) {
|
|
29251
|
+
return classifyP2pRelayFailure(error48).recoverable === true;
|
|
29252
|
+
}
|
|
29253
|
+
function buildP2pRelayFailurePayload(error48, context = {}) {
|
|
29254
|
+
const classification = classifyP2pRelayFailure(error48, context);
|
|
29255
|
+
return {
|
|
29256
|
+
success: false,
|
|
29257
|
+
...classification,
|
|
29258
|
+
error: messageFromError(error48),
|
|
29259
|
+
...context.command ? { command: context.command } : {},
|
|
29260
|
+
...context.targetDaemonId ? { targetDaemonId: context.targetDaemonId } : {}
|
|
29261
|
+
};
|
|
29262
|
+
}
|
|
28790
29263
|
function isPlainObject22(value) {
|
|
28791
29264
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
28792
29265
|
}
|
|
@@ -28827,11 +29300,11 @@ function normalizeState(raw) {
|
|
|
28827
29300
|
}
|
|
28828
29301
|
function loadState() {
|
|
28829
29302
|
const statePath = getStatePath();
|
|
28830
|
-
if (!(0,
|
|
29303
|
+
if (!(0, import_fs10.existsSync)(statePath)) {
|
|
28831
29304
|
return { ...DEFAULT_STATE };
|
|
28832
29305
|
}
|
|
28833
29306
|
try {
|
|
28834
|
-
const raw = (0,
|
|
29307
|
+
const raw = (0, import_fs10.readFileSync)(statePath, "utf-8");
|
|
28835
29308
|
return normalizeState(JSON.parse(raw));
|
|
28836
29309
|
} catch {
|
|
28837
29310
|
return { ...DEFAULT_STATE };
|
|
@@ -28840,7 +29313,7 @@ function loadState() {
|
|
|
28840
29313
|
function saveState(state) {
|
|
28841
29314
|
const statePath = getStatePath();
|
|
28842
29315
|
const normalized = normalizeState(state);
|
|
28843
|
-
(0,
|
|
29316
|
+
(0, import_fs10.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
28844
29317
|
}
|
|
28845
29318
|
function resetState() {
|
|
28846
29319
|
saveState({ ...DEFAULT_STATE });
|
|
@@ -28861,13 +29334,13 @@ function getMergedDefinitions() {
|
|
|
28861
29334
|
function findCliCommand(command) {
|
|
28862
29335
|
const trimmed = String(command || "").trim();
|
|
28863
29336
|
if (!trimmed) return null;
|
|
28864
|
-
if (
|
|
28865
|
-
const candidate = trimmed.startsWith("~") ?
|
|
28866
|
-
const resolved =
|
|
28867
|
-
return (0,
|
|
29337
|
+
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
29338
|
+
const candidate = trimmed.startsWith("~") ? path10.join((0, import_os3.homedir)(), trimmed.slice(1)) : trimmed;
|
|
29339
|
+
const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
|
|
29340
|
+
return (0, import_fs11.existsSync)(resolved) ? resolved : null;
|
|
28868
29341
|
}
|
|
28869
29342
|
try {
|
|
28870
|
-
const result = (0,
|
|
29343
|
+
const result = (0, import_child_process5.execSync)(
|
|
28871
29344
|
(0, import_os3.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
|
|
28872
29345
|
{ encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
|
|
28873
29346
|
).trim();
|
|
@@ -28878,7 +29351,7 @@ function findCliCommand(command) {
|
|
|
28878
29351
|
}
|
|
28879
29352
|
function getIdeVersion(cliCommand) {
|
|
28880
29353
|
try {
|
|
28881
|
-
const result = (0,
|
|
29354
|
+
const result = (0, import_child_process5.execSync)(`"${cliCommand}" --version`, {
|
|
28882
29355
|
encoding: "utf-8",
|
|
28883
29356
|
timeout: 1e4,
|
|
28884
29357
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -28891,13 +29364,13 @@ function getIdeVersion(cliCommand) {
|
|
|
28891
29364
|
function checkPathExists(paths) {
|
|
28892
29365
|
const home = (0, import_os3.homedir)();
|
|
28893
29366
|
for (const p of paths) {
|
|
28894
|
-
const normalized = p.startsWith("~") ?
|
|
29367
|
+
const normalized = p.startsWith("~") ? path10.join(home, p.slice(1)) : p;
|
|
28895
29368
|
if (normalized.includes("*")) {
|
|
28896
29369
|
const username = home.split(/[\\/]/).pop() || "";
|
|
28897
29370
|
const resolved = normalized.replace("*", username);
|
|
28898
|
-
if ((0,
|
|
29371
|
+
if ((0, import_fs11.existsSync)(resolved)) return resolved;
|
|
28899
29372
|
} else {
|
|
28900
|
-
if ((0,
|
|
29373
|
+
if ((0, import_fs11.existsSync)(normalized)) return normalized;
|
|
28901
29374
|
}
|
|
28902
29375
|
}
|
|
28903
29376
|
return null;
|
|
@@ -28911,7 +29384,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28911
29384
|
let resolvedCli = cliPath;
|
|
28912
29385
|
if (!resolvedCli && appPath && os222 === "darwin") {
|
|
28913
29386
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
28914
|
-
if ((0,
|
|
29387
|
+
if ((0, import_fs11.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
28915
29388
|
}
|
|
28916
29389
|
if (!resolvedCli && appPath && os222 === "win32") {
|
|
28917
29390
|
const { dirname: dirname92 } = await import("path");
|
|
@@ -28924,7 +29397,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28924
29397
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
28925
29398
|
];
|
|
28926
29399
|
for (const c of candidates) {
|
|
28927
|
-
if ((0,
|
|
29400
|
+
if ((0, import_fs11.existsSync)(c)) {
|
|
28928
29401
|
resolvedCli = c;
|
|
28929
29402
|
break;
|
|
28930
29403
|
}
|
|
@@ -28945,129 +29418,6 @@ async function detectIDEs(providerLoader) {
|
|
|
28945
29418
|
}
|
|
28946
29419
|
return results;
|
|
28947
29420
|
}
|
|
28948
|
-
function parseVersion(raw) {
|
|
28949
|
-
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
28950
|
-
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
28951
|
-
}
|
|
28952
|
-
function shellQuote(value) {
|
|
28953
|
-
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
28954
|
-
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
28955
|
-
}
|
|
28956
|
-
function expandHome(value) {
|
|
28957
|
-
const trimmed = value.trim();
|
|
28958
|
-
if (!trimmed.startsWith("~")) return trimmed;
|
|
28959
|
-
return path10.join(os32.homedir(), trimmed.slice(1));
|
|
28960
|
-
}
|
|
28961
|
-
function isExplicitCommandPath(command) {
|
|
28962
|
-
const trimmed = command.trim();
|
|
28963
|
-
return path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
28964
|
-
}
|
|
28965
|
-
function resolveCommandPath(command) {
|
|
28966
|
-
const trimmed = command.trim();
|
|
28967
|
-
if (!trimmed) return null;
|
|
28968
|
-
if (isExplicitCommandPath(trimmed)) {
|
|
28969
|
-
const expanded = expandHome(trimmed);
|
|
28970
|
-
const candidate = path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
|
|
28971
|
-
return (0, import_fs11.existsSync)(candidate) ? candidate : null;
|
|
28972
|
-
}
|
|
28973
|
-
return null;
|
|
28974
|
-
}
|
|
28975
|
-
function execAsync(cmd, timeoutMs = 5e3) {
|
|
28976
|
-
return new Promise((resolve162) => {
|
|
28977
|
-
const child = (0, import_child_process5.exec)(cmd, {
|
|
28978
|
-
encoding: "utf-8",
|
|
28979
|
-
timeout: timeoutMs,
|
|
28980
|
-
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
28981
|
-
}, (err, stdout) => {
|
|
28982
|
-
if (err || !stdout?.trim()) {
|
|
28983
|
-
resolve162(null);
|
|
28984
|
-
} else {
|
|
28985
|
-
resolve162(stdout.trim());
|
|
28986
|
-
}
|
|
28987
|
-
});
|
|
28988
|
-
child.on("error", () => resolve162(null));
|
|
28989
|
-
});
|
|
28990
|
-
}
|
|
28991
|
-
async function detectCLIs(providerLoader, options) {
|
|
28992
|
-
const platform10 = os32.platform();
|
|
28993
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
28994
|
-
const includeVersion = options?.includeVersion !== false;
|
|
28995
|
-
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
28996
|
-
const results = await Promise.all(
|
|
28997
|
-
cliList.map(async (cli) => {
|
|
28998
|
-
try {
|
|
28999
|
-
const explicitPath = resolveCommandPath(cli.command);
|
|
29000
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
29001
|
-
if (!pathResult) return { ...cli, installed: false };
|
|
29002
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29003
|
-
let version2;
|
|
29004
|
-
if (includeVersion) {
|
|
29005
|
-
const versionCommands = [
|
|
29006
|
-
`"${firstPath}" --version`,
|
|
29007
|
-
`"${firstPath}" -V`,
|
|
29008
|
-
`"${firstPath}" -v`,
|
|
29009
|
-
cli.versionCommand
|
|
29010
|
-
].filter((v) => !!v);
|
|
29011
|
-
try {
|
|
29012
|
-
for (const versionCommand of versionCommands) {
|
|
29013
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29014
|
-
if (versionResult) {
|
|
29015
|
-
version2 = parseVersion(versionResult);
|
|
29016
|
-
break;
|
|
29017
|
-
}
|
|
29018
|
-
}
|
|
29019
|
-
} catch {
|
|
29020
|
-
}
|
|
29021
|
-
}
|
|
29022
|
-
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
29023
|
-
} catch {
|
|
29024
|
-
return { ...cli, installed: false };
|
|
29025
|
-
}
|
|
29026
|
-
})
|
|
29027
|
-
);
|
|
29028
|
-
return results;
|
|
29029
|
-
}
|
|
29030
|
-
async function detectCLI(cliId, providerLoader, options) {
|
|
29031
|
-
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
29032
|
-
if (providerLoader) {
|
|
29033
|
-
const cliList = providerLoader.getCliDetectionList();
|
|
29034
|
-
const target = cliList.find((c) => c.id === resolvedId);
|
|
29035
|
-
if (target) {
|
|
29036
|
-
const platform10 = os32.platform();
|
|
29037
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
29038
|
-
try {
|
|
29039
|
-
const explicitPath = resolveCommandPath(target.command);
|
|
29040
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
29041
|
-
if (!pathResult) return null;
|
|
29042
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29043
|
-
let version2;
|
|
29044
|
-
if (options?.includeVersion !== false) {
|
|
29045
|
-
const versionCommands = [
|
|
29046
|
-
`"${firstPath}" --version`,
|
|
29047
|
-
`"${firstPath}" -V`,
|
|
29048
|
-
`"${firstPath}" -v`,
|
|
29049
|
-
target.versionCommand
|
|
29050
|
-
].filter((v) => !!v);
|
|
29051
|
-
try {
|
|
29052
|
-
for (const versionCommand of versionCommands) {
|
|
29053
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29054
|
-
if (versionResult) {
|
|
29055
|
-
version2 = parseVersion(versionResult);
|
|
29056
|
-
break;
|
|
29057
|
-
}
|
|
29058
|
-
}
|
|
29059
|
-
} catch {
|
|
29060
|
-
}
|
|
29061
|
-
}
|
|
29062
|
-
return { ...target, installed: true, version: version2, path: firstPath };
|
|
29063
|
-
} catch {
|
|
29064
|
-
return null;
|
|
29065
|
-
}
|
|
29066
|
-
}
|
|
29067
|
-
}
|
|
29068
|
-
const all = await detectCLIs(providerLoader, options);
|
|
29069
|
-
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
29070
|
-
}
|
|
29071
29421
|
function parseDarwinAvailableBytes(totalMem) {
|
|
29072
29422
|
if (os42.platform() !== "darwin") return null;
|
|
29073
29423
|
try {
|
|
@@ -36589,6 +36939,204 @@ async function resolveProviderTypeFromPriority(args) {
|
|
|
36589
36939
|
}
|
|
36590
36940
|
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
|
|
36591
36941
|
}
|
|
36942
|
+
function truncateValidationOutput(value) {
|
|
36943
|
+
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
36944
|
+
if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
|
|
36945
|
+
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
36946
|
+
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
36947
|
+
}
|
|
36948
|
+
function readPackageScripts(workspace) {
|
|
36949
|
+
try {
|
|
36950
|
+
const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
|
|
36951
|
+
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
36952
|
+
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
36953
|
+
} catch {
|
|
36954
|
+
return {};
|
|
36955
|
+
}
|
|
36956
|
+
}
|
|
36957
|
+
function tokenizeValidationCommand(command) {
|
|
36958
|
+
const trimmed = command.trim();
|
|
36959
|
+
if (!trimmed) return null;
|
|
36960
|
+
if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
|
|
36961
|
+
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
36962
|
+
if (!tokens.length) return null;
|
|
36963
|
+
if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
|
|
36964
|
+
return tokens;
|
|
36965
|
+
}
|
|
36966
|
+
function scriptMatchesValidationCategory(scriptName, category) {
|
|
36967
|
+
return scriptName === category || scriptName.startsWith(`${category}:`);
|
|
36968
|
+
}
|
|
36969
|
+
function parsePackageManagerValidationCommand(rawCommand, category, scripts, source) {
|
|
36970
|
+
const tokens = tokenizeValidationCommand(rawCommand);
|
|
36971
|
+
if (!tokens) {
|
|
36972
|
+
return { rejected: { command: rawCommand, category, source, reason: "unsafe command string is not allowlisted" } };
|
|
36973
|
+
}
|
|
36974
|
+
const [binary2, second, third, ...rest] = tokens;
|
|
36975
|
+
let scriptName = "";
|
|
36976
|
+
let command = binary2;
|
|
36977
|
+
let args = [];
|
|
36978
|
+
if ((binary2 === "npm" || binary2 === "pnpm" || binary2 === "bun") && second === "run" && third) {
|
|
36979
|
+
scriptName = third;
|
|
36980
|
+
args = ["run", scriptName, ...rest];
|
|
36981
|
+
} else if (binary2 === "npm" && second === "test" && !third) {
|
|
36982
|
+
scriptName = "test";
|
|
36983
|
+
args = ["test"];
|
|
36984
|
+
} else if (binary2 === "yarn" && second === "run" && third) {
|
|
36985
|
+
scriptName = third;
|
|
36986
|
+
args = ["run", scriptName, ...rest];
|
|
36987
|
+
} else if (binary2 === "yarn" && second && !third) {
|
|
36988
|
+
scriptName = second;
|
|
36989
|
+
args = [scriptName];
|
|
36990
|
+
} else {
|
|
36991
|
+
return { rejected: { command: rawCommand, category, source, reason: "command is not a supported package-manager script invocation" } };
|
|
36992
|
+
}
|
|
36993
|
+
if (!scriptName || !Object.prototype.hasOwnProperty.call(scripts, scriptName)) {
|
|
36994
|
+
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script is not declared in package.json" } };
|
|
36995
|
+
}
|
|
36996
|
+
if (!scriptMatchesValidationCategory(scriptName, category)) {
|
|
36997
|
+
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script name is outside the validation category allowlist" } };
|
|
36998
|
+
}
|
|
36999
|
+
return {
|
|
37000
|
+
command: {
|
|
37001
|
+
command,
|
|
37002
|
+
args,
|
|
37003
|
+
displayCommand: [command, ...args].join(" "),
|
|
37004
|
+
category,
|
|
37005
|
+
source
|
|
37006
|
+
}
|
|
37007
|
+
};
|
|
37008
|
+
}
|
|
37009
|
+
function collectProjectContextValidationCandidates(mesh) {
|
|
37010
|
+
const commands = mesh?.projectContext?.commands;
|
|
37011
|
+
if (!commands || typeof commands !== "object" || Array.isArray(commands)) return [];
|
|
37012
|
+
const candidates = [];
|
|
37013
|
+
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
37014
|
+
const entries = Array.isArray(commands[category]) ? commands[category] : [];
|
|
37015
|
+
for (const entry of entries) {
|
|
37016
|
+
if (typeof entry?.command !== "string") continue;
|
|
37017
|
+
candidates.push({
|
|
37018
|
+
command: entry.command,
|
|
37019
|
+
category,
|
|
37020
|
+
source: typeof entry.sourcePath === "string" ? entry.sourcePath : "projectContext.commands",
|
|
37021
|
+
confidence: typeof entry.confidence === "string" ? entry.confidence : void 0
|
|
37022
|
+
});
|
|
37023
|
+
}
|
|
37024
|
+
}
|
|
37025
|
+
return candidates.sort((a, b) => {
|
|
37026
|
+
const rank = (value) => value === "high" ? 0 : value === "medium" ? 1 : 2;
|
|
37027
|
+
return rank(a.confidence) - rank(b.confidence);
|
|
37028
|
+
});
|
|
37029
|
+
}
|
|
37030
|
+
function collectPolicyValidationCandidates(mesh) {
|
|
37031
|
+
const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
|
|
37032
|
+
const configured = Array.isArray(policy.validationCommands) ? policy.validationCommands : Array.isArray(policy.validationGate?.commands) ? policy.validationGate.commands : [];
|
|
37033
|
+
return configured.map((entry) => typeof entry === "string" ? { command: entry, category: "", source: "mesh.policy.validationCommands" } : entry).filter((entry) => entry && typeof entry.command === "string").map((entry) => {
|
|
37034
|
+
const commandText = entry.command.trim();
|
|
37035
|
+
const category = REFINE_VALIDATION_CATEGORIES.find((cat) => commandText.includes(` ${cat}`)) ?? "";
|
|
37036
|
+
return { command: commandText, category, source: "mesh.policy.validationCommands" };
|
|
37037
|
+
}).filter((entry) => !!entry.category);
|
|
37038
|
+
}
|
|
37039
|
+
function selectMeshRefineValidationCommands(mesh, workspace) {
|
|
37040
|
+
const scripts = readPackageScripts(workspace);
|
|
37041
|
+
const rejectedCommands = [];
|
|
37042
|
+
const selected = [];
|
|
37043
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37044
|
+
const candidates = [
|
|
37045
|
+
...collectPolicyValidationCandidates(mesh),
|
|
37046
|
+
...collectProjectContextValidationCandidates(mesh)
|
|
37047
|
+
];
|
|
37048
|
+
for (const candidate of candidates) {
|
|
37049
|
+
const parsed = parsePackageManagerValidationCommand(candidate.command, candidate.category, scripts, candidate.source);
|
|
37050
|
+
if (parsed.rejected) {
|
|
37051
|
+
rejectedCommands.push(parsed.rejected);
|
|
37052
|
+
continue;
|
|
37053
|
+
}
|
|
37054
|
+
if (!parsed.command || seen.has(parsed.command.displayCommand)) continue;
|
|
37055
|
+
selected.push(parsed.command);
|
|
37056
|
+
seen.add(parsed.command.displayCommand);
|
|
37057
|
+
if (selected.length >= REFINE_VALIDATION_MAX_COMMANDS) break;
|
|
37058
|
+
}
|
|
37059
|
+
if (!selected.length && candidates.length === 0) {
|
|
37060
|
+
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
37061
|
+
if (!Object.prototype.hasOwnProperty.call(scripts, category)) continue;
|
|
37062
|
+
const fallback = parsePackageManagerValidationCommand(`npm run ${category}`, category, scripts, "package.json:scripts");
|
|
37063
|
+
if (fallback.command && !seen.has(fallback.command.displayCommand)) {
|
|
37064
|
+
selected.push(fallback.command);
|
|
37065
|
+
seen.add(fallback.command.displayCommand);
|
|
37066
|
+
} else if (fallback.rejected) {
|
|
37067
|
+
rejectedCommands.push(fallback.rejected);
|
|
37068
|
+
}
|
|
37069
|
+
if (selected.length >= 2) break;
|
|
37070
|
+
}
|
|
37071
|
+
}
|
|
37072
|
+
return {
|
|
37073
|
+
commands: selected,
|
|
37074
|
+
rejectedCommands,
|
|
37075
|
+
source: selected.some((command) => command.source === "mesh.policy.validationCommands") ? "mesh_policy" : selected.some((command) => command.source !== "package.json:scripts") ? "project_context" : selected.length ? "package_json_scripts" : "unavailable"
|
|
37076
|
+
};
|
|
37077
|
+
}
|
|
37078
|
+
async function runMeshRefineValidationGate(mesh, workspace) {
|
|
37079
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
37080
|
+
const { promisify: promisify3 } = await import("util");
|
|
37081
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
37082
|
+
const selection = selectMeshRefineValidationCommands(mesh, workspace);
|
|
37083
|
+
const summary = {
|
|
37084
|
+
status: "skipped",
|
|
37085
|
+
required: true,
|
|
37086
|
+
commandsRun: [],
|
|
37087
|
+
rejectedCommands: selection.rejectedCommands,
|
|
37088
|
+
skippedReason: void 0,
|
|
37089
|
+
timeoutMs: REFINE_VALIDATION_TIMEOUT_MS,
|
|
37090
|
+
outputLimitBytes: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES
|
|
37091
|
+
};
|
|
37092
|
+
if (!selection.commands.length) {
|
|
37093
|
+
summary.skippedReason = "validation_unavailable: no allowlisted projectContext, mesh policy, or package.json build/test/typecheck/lint command was available";
|
|
37094
|
+
return summary;
|
|
37095
|
+
}
|
|
37096
|
+
for (const candidate of selection.commands) {
|
|
37097
|
+
const startedAt = Date.now();
|
|
37098
|
+
try {
|
|
37099
|
+
const result = await execFileAsync3(candidate.command, candidate.args, {
|
|
37100
|
+
cwd: workspace,
|
|
37101
|
+
encoding: "utf8",
|
|
37102
|
+
timeout: REFINE_VALIDATION_TIMEOUT_MS,
|
|
37103
|
+
maxBuffer: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
|
|
37104
|
+
env: { ...process.env, CI: process.env.CI || "1" }
|
|
37105
|
+
});
|
|
37106
|
+
summary.commandsRun.push({
|
|
37107
|
+
command: candidate.command,
|
|
37108
|
+
args: candidate.args,
|
|
37109
|
+
displayCommand: candidate.displayCommand,
|
|
37110
|
+
category: candidate.category,
|
|
37111
|
+
source: candidate.source,
|
|
37112
|
+
passed: true,
|
|
37113
|
+
exitCode: 0,
|
|
37114
|
+
durationMs: Date.now() - startedAt,
|
|
37115
|
+
stdout: truncateValidationOutput(result.stdout),
|
|
37116
|
+
stderr: truncateValidationOutput(result.stderr)
|
|
37117
|
+
});
|
|
37118
|
+
} catch (error48) {
|
|
37119
|
+
summary.commandsRun.push({
|
|
37120
|
+
command: candidate.command,
|
|
37121
|
+
args: candidate.args,
|
|
37122
|
+
displayCommand: candidate.displayCommand,
|
|
37123
|
+
category: candidate.category,
|
|
37124
|
+
source: candidate.source,
|
|
37125
|
+
passed: false,
|
|
37126
|
+
exitCode: typeof error48?.code === "number" ? error48.code : null,
|
|
37127
|
+
signal: typeof error48?.signal === "string" ? error48.signal : null,
|
|
37128
|
+
timedOut: error48?.killed === true || /timed out/i.test(String(error48?.message || "")),
|
|
37129
|
+
durationMs: Date.now() - startedAt,
|
|
37130
|
+
stdout: truncateValidationOutput(error48?.stdout),
|
|
37131
|
+
stderr: truncateValidationOutput(error48?.stderr || error48?.message)
|
|
37132
|
+
});
|
|
37133
|
+
summary.status = "failed";
|
|
37134
|
+
return summary;
|
|
37135
|
+
}
|
|
37136
|
+
}
|
|
37137
|
+
summary.status = "passed";
|
|
37138
|
+
return summary;
|
|
37139
|
+
}
|
|
36592
37140
|
function loadYamlModule() {
|
|
36593
37141
|
return js_yaml_exports;
|
|
36594
37142
|
}
|
|
@@ -41136,7 +41684,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
41136
41684
|
}
|
|
41137
41685
|
cdpManagers.clear();
|
|
41138
41686
|
}
|
|
41139
|
-
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, import_fs6, import_path3, import_crypto4, import_events2, import_fs7, import_path4, import_crypto5,
|
|
41687
|
+
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, import_fs6, import_path3, import_crypto4, import_events2, import_fs7, import_path4, import_crypto5, import_child_process2, os22, path8, import_fs8, fs2, path9, os32, os8, os9, path14, import_child_process3, os10, path15, os11, import_child_process4, import_fs9, import_promises5, path, import_util4, import_promises6, path22, path32, fs, os4, path5, import_crypto6, path6, path7, import_fs10, import_path5, import_child_process5, import_fs11, import_os3, path10, os42, import_child_process6, http, crypto2, fs3, path11, os5, fs4, os6, path12, import_crypto7, fs5, path13, os7, os13, path18, crypto4, import_fs12, import_child_process7, os12, path16, crypto3, fs6, import_module, path17, import_stream2, import_child_process8, import_child_process9, net2, os15, path20, fs7, path19, os14, fs8, path21, os16, import_child_process10, import_crypto8, import_fs13, import_module2, os17, import_path6, os18, import_child_process11, import_child_process12, fs9, os19, path222, import_os4, import_path7, fs10, fs11, path23, os20, import_child_process13, import_os5, http2, fs15, path27, fs12, path24, fs13, path25, fs14, path26, os21, import_child_process14, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __require2, __esm2, __export2, __copyProps2, __toCommonJS2, DEFAULT_MESH_POLICY, init_repo_mesh_types, git_worktree_exports, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER, SUBMODULE_WORKTREE_REMOVE_RE, init_git_worktree, config_exports, DEFAULT_CONFIG, MACHINE_ID_PREFIX, init_config, mesh_config_exports, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES, init_mesh_config, coordinator_prompt_exports, TOOLS_SECTION, TOOL_EXPOSURE_PREFLIGHT_SECTION, WORKFLOW_SECTION, init_coordinator_prompt, mesh_ledger_exports, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, meshLedgerEvents, init_mesh_ledger, mesh_work_queue_exports, init_mesh_work_queue, init_cli_detector, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, init_logger, mesh_events_exports, remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, init_mesh_events, NORMAL_TRACE_BUFFER_SIZE, DEV_TRACE_BUFFER_SIZE, DEFAULT_CONFIG2, currentConfig, init_debug_config, DEFAULT_BINDING_CANDIDATES, cachedBinding, cachedBindingError, GhosttyVtTerminalBackend, init_ghostty_vt_backend, TerminalCtor, XtermTerminalBackend, init_xterm_backend, DEFAULT_SCROLLBACK, loggedTerminalBackends, TerminalScreen, init_terminal_screen, init_spawn_env, cachedPty, NodePtyRuntimeTransport, NodePtyTransportFactory, init_pty_transport, TerminalTranscriptAccumulator, buildCliSpawnEnv, init_provider_cli_shared, init_provider_cli_parse, init_provider_cli_config, init_provider_cli_runtime, provider_cli_adapter_exports, ProviderCliAdapter, init_provider_cli_adapter, execFileAsync, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_BUFFER, GitCommandError, DEFAULT_MAX_FILES, DEFAULT_MAX_BYTES, summarizeGitStatus, InMemoryGitSnapshotStore, DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS, MIN_GIT_WORKSPACE_POLL_INTERVAL_MS, GitWorkspaceMonitor, GIT_COMMAND_NAMES, SNAPSHOT_REASONS, FAILURE_REASONS, defaultSnapshotStore, defaultGitCommandServices, BUSY_STATUSES, TERMINAL_STATUSES, TurnSnapshotTracker, MAX_WORKSPACES, MAX_ACTIVITY, MAX_SAVED_SESSIONS, NO_FALLBACK_REASON, P2P_NEXT_ACTION, NON_P2P_NEXT_ACTION, P2pRelayFailureError, DEFAULT_STATE, BUILTIN_IDE_DEFINITIONS, registeredIDEs, LIVE_LIFECYCLES, DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, LIVE_RUNTIME_LIFECYCLES, DaemonCdpManager, CdpDomHandlers, DEFAULT_MONITOR_CONFIG, StatusMonitor, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET, HISTORY_DIR, RETAIN_DAYS, SAVED_HISTORY_INDEX_VERSION, SAVED_HISTORY_INDEX_FILE, SAVED_HISTORY_INDEX_LOCK_SUFFIX, SAVED_HISTORY_INDEX_LOCK_WAIT_MS, SAVED_HISTORY_INDEX_LOCK_STALE_MS, SAVED_HISTORY_INDEX_LOCK_POLL_MS, SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES, savedHistorySessionCache, savedHistoryFileSummaryCache, savedHistoryBackgroundRefresh, savedHistoryRollupInFlight, ChatHistoryWriter, IDE_PROVIDER_SESSION_CAPABILITIES_BASE, EXTENSION_PROVIDER_SESSION_CAPABILITIES_BASE, ExtensionProviderInstance, VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES, DEFAULT_APPROVAL_POSITIVE_HINTS, IdeProviderInstance, DEFAULT_CDP_SCAN_INTERVAL_MS, DEFAULT_CDP_DISCOVERY_INTERVAL_MS, DEFAULT_STATUS_INITIAL_REPORT_DELAY_MS, DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS, DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS, MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_READY_TIMEOUT_MS, STANDALONE_CDP_SCAN_INTERVAL_MS, DaemonCdpScanner, DaemonCdpInitializer, WORKING_STATUSES, FULL_STATUS_ACTIVE_CHAT_OPTIONS, LIVE_STATUS_ACTIVE_CHAT_OPTIONS, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT, VALID_INPUT_MEDIA_TYPES, VALID_INPUT_STRATEGIES, TEXT_ONLY_MESSAGE_INPUT_SUPPORT, IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, CLI_CHAT_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES, globalStore, RECENT_SEND_WINDOW_MS, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS, HERMES_CLI_STARTING_SEND_SETTLE_MS, recentSendByTarget, DEFAULT_DEBUG_SANITIZE_OPTIONS, SECRET_KEY_PATTERN, KEY_TO_VK, COMMAND_DEBUG_LEVELS, DaemonCommandHandler, COMPLETED_FINALIZATION_RETRY_MS, COMPLETED_FINALIZATION_MAX_WAIT_MS, IMAGE_MIME_EXTENSIONS, MATERIALIZED_IMAGE_MAX_AGE_MS, MATERIALIZED_IMAGE_CLEANUP_INTERVAL_MS, lastMaterializedImageCleanupAt, CachedDatabaseSync, CliProviderInstance, AcpProviderInstance, chalkModule, chalkApi, COORDINATOR_DELEGATED_ENV_UNSETS, DaemonCliManager, VALID_CAPABILITY_MEDIA_TYPES, VALID_INPUT_STRATEGIES2, KNOWN_PROVIDER_FIELDS, VALUE_CONTROL_TYPES, ProviderLoader, _providerLoader, LOG_DIR2, MAX_FILE_SIZE, MAX_DAYS, SENSITIVE_KEYS, currentDate2, currentFile, writeCount2, SKIP_COMMANDS, DEFAULT_SERVER_NAME, DEFAULT_ADHDEV_MCP_COMMAND, HERMES_CLI_TYPE, HERMES_MCP_CONFIG_PATH, READ_DEBUG_ENABLED, recentReadDebugSignatureBySession, UPGRADE_HELPER_ENV, CHANNEL_NPM_TAG, CHANNEL_SERVER_URL, REFINE_VALIDATION_CATEGORIES, REFINE_VALIDATION_TIMEOUT_MS, REFINE_VALIDATION_OUTPUT_LIMIT_BYTES, REFINE_VALIDATION_SUMMARY_CHARS, REFINE_VALIDATION_MAX_COMMANDS, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter, DaemonStatusReporter, DEFAULT_DAEMON_PORT, DAEMON_WS_PATH, ProviderStreamAdapter, DaemonAgentStreamManager, AgentStreamPoller, ProviderInstanceManager, ARCHIVE_PATH, MAX_ENTRIES_PER_PROVIDER, VersionArchive, DEV_SERVER_PORT, DevServer, SessionHostRuntimeTransport, SessionHostPtyTransportFactory, DEFAULT_SESSION_HOST_APP_NAME, DEFAULT_STANDALONE_SESSION_HOST_APP_NAME, STARTUP_TIMEOUT_MS, STARTUP_POLL_MS, SessionHostCompatibilityError, EXTENSION_CATALOG, SessionRegistry;
|
|
41140
41688
|
var init_dist2 = __esm({
|
|
41141
41689
|
"../daemon-core/dist/index.mjs"() {
|
|
41142
41690
|
"use strict";
|
|
@@ -41159,20 +41707,24 @@ var init_dist2 = __esm({
|
|
|
41159
41707
|
import_fs7 = require("fs");
|
|
41160
41708
|
import_path4 = require("path");
|
|
41161
41709
|
import_crypto5 = require("crypto");
|
|
41162
|
-
|
|
41163
|
-
path8 = __toESM(require("path"), 1);
|
|
41710
|
+
import_child_process2 = require("child_process");
|
|
41164
41711
|
os22 = __toESM(require("os"), 1);
|
|
41712
|
+
path8 = __toESM(require("path"), 1);
|
|
41713
|
+
import_fs8 = require("fs");
|
|
41714
|
+
fs2 = __toESM(require("fs"), 1);
|
|
41715
|
+
path9 = __toESM(require("path"), 1);
|
|
41716
|
+
os32 = __toESM(require("os"), 1);
|
|
41165
41717
|
init_dist();
|
|
41166
41718
|
os8 = __toESM(require("os"), 1);
|
|
41167
41719
|
os9 = __toESM(require("os"), 1);
|
|
41168
41720
|
path14 = __toESM(require("path"), 1);
|
|
41169
|
-
|
|
41721
|
+
import_child_process3 = require("child_process");
|
|
41170
41722
|
os10 = __toESM(require("os"), 1);
|
|
41171
41723
|
path15 = __toESM(require("path"), 1);
|
|
41172
41724
|
init_dist();
|
|
41173
41725
|
os11 = __toESM(require("os"), 1);
|
|
41174
|
-
|
|
41175
|
-
|
|
41726
|
+
import_child_process4 = require("child_process");
|
|
41727
|
+
import_fs9 = require("fs");
|
|
41176
41728
|
import_promises5 = require("fs/promises");
|
|
41177
41729
|
path = __toESM(require("path"), 1);
|
|
41178
41730
|
import_util4 = require("util");
|
|
@@ -41185,16 +41737,12 @@ var init_dist2 = __esm({
|
|
|
41185
41737
|
import_crypto6 = require("crypto");
|
|
41186
41738
|
path6 = __toESM(require("path"), 1);
|
|
41187
41739
|
path7 = __toESM(require("path"), 1);
|
|
41188
|
-
import_fs9 = require("fs");
|
|
41189
|
-
import_path5 = require("path");
|
|
41190
|
-
import_child_process4 = require("child_process");
|
|
41191
41740
|
import_fs10 = require("fs");
|
|
41192
|
-
|
|
41193
|
-
path9 = __toESM(require("path"), 1);
|
|
41741
|
+
import_path5 = require("path");
|
|
41194
41742
|
import_child_process5 = require("child_process");
|
|
41195
|
-
os32 = __toESM(require("os"), 1);
|
|
41196
|
-
path10 = __toESM(require("path"), 1);
|
|
41197
41743
|
import_fs11 = require("fs");
|
|
41744
|
+
import_os3 = require("os");
|
|
41745
|
+
path10 = __toESM(require("path"), 1);
|
|
41198
41746
|
os42 = __toESM(require("os"), 1);
|
|
41199
41747
|
import_child_process6 = require("child_process");
|
|
41200
41748
|
init_wrapper();
|
|
@@ -41327,6 +41875,7 @@ var init_dist2 = __esm({
|
|
|
41327
41875
|
WORKTREE_DIR_NAME = ".adhdev-worktrees";
|
|
41328
41876
|
GIT_TIMEOUT_MS = 3e4;
|
|
41329
41877
|
GIT_MAX_BUFFER = 4 * 1024 * 1024;
|
|
41878
|
+
SUBMODULE_WORKTREE_REMOVE_RE = /working trees containing submodules cannot be moved or removed/i;
|
|
41330
41879
|
}
|
|
41331
41880
|
});
|
|
41332
41881
|
config_exports = {};
|
|
@@ -41485,6 +42034,7 @@ Follow these recovery rules:
|
|
|
41485
42034
|
enqueueTask: () => enqueueTask,
|
|
41486
42035
|
getMeshQueueStats: () => getMeshQueueStats,
|
|
41487
42036
|
getQueue: () => getQueue,
|
|
42037
|
+
recordTaskAutoLaunch: () => recordTaskAutoLaunch,
|
|
41488
42038
|
requeueTask: () => requeueTask,
|
|
41489
42039
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
41490
42040
|
updateTaskStatus: () => updateTaskStatus
|
|
@@ -41495,13 +42045,18 @@ Follow these recovery rules:
|
|
|
41495
42045
|
init_mesh_ledger();
|
|
41496
42046
|
}
|
|
41497
42047
|
});
|
|
42048
|
+
init_cli_detector = __esm2({
|
|
42049
|
+
"src/detection/cli-detector.ts"() {
|
|
42050
|
+
"use strict";
|
|
42051
|
+
}
|
|
42052
|
+
});
|
|
41498
42053
|
init_logger = __esm2({
|
|
41499
42054
|
"src/logging/logger.ts"() {
|
|
41500
42055
|
"use strict";
|
|
41501
42056
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
41502
42057
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
41503
42058
|
currentLevel = "info";
|
|
41504
|
-
LOG_DIR = process.platform === "win32" ?
|
|
42059
|
+
LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os32.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os32.homedir(), "Library", "Logs", "adhdev") : path9.join(os32.homedir(), ".local", "share", "adhdev", "logs");
|
|
41505
42060
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
41506
42061
|
MAX_LOG_DAYS = 7;
|
|
41507
42062
|
try {
|
|
@@ -41509,16 +42064,16 @@ Follow these recovery rules:
|
|
|
41509
42064
|
} catch {
|
|
41510
42065
|
}
|
|
41511
42066
|
currentDate = getDateStr();
|
|
41512
|
-
currentLogFile =
|
|
42067
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
41513
42068
|
cleanOldLogs();
|
|
41514
42069
|
try {
|
|
41515
|
-
const oldLog =
|
|
42070
|
+
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
41516
42071
|
if (fs2.existsSync(oldLog)) {
|
|
41517
42072
|
const stat22 = fs2.statSync(oldLog);
|
|
41518
42073
|
const oldDate = stat22.mtime.toISOString().slice(0, 10);
|
|
41519
|
-
fs2.renameSync(oldLog,
|
|
42074
|
+
fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
41520
42075
|
}
|
|
41521
|
-
const oldLogBackup =
|
|
42076
|
+
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
41522
42077
|
if (fs2.existsSync(oldLogBackup)) {
|
|
41523
42078
|
fs2.unlinkSync(oldLogBackup);
|
|
41524
42079
|
}
|
|
@@ -41550,7 +42105,7 @@ Follow these recovery rules:
|
|
|
41550
42105
|
}
|
|
41551
42106
|
};
|
|
41552
42107
|
interceptorInstalled = false;
|
|
41553
|
-
LOG_PATH =
|
|
42108
|
+
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
41554
42109
|
}
|
|
41555
42110
|
});
|
|
41556
42111
|
mesh_events_exports = {};
|
|
@@ -41564,7 +42119,9 @@ Follow these recovery rules:
|
|
|
41564
42119
|
init_mesh_events = __esm2({
|
|
41565
42120
|
"src/mesh/mesh-events.ts"() {
|
|
41566
42121
|
"use strict";
|
|
42122
|
+
init_config();
|
|
41567
42123
|
init_mesh_config();
|
|
42124
|
+
init_cli_detector();
|
|
41568
42125
|
init_logger();
|
|
41569
42126
|
init_mesh_ledger();
|
|
41570
42127
|
init_mesh_work_queue();
|
|
@@ -41585,6 +42142,9 @@ Follow these recovery rules:
|
|
|
41585
42142
|
"agent:stopped": "task_failed",
|
|
41586
42143
|
"monitor:long_generating": "task_stalled"
|
|
41587
42144
|
};
|
|
42145
|
+
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
42146
|
+
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
42147
|
+
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
41588
42148
|
}
|
|
41589
42149
|
});
|
|
41590
42150
|
init_debug_config = __esm2({
|
|
@@ -44078,7 +44638,7 @@ ${lastSnapshot}`;
|
|
|
44078
44638
|
}
|
|
44079
44639
|
});
|
|
44080
44640
|
init_repo_mesh_types();
|
|
44081
|
-
execFileAsync = (0, import_util4.promisify)(
|
|
44641
|
+
execFileAsync = (0, import_util4.promisify)(import_child_process4.execFile);
|
|
44082
44642
|
DEFAULT_TIMEOUT_MS = 5e3;
|
|
44083
44643
|
DEFAULT_MAX_BUFFER = 1024 * 1024;
|
|
44084
44644
|
GitCommandError = class extends Error {
|
|
@@ -44337,6 +44897,34 @@ ${lastSnapshot}`;
|
|
|
44337
44897
|
init_mesh_ledger();
|
|
44338
44898
|
init_mesh_work_queue();
|
|
44339
44899
|
init_mesh_events();
|
|
44900
|
+
NO_FALLBACK_REASON = "Repo Mesh command/data-plane is P2P-only; WS/REST command fallback is intentionally disabled to preserve the transport boundary.";
|
|
44901
|
+
P2P_NEXT_ACTION = "Check daemon/P2P health, wait briefly for connection establishment, then do one bounded retry or requeue the mesh task after clearing stale target session metadata.";
|
|
44902
|
+
NON_P2P_NEXT_ACTION = "Inspect the provider/command error and fix the underlying logic or configuration before retrying.";
|
|
44903
|
+
P2pRelayFailureError = class extends Error {
|
|
44904
|
+
code;
|
|
44905
|
+
reason;
|
|
44906
|
+
transport;
|
|
44907
|
+
recoverable;
|
|
44908
|
+
retryRecommended;
|
|
44909
|
+
nextAction;
|
|
44910
|
+
noFallbackReason;
|
|
44911
|
+
command;
|
|
44912
|
+
targetDaemonId;
|
|
44913
|
+
constructor(message, context = {}) {
|
|
44914
|
+
super(message);
|
|
44915
|
+
this.name = "P2pRelayFailureError";
|
|
44916
|
+
const payload = buildP2pRelayFailurePayload(message, context);
|
|
44917
|
+
this.code = payload.code;
|
|
44918
|
+
this.reason = payload.reason;
|
|
44919
|
+
this.transport = payload.transport;
|
|
44920
|
+
this.recoverable = payload.recoverable;
|
|
44921
|
+
this.retryRecommended = payload.retryRecommended;
|
|
44922
|
+
this.nextAction = payload.nextAction;
|
|
44923
|
+
this.noFallbackReason = payload.noFallbackReason;
|
|
44924
|
+
this.command = context.command;
|
|
44925
|
+
this.targetDaemonId = context.targetDaemonId;
|
|
44926
|
+
}
|
|
44927
|
+
};
|
|
44340
44928
|
init_config();
|
|
44341
44929
|
DEFAULT_STATE = {
|
|
44342
44930
|
recentActivity: [],
|
|
@@ -44348,6 +44936,7 @@ ${lastSnapshot}`;
|
|
|
44348
44936
|
};
|
|
44349
44937
|
BUILTIN_IDE_DEFINITIONS = [];
|
|
44350
44938
|
registeredIDEs = /* @__PURE__ */ new Map();
|
|
44939
|
+
init_cli_detector();
|
|
44351
44940
|
LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
44352
44941
|
DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
44353
44942
|
"generating",
|
|
@@ -48079,6 +48668,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
48079
48668
|
}
|
|
48080
48669
|
};
|
|
48081
48670
|
init_provider_cli_adapter();
|
|
48671
|
+
init_cli_detector();
|
|
48082
48672
|
init_config();
|
|
48083
48673
|
init_provider_cli_adapter();
|
|
48084
48674
|
init_logger();
|
|
@@ -52430,6 +53020,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52430
53020
|
};
|
|
52431
53021
|
_providerLoader = null;
|
|
52432
53022
|
init_config();
|
|
53023
|
+
init_cli_detector();
|
|
52433
53024
|
init_logger();
|
|
52434
53025
|
LOG_DIR2 = process.platform === "win32" ? path21.join(process.env.LOCALAPPDATA || process.env.APPDATA || path21.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path21.join(os16.homedir(), "Library", "Logs", "adhdev") : path21.join(os16.homedir(), ".local", "share", "adhdev", "logs");
|
|
52435
53026
|
MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
@@ -52478,6 +53069,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52478
53069
|
stable: "https://api.adhf.dev",
|
|
52479
53070
|
preview: "https://api-preview.adhf.dev"
|
|
52480
53071
|
};
|
|
53072
|
+
REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
|
|
53073
|
+
REFINE_VALIDATION_TIMEOUT_MS = 12e4;
|
|
53074
|
+
REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
53075
|
+
REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
|
|
53076
|
+
REFINE_VALIDATION_MAX_COMMANDS = 4;
|
|
52481
53077
|
CHAT_COMMANDS = [
|
|
52482
53078
|
"send_chat",
|
|
52483
53079
|
"new_chat",
|
|
@@ -52610,20 +53206,98 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52610
53206
|
recoveryHint: "Inspect the worktree branch and mesh metadata before retrying cleanup."
|
|
52611
53207
|
};
|
|
52612
53208
|
}
|
|
53209
|
+
const forceFallbackConvergence = await this.getWorktreeForceCleanupConvergence({
|
|
53210
|
+
repoRoot,
|
|
53211
|
+
workspace,
|
|
53212
|
+
node: args.node
|
|
53213
|
+
});
|
|
52613
53214
|
try {
|
|
52614
|
-
const result = await removeWorktree2(repoRoot, workspace, {
|
|
52615
|
-
|
|
53215
|
+
const result = await removeWorktree2(repoRoot, workspace, {
|
|
53216
|
+
requireClean: true,
|
|
53217
|
+
allowSubmoduleForceFallback: forceFallbackConvergence.allow
|
|
53218
|
+
});
|
|
53219
|
+
return {
|
|
53220
|
+
success: true,
|
|
53221
|
+
removedPath: result.removedPath,
|
|
53222
|
+
repoRoot,
|
|
53223
|
+
...result.fallback ? {
|
|
53224
|
+
fallback: result.fallback,
|
|
53225
|
+
forced: result.forced,
|
|
53226
|
+
reason: result.reason,
|
|
53227
|
+
convergence: forceFallbackConvergence
|
|
53228
|
+
} : {}
|
|
53229
|
+
};
|
|
52616
53230
|
} catch (e) {
|
|
52617
53231
|
const message = String(e?.message || e || "worktree cleanup failed");
|
|
52618
53232
|
const dirty = message.includes("dirty worktree") || message.includes("local changes");
|
|
53233
|
+
const submoduleForceBlocked = /working trees containing submodules cannot be moved or removed/i.test(message) && !forceFallbackConvergence.allow;
|
|
52619
53234
|
return {
|
|
52620
53235
|
success: false,
|
|
52621
|
-
code: dirty ? "mesh_worktree_cleanup_dirty" : "mesh_worktree_cleanup_failed",
|
|
52622
|
-
error: message,
|
|
52623
|
-
recoveryHint: dirty ? "Commit, stash, or intentionally discard the worktree changes before retrying mesh_remove_node. The mesh registry entry is preserved until cleanup is safe." : "Inspect git worktree status/list from the source repo and retry after resolving the reported cleanup failure."
|
|
53236
|
+
code: dirty ? "mesh_worktree_cleanup_dirty" : submoduleForceBlocked ? "mesh_worktree_cleanup_force_fallback_blocked" : "mesh_worktree_cleanup_failed",
|
|
53237
|
+
error: submoduleForceBlocked ? `${message}; refusing --force fallback because convergence could not be verified: ${forceFallbackConvergence.error || "unknown convergence state"}` : message,
|
|
53238
|
+
recoveryHint: dirty ? "Commit, stash, or intentionally discard the worktree changes before retrying mesh_remove_node. The mesh registry entry is preserved until cleanup is safe." : submoduleForceBlocked ? "Verify the worktree branch is merged/contained in the source default branch (for example origin/main) or mark the node with a safe branchConvergence final state before retrying. The mesh registry entry is preserved." : "Inspect git worktree status/list from the source repo and retry after resolving the reported cleanup failure.",
|
|
53239
|
+
...submoduleForceBlocked ? { convergence: forceFallbackConvergence } : {}
|
|
52624
53240
|
};
|
|
52625
53241
|
}
|
|
52626
53242
|
}
|
|
53243
|
+
async getWorktreeForceCleanupConvergence(args) {
|
|
53244
|
+
const metadataStatus = typeof args.node?.branchConvergence?.status === "string" ? args.node.branchConvergence.status : "";
|
|
53245
|
+
if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate") {
|
|
53246
|
+
return { allow: true, status: metadataStatus, source: "node_branch_convergence" };
|
|
53247
|
+
}
|
|
53248
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
53249
|
+
const { promisify: promisify3 } = await import("util");
|
|
53250
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
53251
|
+
const runGit2 = async (gitArgs, cwd) => {
|
|
53252
|
+
const { stdout } = await execFileAsync3("git", gitArgs, {
|
|
53253
|
+
cwd,
|
|
53254
|
+
encoding: "utf8",
|
|
53255
|
+
timeout: 3e4,
|
|
53256
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
53257
|
+
windowsHide: true
|
|
53258
|
+
});
|
|
53259
|
+
return String(stdout || "").trim();
|
|
53260
|
+
};
|
|
53261
|
+
let head = "";
|
|
53262
|
+
try {
|
|
53263
|
+
head = await runGit2(["rev-parse", "HEAD"], args.workspace);
|
|
53264
|
+
} catch (e) {
|
|
53265
|
+
return { allow: false, error: `could not resolve worktree HEAD: ${e?.message || e}` };
|
|
53266
|
+
}
|
|
53267
|
+
if (!head) return { allow: false, error: "worktree HEAD is empty" };
|
|
53268
|
+
const candidateRefs = [];
|
|
53269
|
+
try {
|
|
53270
|
+
const defaultBranch = await runGit2(["branch", "--show-current"], args.repoRoot);
|
|
53271
|
+
if (defaultBranch) {
|
|
53272
|
+
candidateRefs.push(defaultBranch, `origin/${defaultBranch}`);
|
|
53273
|
+
}
|
|
53274
|
+
} catch {
|
|
53275
|
+
}
|
|
53276
|
+
candidateRefs.push("origin/main", "origin/master", "main", "master");
|
|
53277
|
+
const seen = /* @__PURE__ */ new Set();
|
|
53278
|
+
const checkedRefs = [];
|
|
53279
|
+
for (const ref of candidateRefs) {
|
|
53280
|
+
if (!ref || seen.has(ref)) continue;
|
|
53281
|
+
seen.add(ref);
|
|
53282
|
+
let commit = "";
|
|
53283
|
+
try {
|
|
53284
|
+
commit = await runGit2(["rev-parse", "--verify", `${ref}^{commit}`], args.repoRoot);
|
|
53285
|
+
} catch {
|
|
53286
|
+
continue;
|
|
53287
|
+
}
|
|
53288
|
+
checkedRefs.push(ref);
|
|
53289
|
+
try {
|
|
53290
|
+
await runGit2(["merge-base", "--is-ancestor", head, commit], args.repoRoot);
|
|
53291
|
+
return { allow: true, status: "merged_to_default_ref", source: "git_merge_base", ref };
|
|
53292
|
+
} catch {
|
|
53293
|
+
}
|
|
53294
|
+
}
|
|
53295
|
+
return {
|
|
53296
|
+
allow: false,
|
|
53297
|
+
status: metadataStatus || void 0,
|
|
53298
|
+
error: checkedRefs.length ? `worktree HEAD is not contained in checked refs: ${checkedRefs.join(", ")}` : "no default/main refs were available for convergence verification"
|
|
53299
|
+
};
|
|
53300
|
+
}
|
|
52627
53301
|
isCompletedHostedSession(record2) {
|
|
52628
53302
|
return record2?.lifecycle === "stopped" || record2?.lifecycle === "failed" || record2?.lifecycle === "interrupted";
|
|
52629
53303
|
}
|
|
@@ -53583,10 +54257,61 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53583
54257
|
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
53584
54258
|
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
53585
54259
|
const baseBranch = baseBranchStdout.trim();
|
|
54260
|
+
const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
|
|
54261
|
+
if (validationSummary.status === "failed") {
|
|
54262
|
+
return {
|
|
54263
|
+
success: false,
|
|
54264
|
+
code: "validation_failed",
|
|
54265
|
+
convergenceStatus: "blocked_review",
|
|
54266
|
+
error: "Refinery validation gate failed; merge/refine was not attempted.",
|
|
54267
|
+
branch,
|
|
54268
|
+
into: baseBranch,
|
|
54269
|
+
validationSummary,
|
|
54270
|
+
finalBranchConvergenceState: {
|
|
54271
|
+
branch,
|
|
54272
|
+
baseBranch,
|
|
54273
|
+
merged: false,
|
|
54274
|
+
removed: false,
|
|
54275
|
+
validation: "failed",
|
|
54276
|
+
status: "blocked_review"
|
|
54277
|
+
}
|
|
54278
|
+
};
|
|
54279
|
+
}
|
|
54280
|
+
if (validationSummary.status === "skipped") {
|
|
54281
|
+
return {
|
|
54282
|
+
success: false,
|
|
54283
|
+
code: "validation_unavailable",
|
|
54284
|
+
convergenceStatus: "blocked_review",
|
|
54285
|
+
error: "Refinery validation gate is required but no allowlisted validation command was available; merge/refine was not attempted.",
|
|
54286
|
+
branch,
|
|
54287
|
+
into: baseBranch,
|
|
54288
|
+
validationSummary,
|
|
54289
|
+
finalBranchConvergenceState: {
|
|
54290
|
+
branch,
|
|
54291
|
+
baseBranch,
|
|
54292
|
+
merged: false,
|
|
54293
|
+
removed: false,
|
|
54294
|
+
validation: "unavailable",
|
|
54295
|
+
status: "blocked_review"
|
|
54296
|
+
}
|
|
54297
|
+
};
|
|
54298
|
+
}
|
|
53586
54299
|
try {
|
|
53587
54300
|
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
53588
54301
|
} catch (e) {
|
|
53589
|
-
return {
|
|
54302
|
+
return {
|
|
54303
|
+
success: false,
|
|
54304
|
+
error: `Merge failed (conflicts?): ${e.message}`,
|
|
54305
|
+
validationSummary,
|
|
54306
|
+
finalBranchConvergenceState: {
|
|
54307
|
+
branch,
|
|
54308
|
+
baseBranch,
|
|
54309
|
+
merged: false,
|
|
54310
|
+
removed: false,
|
|
54311
|
+
validation: "passed",
|
|
54312
|
+
status: "not_mergeable"
|
|
54313
|
+
}
|
|
54314
|
+
};
|
|
53590
54315
|
}
|
|
53591
54316
|
const removeResult = await this.execute("remove_mesh_node", {
|
|
53592
54317
|
meshId,
|
|
@@ -53599,11 +54324,27 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53599
54324
|
appendLedgerEntry2(meshId, {
|
|
53600
54325
|
kind: "node_removed",
|
|
53601
54326
|
nodeId,
|
|
53602
|
-
payload: { refined: true, mergedBranch: branch, into: baseBranch }
|
|
54327
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
|
|
53603
54328
|
});
|
|
53604
54329
|
} catch {
|
|
53605
54330
|
}
|
|
53606
|
-
return {
|
|
54331
|
+
return {
|
|
54332
|
+
success: true,
|
|
54333
|
+
merged: true,
|
|
54334
|
+
branch,
|
|
54335
|
+
into: baseBranch,
|
|
54336
|
+
removeResult,
|
|
54337
|
+
validationSummary,
|
|
54338
|
+
finalBranchConvergenceState: {
|
|
54339
|
+
branch: baseBranch,
|
|
54340
|
+
mergedBranch: branch,
|
|
54341
|
+
baseBranch,
|
|
54342
|
+
merged: true,
|
|
54343
|
+
removed: removeResult?.success !== false,
|
|
54344
|
+
validation: "passed",
|
|
54345
|
+
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
54346
|
+
}
|
|
54347
|
+
};
|
|
53607
54348
|
} catch (e) {
|
|
53608
54349
|
return { success: false, error: e.message };
|
|
53609
54350
|
}
|
|
@@ -53658,7 +54399,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53658
54399
|
sessionCleanupMode,
|
|
53659
54400
|
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
53660
54401
|
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
53661
|
-
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0
|
|
54402
|
+
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0,
|
|
54403
|
+
worktreeCleanupFallback: typeof worktreeCleanup?.fallback === "string" ? worktreeCleanup.fallback : void 0,
|
|
54404
|
+
forced: worktreeCleanup?.forced === true ? true : void 0,
|
|
54405
|
+
forceFallbackReason: typeof worktreeCleanup?.reason === "string" ? worktreeCleanup.reason : void 0
|
|
53662
54406
|
}
|
|
53663
54407
|
});
|
|
53664
54408
|
} catch {
|
|
@@ -57555,6 +58299,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
57555
58299
|
apiKeyName: "OpenAI/Anthropic API key"
|
|
57556
58300
|
}
|
|
57557
58301
|
];
|
|
58302
|
+
init_cli_detector();
|
|
57558
58303
|
SessionRegistry = class {
|
|
57559
58304
|
bySessionId = /* @__PURE__ */ new Map();
|
|
57560
58305
|
byManagerKey = /* @__PURE__ */ new Map();
|
|
@@ -58040,16 +58785,38 @@ function extractLaunchPayload(value) {
|
|
|
58040
58785
|
function classifyMeshLaunchFailure(error48) {
|
|
58041
58786
|
const message = error48 instanceof Error ? error48.message : String(error48 || "launch failed");
|
|
58042
58787
|
const lower = message.toLowerCase();
|
|
58043
|
-
|
|
58044
|
-
|
|
58788
|
+
const p2pClassification = classifyP2pRelayFailure(error48, { command: "launch_cli" });
|
|
58789
|
+
if (p2pClassification.recoverable) {
|
|
58790
|
+
return p2pClassification;
|
|
58045
58791
|
}
|
|
58046
58792
|
if (lower.includes("cannot connect to daemon ipc") || lower.includes("daemon ipc command")) {
|
|
58047
|
-
return {
|
|
58793
|
+
return {
|
|
58794
|
+
code: "local_ipc_unavailable",
|
|
58795
|
+
reason: "local_daemon_ipc_unavailable",
|
|
58796
|
+
transport: "local_ipc",
|
|
58797
|
+
recoverable: true,
|
|
58798
|
+
retryRecommended: true,
|
|
58799
|
+
nextAction: "Check the local daemon IPC connection, then retry mesh_launch_session once after the daemon is reachable."
|
|
58800
|
+
};
|
|
58048
58801
|
}
|
|
58049
58802
|
if (lower.includes("timed out") || lower.includes("timeout")) {
|
|
58050
|
-
return {
|
|
58803
|
+
return {
|
|
58804
|
+
code: "mesh_transport_timeout",
|
|
58805
|
+
reason: "mesh_transport_timeout",
|
|
58806
|
+
transport: "mesh_transport",
|
|
58807
|
+
recoverable: true,
|
|
58808
|
+
retryRecommended: true,
|
|
58809
|
+
nextAction: "Check mesh transport health, then do one bounded retry before requeueing or relaunching the task."
|
|
58810
|
+
};
|
|
58051
58811
|
}
|
|
58052
|
-
return {
|
|
58812
|
+
return {
|
|
58813
|
+
code: "mesh_launch_failed",
|
|
58814
|
+
reason: "provider_launch_failed",
|
|
58815
|
+
transport: "mesh_transport",
|
|
58816
|
+
recoverable: false,
|
|
58817
|
+
retryRecommended: false,
|
|
58818
|
+
nextAction: "Inspect the provider launch error and fix the underlying provider/configuration issue before retrying."
|
|
58819
|
+
};
|
|
58053
58820
|
}
|
|
58054
58821
|
function buildWorktreeCleanupHint(node) {
|
|
58055
58822
|
if (!node.isLocalWorktree) return void 0;
|
|
@@ -58065,10 +58832,13 @@ function buildRecoverableLaunchFailure(ctx, node, providerType, error48) {
|
|
|
58065
58832
|
const cleanup = buildWorktreeCleanupHint(node);
|
|
58066
58833
|
return {
|
|
58067
58834
|
success: false,
|
|
58068
|
-
recoverable:
|
|
58835
|
+
recoverable: classified.recoverable,
|
|
58069
58836
|
code: classified.code,
|
|
58070
58837
|
reason: classified.reason,
|
|
58071
58838
|
transport: classified.transport,
|
|
58839
|
+
retryRecommended: classified.retryRecommended,
|
|
58840
|
+
nextAction: classified.nextAction,
|
|
58841
|
+
...classified.noFallbackReason ? { noFallbackReason: classified.noFallbackReason } : {},
|
|
58072
58842
|
error: message,
|
|
58073
58843
|
meshId: ctx.mesh.id,
|
|
58074
58844
|
nodeId: node.id,
|
|
@@ -58115,6 +58885,18 @@ function getLatestActiveLaunchFailure(meshId, nodeId) {
|
|
|
58115
58885
|
}
|
|
58116
58886
|
return null;
|
|
58117
58887
|
}
|
|
58888
|
+
function buildCoordinatorP2pRelayFailure(error48, context) {
|
|
58889
|
+
const payload = buildP2pRelayFailurePayload(error48, {
|
|
58890
|
+
command: context.command,
|
|
58891
|
+
targetDaemonId: context.targetDaemonId
|
|
58892
|
+
});
|
|
58893
|
+
return {
|
|
58894
|
+
...payload,
|
|
58895
|
+
...context.nodeId ? { nodeId: context.nodeId } : {},
|
|
58896
|
+
...context.sessionId ? { sessionId: context.sessionId } : {},
|
|
58897
|
+
retryHint: payload.retryRecommended ? payload.nextAction : "Do not retry as a P2P transport recovery; inspect the command/provider error first."
|
|
58898
|
+
};
|
|
58899
|
+
}
|
|
58118
58900
|
async function ipcDispatchToRemoteAgent(ctx, node, args) {
|
|
58119
58901
|
const transport = ctx.transport;
|
|
58120
58902
|
const daemonId = node.daemonId;
|
|
@@ -58150,11 +58932,32 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
|
|
|
58150
58932
|
});
|
|
58151
58933
|
const dispatchPayload = unwrapCommandPayload(dispatchResult);
|
|
58152
58934
|
if (dispatchPayload?.success === false || dispatchResult?.success === false) {
|
|
58153
|
-
|
|
58935
|
+
const source = dispatchPayload?.success === false ? dispatchPayload : dispatchResult;
|
|
58936
|
+
const errorMessage = dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task";
|
|
58937
|
+
return {
|
|
58938
|
+
...buildCoordinatorP2pRelayFailure(source?.error || errorMessage, {
|
|
58939
|
+
command: "agent_command",
|
|
58940
|
+
targetDaemonId: daemonId,
|
|
58941
|
+
nodeId: node.id,
|
|
58942
|
+
sessionId
|
|
58943
|
+
}),
|
|
58944
|
+
...source && typeof source === "object" ? source : {},
|
|
58945
|
+
success: false,
|
|
58946
|
+
error: `P2P dispatch failed: ${errorMessage}`
|
|
58947
|
+
};
|
|
58154
58948
|
}
|
|
58155
58949
|
return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType };
|
|
58156
58950
|
} catch (e) {
|
|
58157
|
-
|
|
58951
|
+
const errorMessage = e?.message || String(e);
|
|
58952
|
+
return {
|
|
58953
|
+
...buildCoordinatorP2pRelayFailure(e, {
|
|
58954
|
+
command: "agent_command",
|
|
58955
|
+
targetDaemonId: daemonId,
|
|
58956
|
+
nodeId: node.id,
|
|
58957
|
+
sessionId
|
|
58958
|
+
}),
|
|
58959
|
+
error: `P2P dispatch failed: ${errorMessage}`
|
|
58960
|
+
};
|
|
58158
58961
|
}
|
|
58159
58962
|
}
|
|
58160
58963
|
function resolveCoordinatorNode(ctx) {
|
|
@@ -58399,8 +59202,7 @@ async function commandForNode(ctx, node, command, args = {}) {
|
|
|
58399
59202
|
throw new Error(`Command '${command}' requires daemon IPC/local transport for node '${node.id}'`);
|
|
58400
59203
|
}
|
|
58401
59204
|
function isP2pTransportUnavailableError(error48) {
|
|
58402
|
-
|
|
58403
|
-
return /p2p|datachannel|mesh_relay_command|daemon_mesh_p2p_transport_unavailable/i.test(message) && /unavailable|failed|timeout|timed out|not connected|closed/i.test(message);
|
|
59205
|
+
return isP2pRelayTransportFailure(error48);
|
|
58404
59206
|
}
|
|
58405
59207
|
function buildRemoveNodeArgs(ctx, nodeId, sessionCleanupMode) {
|
|
58406
59208
|
return {
|
|
@@ -58993,7 +59795,13 @@ async function meshSendTask(ctx, args) {
|
|
|
58993
59795
|
}
|
|
58994
59796
|
return JSON.stringify({ success: true, nodeId: args.node_id, taskId: task.id, status: task.status });
|
|
58995
59797
|
} catch (e) {
|
|
58996
|
-
|
|
59798
|
+
const failure2 = buildCoordinatorP2pRelayFailure(e, {
|
|
59799
|
+
command: "mesh_send_task",
|
|
59800
|
+
targetDaemonId: node.daemonId,
|
|
59801
|
+
nodeId: args.node_id,
|
|
59802
|
+
sessionId: args.session_id
|
|
59803
|
+
});
|
|
59804
|
+
return JSON.stringify(failure2);
|
|
58997
59805
|
}
|
|
58998
59806
|
}
|
|
58999
59807
|
async function meshReadChat(ctx, args) {
|