@adhdev/daemon-standalone 0.9.77-rc.43 → 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 +941 -180
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +1011 -195
- 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
|
}
|
|
@@ -25798,7 +25828,8 @@ function buildRulesSection(coordinatorCliType) {
|
|
|
25798
25828
|
- **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
|
|
25799
25829
|
- **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to the queue or a node. Do not do it yourself.
|
|
25800
25830
|
- **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes \u2192 \`hermes-cli\`, Claude Code/Claude \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
|
|
25801
|
-
- **Front-load
|
|
25831
|
+
- **Front-load new task messages.** When calling \`mesh_enqueue_task\` or \`mesh_send_task\` for a new task, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
|
|
25832
|
+
- **Avoid context-wasting restarts.** For follow-up, retry, commit/push, preview, or cleanup work on the same issue, prefer the existing idle session and send only the delta from its last verified state. Start a fresh chat/session only for genuinely independent work, explicit provider/user request, unsafe transcript contamination, or required branch/worktree isolation.
|
|
25802
25833
|
- **Don't inspect code.** Treat delegated agent summaries as self-reports, not verification. Verify side effects via \`mesh_git_status\` (including related repo freshness when configured), not by reading source files.
|
|
25803
25834
|
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed. Never launch a duplicate session or second worker solely because \`mesh_read_chat\` has no final assistant message while the delegated session is still showing tool/terminal activity.
|
|
25804
25835
|
- **Handle failures with context.** If a task fails, check \`mesh_task_history\` first to see if this task was attempted before and how it failed. Read the chat to understand why, then decide: retry on the same node, reassign to a different node, or escalate to the user.
|
|
@@ -26091,6 +26122,19 @@ function updateTaskStatus(meshId, taskId, status) {
|
|
|
26091
26122
|
writeQueue(meshId, queue);
|
|
26092
26123
|
return queue[idx];
|
|
26093
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
|
+
}
|
|
26094
26138
|
function cancelTask(meshId, taskId, opts) {
|
|
26095
26139
|
const queue = readQueue(meshId);
|
|
26096
26140
|
const idx = queue.findIndex((q) => q.id === taskId);
|
|
@@ -26153,6 +26197,129 @@ function getMeshQueueStats(meshId) {
|
|
|
26153
26197
|
}))
|
|
26154
26198
|
};
|
|
26155
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
|
+
}
|
|
26156
26323
|
function setLogLevel(level) {
|
|
26157
26324
|
currentLevel = level;
|
|
26158
26325
|
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
@@ -26167,13 +26334,13 @@ function getDaemonLogDir() {
|
|
|
26167
26334
|
return LOG_DIR;
|
|
26168
26335
|
}
|
|
26169
26336
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
26170
|
-
return
|
|
26337
|
+
return path9.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
26171
26338
|
}
|
|
26172
26339
|
function checkDateRotation() {
|
|
26173
26340
|
const today = getDateStr();
|
|
26174
26341
|
if (today !== currentDate) {
|
|
26175
26342
|
currentDate = today;
|
|
26176
|
-
currentLogFile =
|
|
26343
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
26177
26344
|
cleanOldLogs();
|
|
26178
26345
|
}
|
|
26179
26346
|
}
|
|
@@ -26187,7 +26354,7 @@ function cleanOldLogs() {
|
|
|
26187
26354
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
26188
26355
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
26189
26356
|
try {
|
|
26190
|
-
fs2.unlinkSync(
|
|
26357
|
+
fs2.unlinkSync(path9.join(LOG_DIR, file2));
|
|
26191
26358
|
} catch {
|
|
26192
26359
|
}
|
|
26193
26360
|
}
|
|
@@ -26362,7 +26529,235 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
26362
26529
|
});
|
|
26363
26530
|
return true;
|
|
26364
26531
|
}
|
|
26365
|
-
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) {
|
|
26366
26761
|
const mesh = getMeshWithCache(components, meshId);
|
|
26367
26762
|
if (!mesh) return;
|
|
26368
26763
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
@@ -26373,9 +26768,7 @@ function triggerMeshQueue(components, meshId) {
|
|
|
26373
26768
|
if (instMeshId !== meshId) continue;
|
|
26374
26769
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
26375
26770
|
if (!nodeId) continue;
|
|
26376
|
-
|
|
26377
|
-
if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
|
|
26378
|
-
if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
|
|
26771
|
+
if (!isIdleSessionState(state)) continue;
|
|
26379
26772
|
const sessionId = state.instanceId;
|
|
26380
26773
|
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
26381
26774
|
if (providerType) {
|
|
@@ -26391,6 +26784,7 @@ function triggerMeshQueue(components, meshId) {
|
|
|
26391
26784
|
}
|
|
26392
26785
|
}
|
|
26393
26786
|
}
|
|
26787
|
+
await maybeAutoLaunchOneQueueSession(components, meshId, mesh);
|
|
26394
26788
|
}
|
|
26395
26789
|
function buildMeshSystemMessage(args) {
|
|
26396
26790
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
@@ -26898,7 +27292,7 @@ function findBinary(name) {
|
|
|
26898
27292
|
const isWin = os9.platform() === "win32";
|
|
26899
27293
|
try {
|
|
26900
27294
|
const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
|
|
26901
|
-
return (0,
|
|
27295
|
+
return (0, import_child_process3.execSync)(cmd, {
|
|
26902
27296
|
encoding: "utf-8",
|
|
26903
27297
|
timeout: 5e3,
|
|
26904
27298
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -27273,7 +27667,7 @@ async function validateWorkspace(workspace) {
|
|
|
27273
27667
|
cwd: normalizedWorkspace
|
|
27274
27668
|
});
|
|
27275
27669
|
}
|
|
27276
|
-
await (0, import_promises5.access)(normalizedWorkspace,
|
|
27670
|
+
await (0, import_promises5.access)(normalizedWorkspace, import_fs9.constants.R_OK);
|
|
27277
27671
|
} catch (error48) {
|
|
27278
27672
|
if (error48 instanceof GitCommandError) throw error48;
|
|
27279
27673
|
throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
|
|
@@ -28786,6 +29180,86 @@ async function syncMeshLedger(meshId, transport) {
|
|
|
28786
29180
|
appendRemoteLedgerEntries2(meshId, res.missingEntries);
|
|
28787
29181
|
}
|
|
28788
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
|
+
}
|
|
28789
29263
|
function isPlainObject22(value) {
|
|
28790
29264
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
28791
29265
|
}
|
|
@@ -28826,11 +29300,11 @@ function normalizeState(raw) {
|
|
|
28826
29300
|
}
|
|
28827
29301
|
function loadState() {
|
|
28828
29302
|
const statePath = getStatePath();
|
|
28829
|
-
if (!(0,
|
|
29303
|
+
if (!(0, import_fs10.existsSync)(statePath)) {
|
|
28830
29304
|
return { ...DEFAULT_STATE };
|
|
28831
29305
|
}
|
|
28832
29306
|
try {
|
|
28833
|
-
const raw = (0,
|
|
29307
|
+
const raw = (0, import_fs10.readFileSync)(statePath, "utf-8");
|
|
28834
29308
|
return normalizeState(JSON.parse(raw));
|
|
28835
29309
|
} catch {
|
|
28836
29310
|
return { ...DEFAULT_STATE };
|
|
@@ -28839,7 +29313,7 @@ function loadState() {
|
|
|
28839
29313
|
function saveState(state) {
|
|
28840
29314
|
const statePath = getStatePath();
|
|
28841
29315
|
const normalized = normalizeState(state);
|
|
28842
|
-
(0,
|
|
29316
|
+
(0, import_fs10.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
28843
29317
|
}
|
|
28844
29318
|
function resetState() {
|
|
28845
29319
|
saveState({ ...DEFAULT_STATE });
|
|
@@ -28860,13 +29334,13 @@ function getMergedDefinitions() {
|
|
|
28860
29334
|
function findCliCommand(command) {
|
|
28861
29335
|
const trimmed = String(command || "").trim();
|
|
28862
29336
|
if (!trimmed) return null;
|
|
28863
|
-
if (
|
|
28864
|
-
const candidate = trimmed.startsWith("~") ?
|
|
28865
|
-
const resolved =
|
|
28866
|
-
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;
|
|
28867
29341
|
}
|
|
28868
29342
|
try {
|
|
28869
|
-
const result = (0,
|
|
29343
|
+
const result = (0, import_child_process5.execSync)(
|
|
28870
29344
|
(0, import_os3.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
|
|
28871
29345
|
{ encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
|
|
28872
29346
|
).trim();
|
|
@@ -28877,7 +29351,7 @@ function findCliCommand(command) {
|
|
|
28877
29351
|
}
|
|
28878
29352
|
function getIdeVersion(cliCommand) {
|
|
28879
29353
|
try {
|
|
28880
|
-
const result = (0,
|
|
29354
|
+
const result = (0, import_child_process5.execSync)(`"${cliCommand}" --version`, {
|
|
28881
29355
|
encoding: "utf-8",
|
|
28882
29356
|
timeout: 1e4,
|
|
28883
29357
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -28890,13 +29364,13 @@ function getIdeVersion(cliCommand) {
|
|
|
28890
29364
|
function checkPathExists(paths) {
|
|
28891
29365
|
const home = (0, import_os3.homedir)();
|
|
28892
29366
|
for (const p of paths) {
|
|
28893
|
-
const normalized = p.startsWith("~") ?
|
|
29367
|
+
const normalized = p.startsWith("~") ? path10.join(home, p.slice(1)) : p;
|
|
28894
29368
|
if (normalized.includes("*")) {
|
|
28895
29369
|
const username = home.split(/[\\/]/).pop() || "";
|
|
28896
29370
|
const resolved = normalized.replace("*", username);
|
|
28897
|
-
if ((0,
|
|
29371
|
+
if ((0, import_fs11.existsSync)(resolved)) return resolved;
|
|
28898
29372
|
} else {
|
|
28899
|
-
if ((0,
|
|
29373
|
+
if ((0, import_fs11.existsSync)(normalized)) return normalized;
|
|
28900
29374
|
}
|
|
28901
29375
|
}
|
|
28902
29376
|
return null;
|
|
@@ -28910,7 +29384,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28910
29384
|
let resolvedCli = cliPath;
|
|
28911
29385
|
if (!resolvedCli && appPath && os222 === "darwin") {
|
|
28912
29386
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
28913
|
-
if ((0,
|
|
29387
|
+
if ((0, import_fs11.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
28914
29388
|
}
|
|
28915
29389
|
if (!resolvedCli && appPath && os222 === "win32") {
|
|
28916
29390
|
const { dirname: dirname92 } = await import("path");
|
|
@@ -28923,7 +29397,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28923
29397
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
28924
29398
|
];
|
|
28925
29399
|
for (const c of candidates) {
|
|
28926
|
-
if ((0,
|
|
29400
|
+
if ((0, import_fs11.existsSync)(c)) {
|
|
28927
29401
|
resolvedCli = c;
|
|
28928
29402
|
break;
|
|
28929
29403
|
}
|
|
@@ -28944,129 +29418,6 @@ async function detectIDEs(providerLoader) {
|
|
|
28944
29418
|
}
|
|
28945
29419
|
return results;
|
|
28946
29420
|
}
|
|
28947
|
-
function parseVersion(raw) {
|
|
28948
|
-
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
28949
|
-
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
28950
|
-
}
|
|
28951
|
-
function shellQuote(value) {
|
|
28952
|
-
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
28953
|
-
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
28954
|
-
}
|
|
28955
|
-
function expandHome(value) {
|
|
28956
|
-
const trimmed = value.trim();
|
|
28957
|
-
if (!trimmed.startsWith("~")) return trimmed;
|
|
28958
|
-
return path10.join(os32.homedir(), trimmed.slice(1));
|
|
28959
|
-
}
|
|
28960
|
-
function isExplicitCommandPath(command) {
|
|
28961
|
-
const trimmed = command.trim();
|
|
28962
|
-
return path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
28963
|
-
}
|
|
28964
|
-
function resolveCommandPath(command) {
|
|
28965
|
-
const trimmed = command.trim();
|
|
28966
|
-
if (!trimmed) return null;
|
|
28967
|
-
if (isExplicitCommandPath(trimmed)) {
|
|
28968
|
-
const expanded = expandHome(trimmed);
|
|
28969
|
-
const candidate = path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
|
|
28970
|
-
return (0, import_fs11.existsSync)(candidate) ? candidate : null;
|
|
28971
|
-
}
|
|
28972
|
-
return null;
|
|
28973
|
-
}
|
|
28974
|
-
function execAsync(cmd, timeoutMs = 5e3) {
|
|
28975
|
-
return new Promise((resolve162) => {
|
|
28976
|
-
const child = (0, import_child_process5.exec)(cmd, {
|
|
28977
|
-
encoding: "utf-8",
|
|
28978
|
-
timeout: timeoutMs,
|
|
28979
|
-
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
28980
|
-
}, (err, stdout) => {
|
|
28981
|
-
if (err || !stdout?.trim()) {
|
|
28982
|
-
resolve162(null);
|
|
28983
|
-
} else {
|
|
28984
|
-
resolve162(stdout.trim());
|
|
28985
|
-
}
|
|
28986
|
-
});
|
|
28987
|
-
child.on("error", () => resolve162(null));
|
|
28988
|
-
});
|
|
28989
|
-
}
|
|
28990
|
-
async function detectCLIs(providerLoader, options) {
|
|
28991
|
-
const platform10 = os32.platform();
|
|
28992
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
28993
|
-
const includeVersion = options?.includeVersion !== false;
|
|
28994
|
-
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
28995
|
-
const results = await Promise.all(
|
|
28996
|
-
cliList.map(async (cli) => {
|
|
28997
|
-
try {
|
|
28998
|
-
const explicitPath = resolveCommandPath(cli.command);
|
|
28999
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
29000
|
-
if (!pathResult) return { ...cli, installed: false };
|
|
29001
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29002
|
-
let version2;
|
|
29003
|
-
if (includeVersion) {
|
|
29004
|
-
const versionCommands = [
|
|
29005
|
-
`"${firstPath}" --version`,
|
|
29006
|
-
`"${firstPath}" -V`,
|
|
29007
|
-
`"${firstPath}" -v`,
|
|
29008
|
-
cli.versionCommand
|
|
29009
|
-
].filter((v) => !!v);
|
|
29010
|
-
try {
|
|
29011
|
-
for (const versionCommand of versionCommands) {
|
|
29012
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29013
|
-
if (versionResult) {
|
|
29014
|
-
version2 = parseVersion(versionResult);
|
|
29015
|
-
break;
|
|
29016
|
-
}
|
|
29017
|
-
}
|
|
29018
|
-
} catch {
|
|
29019
|
-
}
|
|
29020
|
-
}
|
|
29021
|
-
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
29022
|
-
} catch {
|
|
29023
|
-
return { ...cli, installed: false };
|
|
29024
|
-
}
|
|
29025
|
-
})
|
|
29026
|
-
);
|
|
29027
|
-
return results;
|
|
29028
|
-
}
|
|
29029
|
-
async function detectCLI(cliId, providerLoader, options) {
|
|
29030
|
-
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
29031
|
-
if (providerLoader) {
|
|
29032
|
-
const cliList = providerLoader.getCliDetectionList();
|
|
29033
|
-
const target = cliList.find((c) => c.id === resolvedId);
|
|
29034
|
-
if (target) {
|
|
29035
|
-
const platform10 = os32.platform();
|
|
29036
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
29037
|
-
try {
|
|
29038
|
-
const explicitPath = resolveCommandPath(target.command);
|
|
29039
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
29040
|
-
if (!pathResult) return null;
|
|
29041
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29042
|
-
let version2;
|
|
29043
|
-
if (options?.includeVersion !== false) {
|
|
29044
|
-
const versionCommands = [
|
|
29045
|
-
`"${firstPath}" --version`,
|
|
29046
|
-
`"${firstPath}" -V`,
|
|
29047
|
-
`"${firstPath}" -v`,
|
|
29048
|
-
target.versionCommand
|
|
29049
|
-
].filter((v) => !!v);
|
|
29050
|
-
try {
|
|
29051
|
-
for (const versionCommand of versionCommands) {
|
|
29052
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29053
|
-
if (versionResult) {
|
|
29054
|
-
version2 = parseVersion(versionResult);
|
|
29055
|
-
break;
|
|
29056
|
-
}
|
|
29057
|
-
}
|
|
29058
|
-
} catch {
|
|
29059
|
-
}
|
|
29060
|
-
}
|
|
29061
|
-
return { ...target, installed: true, version: version2, path: firstPath };
|
|
29062
|
-
} catch {
|
|
29063
|
-
return null;
|
|
29064
|
-
}
|
|
29065
|
-
}
|
|
29066
|
-
}
|
|
29067
|
-
const all = await detectCLIs(providerLoader, options);
|
|
29068
|
-
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
29069
|
-
}
|
|
29070
29421
|
function parseDarwinAvailableBytes(totalMem) {
|
|
29071
29422
|
if (os42.platform() !== "darwin") return null;
|
|
29072
29423
|
try {
|
|
@@ -36588,6 +36939,204 @@ async function resolveProviderTypeFromPriority(args) {
|
|
|
36588
36939
|
}
|
|
36589
36940
|
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
|
|
36590
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
|
+
}
|
|
36591
37140
|
function loadYamlModule() {
|
|
36592
37141
|
return js_yaml_exports;
|
|
36593
37142
|
}
|
|
@@ -41135,7 +41684,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
41135
41684
|
}
|
|
41136
41685
|
cdpManagers.clear();
|
|
41137
41686
|
}
|
|
41138
|
-
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;
|
|
41139
41688
|
var init_dist2 = __esm({
|
|
41140
41689
|
"../daemon-core/dist/index.mjs"() {
|
|
41141
41690
|
"use strict";
|
|
@@ -41158,20 +41707,24 @@ var init_dist2 = __esm({
|
|
|
41158
41707
|
import_fs7 = require("fs");
|
|
41159
41708
|
import_path4 = require("path");
|
|
41160
41709
|
import_crypto5 = require("crypto");
|
|
41161
|
-
|
|
41162
|
-
path8 = __toESM(require("path"), 1);
|
|
41710
|
+
import_child_process2 = require("child_process");
|
|
41163
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);
|
|
41164
41717
|
init_dist();
|
|
41165
41718
|
os8 = __toESM(require("os"), 1);
|
|
41166
41719
|
os9 = __toESM(require("os"), 1);
|
|
41167
41720
|
path14 = __toESM(require("path"), 1);
|
|
41168
|
-
|
|
41721
|
+
import_child_process3 = require("child_process");
|
|
41169
41722
|
os10 = __toESM(require("os"), 1);
|
|
41170
41723
|
path15 = __toESM(require("path"), 1);
|
|
41171
41724
|
init_dist();
|
|
41172
41725
|
os11 = __toESM(require("os"), 1);
|
|
41173
|
-
|
|
41174
|
-
|
|
41726
|
+
import_child_process4 = require("child_process");
|
|
41727
|
+
import_fs9 = require("fs");
|
|
41175
41728
|
import_promises5 = require("fs/promises");
|
|
41176
41729
|
path = __toESM(require("path"), 1);
|
|
41177
41730
|
import_util4 = require("util");
|
|
@@ -41184,16 +41737,12 @@ var init_dist2 = __esm({
|
|
|
41184
41737
|
import_crypto6 = require("crypto");
|
|
41185
41738
|
path6 = __toESM(require("path"), 1);
|
|
41186
41739
|
path7 = __toESM(require("path"), 1);
|
|
41187
|
-
import_fs9 = require("fs");
|
|
41188
|
-
import_path5 = require("path");
|
|
41189
|
-
import_child_process4 = require("child_process");
|
|
41190
41740
|
import_fs10 = require("fs");
|
|
41191
|
-
|
|
41192
|
-
path9 = __toESM(require("path"), 1);
|
|
41741
|
+
import_path5 = require("path");
|
|
41193
41742
|
import_child_process5 = require("child_process");
|
|
41194
|
-
os32 = __toESM(require("os"), 1);
|
|
41195
|
-
path10 = __toESM(require("path"), 1);
|
|
41196
41743
|
import_fs11 = require("fs");
|
|
41744
|
+
import_os3 = require("os");
|
|
41745
|
+
path10 = __toESM(require("path"), 1);
|
|
41197
41746
|
os42 = __toESM(require("os"), 1);
|
|
41198
41747
|
import_child_process6 = require("child_process");
|
|
41199
41748
|
init_wrapper();
|
|
@@ -41326,6 +41875,7 @@ var init_dist2 = __esm({
|
|
|
41326
41875
|
WORKTREE_DIR_NAME = ".adhdev-worktrees";
|
|
41327
41876
|
GIT_TIMEOUT_MS = 3e4;
|
|
41328
41877
|
GIT_MAX_BUFFER = 4 * 1024 * 1024;
|
|
41878
|
+
SUBMODULE_WORKTREE_REMOVE_RE = /working trees containing submodules cannot be moved or removed/i;
|
|
41329
41879
|
}
|
|
41330
41880
|
});
|
|
41331
41881
|
config_exports = {};
|
|
@@ -41405,18 +41955,24 @@ var init_dist2 = __esm({
|
|
|
41405
41955
|
|
|
41406
41956
|
| Tool | Purpose |
|
|
41407
41957
|
|------|---------|
|
|
41408
|
-
| \`mesh_status\` | Check all nodes' health, git state,
|
|
41958
|
+
| \`mesh_status\` | Check all nodes' health, git state, active sessions, and branch convergence |
|
|
41409
41959
|
| \`mesh_list_nodes\` | List nodes with workspace paths |
|
|
41960
|
+
| \`mesh_enqueue_task\` | Add a task to the pull-based work queue; idle nodes auto-claim |
|
|
41961
|
+
| \`mesh_view_queue\` | View queue status \u2014 pending, assigned, completed, failed, cancelled tasks |
|
|
41962
|
+
| \`mesh_queue_cancel\` | Cancel a queue task without deleting audit history |
|
|
41963
|
+
| \`mesh_queue_requeue\` | Return a task to pending for retry; clears stale session targets |
|
|
41964
|
+
| \`mesh_send_task\` | Legacy push: enqueue a task targeted at a specific node |
|
|
41410
41965
|
| \`mesh_launch_session\` | Start a new agent session on a node |
|
|
41411
|
-
| \`
|
|
41412
|
-
| \`
|
|
41966
|
+
| \`mesh_read_chat\` | Read recent chat messages from a delegated agent session |
|
|
41967
|
+
| \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
|
|
41413
41968
|
| \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
|
|
41414
41969
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
41415
41970
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
41416
41971
|
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
41417
41972
|
| \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
|
|
41418
41973
|
| \`mesh_refine_node\` | Validate and merge a completed worktree node back into its base branch |
|
|
41419
|
-
| \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable)
|
|
41974
|
+
| \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |
|
|
41975
|
+
| \`mesh_cleanup_sessions\` | Manually clean up delegated session records for a node |`;
|
|
41420
41976
|
TOOL_EXPOSURE_PREFLIGHT_SECTION = `## Tool Exposure Preflight
|
|
41421
41977
|
|
|
41422
41978
|
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\`.`;
|
|
@@ -41426,9 +41982,10 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
41426
41982
|
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist. If \`mesh_task_history\` shows a recent failure for a task, decide whether to retry or reassign.
|
|
41427
41983
|
3. **Queue / Delegate** \u2014 The Mesh uses an autonomous pull-based Work Queue:
|
|
41428
41984
|
a. **General Tasks**: Enqueue tasks using \`mesh_enqueue_task\`. Idle node agents will automatically pull tasks from the queue and begin working.
|
|
41429
|
-
b. **Node Preparation**: Call \`mesh_launch_session\`
|
|
41985
|
+
b. **Node Preparation**: Reuse an existing idle session on the correct node/provider before launching a new chat/session. Call \`mesh_launch_session\` only when no suitable session exists, when the user explicitly asks for a fresh provider/session, or when branch/worktree isolation requires it. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
41430
41986
|
c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
|
|
41431
|
-
d.
|
|
41987
|
+
d. For the first dispatch of a new task, provide a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
|
|
41988
|
+
e. For a continuation of the same issue in an existing session, send a concise **delta instruction**: current verified state, the exact failed/blocked step, the newly approved action, and final reporting requirements. Do not resend the full original task or open a new chat solely to continue the same work; that wastes coordinator and worker context.
|
|
41432
41989
|
4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Use \`mesh_view_queue\` to see the status of all pending, assigned, completed, and failed tasks. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal. Handle approvals via \`mesh_approve\`.
|
|
41433
41990
|
5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
|
|
41434
41991
|
6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
|
|
@@ -41444,7 +42001,7 @@ When a node agent stops unexpectedly, the daemon automatically enriches the syst
|
|
|
41444
42001
|
- A recommendation: **retry**, **reassign**, or **escalate**
|
|
41445
42002
|
|
|
41446
42003
|
Follow these recovery rules:
|
|
41447
|
-
1. **If "Retry recommended"**:
|
|
42004
|
+
1. **If "Retry recommended"**: Check \`mesh_view_queue\` first \u2014 the daemon may have auto-requeued. If not, re-launch the session on the same node (\`mesh_launch_session\`), then resend the original task (\`mesh_send_task\`). The system message includes the original task text.
|
|
41448
42005
|
2. **If "Max retries exceeded"**: Do NOT retry on the same node. Either reassign the task to a different node, or inform the user that the task requires manual intervention.
|
|
41449
42006
|
3. **If no recovery context**: The stop may be intentional (normal completion). Use \`mesh_read_chat\` once to verify, then move on.
|
|
41450
42007
|
4. **Always record what happened**: After handling a failure, briefly note the outcome in your report to the user.`;
|
|
@@ -41477,6 +42034,7 @@ Follow these recovery rules:
|
|
|
41477
42034
|
enqueueTask: () => enqueueTask,
|
|
41478
42035
|
getMeshQueueStats: () => getMeshQueueStats,
|
|
41479
42036
|
getQueue: () => getQueue,
|
|
42037
|
+
recordTaskAutoLaunch: () => recordTaskAutoLaunch,
|
|
41480
42038
|
requeueTask: () => requeueTask,
|
|
41481
42039
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
41482
42040
|
updateTaskStatus: () => updateTaskStatus
|
|
@@ -41487,13 +42045,18 @@ Follow these recovery rules:
|
|
|
41487
42045
|
init_mesh_ledger();
|
|
41488
42046
|
}
|
|
41489
42047
|
});
|
|
42048
|
+
init_cli_detector = __esm2({
|
|
42049
|
+
"src/detection/cli-detector.ts"() {
|
|
42050
|
+
"use strict";
|
|
42051
|
+
}
|
|
42052
|
+
});
|
|
41490
42053
|
init_logger = __esm2({
|
|
41491
42054
|
"src/logging/logger.ts"() {
|
|
41492
42055
|
"use strict";
|
|
41493
42056
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
41494
42057
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
41495
42058
|
currentLevel = "info";
|
|
41496
|
-
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");
|
|
41497
42060
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
41498
42061
|
MAX_LOG_DAYS = 7;
|
|
41499
42062
|
try {
|
|
@@ -41501,16 +42064,16 @@ Follow these recovery rules:
|
|
|
41501
42064
|
} catch {
|
|
41502
42065
|
}
|
|
41503
42066
|
currentDate = getDateStr();
|
|
41504
|
-
currentLogFile =
|
|
42067
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
41505
42068
|
cleanOldLogs();
|
|
41506
42069
|
try {
|
|
41507
|
-
const oldLog =
|
|
42070
|
+
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
41508
42071
|
if (fs2.existsSync(oldLog)) {
|
|
41509
42072
|
const stat22 = fs2.statSync(oldLog);
|
|
41510
42073
|
const oldDate = stat22.mtime.toISOString().slice(0, 10);
|
|
41511
|
-
fs2.renameSync(oldLog,
|
|
42074
|
+
fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
41512
42075
|
}
|
|
41513
|
-
const oldLogBackup =
|
|
42076
|
+
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
41514
42077
|
if (fs2.existsSync(oldLogBackup)) {
|
|
41515
42078
|
fs2.unlinkSync(oldLogBackup);
|
|
41516
42079
|
}
|
|
@@ -41542,7 +42105,7 @@ Follow these recovery rules:
|
|
|
41542
42105
|
}
|
|
41543
42106
|
};
|
|
41544
42107
|
interceptorInstalled = false;
|
|
41545
|
-
LOG_PATH =
|
|
42108
|
+
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
41546
42109
|
}
|
|
41547
42110
|
});
|
|
41548
42111
|
mesh_events_exports = {};
|
|
@@ -41556,7 +42119,9 @@ Follow these recovery rules:
|
|
|
41556
42119
|
init_mesh_events = __esm2({
|
|
41557
42120
|
"src/mesh/mesh-events.ts"() {
|
|
41558
42121
|
"use strict";
|
|
42122
|
+
init_config();
|
|
41559
42123
|
init_mesh_config();
|
|
42124
|
+
init_cli_detector();
|
|
41560
42125
|
init_logger();
|
|
41561
42126
|
init_mesh_ledger();
|
|
41562
42127
|
init_mesh_work_queue();
|
|
@@ -41577,6 +42142,9 @@ Follow these recovery rules:
|
|
|
41577
42142
|
"agent:stopped": "task_failed",
|
|
41578
42143
|
"monitor:long_generating": "task_stalled"
|
|
41579
42144
|
};
|
|
42145
|
+
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
42146
|
+
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
42147
|
+
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
41580
42148
|
}
|
|
41581
42149
|
});
|
|
41582
42150
|
init_debug_config = __esm2({
|
|
@@ -44070,7 +44638,7 @@ ${lastSnapshot}`;
|
|
|
44070
44638
|
}
|
|
44071
44639
|
});
|
|
44072
44640
|
init_repo_mesh_types();
|
|
44073
|
-
execFileAsync = (0, import_util4.promisify)(
|
|
44641
|
+
execFileAsync = (0, import_util4.promisify)(import_child_process4.execFile);
|
|
44074
44642
|
DEFAULT_TIMEOUT_MS = 5e3;
|
|
44075
44643
|
DEFAULT_MAX_BUFFER = 1024 * 1024;
|
|
44076
44644
|
GitCommandError = class extends Error {
|
|
@@ -44329,6 +44897,34 @@ ${lastSnapshot}`;
|
|
|
44329
44897
|
init_mesh_ledger();
|
|
44330
44898
|
init_mesh_work_queue();
|
|
44331
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
|
+
};
|
|
44332
44928
|
init_config();
|
|
44333
44929
|
DEFAULT_STATE = {
|
|
44334
44930
|
recentActivity: [],
|
|
@@ -44340,6 +44936,7 @@ ${lastSnapshot}`;
|
|
|
44340
44936
|
};
|
|
44341
44937
|
BUILTIN_IDE_DEFINITIONS = [];
|
|
44342
44938
|
registeredIDEs = /* @__PURE__ */ new Map();
|
|
44939
|
+
init_cli_detector();
|
|
44343
44940
|
LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
44344
44941
|
DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
44345
44942
|
"generating",
|
|
@@ -48071,6 +48668,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
48071
48668
|
}
|
|
48072
48669
|
};
|
|
48073
48670
|
init_provider_cli_adapter();
|
|
48671
|
+
init_cli_detector();
|
|
48074
48672
|
init_config();
|
|
48075
48673
|
init_provider_cli_adapter();
|
|
48076
48674
|
init_logger();
|
|
@@ -52422,6 +53020,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52422
53020
|
};
|
|
52423
53021
|
_providerLoader = null;
|
|
52424
53022
|
init_config();
|
|
53023
|
+
init_cli_detector();
|
|
52425
53024
|
init_logger();
|
|
52426
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");
|
|
52427
53026
|
MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
@@ -52470,6 +53069,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52470
53069
|
stable: "https://api.adhf.dev",
|
|
52471
53070
|
preview: "https://api-preview.adhf.dev"
|
|
52472
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;
|
|
52473
53077
|
CHAT_COMMANDS = [
|
|
52474
53078
|
"send_chat",
|
|
52475
53079
|
"new_chat",
|
|
@@ -52602,20 +53206,98 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52602
53206
|
recoveryHint: "Inspect the worktree branch and mesh metadata before retrying cleanup."
|
|
52603
53207
|
};
|
|
52604
53208
|
}
|
|
53209
|
+
const forceFallbackConvergence = await this.getWorktreeForceCleanupConvergence({
|
|
53210
|
+
repoRoot,
|
|
53211
|
+
workspace,
|
|
53212
|
+
node: args.node
|
|
53213
|
+
});
|
|
52605
53214
|
try {
|
|
52606
|
-
const result = await removeWorktree2(repoRoot, workspace, {
|
|
52607
|
-
|
|
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
|
+
};
|
|
52608
53230
|
} catch (e) {
|
|
52609
53231
|
const message = String(e?.message || e || "worktree cleanup failed");
|
|
52610
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;
|
|
52611
53234
|
return {
|
|
52612
53235
|
success: false,
|
|
52613
|
-
code: dirty ? "mesh_worktree_cleanup_dirty" : "mesh_worktree_cleanup_failed",
|
|
52614
|
-
error: message,
|
|
52615
|
-
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 } : {}
|
|
52616
53240
|
};
|
|
52617
53241
|
}
|
|
52618
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
|
+
}
|
|
52619
53301
|
isCompletedHostedSession(record2) {
|
|
52620
53302
|
return record2?.lifecycle === "stopped" || record2?.lifecycle === "failed" || record2?.lifecycle === "interrupted";
|
|
52621
53303
|
}
|
|
@@ -53575,10 +54257,61 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53575
54257
|
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
53576
54258
|
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
53577
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
|
+
}
|
|
53578
54299
|
try {
|
|
53579
54300
|
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
53580
54301
|
} catch (e) {
|
|
53581
|
-
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
|
+
};
|
|
53582
54315
|
}
|
|
53583
54316
|
const removeResult = await this.execute("remove_mesh_node", {
|
|
53584
54317
|
meshId,
|
|
@@ -53591,11 +54324,27 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53591
54324
|
appendLedgerEntry2(meshId, {
|
|
53592
54325
|
kind: "node_removed",
|
|
53593
54326
|
nodeId,
|
|
53594
|
-
payload: { refined: true, mergedBranch: branch, into: baseBranch }
|
|
54327
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
|
|
53595
54328
|
});
|
|
53596
54329
|
} catch {
|
|
53597
54330
|
}
|
|
53598
|
-
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
|
+
};
|
|
53599
54348
|
} catch (e) {
|
|
53600
54349
|
return { success: false, error: e.message };
|
|
53601
54350
|
}
|
|
@@ -53650,7 +54399,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53650
54399
|
sessionCleanupMode,
|
|
53651
54400
|
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
53652
54401
|
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
53653
|
-
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
|
|
53654
54406
|
}
|
|
53655
54407
|
});
|
|
53656
54408
|
} catch {
|
|
@@ -57547,6 +58299,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
57547
58299
|
apiKeyName: "OpenAI/Anthropic API key"
|
|
57548
58300
|
}
|
|
57549
58301
|
];
|
|
58302
|
+
init_cli_detector();
|
|
57550
58303
|
SessionRegistry = class {
|
|
57551
58304
|
bySessionId = /* @__PURE__ */ new Map();
|
|
57552
58305
|
byManagerKey = /* @__PURE__ */ new Map();
|
|
@@ -58032,16 +58785,38 @@ function extractLaunchPayload(value) {
|
|
|
58032
58785
|
function classifyMeshLaunchFailure(error48) {
|
|
58033
58786
|
const message = error48 instanceof Error ? error48.message : String(error48 || "launch failed");
|
|
58034
58787
|
const lower = message.toLowerCase();
|
|
58035
|
-
|
|
58036
|
-
|
|
58788
|
+
const p2pClassification = classifyP2pRelayFailure(error48, { command: "launch_cli" });
|
|
58789
|
+
if (p2pClassification.recoverable) {
|
|
58790
|
+
return p2pClassification;
|
|
58037
58791
|
}
|
|
58038
58792
|
if (lower.includes("cannot connect to daemon ipc") || lower.includes("daemon ipc command")) {
|
|
58039
|
-
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
|
+
};
|
|
58040
58801
|
}
|
|
58041
58802
|
if (lower.includes("timed out") || lower.includes("timeout")) {
|
|
58042
|
-
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
|
+
};
|
|
58043
58811
|
}
|
|
58044
|
-
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
|
+
};
|
|
58045
58820
|
}
|
|
58046
58821
|
function buildWorktreeCleanupHint(node) {
|
|
58047
58822
|
if (!node.isLocalWorktree) return void 0;
|
|
@@ -58057,10 +58832,13 @@ function buildRecoverableLaunchFailure(ctx, node, providerType, error48) {
|
|
|
58057
58832
|
const cleanup = buildWorktreeCleanupHint(node);
|
|
58058
58833
|
return {
|
|
58059
58834
|
success: false,
|
|
58060
|
-
recoverable:
|
|
58835
|
+
recoverable: classified.recoverable,
|
|
58061
58836
|
code: classified.code,
|
|
58062
58837
|
reason: classified.reason,
|
|
58063
58838
|
transport: classified.transport,
|
|
58839
|
+
retryRecommended: classified.retryRecommended,
|
|
58840
|
+
nextAction: classified.nextAction,
|
|
58841
|
+
...classified.noFallbackReason ? { noFallbackReason: classified.noFallbackReason } : {},
|
|
58064
58842
|
error: message,
|
|
58065
58843
|
meshId: ctx.mesh.id,
|
|
58066
58844
|
nodeId: node.id,
|
|
@@ -58107,6 +58885,18 @@ function getLatestActiveLaunchFailure(meshId, nodeId) {
|
|
|
58107
58885
|
}
|
|
58108
58886
|
return null;
|
|
58109
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
|
+
}
|
|
58110
58900
|
async function ipcDispatchToRemoteAgent(ctx, node, args) {
|
|
58111
58901
|
const transport = ctx.transport;
|
|
58112
58902
|
const daemonId = node.daemonId;
|
|
@@ -58142,11 +58932,32 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
|
|
|
58142
58932
|
});
|
|
58143
58933
|
const dispatchPayload = unwrapCommandPayload(dispatchResult);
|
|
58144
58934
|
if (dispatchPayload?.success === false || dispatchResult?.success === false) {
|
|
58145
|
-
|
|
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
|
+
};
|
|
58146
58948
|
}
|
|
58147
58949
|
return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType };
|
|
58148
58950
|
} catch (e) {
|
|
58149
|
-
|
|
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
|
+
};
|
|
58150
58961
|
}
|
|
58151
58962
|
}
|
|
58152
58963
|
function resolveCoordinatorNode(ctx) {
|
|
@@ -58391,8 +59202,7 @@ async function commandForNode(ctx, node, command, args = {}) {
|
|
|
58391
59202
|
throw new Error(`Command '${command}' requires daemon IPC/local transport for node '${node.id}'`);
|
|
58392
59203
|
}
|
|
58393
59204
|
function isP2pTransportUnavailableError(error48) {
|
|
58394
|
-
|
|
58395
|
-
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);
|
|
58396
59206
|
}
|
|
58397
59207
|
function buildRemoveNodeArgs(ctx, nodeId, sessionCleanupMode) {
|
|
58398
59208
|
return {
|
|
@@ -58985,7 +59795,13 @@ async function meshSendTask(ctx, args) {
|
|
|
58985
59795
|
}
|
|
58986
59796
|
return JSON.stringify({ success: true, nodeId: args.node_id, taskId: task.id, status: task.status });
|
|
58987
59797
|
} catch (e) {
|
|
58988
|
-
|
|
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);
|
|
58989
59805
|
}
|
|
58990
59806
|
}
|
|
58991
59807
|
async function meshReadChat(ctx, args) {
|