@adhdev/daemon-standalone 0.9.77-rc.44 → 0.9.77-rc.46
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 -179
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +1121 -200
- 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
|
}
|
|
@@ -25473,7 +25503,8 @@ function ensureMachineId(config2) {
|
|
|
25473
25503
|
};
|
|
25474
25504
|
}
|
|
25475
25505
|
function getConfigDir() {
|
|
25476
|
-
const
|
|
25506
|
+
const override = process.env.ADHDEV_CONFIG_DIR;
|
|
25507
|
+
const dir = override && override.trim() ? override.trim() : (0, import_path.join)((0, import_os2.homedir)(), ".adhdev");
|
|
25477
25508
|
if (!(0, import_fs4.existsSync)(dir)) {
|
|
25478
25509
|
(0, import_fs4.mkdirSync)(dir, { recursive: true });
|
|
25479
25510
|
}
|
|
@@ -26092,6 +26123,19 @@ function updateTaskStatus(meshId, taskId, status) {
|
|
|
26092
26123
|
writeQueue(meshId, queue);
|
|
26093
26124
|
return queue[idx];
|
|
26094
26125
|
}
|
|
26126
|
+
function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
|
|
26127
|
+
const queue = readQueue(meshId);
|
|
26128
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
26129
|
+
if (idx === -1) return null;
|
|
26130
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26131
|
+
queue[idx].autoLaunch = {
|
|
26132
|
+
...autoLaunch,
|
|
26133
|
+
updatedAt: now
|
|
26134
|
+
};
|
|
26135
|
+
queue[idx].updatedAt = now;
|
|
26136
|
+
writeQueue(meshId, queue);
|
|
26137
|
+
return queue[idx];
|
|
26138
|
+
}
|
|
26095
26139
|
function cancelTask(meshId, taskId, opts) {
|
|
26096
26140
|
const queue = readQueue(meshId);
|
|
26097
26141
|
const idx = queue.findIndex((q) => q.id === taskId);
|
|
@@ -26140,12 +26184,20 @@ function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
|
26140
26184
|
}
|
|
26141
26185
|
function getMeshQueueStats(meshId) {
|
|
26142
26186
|
const queue = readQueue(meshId);
|
|
26187
|
+
const pending = queue.filter((q) => q.status === "pending").length;
|
|
26188
|
+
const assigned = queue.filter((q) => q.status === "assigned").length;
|
|
26189
|
+
const completed = queue.filter((q) => q.status === "completed").length;
|
|
26190
|
+
const failed = queue.filter((q) => q.status === "failed").length;
|
|
26191
|
+
const cancelled = queue.filter((q) => q.status === "cancelled").length;
|
|
26143
26192
|
return {
|
|
26144
|
-
|
|
26145
|
-
|
|
26146
|
-
|
|
26147
|
-
|
|
26148
|
-
|
|
26193
|
+
total: queue.length,
|
|
26194
|
+
active: pending + assigned,
|
|
26195
|
+
historical: completed + failed + cancelled,
|
|
26196
|
+
pending,
|
|
26197
|
+
assigned,
|
|
26198
|
+
completed,
|
|
26199
|
+
failed,
|
|
26200
|
+
cancelled,
|
|
26149
26201
|
activeAssignments: queue.filter((q) => q.status === "assigned").map((q) => ({
|
|
26150
26202
|
id: q.id,
|
|
26151
26203
|
nodeId: q.assignedNodeId,
|
|
@@ -26154,6 +26206,129 @@ function getMeshQueueStats(meshId) {
|
|
|
26154
26206
|
}))
|
|
26155
26207
|
};
|
|
26156
26208
|
}
|
|
26209
|
+
function parseVersion(raw) {
|
|
26210
|
+
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
26211
|
+
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
26212
|
+
}
|
|
26213
|
+
function shellQuote(value) {
|
|
26214
|
+
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
26215
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
26216
|
+
}
|
|
26217
|
+
function expandHome(value) {
|
|
26218
|
+
const trimmed = value.trim();
|
|
26219
|
+
if (!trimmed.startsWith("~")) return trimmed;
|
|
26220
|
+
return path8.join(os22.homedir(), trimmed.slice(1));
|
|
26221
|
+
}
|
|
26222
|
+
function isExplicitCommandPath(command) {
|
|
26223
|
+
const trimmed = command.trim();
|
|
26224
|
+
return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
26225
|
+
}
|
|
26226
|
+
function resolveCommandPath(command) {
|
|
26227
|
+
const trimmed = command.trim();
|
|
26228
|
+
if (!trimmed) return null;
|
|
26229
|
+
if (isExplicitCommandPath(trimmed)) {
|
|
26230
|
+
const expanded = expandHome(trimmed);
|
|
26231
|
+
const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
|
|
26232
|
+
return (0, import_fs8.existsSync)(candidate) ? candidate : null;
|
|
26233
|
+
}
|
|
26234
|
+
return null;
|
|
26235
|
+
}
|
|
26236
|
+
function execAsync(cmd, timeoutMs = 5e3) {
|
|
26237
|
+
return new Promise((resolve162) => {
|
|
26238
|
+
const child = (0, import_child_process2.exec)(cmd, {
|
|
26239
|
+
encoding: "utf-8",
|
|
26240
|
+
timeout: timeoutMs,
|
|
26241
|
+
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
26242
|
+
}, (err, stdout) => {
|
|
26243
|
+
if (err || !stdout?.trim()) {
|
|
26244
|
+
resolve162(null);
|
|
26245
|
+
} else {
|
|
26246
|
+
resolve162(stdout.trim());
|
|
26247
|
+
}
|
|
26248
|
+
});
|
|
26249
|
+
child.on("error", () => resolve162(null));
|
|
26250
|
+
});
|
|
26251
|
+
}
|
|
26252
|
+
async function detectCLIs(providerLoader, options) {
|
|
26253
|
+
const platform10 = os22.platform();
|
|
26254
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
26255
|
+
const includeVersion = options?.includeVersion !== false;
|
|
26256
|
+
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
26257
|
+
const results = await Promise.all(
|
|
26258
|
+
cliList.map(async (cli) => {
|
|
26259
|
+
try {
|
|
26260
|
+
const explicitPath = resolveCommandPath(cli.command);
|
|
26261
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
26262
|
+
if (!pathResult) return { ...cli, installed: false };
|
|
26263
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
26264
|
+
let version2;
|
|
26265
|
+
if (includeVersion) {
|
|
26266
|
+
const versionCommands = [
|
|
26267
|
+
`"${firstPath}" --version`,
|
|
26268
|
+
`"${firstPath}" -V`,
|
|
26269
|
+
`"${firstPath}" -v`,
|
|
26270
|
+
cli.versionCommand
|
|
26271
|
+
].filter((v) => !!v);
|
|
26272
|
+
try {
|
|
26273
|
+
for (const versionCommand of versionCommands) {
|
|
26274
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
26275
|
+
if (versionResult) {
|
|
26276
|
+
version2 = parseVersion(versionResult);
|
|
26277
|
+
break;
|
|
26278
|
+
}
|
|
26279
|
+
}
|
|
26280
|
+
} catch {
|
|
26281
|
+
}
|
|
26282
|
+
}
|
|
26283
|
+
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
26284
|
+
} catch {
|
|
26285
|
+
return { ...cli, installed: false };
|
|
26286
|
+
}
|
|
26287
|
+
})
|
|
26288
|
+
);
|
|
26289
|
+
return results;
|
|
26290
|
+
}
|
|
26291
|
+
async function detectCLI(cliId, providerLoader, options) {
|
|
26292
|
+
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
26293
|
+
if (providerLoader) {
|
|
26294
|
+
const cliList = providerLoader.getCliDetectionList();
|
|
26295
|
+
const target = cliList.find((c) => c.id === resolvedId);
|
|
26296
|
+
if (target) {
|
|
26297
|
+
const platform10 = os22.platform();
|
|
26298
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
26299
|
+
try {
|
|
26300
|
+
const explicitPath = resolveCommandPath(target.command);
|
|
26301
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
26302
|
+
if (!pathResult) return null;
|
|
26303
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
26304
|
+
let version2;
|
|
26305
|
+
if (options?.includeVersion !== false) {
|
|
26306
|
+
const versionCommands = [
|
|
26307
|
+
`"${firstPath}" --version`,
|
|
26308
|
+
`"${firstPath}" -V`,
|
|
26309
|
+
`"${firstPath}" -v`,
|
|
26310
|
+
target.versionCommand
|
|
26311
|
+
].filter((v) => !!v);
|
|
26312
|
+
try {
|
|
26313
|
+
for (const versionCommand of versionCommands) {
|
|
26314
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
26315
|
+
if (versionResult) {
|
|
26316
|
+
version2 = parseVersion(versionResult);
|
|
26317
|
+
break;
|
|
26318
|
+
}
|
|
26319
|
+
}
|
|
26320
|
+
} catch {
|
|
26321
|
+
}
|
|
26322
|
+
}
|
|
26323
|
+
return { ...target, installed: true, version: version2, path: firstPath };
|
|
26324
|
+
} catch {
|
|
26325
|
+
return null;
|
|
26326
|
+
}
|
|
26327
|
+
}
|
|
26328
|
+
}
|
|
26329
|
+
const all = await detectCLIs(providerLoader, options);
|
|
26330
|
+
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
26331
|
+
}
|
|
26157
26332
|
function setLogLevel(level) {
|
|
26158
26333
|
currentLevel = level;
|
|
26159
26334
|
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
@@ -26168,13 +26343,13 @@ function getDaemonLogDir() {
|
|
|
26168
26343
|
return LOG_DIR;
|
|
26169
26344
|
}
|
|
26170
26345
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
26171
|
-
return
|
|
26346
|
+
return path9.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
26172
26347
|
}
|
|
26173
26348
|
function checkDateRotation() {
|
|
26174
26349
|
const today = getDateStr();
|
|
26175
26350
|
if (today !== currentDate) {
|
|
26176
26351
|
currentDate = today;
|
|
26177
|
-
currentLogFile =
|
|
26352
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
26178
26353
|
cleanOldLogs();
|
|
26179
26354
|
}
|
|
26180
26355
|
}
|
|
@@ -26188,7 +26363,7 @@ function cleanOldLogs() {
|
|
|
26188
26363
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
26189
26364
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
26190
26365
|
try {
|
|
26191
|
-
fs2.unlinkSync(
|
|
26366
|
+
fs2.unlinkSync(path9.join(LOG_DIR, file2));
|
|
26192
26367
|
} catch {
|
|
26193
26368
|
}
|
|
26194
26369
|
}
|
|
@@ -26363,7 +26538,235 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
26363
26538
|
});
|
|
26364
26539
|
return true;
|
|
26365
26540
|
}
|
|
26366
|
-
function
|
|
26541
|
+
function normalizeProviderPriority(policy) {
|
|
26542
|
+
const raw = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerPriority : void 0;
|
|
26543
|
+
if (!Array.isArray(raw)) return [];
|
|
26544
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26545
|
+
return raw.map((type2) => typeof type2 === "string" ? type2.trim() : "").filter(Boolean).filter((type2) => {
|
|
26546
|
+
if (seen.has(type2)) return false;
|
|
26547
|
+
seen.add(type2);
|
|
26548
|
+
return true;
|
|
26549
|
+
});
|
|
26550
|
+
}
|
|
26551
|
+
function isTerminalSessionStatus(status) {
|
|
26552
|
+
return ["stopped", "failed", "terminated", "exited", "closed"].includes(status);
|
|
26553
|
+
}
|
|
26554
|
+
function isIdleSessionState(state) {
|
|
26555
|
+
const status = readNonEmptyString(state?.status).toLowerCase();
|
|
26556
|
+
if (isTerminalSessionStatus(status)) return false;
|
|
26557
|
+
return status === "idle" || state?.activeChat?.status === "waiting_input";
|
|
26558
|
+
}
|
|
26559
|
+
function isDirtyNode(node) {
|
|
26560
|
+
return node?.health === "dirty" || node?.git?.dirty === true;
|
|
26561
|
+
}
|
|
26562
|
+
function isLaunchableNode(node) {
|
|
26563
|
+
if (!node || node.status === "disabled" || node.status === "removed") return false;
|
|
26564
|
+
const health = readNonEmptyString(node.health).toLowerCase();
|
|
26565
|
+
if (!health) return true;
|
|
26566
|
+
return health === "online" || health === "unknown";
|
|
26567
|
+
}
|
|
26568
|
+
function localAutoLaunchSkipReason(node) {
|
|
26569
|
+
const daemonId = readNonEmptyString(node?.daemonId);
|
|
26570
|
+
const machineId = readNonEmptyString(node?.machineId);
|
|
26571
|
+
const appConfig = loadConfig();
|
|
26572
|
+
const localMachineId = readNonEmptyString(appConfig.machineId) || readNonEmptyString(appConfig.registeredMachineId);
|
|
26573
|
+
const cloudDaemonId = localMachineId ? `daemon_${localMachineId}` : "";
|
|
26574
|
+
const standaloneDaemonId = localMachineId ? `standalone_${localMachineId}` : "";
|
|
26575
|
+
const daemonMatchesLocal = !daemonId || daemonId === cloudDaemonId || daemonId === standaloneDaemonId;
|
|
26576
|
+
const machineMatchesLocal = !machineId || localMachineId && machineId === localMachineId;
|
|
26577
|
+
if (node?.isLocalWorktree === true) {
|
|
26578
|
+
return daemonMatchesLocal && machineMatchesLocal ? null : "remote_auto_launch_unsupported";
|
|
26579
|
+
}
|
|
26580
|
+
if (daemonId || machineId) {
|
|
26581
|
+
return daemonMatchesLocal && machineMatchesLocal ? null : "remote_auto_launch_unsupported";
|
|
26582
|
+
}
|
|
26583
|
+
return null;
|
|
26584
|
+
}
|
|
26585
|
+
function activeAssignedCount(meshId) {
|
|
26586
|
+
return getQueue(meshId, { status: ["assigned"] }).length;
|
|
26587
|
+
}
|
|
26588
|
+
function nodeHasActiveAssignment(meshId, nodeId) {
|
|
26589
|
+
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
26590
|
+
}
|
|
26591
|
+
function liveSessionCountForNode(components, meshId, nodeId) {
|
|
26592
|
+
return components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
26593
|
+
const state = inst.getState();
|
|
26594
|
+
const settings = state.settings || {};
|
|
26595
|
+
if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
|
|
26596
|
+
const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
26597
|
+
if (instNodeId !== nodeId) return false;
|
|
26598
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
26599
|
+
return !isTerminalSessionStatus(status);
|
|
26600
|
+
}).length;
|
|
26601
|
+
}
|
|
26602
|
+
function recordAutoLaunchEvent(meshId, args) {
|
|
26603
|
+
try {
|
|
26604
|
+
appendLedgerEntry(meshId, {
|
|
26605
|
+
kind: "session_auto_launch",
|
|
26606
|
+
nodeId: args.nodeId,
|
|
26607
|
+
sessionId: args.sessionId,
|
|
26608
|
+
providerType: args.providerType,
|
|
26609
|
+
payload: {
|
|
26610
|
+
phase: args.phase,
|
|
26611
|
+
taskId: args.taskId,
|
|
26612
|
+
reason: args.reason,
|
|
26613
|
+
error: args.error
|
|
26614
|
+
}
|
|
26615
|
+
});
|
|
26616
|
+
} catch (e) {
|
|
26617
|
+
LOG.warn("MeshQueue", `Failed to record auto-launch ledger event: ${e?.message || e}`);
|
|
26618
|
+
}
|
|
26619
|
+
}
|
|
26620
|
+
function markAutoLaunch(meshId, taskId, args) {
|
|
26621
|
+
recordTaskAutoLaunch(meshId, taskId, {
|
|
26622
|
+
status: args.status,
|
|
26623
|
+
reason: args.reason || args.error,
|
|
26624
|
+
nodeId: args.nodeId,
|
|
26625
|
+
providerType: args.providerType,
|
|
26626
|
+
sessionId: args.sessionId
|
|
26627
|
+
});
|
|
26628
|
+
recordAutoLaunchEvent(meshId, {
|
|
26629
|
+
phase: args.status,
|
|
26630
|
+
taskId,
|
|
26631
|
+
nodeId: args.nodeId,
|
|
26632
|
+
providerType: args.providerType,
|
|
26633
|
+
sessionId: args.sessionId,
|
|
26634
|
+
reason: args.reason,
|
|
26635
|
+
error: args.error
|
|
26636
|
+
});
|
|
26637
|
+
}
|
|
26638
|
+
async function resolveUsableProvider(components, nodeId, node) {
|
|
26639
|
+
const providerPriority = normalizeProviderPriority(node?.policy);
|
|
26640
|
+
if (!providerPriority.length) return { reason: "missing_provider_priority" };
|
|
26641
|
+
const providerLoader = components.providerLoader;
|
|
26642
|
+
if (!providerLoader) return { reason: "provider_loader_unavailable" };
|
|
26643
|
+
const failed = [];
|
|
26644
|
+
for (const requestedType of providerPriority) {
|
|
26645
|
+
const normalizedType = typeof providerLoader.resolveAlias === "function" ? providerLoader.resolveAlias(requestedType) : requestedType;
|
|
26646
|
+
if (typeof providerLoader.isMachineProviderEnabled === "function" && !providerLoader.isMachineProviderEnabled(normalizedType)) {
|
|
26647
|
+
failed.push(`${requestedType}: disabled`);
|
|
26648
|
+
continue;
|
|
26649
|
+
}
|
|
26650
|
+
let detected;
|
|
26651
|
+
try {
|
|
26652
|
+
detected = await detectCLI(normalizedType, providerLoader, { includeVersion: false });
|
|
26653
|
+
} catch (e) {
|
|
26654
|
+
failed.push(`${requestedType}: detect failed: ${e?.message || e}`);
|
|
26655
|
+
continue;
|
|
26656
|
+
}
|
|
26657
|
+
if (typeof providerLoader.setCliDetectionResults === "function") {
|
|
26658
|
+
providerLoader.setCliDetectionResults([{
|
|
26659
|
+
id: normalizedType,
|
|
26660
|
+
installed: !!detected,
|
|
26661
|
+
path: detected?.path
|
|
26662
|
+
}], false);
|
|
26663
|
+
}
|
|
26664
|
+
components.onStatusChange?.();
|
|
26665
|
+
if (detected) return { providerType: normalizedType };
|
|
26666
|
+
failed.push(`${requestedType}: not detected`);
|
|
26667
|
+
}
|
|
26668
|
+
return { reason: `provider_priority_unusable: ${failed.join("; ") || nodeId}` };
|
|
26669
|
+
}
|
|
26670
|
+
async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
26671
|
+
const queue = getQueue(meshId);
|
|
26672
|
+
const pending = queue.filter((task) => task.status === "pending");
|
|
26673
|
+
if (!pending.length) return false;
|
|
26674
|
+
const maxParallelTasks = Math.max(1, Math.floor(Number(mesh?.policy?.maxParallelTasks) || 2));
|
|
26675
|
+
for (const task of pending) {
|
|
26676
|
+
if (activeAssignedCount(meshId) >= maxParallelTasks) {
|
|
26677
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_parallel_tasks_reached" });
|
|
26678
|
+
return false;
|
|
26679
|
+
}
|
|
26680
|
+
if (task.targetSessionId) {
|
|
26681
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_constraint" });
|
|
26682
|
+
continue;
|
|
26683
|
+
}
|
|
26684
|
+
const candidateNodes = Array.isArray(mesh?.nodes) ? mesh.nodes.filter((node) => task.targetNodeId ? node?.id === task.targetNodeId : true) : [];
|
|
26685
|
+
if (!candidateNodes.length) {
|
|
26686
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "no_matching_node", nodeId: task.targetNodeId });
|
|
26687
|
+
continue;
|
|
26688
|
+
}
|
|
26689
|
+
for (const node of candidateNodes) {
|
|
26690
|
+
const nodeId = readNonEmptyString(node?.id);
|
|
26691
|
+
if (!nodeId) continue;
|
|
26692
|
+
const launchKey = `${meshId}:${nodeId}`;
|
|
26693
|
+
const cooldownUntil = autoLaunchCooldownUntil.get(launchKey) || 0;
|
|
26694
|
+
if (autoLaunchInProgress.has(launchKey)) {
|
|
26695
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_in_progress", nodeId });
|
|
26696
|
+
continue;
|
|
26697
|
+
}
|
|
26698
|
+
if (Date.now() < cooldownUntil) {
|
|
26699
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_cooldown", nodeId });
|
|
26700
|
+
continue;
|
|
26701
|
+
}
|
|
26702
|
+
if (isDirtyNode(node)) {
|
|
26703
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "dirty_workspace", nodeId });
|
|
26704
|
+
continue;
|
|
26705
|
+
}
|
|
26706
|
+
if (!isLaunchableNode(node)) {
|
|
26707
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_not_launch_ready", nodeId });
|
|
26708
|
+
continue;
|
|
26709
|
+
}
|
|
26710
|
+
const localSkipReason = localAutoLaunchSkipReason(node);
|
|
26711
|
+
if (localSkipReason) {
|
|
26712
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: localSkipReason, nodeId });
|
|
26713
|
+
continue;
|
|
26714
|
+
}
|
|
26715
|
+
if (nodeHasActiveAssignment(meshId, nodeId)) {
|
|
26716
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
|
|
26717
|
+
continue;
|
|
26718
|
+
}
|
|
26719
|
+
const maxConcurrentSessions = Number(node?.policy?.maxConcurrentSessions);
|
|
26720
|
+
if (Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0 && liveSessionCountForNode(components, meshId, nodeId) >= maxConcurrentSessions) {
|
|
26721
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_concurrent_sessions_reached", nodeId });
|
|
26722
|
+
continue;
|
|
26723
|
+
}
|
|
26724
|
+
autoLaunchInProgress.add(launchKey);
|
|
26725
|
+
try {
|
|
26726
|
+
const resolved = await resolveUsableProvider(components, nodeId, node);
|
|
26727
|
+
if (!resolved.providerType) {
|
|
26728
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: resolved.reason || "provider_unusable", nodeId });
|
|
26729
|
+
continue;
|
|
26730
|
+
}
|
|
26731
|
+
markAutoLaunch(meshId, task.id, { status: "started", nodeId, providerType: resolved.providerType });
|
|
26732
|
+
const launchResult = await components.cliManager.handleCliCommand("launch_cli", {
|
|
26733
|
+
cliType: resolved.providerType,
|
|
26734
|
+
dir: node.workspace,
|
|
26735
|
+
settings: {
|
|
26736
|
+
meshNodeFor: meshId,
|
|
26737
|
+
meshNodeId: nodeId,
|
|
26738
|
+
spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
|
|
26739
|
+
launchedByCoordinator: true,
|
|
26740
|
+
autoLaunchedForQueueTaskId: task.id
|
|
26741
|
+
}
|
|
26742
|
+
});
|
|
26743
|
+
if (!launchResult?.success) {
|
|
26744
|
+
const reason = launchResult?.error || "launch_cli_failed";
|
|
26745
|
+
markAutoLaunch(meshId, task.id, { status: "failed", reason, nodeId, providerType: resolved.providerType });
|
|
26746
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
26747
|
+
return false;
|
|
26748
|
+
}
|
|
26749
|
+
const sessionId = readNonEmptyString(launchResult.sessionId) || readNonEmptyString(launchResult.id) || readNonEmptyString(launchResult.runtimeSessionId);
|
|
26750
|
+
if (!sessionId) {
|
|
26751
|
+
markAutoLaunch(meshId, task.id, { status: "failed", reason: "launch_missing_session_id", nodeId, providerType: resolved.providerType });
|
|
26752
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
26753
|
+
return false;
|
|
26754
|
+
}
|
|
26755
|
+
markAutoLaunch(meshId, task.id, { status: "completed", nodeId, providerType: resolved.providerType, sessionId });
|
|
26756
|
+
tryAssignQueueTask(components, meshId, nodeId, sessionId, resolved.providerType);
|
|
26757
|
+
return true;
|
|
26758
|
+
} catch (e) {
|
|
26759
|
+
markAutoLaunch(meshId, task.id, { status: "failed", error: e?.message || String(e), nodeId });
|
|
26760
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
26761
|
+
return false;
|
|
26762
|
+
} finally {
|
|
26763
|
+
autoLaunchInProgress.delete(launchKey);
|
|
26764
|
+
}
|
|
26765
|
+
}
|
|
26766
|
+
}
|
|
26767
|
+
return false;
|
|
26768
|
+
}
|
|
26769
|
+
async function triggerMeshQueue(components, meshId) {
|
|
26367
26770
|
const mesh = getMeshWithCache(components, meshId);
|
|
26368
26771
|
if (!mesh) return;
|
|
26369
26772
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
@@ -26374,9 +26777,7 @@ function triggerMeshQueue(components, meshId) {
|
|
|
26374
26777
|
if (instMeshId !== meshId) continue;
|
|
26375
26778
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
26376
26779
|
if (!nodeId) continue;
|
|
26377
|
-
|
|
26378
|
-
if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
|
|
26379
|
-
if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
|
|
26780
|
+
if (!isIdleSessionState(state)) continue;
|
|
26380
26781
|
const sessionId = state.instanceId;
|
|
26381
26782
|
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
26382
26783
|
if (providerType) {
|
|
@@ -26392,6 +26793,7 @@ function triggerMeshQueue(components, meshId) {
|
|
|
26392
26793
|
}
|
|
26393
26794
|
}
|
|
26394
26795
|
}
|
|
26796
|
+
await maybeAutoLaunchOneQueueSession(components, meshId, mesh);
|
|
26395
26797
|
}
|
|
26396
26798
|
function buildMeshSystemMessage(args) {
|
|
26397
26799
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
@@ -26899,7 +27301,7 @@ function findBinary(name) {
|
|
|
26899
27301
|
const isWin = os9.platform() === "win32";
|
|
26900
27302
|
try {
|
|
26901
27303
|
const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
|
|
26902
|
-
return (0,
|
|
27304
|
+
return (0, import_child_process3.execSync)(cmd, {
|
|
26903
27305
|
encoding: "utf-8",
|
|
26904
27306
|
timeout: 5e3,
|
|
26905
27307
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -27274,7 +27676,7 @@ async function validateWorkspace(workspace) {
|
|
|
27274
27676
|
cwd: normalizedWorkspace
|
|
27275
27677
|
});
|
|
27276
27678
|
}
|
|
27277
|
-
await (0, import_promises5.access)(normalizedWorkspace,
|
|
27679
|
+
await (0, import_promises5.access)(normalizedWorkspace, import_fs9.constants.R_OK);
|
|
27278
27680
|
} catch (error48) {
|
|
27279
27681
|
if (error48 instanceof GitCommandError) throw error48;
|
|
27280
27682
|
throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
|
|
@@ -28403,7 +28805,7 @@ function addWorkspaceEntry(config2, rawPath, label, options) {
|
|
|
28403
28805
|
}
|
|
28404
28806
|
}
|
|
28405
28807
|
const v = validateWorkspacePath(abs);
|
|
28406
|
-
if (
|
|
28808
|
+
if (v.ok !== true) return { error: v.error };
|
|
28407
28809
|
const list = [...config2.workspaces || []];
|
|
28408
28810
|
if (list.some((w) => path5.resolve(w.path) === abs)) {
|
|
28409
28811
|
return { error: "Workspace already in list" };
|
|
@@ -28787,6 +29189,86 @@ async function syncMeshLedger(meshId, transport) {
|
|
|
28787
29189
|
appendRemoteLedgerEntries2(meshId, res.missingEntries);
|
|
28788
29190
|
}
|
|
28789
29191
|
}
|
|
29192
|
+
function messageFromError(error48) {
|
|
29193
|
+
if (error48 instanceof Error) return error48.message;
|
|
29194
|
+
if (typeof error48 === "string") return error48;
|
|
29195
|
+
if (error48 && typeof error48 === "object") {
|
|
29196
|
+
const candidate = error48.error ?? error48.message ?? error48.reason;
|
|
29197
|
+
if (typeof candidate === "string") return candidate;
|
|
29198
|
+
}
|
|
29199
|
+
return String(error48 || "mesh relay command failed");
|
|
29200
|
+
}
|
|
29201
|
+
function classifyP2pRelayFailure(error48, _context = {}) {
|
|
29202
|
+
const message = messageFromError(error48);
|
|
29203
|
+
const lower = message.toLowerCase();
|
|
29204
|
+
const hasP2pSignal = /p2p|datachannel|node-datachannel|webrtc|ice|mesh_relay_command|daemon_mesh_p2p_transport/i.test(message);
|
|
29205
|
+
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);
|
|
29206
|
+
if (/requires targetdaemonid and command|providerpriority|no inference provider|permission denied|read-only|not a member/i.test(message)) {
|
|
29207
|
+
return {
|
|
29208
|
+
code: "mesh_logic_or_provider_failure",
|
|
29209
|
+
reason: "mesh_logic_or_provider_failure",
|
|
29210
|
+
transport: "unknown",
|
|
29211
|
+
recoverable: false,
|
|
29212
|
+
retryRecommended: false,
|
|
29213
|
+
nextAction: NON_P2P_NEXT_ACTION,
|
|
29214
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29215
|
+
};
|
|
29216
|
+
}
|
|
29217
|
+
let code = null;
|
|
29218
|
+
let reason = "";
|
|
29219
|
+
if (/timeout|timed out/i.test(message) && (hasP2pSignal || /mesh transport/i.test(message))) {
|
|
29220
|
+
code = "p2p_timeout";
|
|
29221
|
+
reason = "daemon_mesh_p2p_timeout";
|
|
29222
|
+
} else if (/no route|route unavailable/i.test(message)) {
|
|
29223
|
+
code = "p2p_no_route";
|
|
29224
|
+
reason = "daemon_mesh_p2p_no_route";
|
|
29225
|
+
} else if (/offline|not owned|not found|not connected to server/i.test(message) && /daemon|peer|target/i.test(message)) {
|
|
29226
|
+
code = "p2p_daemon_offline";
|
|
29227
|
+
reason = "daemon_mesh_target_offline";
|
|
29228
|
+
} else if (/closed|disconnected/i.test(message) && (hasP2pSignal || /state changed/i.test(message))) {
|
|
29229
|
+
code = "p2p_datachannel_closed";
|
|
29230
|
+
reason = "daemon_mesh_p2p_datachannel_closed";
|
|
29231
|
+
} else if (/not connected|cannot send|cannot establish/i.test(message) && hasP2pSignal) {
|
|
29232
|
+
code = "p2p_not_connected";
|
|
29233
|
+
reason = "daemon_mesh_p2p_not_connected";
|
|
29234
|
+
} else if (hasP2pSignal && hasFailureSignal) {
|
|
29235
|
+
code = "p2p_unavailable";
|
|
29236
|
+
reason = "daemon_mesh_p2p_transport_unavailable";
|
|
29237
|
+
}
|
|
29238
|
+
if (!code) {
|
|
29239
|
+
return {
|
|
29240
|
+
code: "mesh_logic_or_provider_failure",
|
|
29241
|
+
reason: "mesh_logic_or_provider_failure",
|
|
29242
|
+
transport: "unknown",
|
|
29243
|
+
recoverable: false,
|
|
29244
|
+
retryRecommended: false,
|
|
29245
|
+
nextAction: NON_P2P_NEXT_ACTION,
|
|
29246
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29247
|
+
};
|
|
29248
|
+
}
|
|
29249
|
+
return {
|
|
29250
|
+
code,
|
|
29251
|
+
reason,
|
|
29252
|
+
transport: "p2p",
|
|
29253
|
+
recoverable: true,
|
|
29254
|
+
retryRecommended: true,
|
|
29255
|
+
nextAction: P2P_NEXT_ACTION,
|
|
29256
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29257
|
+
};
|
|
29258
|
+
}
|
|
29259
|
+
function isP2pRelayTransportFailure(error48) {
|
|
29260
|
+
return classifyP2pRelayFailure(error48).recoverable === true;
|
|
29261
|
+
}
|
|
29262
|
+
function buildP2pRelayFailurePayload(error48, context = {}) {
|
|
29263
|
+
const classification = classifyP2pRelayFailure(error48, context);
|
|
29264
|
+
return {
|
|
29265
|
+
success: false,
|
|
29266
|
+
...classification,
|
|
29267
|
+
error: messageFromError(error48),
|
|
29268
|
+
...context.command ? { command: context.command } : {},
|
|
29269
|
+
...context.targetDaemonId ? { targetDaemonId: context.targetDaemonId } : {}
|
|
29270
|
+
};
|
|
29271
|
+
}
|
|
28790
29272
|
function isPlainObject22(value) {
|
|
28791
29273
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
28792
29274
|
}
|
|
@@ -28827,11 +29309,11 @@ function normalizeState(raw) {
|
|
|
28827
29309
|
}
|
|
28828
29310
|
function loadState() {
|
|
28829
29311
|
const statePath = getStatePath();
|
|
28830
|
-
if (!(0,
|
|
29312
|
+
if (!(0, import_fs10.existsSync)(statePath)) {
|
|
28831
29313
|
return { ...DEFAULT_STATE };
|
|
28832
29314
|
}
|
|
28833
29315
|
try {
|
|
28834
|
-
const raw = (0,
|
|
29316
|
+
const raw = (0, import_fs10.readFileSync)(statePath, "utf-8");
|
|
28835
29317
|
return normalizeState(JSON.parse(raw));
|
|
28836
29318
|
} catch {
|
|
28837
29319
|
return { ...DEFAULT_STATE };
|
|
@@ -28840,7 +29322,7 @@ function loadState() {
|
|
|
28840
29322
|
function saveState(state) {
|
|
28841
29323
|
const statePath = getStatePath();
|
|
28842
29324
|
const normalized = normalizeState(state);
|
|
28843
|
-
(0,
|
|
29325
|
+
(0, import_fs10.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
28844
29326
|
}
|
|
28845
29327
|
function resetState() {
|
|
28846
29328
|
saveState({ ...DEFAULT_STATE });
|
|
@@ -28861,13 +29343,13 @@ function getMergedDefinitions() {
|
|
|
28861
29343
|
function findCliCommand(command) {
|
|
28862
29344
|
const trimmed = String(command || "").trim();
|
|
28863
29345
|
if (!trimmed) return null;
|
|
28864
|
-
if (
|
|
28865
|
-
const candidate = trimmed.startsWith("~") ?
|
|
28866
|
-
const resolved =
|
|
28867
|
-
return (0,
|
|
29346
|
+
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
29347
|
+
const candidate = trimmed.startsWith("~") ? path10.join((0, import_os3.homedir)(), trimmed.slice(1)) : trimmed;
|
|
29348
|
+
const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
|
|
29349
|
+
return (0, import_fs11.existsSync)(resolved) ? resolved : null;
|
|
28868
29350
|
}
|
|
28869
29351
|
try {
|
|
28870
|
-
const result = (0,
|
|
29352
|
+
const result = (0, import_child_process5.execSync)(
|
|
28871
29353
|
(0, import_os3.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
|
|
28872
29354
|
{ encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
|
|
28873
29355
|
).trim();
|
|
@@ -28878,7 +29360,7 @@ function findCliCommand(command) {
|
|
|
28878
29360
|
}
|
|
28879
29361
|
function getIdeVersion(cliCommand) {
|
|
28880
29362
|
try {
|
|
28881
|
-
const result = (0,
|
|
29363
|
+
const result = (0, import_child_process5.execSync)(`"${cliCommand}" --version`, {
|
|
28882
29364
|
encoding: "utf-8",
|
|
28883
29365
|
timeout: 1e4,
|
|
28884
29366
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -28891,13 +29373,13 @@ function getIdeVersion(cliCommand) {
|
|
|
28891
29373
|
function checkPathExists(paths) {
|
|
28892
29374
|
const home = (0, import_os3.homedir)();
|
|
28893
29375
|
for (const p of paths) {
|
|
28894
|
-
const normalized = p.startsWith("~") ?
|
|
29376
|
+
const normalized = p.startsWith("~") ? path10.join(home, p.slice(1)) : p;
|
|
28895
29377
|
if (normalized.includes("*")) {
|
|
28896
29378
|
const username = home.split(/[\\/]/).pop() || "";
|
|
28897
29379
|
const resolved = normalized.replace("*", username);
|
|
28898
|
-
if ((0,
|
|
29380
|
+
if ((0, import_fs11.existsSync)(resolved)) return resolved;
|
|
28899
29381
|
} else {
|
|
28900
|
-
if ((0,
|
|
29382
|
+
if ((0, import_fs11.existsSync)(normalized)) return normalized;
|
|
28901
29383
|
}
|
|
28902
29384
|
}
|
|
28903
29385
|
return null;
|
|
@@ -28911,7 +29393,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28911
29393
|
let resolvedCli = cliPath;
|
|
28912
29394
|
if (!resolvedCli && appPath && os222 === "darwin") {
|
|
28913
29395
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
28914
|
-
if ((0,
|
|
29396
|
+
if ((0, import_fs11.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
28915
29397
|
}
|
|
28916
29398
|
if (!resolvedCli && appPath && os222 === "win32") {
|
|
28917
29399
|
const { dirname: dirname92 } = await import("path");
|
|
@@ -28924,7 +29406,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28924
29406
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
28925
29407
|
];
|
|
28926
29408
|
for (const c of candidates) {
|
|
28927
|
-
if ((0,
|
|
29409
|
+
if ((0, import_fs11.existsSync)(c)) {
|
|
28928
29410
|
resolvedCli = c;
|
|
28929
29411
|
break;
|
|
28930
29412
|
}
|
|
@@ -28945,129 +29427,6 @@ async function detectIDEs(providerLoader) {
|
|
|
28945
29427
|
}
|
|
28946
29428
|
return results;
|
|
28947
29429
|
}
|
|
28948
|
-
function parseVersion(raw) {
|
|
28949
|
-
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
28950
|
-
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
28951
|
-
}
|
|
28952
|
-
function shellQuote(value) {
|
|
28953
|
-
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
28954
|
-
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
28955
|
-
}
|
|
28956
|
-
function expandHome(value) {
|
|
28957
|
-
const trimmed = value.trim();
|
|
28958
|
-
if (!trimmed.startsWith("~")) return trimmed;
|
|
28959
|
-
return path10.join(os32.homedir(), trimmed.slice(1));
|
|
28960
|
-
}
|
|
28961
|
-
function isExplicitCommandPath(command) {
|
|
28962
|
-
const trimmed = command.trim();
|
|
28963
|
-
return path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
28964
|
-
}
|
|
28965
|
-
function resolveCommandPath(command) {
|
|
28966
|
-
const trimmed = command.trim();
|
|
28967
|
-
if (!trimmed) return null;
|
|
28968
|
-
if (isExplicitCommandPath(trimmed)) {
|
|
28969
|
-
const expanded = expandHome(trimmed);
|
|
28970
|
-
const candidate = path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
|
|
28971
|
-
return (0, import_fs11.existsSync)(candidate) ? candidate : null;
|
|
28972
|
-
}
|
|
28973
|
-
return null;
|
|
28974
|
-
}
|
|
28975
|
-
function execAsync(cmd, timeoutMs = 5e3) {
|
|
28976
|
-
return new Promise((resolve162) => {
|
|
28977
|
-
const child = (0, import_child_process5.exec)(cmd, {
|
|
28978
|
-
encoding: "utf-8",
|
|
28979
|
-
timeout: timeoutMs,
|
|
28980
|
-
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
28981
|
-
}, (err, stdout) => {
|
|
28982
|
-
if (err || !stdout?.trim()) {
|
|
28983
|
-
resolve162(null);
|
|
28984
|
-
} else {
|
|
28985
|
-
resolve162(stdout.trim());
|
|
28986
|
-
}
|
|
28987
|
-
});
|
|
28988
|
-
child.on("error", () => resolve162(null));
|
|
28989
|
-
});
|
|
28990
|
-
}
|
|
28991
|
-
async function detectCLIs(providerLoader, options) {
|
|
28992
|
-
const platform10 = os32.platform();
|
|
28993
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
28994
|
-
const includeVersion = options?.includeVersion !== false;
|
|
28995
|
-
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
28996
|
-
const results = await Promise.all(
|
|
28997
|
-
cliList.map(async (cli) => {
|
|
28998
|
-
try {
|
|
28999
|
-
const explicitPath = resolveCommandPath(cli.command);
|
|
29000
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
29001
|
-
if (!pathResult) return { ...cli, installed: false };
|
|
29002
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29003
|
-
let version2;
|
|
29004
|
-
if (includeVersion) {
|
|
29005
|
-
const versionCommands = [
|
|
29006
|
-
`"${firstPath}" --version`,
|
|
29007
|
-
`"${firstPath}" -V`,
|
|
29008
|
-
`"${firstPath}" -v`,
|
|
29009
|
-
cli.versionCommand
|
|
29010
|
-
].filter((v) => !!v);
|
|
29011
|
-
try {
|
|
29012
|
-
for (const versionCommand of versionCommands) {
|
|
29013
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29014
|
-
if (versionResult) {
|
|
29015
|
-
version2 = parseVersion(versionResult);
|
|
29016
|
-
break;
|
|
29017
|
-
}
|
|
29018
|
-
}
|
|
29019
|
-
} catch {
|
|
29020
|
-
}
|
|
29021
|
-
}
|
|
29022
|
-
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
29023
|
-
} catch {
|
|
29024
|
-
return { ...cli, installed: false };
|
|
29025
|
-
}
|
|
29026
|
-
})
|
|
29027
|
-
);
|
|
29028
|
-
return results;
|
|
29029
|
-
}
|
|
29030
|
-
async function detectCLI(cliId, providerLoader, options) {
|
|
29031
|
-
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
29032
|
-
if (providerLoader) {
|
|
29033
|
-
const cliList = providerLoader.getCliDetectionList();
|
|
29034
|
-
const target = cliList.find((c) => c.id === resolvedId);
|
|
29035
|
-
if (target) {
|
|
29036
|
-
const platform10 = os32.platform();
|
|
29037
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
29038
|
-
try {
|
|
29039
|
-
const explicitPath = resolveCommandPath(target.command);
|
|
29040
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
29041
|
-
if (!pathResult) return null;
|
|
29042
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29043
|
-
let version2;
|
|
29044
|
-
if (options?.includeVersion !== false) {
|
|
29045
|
-
const versionCommands = [
|
|
29046
|
-
`"${firstPath}" --version`,
|
|
29047
|
-
`"${firstPath}" -V`,
|
|
29048
|
-
`"${firstPath}" -v`,
|
|
29049
|
-
target.versionCommand
|
|
29050
|
-
].filter((v) => !!v);
|
|
29051
|
-
try {
|
|
29052
|
-
for (const versionCommand of versionCommands) {
|
|
29053
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29054
|
-
if (versionResult) {
|
|
29055
|
-
version2 = parseVersion(versionResult);
|
|
29056
|
-
break;
|
|
29057
|
-
}
|
|
29058
|
-
}
|
|
29059
|
-
} catch {
|
|
29060
|
-
}
|
|
29061
|
-
}
|
|
29062
|
-
return { ...target, installed: true, version: version2, path: firstPath };
|
|
29063
|
-
} catch {
|
|
29064
|
-
return null;
|
|
29065
|
-
}
|
|
29066
|
-
}
|
|
29067
|
-
}
|
|
29068
|
-
const all = await detectCLIs(providerLoader, options);
|
|
29069
|
-
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
29070
|
-
}
|
|
29071
29430
|
function parseDarwinAvailableBytes(totalMem) {
|
|
29072
29431
|
if (os42.platform() !== "darwin") return null;
|
|
29073
29432
|
try {
|
|
@@ -36589,6 +36948,204 @@ async function resolveProviderTypeFromPriority(args) {
|
|
|
36589
36948
|
}
|
|
36590
36949
|
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
|
|
36591
36950
|
}
|
|
36951
|
+
function truncateValidationOutput(value) {
|
|
36952
|
+
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
36953
|
+
if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
|
|
36954
|
+
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
36955
|
+
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
36956
|
+
}
|
|
36957
|
+
function readPackageScripts(workspace) {
|
|
36958
|
+
try {
|
|
36959
|
+
const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
|
|
36960
|
+
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
36961
|
+
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
36962
|
+
} catch {
|
|
36963
|
+
return {};
|
|
36964
|
+
}
|
|
36965
|
+
}
|
|
36966
|
+
function tokenizeValidationCommand(command) {
|
|
36967
|
+
const trimmed = command.trim();
|
|
36968
|
+
if (!trimmed) return null;
|
|
36969
|
+
if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
|
|
36970
|
+
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
36971
|
+
if (!tokens.length) return null;
|
|
36972
|
+
if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
|
|
36973
|
+
return tokens;
|
|
36974
|
+
}
|
|
36975
|
+
function scriptMatchesValidationCategory(scriptName, category) {
|
|
36976
|
+
return scriptName === category || scriptName.startsWith(`${category}:`);
|
|
36977
|
+
}
|
|
36978
|
+
function parsePackageManagerValidationCommand(rawCommand, category, scripts, source) {
|
|
36979
|
+
const tokens = tokenizeValidationCommand(rawCommand);
|
|
36980
|
+
if (!tokens) {
|
|
36981
|
+
return { rejected: { command: rawCommand, category, source, reason: "unsafe command string is not allowlisted" } };
|
|
36982
|
+
}
|
|
36983
|
+
const [binary2, second, third, ...rest] = tokens;
|
|
36984
|
+
let scriptName = "";
|
|
36985
|
+
let command = binary2;
|
|
36986
|
+
let args = [];
|
|
36987
|
+
if ((binary2 === "npm" || binary2 === "pnpm" || binary2 === "bun") && second === "run" && third) {
|
|
36988
|
+
scriptName = third;
|
|
36989
|
+
args = ["run", scriptName, ...rest];
|
|
36990
|
+
} else if (binary2 === "npm" && second === "test" && !third) {
|
|
36991
|
+
scriptName = "test";
|
|
36992
|
+
args = ["test"];
|
|
36993
|
+
} else if (binary2 === "yarn" && second === "run" && third) {
|
|
36994
|
+
scriptName = third;
|
|
36995
|
+
args = ["run", scriptName, ...rest];
|
|
36996
|
+
} else if (binary2 === "yarn" && second && !third) {
|
|
36997
|
+
scriptName = second;
|
|
36998
|
+
args = [scriptName];
|
|
36999
|
+
} else {
|
|
37000
|
+
return { rejected: { command: rawCommand, category, source, reason: "command is not a supported package-manager script invocation" } };
|
|
37001
|
+
}
|
|
37002
|
+
if (!scriptName || !Object.prototype.hasOwnProperty.call(scripts, scriptName)) {
|
|
37003
|
+
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script is not declared in package.json" } };
|
|
37004
|
+
}
|
|
37005
|
+
if (!scriptMatchesValidationCategory(scriptName, category)) {
|
|
37006
|
+
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script name is outside the validation category allowlist" } };
|
|
37007
|
+
}
|
|
37008
|
+
return {
|
|
37009
|
+
command: {
|
|
37010
|
+
command,
|
|
37011
|
+
args,
|
|
37012
|
+
displayCommand: [command, ...args].join(" "),
|
|
37013
|
+
category,
|
|
37014
|
+
source
|
|
37015
|
+
}
|
|
37016
|
+
};
|
|
37017
|
+
}
|
|
37018
|
+
function collectProjectContextValidationCandidates(mesh) {
|
|
37019
|
+
const commands = mesh?.projectContext?.commands;
|
|
37020
|
+
if (!commands || typeof commands !== "object" || Array.isArray(commands)) return [];
|
|
37021
|
+
const candidates = [];
|
|
37022
|
+
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
37023
|
+
const entries = Array.isArray(commands[category]) ? commands[category] : [];
|
|
37024
|
+
for (const entry of entries) {
|
|
37025
|
+
if (typeof entry?.command !== "string") continue;
|
|
37026
|
+
candidates.push({
|
|
37027
|
+
command: entry.command,
|
|
37028
|
+
category,
|
|
37029
|
+
source: typeof entry.sourcePath === "string" ? entry.sourcePath : "projectContext.commands",
|
|
37030
|
+
confidence: typeof entry.confidence === "string" ? entry.confidence : void 0
|
|
37031
|
+
});
|
|
37032
|
+
}
|
|
37033
|
+
}
|
|
37034
|
+
return candidates.sort((a, b) => {
|
|
37035
|
+
const rank = (value) => value === "high" ? 0 : value === "medium" ? 1 : 2;
|
|
37036
|
+
return rank(a.confidence) - rank(b.confidence);
|
|
37037
|
+
});
|
|
37038
|
+
}
|
|
37039
|
+
function collectPolicyValidationCandidates(mesh) {
|
|
37040
|
+
const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
|
|
37041
|
+
const configured = Array.isArray(policy.validationCommands) ? policy.validationCommands : Array.isArray(policy.validationGate?.commands) ? policy.validationGate.commands : [];
|
|
37042
|
+
return configured.map((entry) => typeof entry === "string" ? { command: entry, category: "", source: "mesh.policy.validationCommands" } : entry).filter((entry) => entry && typeof entry.command === "string").map((entry) => {
|
|
37043
|
+
const commandText = entry.command.trim();
|
|
37044
|
+
const category = REFINE_VALIDATION_CATEGORIES.find((cat) => commandText.includes(` ${cat}`)) ?? "";
|
|
37045
|
+
return { command: commandText, category, source: "mesh.policy.validationCommands" };
|
|
37046
|
+
}).filter((entry) => !!entry.category);
|
|
37047
|
+
}
|
|
37048
|
+
function selectMeshRefineValidationCommands(mesh, workspace) {
|
|
37049
|
+
const scripts = readPackageScripts(workspace);
|
|
37050
|
+
const rejectedCommands = [];
|
|
37051
|
+
const selected = [];
|
|
37052
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37053
|
+
const candidates = [
|
|
37054
|
+
...collectPolicyValidationCandidates(mesh),
|
|
37055
|
+
...collectProjectContextValidationCandidates(mesh)
|
|
37056
|
+
];
|
|
37057
|
+
for (const candidate of candidates) {
|
|
37058
|
+
const parsed = parsePackageManagerValidationCommand(candidate.command, candidate.category, scripts, candidate.source);
|
|
37059
|
+
if (parsed.rejected) {
|
|
37060
|
+
rejectedCommands.push(parsed.rejected);
|
|
37061
|
+
continue;
|
|
37062
|
+
}
|
|
37063
|
+
if (!parsed.command || seen.has(parsed.command.displayCommand)) continue;
|
|
37064
|
+
selected.push(parsed.command);
|
|
37065
|
+
seen.add(parsed.command.displayCommand);
|
|
37066
|
+
if (selected.length >= REFINE_VALIDATION_MAX_COMMANDS) break;
|
|
37067
|
+
}
|
|
37068
|
+
if (!selected.length && candidates.length === 0) {
|
|
37069
|
+
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
37070
|
+
if (!Object.prototype.hasOwnProperty.call(scripts, category)) continue;
|
|
37071
|
+
const fallback = parsePackageManagerValidationCommand(`npm run ${category}`, category, scripts, "package.json:scripts");
|
|
37072
|
+
if (fallback.command && !seen.has(fallback.command.displayCommand)) {
|
|
37073
|
+
selected.push(fallback.command);
|
|
37074
|
+
seen.add(fallback.command.displayCommand);
|
|
37075
|
+
} else if (fallback.rejected) {
|
|
37076
|
+
rejectedCommands.push(fallback.rejected);
|
|
37077
|
+
}
|
|
37078
|
+
if (selected.length >= 2) break;
|
|
37079
|
+
}
|
|
37080
|
+
}
|
|
37081
|
+
return {
|
|
37082
|
+
commands: selected,
|
|
37083
|
+
rejectedCommands,
|
|
37084
|
+
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"
|
|
37085
|
+
};
|
|
37086
|
+
}
|
|
37087
|
+
async function runMeshRefineValidationGate(mesh, workspace) {
|
|
37088
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
37089
|
+
const { promisify: promisify3 } = await import("util");
|
|
37090
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
37091
|
+
const selection = selectMeshRefineValidationCommands(mesh, workspace);
|
|
37092
|
+
const summary = {
|
|
37093
|
+
status: "skipped",
|
|
37094
|
+
required: true,
|
|
37095
|
+
commandsRun: [],
|
|
37096
|
+
rejectedCommands: selection.rejectedCommands,
|
|
37097
|
+
skippedReason: void 0,
|
|
37098
|
+
timeoutMs: REFINE_VALIDATION_TIMEOUT_MS,
|
|
37099
|
+
outputLimitBytes: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES
|
|
37100
|
+
};
|
|
37101
|
+
if (!selection.commands.length) {
|
|
37102
|
+
summary.skippedReason = "validation_unavailable: no allowlisted projectContext, mesh policy, or package.json build/test/typecheck/lint command was available";
|
|
37103
|
+
return summary;
|
|
37104
|
+
}
|
|
37105
|
+
for (const candidate of selection.commands) {
|
|
37106
|
+
const startedAt = Date.now();
|
|
37107
|
+
try {
|
|
37108
|
+
const result = await execFileAsync3(candidate.command, candidate.args, {
|
|
37109
|
+
cwd: workspace,
|
|
37110
|
+
encoding: "utf8",
|
|
37111
|
+
timeout: REFINE_VALIDATION_TIMEOUT_MS,
|
|
37112
|
+
maxBuffer: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
|
|
37113
|
+
env: { ...process.env, CI: process.env.CI || "1" }
|
|
37114
|
+
});
|
|
37115
|
+
summary.commandsRun.push({
|
|
37116
|
+
command: candidate.command,
|
|
37117
|
+
args: candidate.args,
|
|
37118
|
+
displayCommand: candidate.displayCommand,
|
|
37119
|
+
category: candidate.category,
|
|
37120
|
+
source: candidate.source,
|
|
37121
|
+
passed: true,
|
|
37122
|
+
exitCode: 0,
|
|
37123
|
+
durationMs: Date.now() - startedAt,
|
|
37124
|
+
stdout: truncateValidationOutput(result.stdout),
|
|
37125
|
+
stderr: truncateValidationOutput(result.stderr)
|
|
37126
|
+
});
|
|
37127
|
+
} catch (error48) {
|
|
37128
|
+
summary.commandsRun.push({
|
|
37129
|
+
command: candidate.command,
|
|
37130
|
+
args: candidate.args,
|
|
37131
|
+
displayCommand: candidate.displayCommand,
|
|
37132
|
+
category: candidate.category,
|
|
37133
|
+
source: candidate.source,
|
|
37134
|
+
passed: false,
|
|
37135
|
+
exitCode: typeof error48?.code === "number" ? error48.code : null,
|
|
37136
|
+
signal: typeof error48?.signal === "string" ? error48.signal : null,
|
|
37137
|
+
timedOut: error48?.killed === true || /timed out/i.test(String(error48?.message || "")),
|
|
37138
|
+
durationMs: Date.now() - startedAt,
|
|
37139
|
+
stdout: truncateValidationOutput(error48?.stdout),
|
|
37140
|
+
stderr: truncateValidationOutput(error48?.stderr || error48?.message)
|
|
37141
|
+
});
|
|
37142
|
+
summary.status = "failed";
|
|
37143
|
+
return summary;
|
|
37144
|
+
}
|
|
37145
|
+
}
|
|
37146
|
+
summary.status = "passed";
|
|
37147
|
+
return summary;
|
|
37148
|
+
}
|
|
36592
37149
|
function loadYamlModule() {
|
|
36593
37150
|
return js_yaml_exports;
|
|
36594
37151
|
}
|
|
@@ -41136,7 +41693,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
41136
41693
|
}
|
|
41137
41694
|
cdpManagers.clear();
|
|
41138
41695
|
}
|
|
41139
|
-
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, import_fs6, import_path3, import_crypto4, import_events2, import_fs7, import_path4, import_crypto5,
|
|
41696
|
+
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, import_fs6, import_path3, import_crypto4, import_events2, import_fs7, import_path4, import_crypto5, import_child_process2, os22, path8, import_fs8, fs2, path9, os32, os8, os9, path14, import_child_process3, os10, path15, os11, import_child_process4, import_fs9, import_promises5, path, import_util4, import_promises6, path22, path32, fs, os4, path5, import_crypto6, path6, path7, import_fs10, import_path5, import_child_process5, import_fs11, import_os3, path10, os42, import_child_process6, http, crypto2, fs3, path11, os5, fs4, os6, path12, import_crypto7, fs5, path13, os7, os13, path18, crypto4, import_fs12, import_child_process7, os12, path16, crypto3, fs6, import_module, path17, import_stream2, import_child_process8, import_child_process9, net2, os15, path20, fs7, path19, os14, fs8, path21, os16, import_child_process10, import_crypto8, import_fs13, import_module2, os17, import_path6, os18, import_child_process11, import_child_process12, fs9, os19, path222, import_os4, import_path7, fs10, fs11, path23, os20, import_child_process13, import_os5, http2, fs15, path27, fs12, path24, fs13, path25, fs14, path26, os21, import_child_process14, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __require2, __esm2, __export2, __copyProps2, __toCommonJS2, DEFAULT_MESH_POLICY, init_repo_mesh_types, git_worktree_exports, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER, SUBMODULE_WORKTREE_REMOVE_RE, init_git_worktree, config_exports, DEFAULT_CONFIG, MACHINE_ID_PREFIX, init_config, mesh_config_exports, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES, init_mesh_config, coordinator_prompt_exports, TOOLS_SECTION, TOOL_EXPOSURE_PREFLIGHT_SECTION, WORKFLOW_SECTION, init_coordinator_prompt, mesh_ledger_exports, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, meshLedgerEvents, init_mesh_ledger, mesh_work_queue_exports, init_mesh_work_queue, init_cli_detector, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, init_logger, mesh_events_exports, remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, init_mesh_events, NORMAL_TRACE_BUFFER_SIZE, DEV_TRACE_BUFFER_SIZE, DEFAULT_CONFIG2, currentConfig, init_debug_config, DEFAULT_BINDING_CANDIDATES, cachedBinding, cachedBindingError, GhosttyVtTerminalBackend, init_ghostty_vt_backend, TerminalCtor, XtermTerminalBackend, init_xterm_backend, DEFAULT_SCROLLBACK, loggedTerminalBackends, TerminalScreen, init_terminal_screen, init_spawn_env, cachedPty, NodePtyRuntimeTransport, NodePtyTransportFactory, init_pty_transport, TerminalTranscriptAccumulator, buildCliSpawnEnv, init_provider_cli_shared, init_provider_cli_parse, init_provider_cli_config, init_provider_cli_runtime, provider_cli_adapter_exports, ProviderCliAdapter, init_provider_cli_adapter, execFileAsync, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_BUFFER, GitCommandError, DEFAULT_MAX_FILES, DEFAULT_MAX_BYTES, summarizeGitStatus, InMemoryGitSnapshotStore, DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS, MIN_GIT_WORKSPACE_POLL_INTERVAL_MS, GitWorkspaceMonitor, GIT_COMMAND_NAMES, SNAPSHOT_REASONS, FAILURE_REASONS, defaultSnapshotStore, defaultGitCommandServices, BUSY_STATUSES, TERMINAL_STATUSES, TurnSnapshotTracker, MAX_WORKSPACES, MAX_ACTIVITY, MAX_SAVED_SESSIONS, NO_FALLBACK_REASON, P2P_NEXT_ACTION, NON_P2P_NEXT_ACTION, P2pRelayFailureError, DEFAULT_STATE, BUILTIN_IDE_DEFINITIONS, registeredIDEs, LIVE_LIFECYCLES, DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, LIVE_RUNTIME_LIFECYCLES, DaemonCdpManager, CdpDomHandlers, DEFAULT_MONITOR_CONFIG, StatusMonitor, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET, HISTORY_DIR, RETAIN_DAYS, SAVED_HISTORY_INDEX_VERSION, SAVED_HISTORY_INDEX_FILE, SAVED_HISTORY_INDEX_LOCK_SUFFIX, SAVED_HISTORY_INDEX_LOCK_WAIT_MS, SAVED_HISTORY_INDEX_LOCK_STALE_MS, SAVED_HISTORY_INDEX_LOCK_POLL_MS, SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES, savedHistorySessionCache, savedHistoryFileSummaryCache, savedHistoryBackgroundRefresh, savedHistoryRollupInFlight, ChatHistoryWriter, IDE_PROVIDER_SESSION_CAPABILITIES_BASE, EXTENSION_PROVIDER_SESSION_CAPABILITIES_BASE, ExtensionProviderInstance, VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES, DEFAULT_APPROVAL_POSITIVE_HINTS, IdeProviderInstance, DEFAULT_CDP_SCAN_INTERVAL_MS, DEFAULT_CDP_DISCOVERY_INTERVAL_MS, DEFAULT_STATUS_INITIAL_REPORT_DELAY_MS, DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS, DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS, MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_READY_TIMEOUT_MS, STANDALONE_CDP_SCAN_INTERVAL_MS, DaemonCdpScanner, DaemonCdpInitializer, WORKING_STATUSES, FULL_STATUS_ACTIVE_CHAT_OPTIONS, LIVE_STATUS_ACTIVE_CHAT_OPTIONS, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT, VALID_INPUT_MEDIA_TYPES, VALID_INPUT_STRATEGIES, TEXT_ONLY_MESSAGE_INPUT_SUPPORT, IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, CLI_CHAT_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES, globalStore, RECENT_SEND_WINDOW_MS, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS, HERMES_CLI_STARTING_SEND_SETTLE_MS, recentSendByTarget, DEFAULT_DEBUG_SANITIZE_OPTIONS, SECRET_KEY_PATTERN, KEY_TO_VK, COMMAND_DEBUG_LEVELS, DaemonCommandHandler, COMPLETED_FINALIZATION_RETRY_MS, COMPLETED_FINALIZATION_MAX_WAIT_MS, IMAGE_MIME_EXTENSIONS, MATERIALIZED_IMAGE_MAX_AGE_MS, MATERIALIZED_IMAGE_CLEANUP_INTERVAL_MS, lastMaterializedImageCleanupAt, CachedDatabaseSync, CliProviderInstance, AcpProviderInstance, chalkModule, chalkApi, COORDINATOR_DELEGATED_ENV_UNSETS, DaemonCliManager, VALID_CAPABILITY_MEDIA_TYPES, VALID_INPUT_STRATEGIES2, KNOWN_PROVIDER_FIELDS, VALUE_CONTROL_TYPES, ProviderLoader, _providerLoader, LOG_DIR2, MAX_FILE_SIZE, MAX_DAYS, SENSITIVE_KEYS, currentDate2, currentFile, writeCount2, SKIP_COMMANDS, DEFAULT_SERVER_NAME, DEFAULT_ADHDEV_MCP_COMMAND, HERMES_CLI_TYPE, HERMES_MCP_CONFIG_PATH, READ_DEBUG_ENABLED, recentReadDebugSignatureBySession, UPGRADE_HELPER_ENV, CHANNEL_NPM_TAG, CHANNEL_SERVER_URL, REFINE_VALIDATION_CATEGORIES, REFINE_VALIDATION_TIMEOUT_MS, REFINE_VALIDATION_OUTPUT_LIMIT_BYTES, REFINE_VALIDATION_SUMMARY_CHARS, REFINE_VALIDATION_MAX_COMMANDS, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter, DaemonStatusReporter, DEFAULT_DAEMON_PORT, DAEMON_WS_PATH, ProviderStreamAdapter, DaemonAgentStreamManager, AgentStreamPoller, ProviderInstanceManager, ARCHIVE_PATH, MAX_ENTRIES_PER_PROVIDER, VersionArchive, DEV_SERVER_PORT, DevServer, SessionHostRuntimeTransport, SessionHostPtyTransportFactory, DEFAULT_SESSION_HOST_APP_NAME, DEFAULT_STANDALONE_SESSION_HOST_APP_NAME, STARTUP_TIMEOUT_MS, STARTUP_POLL_MS, SessionHostCompatibilityError, EXTENSION_CATALOG, SessionRegistry;
|
|
41140
41697
|
var init_dist2 = __esm({
|
|
41141
41698
|
"../daemon-core/dist/index.mjs"() {
|
|
41142
41699
|
"use strict";
|
|
@@ -41159,20 +41716,24 @@ var init_dist2 = __esm({
|
|
|
41159
41716
|
import_fs7 = require("fs");
|
|
41160
41717
|
import_path4 = require("path");
|
|
41161
41718
|
import_crypto5 = require("crypto");
|
|
41162
|
-
|
|
41163
|
-
path8 = __toESM(require("path"), 1);
|
|
41719
|
+
import_child_process2 = require("child_process");
|
|
41164
41720
|
os22 = __toESM(require("os"), 1);
|
|
41721
|
+
path8 = __toESM(require("path"), 1);
|
|
41722
|
+
import_fs8 = require("fs");
|
|
41723
|
+
fs2 = __toESM(require("fs"), 1);
|
|
41724
|
+
path9 = __toESM(require("path"), 1);
|
|
41725
|
+
os32 = __toESM(require("os"), 1);
|
|
41165
41726
|
init_dist();
|
|
41166
41727
|
os8 = __toESM(require("os"), 1);
|
|
41167
41728
|
os9 = __toESM(require("os"), 1);
|
|
41168
41729
|
path14 = __toESM(require("path"), 1);
|
|
41169
|
-
|
|
41730
|
+
import_child_process3 = require("child_process");
|
|
41170
41731
|
os10 = __toESM(require("os"), 1);
|
|
41171
41732
|
path15 = __toESM(require("path"), 1);
|
|
41172
41733
|
init_dist();
|
|
41173
41734
|
os11 = __toESM(require("os"), 1);
|
|
41174
|
-
|
|
41175
|
-
|
|
41735
|
+
import_child_process4 = require("child_process");
|
|
41736
|
+
import_fs9 = require("fs");
|
|
41176
41737
|
import_promises5 = require("fs/promises");
|
|
41177
41738
|
path = __toESM(require("path"), 1);
|
|
41178
41739
|
import_util4 = require("util");
|
|
@@ -41185,16 +41746,12 @@ var init_dist2 = __esm({
|
|
|
41185
41746
|
import_crypto6 = require("crypto");
|
|
41186
41747
|
path6 = __toESM(require("path"), 1);
|
|
41187
41748
|
path7 = __toESM(require("path"), 1);
|
|
41188
|
-
import_fs9 = require("fs");
|
|
41189
|
-
import_path5 = require("path");
|
|
41190
|
-
import_child_process4 = require("child_process");
|
|
41191
41749
|
import_fs10 = require("fs");
|
|
41192
|
-
|
|
41193
|
-
path9 = __toESM(require("path"), 1);
|
|
41750
|
+
import_path5 = require("path");
|
|
41194
41751
|
import_child_process5 = require("child_process");
|
|
41195
|
-
os32 = __toESM(require("os"), 1);
|
|
41196
|
-
path10 = __toESM(require("path"), 1);
|
|
41197
41752
|
import_fs11 = require("fs");
|
|
41753
|
+
import_os3 = require("os");
|
|
41754
|
+
path10 = __toESM(require("path"), 1);
|
|
41198
41755
|
os42 = __toESM(require("os"), 1);
|
|
41199
41756
|
import_child_process6 = require("child_process");
|
|
41200
41757
|
init_wrapper();
|
|
@@ -41327,6 +41884,7 @@ var init_dist2 = __esm({
|
|
|
41327
41884
|
WORKTREE_DIR_NAME = ".adhdev-worktrees";
|
|
41328
41885
|
GIT_TIMEOUT_MS = 3e4;
|
|
41329
41886
|
GIT_MAX_BUFFER = 4 * 1024 * 1024;
|
|
41887
|
+
SUBMODULE_WORKTREE_REMOVE_RE = /working trees containing submodules cannot be moved or removed/i;
|
|
41330
41888
|
}
|
|
41331
41889
|
});
|
|
41332
41890
|
config_exports = {};
|
|
@@ -41485,6 +42043,7 @@ Follow these recovery rules:
|
|
|
41485
42043
|
enqueueTask: () => enqueueTask,
|
|
41486
42044
|
getMeshQueueStats: () => getMeshQueueStats,
|
|
41487
42045
|
getQueue: () => getQueue,
|
|
42046
|
+
recordTaskAutoLaunch: () => recordTaskAutoLaunch,
|
|
41488
42047
|
requeueTask: () => requeueTask,
|
|
41489
42048
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
41490
42049
|
updateTaskStatus: () => updateTaskStatus
|
|
@@ -41495,13 +42054,18 @@ Follow these recovery rules:
|
|
|
41495
42054
|
init_mesh_ledger();
|
|
41496
42055
|
}
|
|
41497
42056
|
});
|
|
42057
|
+
init_cli_detector = __esm2({
|
|
42058
|
+
"src/detection/cli-detector.ts"() {
|
|
42059
|
+
"use strict";
|
|
42060
|
+
}
|
|
42061
|
+
});
|
|
41498
42062
|
init_logger = __esm2({
|
|
41499
42063
|
"src/logging/logger.ts"() {
|
|
41500
42064
|
"use strict";
|
|
41501
42065
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
41502
42066
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
41503
42067
|
currentLevel = "info";
|
|
41504
|
-
LOG_DIR = process.platform === "win32" ?
|
|
42068
|
+
LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os32.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os32.homedir(), "Library", "Logs", "adhdev") : path9.join(os32.homedir(), ".local", "share", "adhdev", "logs");
|
|
41505
42069
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
41506
42070
|
MAX_LOG_DAYS = 7;
|
|
41507
42071
|
try {
|
|
@@ -41509,16 +42073,16 @@ Follow these recovery rules:
|
|
|
41509
42073
|
} catch {
|
|
41510
42074
|
}
|
|
41511
42075
|
currentDate = getDateStr();
|
|
41512
|
-
currentLogFile =
|
|
42076
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
41513
42077
|
cleanOldLogs();
|
|
41514
42078
|
try {
|
|
41515
|
-
const oldLog =
|
|
42079
|
+
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
41516
42080
|
if (fs2.existsSync(oldLog)) {
|
|
41517
42081
|
const stat22 = fs2.statSync(oldLog);
|
|
41518
42082
|
const oldDate = stat22.mtime.toISOString().slice(0, 10);
|
|
41519
|
-
fs2.renameSync(oldLog,
|
|
42083
|
+
fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
41520
42084
|
}
|
|
41521
|
-
const oldLogBackup =
|
|
42085
|
+
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
41522
42086
|
if (fs2.existsSync(oldLogBackup)) {
|
|
41523
42087
|
fs2.unlinkSync(oldLogBackup);
|
|
41524
42088
|
}
|
|
@@ -41550,7 +42114,7 @@ Follow these recovery rules:
|
|
|
41550
42114
|
}
|
|
41551
42115
|
};
|
|
41552
42116
|
interceptorInstalled = false;
|
|
41553
|
-
LOG_PATH =
|
|
42117
|
+
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
41554
42118
|
}
|
|
41555
42119
|
});
|
|
41556
42120
|
mesh_events_exports = {};
|
|
@@ -41564,7 +42128,9 @@ Follow these recovery rules:
|
|
|
41564
42128
|
init_mesh_events = __esm2({
|
|
41565
42129
|
"src/mesh/mesh-events.ts"() {
|
|
41566
42130
|
"use strict";
|
|
42131
|
+
init_config();
|
|
41567
42132
|
init_mesh_config();
|
|
42133
|
+
init_cli_detector();
|
|
41568
42134
|
init_logger();
|
|
41569
42135
|
init_mesh_ledger();
|
|
41570
42136
|
init_mesh_work_queue();
|
|
@@ -41585,6 +42151,9 @@ Follow these recovery rules:
|
|
|
41585
42151
|
"agent:stopped": "task_failed",
|
|
41586
42152
|
"monitor:long_generating": "task_stalled"
|
|
41587
42153
|
};
|
|
42154
|
+
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
42155
|
+
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
42156
|
+
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
41588
42157
|
}
|
|
41589
42158
|
});
|
|
41590
42159
|
init_debug_config = __esm2({
|
|
@@ -44078,7 +44647,7 @@ ${lastSnapshot}`;
|
|
|
44078
44647
|
}
|
|
44079
44648
|
});
|
|
44080
44649
|
init_repo_mesh_types();
|
|
44081
|
-
execFileAsync = (0, import_util4.promisify)(
|
|
44650
|
+
execFileAsync = (0, import_util4.promisify)(import_child_process4.execFile);
|
|
44082
44651
|
DEFAULT_TIMEOUT_MS = 5e3;
|
|
44083
44652
|
DEFAULT_MAX_BUFFER = 1024 * 1024;
|
|
44084
44653
|
GitCommandError = class extends Error {
|
|
@@ -44337,6 +44906,34 @@ ${lastSnapshot}`;
|
|
|
44337
44906
|
init_mesh_ledger();
|
|
44338
44907
|
init_mesh_work_queue();
|
|
44339
44908
|
init_mesh_events();
|
|
44909
|
+
NO_FALLBACK_REASON = "Repo Mesh command/data-plane is P2P-only; WS/REST command fallback is intentionally disabled to preserve the transport boundary.";
|
|
44910
|
+
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.";
|
|
44911
|
+
NON_P2P_NEXT_ACTION = "Inspect the provider/command error and fix the underlying logic or configuration before retrying.";
|
|
44912
|
+
P2pRelayFailureError = class extends Error {
|
|
44913
|
+
code;
|
|
44914
|
+
reason;
|
|
44915
|
+
transport;
|
|
44916
|
+
recoverable;
|
|
44917
|
+
retryRecommended;
|
|
44918
|
+
nextAction;
|
|
44919
|
+
noFallbackReason;
|
|
44920
|
+
command;
|
|
44921
|
+
targetDaemonId;
|
|
44922
|
+
constructor(message, context = {}) {
|
|
44923
|
+
super(message);
|
|
44924
|
+
this.name = "P2pRelayFailureError";
|
|
44925
|
+
const payload = buildP2pRelayFailurePayload(message, context);
|
|
44926
|
+
this.code = payload.code;
|
|
44927
|
+
this.reason = payload.reason;
|
|
44928
|
+
this.transport = payload.transport;
|
|
44929
|
+
this.recoverable = payload.recoverable;
|
|
44930
|
+
this.retryRecommended = payload.retryRecommended;
|
|
44931
|
+
this.nextAction = payload.nextAction;
|
|
44932
|
+
this.noFallbackReason = payload.noFallbackReason;
|
|
44933
|
+
this.command = context.command;
|
|
44934
|
+
this.targetDaemonId = context.targetDaemonId;
|
|
44935
|
+
}
|
|
44936
|
+
};
|
|
44340
44937
|
init_config();
|
|
44341
44938
|
DEFAULT_STATE = {
|
|
44342
44939
|
recentActivity: [],
|
|
@@ -44348,6 +44945,7 @@ ${lastSnapshot}`;
|
|
|
44348
44945
|
};
|
|
44349
44946
|
BUILTIN_IDE_DEFINITIONS = [];
|
|
44350
44947
|
registeredIDEs = /* @__PURE__ */ new Map();
|
|
44948
|
+
init_cli_detector();
|
|
44351
44949
|
LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
44352
44950
|
DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
44353
44951
|
"generating",
|
|
@@ -48079,6 +48677,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
48079
48677
|
}
|
|
48080
48678
|
};
|
|
48081
48679
|
init_provider_cli_adapter();
|
|
48680
|
+
init_cli_detector();
|
|
48082
48681
|
init_config();
|
|
48083
48682
|
init_provider_cli_adapter();
|
|
48084
48683
|
init_logger();
|
|
@@ -52430,6 +53029,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52430
53029
|
};
|
|
52431
53030
|
_providerLoader = null;
|
|
52432
53031
|
init_config();
|
|
53032
|
+
init_cli_detector();
|
|
52433
53033
|
init_logger();
|
|
52434
53034
|
LOG_DIR2 = process.platform === "win32" ? path21.join(process.env.LOCALAPPDATA || process.env.APPDATA || path21.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path21.join(os16.homedir(), "Library", "Logs", "adhdev") : path21.join(os16.homedir(), ".local", "share", "adhdev", "logs");
|
|
52435
53035
|
MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
@@ -52478,6 +53078,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52478
53078
|
stable: "https://api.adhf.dev",
|
|
52479
53079
|
preview: "https://api-preview.adhf.dev"
|
|
52480
53080
|
};
|
|
53081
|
+
REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
|
|
53082
|
+
REFINE_VALIDATION_TIMEOUT_MS = 12e4;
|
|
53083
|
+
REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
53084
|
+
REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
|
|
53085
|
+
REFINE_VALIDATION_MAX_COMMANDS = 4;
|
|
52481
53086
|
CHAT_COMMANDS = [
|
|
52482
53087
|
"send_chat",
|
|
52483
53088
|
"new_chat",
|
|
@@ -52610,20 +53215,98 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52610
53215
|
recoveryHint: "Inspect the worktree branch and mesh metadata before retrying cleanup."
|
|
52611
53216
|
};
|
|
52612
53217
|
}
|
|
53218
|
+
const forceFallbackConvergence = await this.getWorktreeForceCleanupConvergence({
|
|
53219
|
+
repoRoot,
|
|
53220
|
+
workspace,
|
|
53221
|
+
node: args.node
|
|
53222
|
+
});
|
|
52613
53223
|
try {
|
|
52614
|
-
const result = await removeWorktree2(repoRoot, workspace, {
|
|
52615
|
-
|
|
53224
|
+
const result = await removeWorktree2(repoRoot, workspace, {
|
|
53225
|
+
requireClean: true,
|
|
53226
|
+
allowSubmoduleForceFallback: forceFallbackConvergence.allow
|
|
53227
|
+
});
|
|
53228
|
+
return {
|
|
53229
|
+
success: true,
|
|
53230
|
+
removedPath: result.removedPath,
|
|
53231
|
+
repoRoot,
|
|
53232
|
+
...result.fallback ? {
|
|
53233
|
+
fallback: result.fallback,
|
|
53234
|
+
forced: result.forced,
|
|
53235
|
+
reason: result.reason,
|
|
53236
|
+
convergence: forceFallbackConvergence
|
|
53237
|
+
} : {}
|
|
53238
|
+
};
|
|
52616
53239
|
} catch (e) {
|
|
52617
53240
|
const message = String(e?.message || e || "worktree cleanup failed");
|
|
52618
53241
|
const dirty = message.includes("dirty worktree") || message.includes("local changes");
|
|
53242
|
+
const submoduleForceBlocked = /working trees containing submodules cannot be moved or removed/i.test(message) && !forceFallbackConvergence.allow;
|
|
52619
53243
|
return {
|
|
52620
53244
|
success: false,
|
|
52621
|
-
code: dirty ? "mesh_worktree_cleanup_dirty" : "mesh_worktree_cleanup_failed",
|
|
52622
|
-
error: message,
|
|
52623
|
-
recoveryHint: dirty ? "Commit, stash, or intentionally discard the worktree changes before retrying mesh_remove_node. The mesh registry entry is preserved until cleanup is safe." : "Inspect git worktree status/list from the source repo and retry after resolving the reported cleanup failure."
|
|
53245
|
+
code: dirty ? "mesh_worktree_cleanup_dirty" : submoduleForceBlocked ? "mesh_worktree_cleanup_force_fallback_blocked" : "mesh_worktree_cleanup_failed",
|
|
53246
|
+
error: submoduleForceBlocked ? `${message}; refusing --force fallback because convergence could not be verified: ${forceFallbackConvergence.error || "unknown convergence state"}` : message,
|
|
53247
|
+
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.",
|
|
53248
|
+
...submoduleForceBlocked ? { convergence: forceFallbackConvergence } : {}
|
|
52624
53249
|
};
|
|
52625
53250
|
}
|
|
52626
53251
|
}
|
|
53252
|
+
async getWorktreeForceCleanupConvergence(args) {
|
|
53253
|
+
const metadataStatus = typeof args.node?.branchConvergence?.status === "string" ? args.node.branchConvergence.status : "";
|
|
53254
|
+
if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate") {
|
|
53255
|
+
return { allow: true, status: metadataStatus, source: "node_branch_convergence" };
|
|
53256
|
+
}
|
|
53257
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
53258
|
+
const { promisify: promisify3 } = await import("util");
|
|
53259
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
53260
|
+
const runGit2 = async (gitArgs, cwd) => {
|
|
53261
|
+
const { stdout } = await execFileAsync3("git", gitArgs, {
|
|
53262
|
+
cwd,
|
|
53263
|
+
encoding: "utf8",
|
|
53264
|
+
timeout: 3e4,
|
|
53265
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
53266
|
+
windowsHide: true
|
|
53267
|
+
});
|
|
53268
|
+
return String(stdout || "").trim();
|
|
53269
|
+
};
|
|
53270
|
+
let head = "";
|
|
53271
|
+
try {
|
|
53272
|
+
head = await runGit2(["rev-parse", "HEAD"], args.workspace);
|
|
53273
|
+
} catch (e) {
|
|
53274
|
+
return { allow: false, error: `could not resolve worktree HEAD: ${e?.message || e}` };
|
|
53275
|
+
}
|
|
53276
|
+
if (!head) return { allow: false, error: "worktree HEAD is empty" };
|
|
53277
|
+
const candidateRefs = [];
|
|
53278
|
+
try {
|
|
53279
|
+
const defaultBranch = await runGit2(["branch", "--show-current"], args.repoRoot);
|
|
53280
|
+
if (defaultBranch) {
|
|
53281
|
+
candidateRefs.push(defaultBranch, `origin/${defaultBranch}`);
|
|
53282
|
+
}
|
|
53283
|
+
} catch {
|
|
53284
|
+
}
|
|
53285
|
+
candidateRefs.push("origin/main", "origin/master", "main", "master");
|
|
53286
|
+
const seen = /* @__PURE__ */ new Set();
|
|
53287
|
+
const checkedRefs = [];
|
|
53288
|
+
for (const ref of candidateRefs) {
|
|
53289
|
+
if (!ref || seen.has(ref)) continue;
|
|
53290
|
+
seen.add(ref);
|
|
53291
|
+
let commit = "";
|
|
53292
|
+
try {
|
|
53293
|
+
commit = await runGit2(["rev-parse", "--verify", `${ref}^{commit}`], args.repoRoot);
|
|
53294
|
+
} catch {
|
|
53295
|
+
continue;
|
|
53296
|
+
}
|
|
53297
|
+
checkedRefs.push(ref);
|
|
53298
|
+
try {
|
|
53299
|
+
await runGit2(["merge-base", "--is-ancestor", head, commit], args.repoRoot);
|
|
53300
|
+
return { allow: true, status: "merged_to_default_ref", source: "git_merge_base", ref };
|
|
53301
|
+
} catch {
|
|
53302
|
+
}
|
|
53303
|
+
}
|
|
53304
|
+
return {
|
|
53305
|
+
allow: false,
|
|
53306
|
+
status: metadataStatus || void 0,
|
|
53307
|
+
error: checkedRefs.length ? `worktree HEAD is not contained in checked refs: ${checkedRefs.join(", ")}` : "no default/main refs were available for convergence verification"
|
|
53308
|
+
};
|
|
53309
|
+
}
|
|
52627
53310
|
isCompletedHostedSession(record2) {
|
|
52628
53311
|
return record2?.lifecycle === "stopped" || record2?.lifecycle === "failed" || record2?.lifecycle === "interrupted";
|
|
52629
53312
|
}
|
|
@@ -53583,10 +54266,61 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53583
54266
|
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
53584
54267
|
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
53585
54268
|
const baseBranch = baseBranchStdout.trim();
|
|
54269
|
+
const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
|
|
54270
|
+
if (validationSummary.status === "failed") {
|
|
54271
|
+
return {
|
|
54272
|
+
success: false,
|
|
54273
|
+
code: "validation_failed",
|
|
54274
|
+
convergenceStatus: "blocked_review",
|
|
54275
|
+
error: "Refinery validation gate failed; merge/refine was not attempted.",
|
|
54276
|
+
branch,
|
|
54277
|
+
into: baseBranch,
|
|
54278
|
+
validationSummary,
|
|
54279
|
+
finalBranchConvergenceState: {
|
|
54280
|
+
branch,
|
|
54281
|
+
baseBranch,
|
|
54282
|
+
merged: false,
|
|
54283
|
+
removed: false,
|
|
54284
|
+
validation: "failed",
|
|
54285
|
+
status: "blocked_review"
|
|
54286
|
+
}
|
|
54287
|
+
};
|
|
54288
|
+
}
|
|
54289
|
+
if (validationSummary.status === "skipped") {
|
|
54290
|
+
return {
|
|
54291
|
+
success: false,
|
|
54292
|
+
code: "validation_unavailable",
|
|
54293
|
+
convergenceStatus: "blocked_review",
|
|
54294
|
+
error: "Refinery validation gate is required but no allowlisted validation command was available; merge/refine was not attempted.",
|
|
54295
|
+
branch,
|
|
54296
|
+
into: baseBranch,
|
|
54297
|
+
validationSummary,
|
|
54298
|
+
finalBranchConvergenceState: {
|
|
54299
|
+
branch,
|
|
54300
|
+
baseBranch,
|
|
54301
|
+
merged: false,
|
|
54302
|
+
removed: false,
|
|
54303
|
+
validation: "unavailable",
|
|
54304
|
+
status: "blocked_review"
|
|
54305
|
+
}
|
|
54306
|
+
};
|
|
54307
|
+
}
|
|
53586
54308
|
try {
|
|
53587
54309
|
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
53588
54310
|
} catch (e) {
|
|
53589
|
-
return {
|
|
54311
|
+
return {
|
|
54312
|
+
success: false,
|
|
54313
|
+
error: `Merge failed (conflicts?): ${e.message}`,
|
|
54314
|
+
validationSummary,
|
|
54315
|
+
finalBranchConvergenceState: {
|
|
54316
|
+
branch,
|
|
54317
|
+
baseBranch,
|
|
54318
|
+
merged: false,
|
|
54319
|
+
removed: false,
|
|
54320
|
+
validation: "passed",
|
|
54321
|
+
status: "not_mergeable"
|
|
54322
|
+
}
|
|
54323
|
+
};
|
|
53590
54324
|
}
|
|
53591
54325
|
const removeResult = await this.execute("remove_mesh_node", {
|
|
53592
54326
|
meshId,
|
|
@@ -53599,11 +54333,27 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53599
54333
|
appendLedgerEntry2(meshId, {
|
|
53600
54334
|
kind: "node_removed",
|
|
53601
54335
|
nodeId,
|
|
53602
|
-
payload: { refined: true, mergedBranch: branch, into: baseBranch }
|
|
54336
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
|
|
53603
54337
|
});
|
|
53604
54338
|
} catch {
|
|
53605
54339
|
}
|
|
53606
|
-
return {
|
|
54340
|
+
return {
|
|
54341
|
+
success: true,
|
|
54342
|
+
merged: true,
|
|
54343
|
+
branch,
|
|
54344
|
+
into: baseBranch,
|
|
54345
|
+
removeResult,
|
|
54346
|
+
validationSummary,
|
|
54347
|
+
finalBranchConvergenceState: {
|
|
54348
|
+
branch: baseBranch,
|
|
54349
|
+
mergedBranch: branch,
|
|
54350
|
+
baseBranch,
|
|
54351
|
+
merged: true,
|
|
54352
|
+
removed: removeResult?.success !== false,
|
|
54353
|
+
validation: "passed",
|
|
54354
|
+
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
54355
|
+
}
|
|
54356
|
+
};
|
|
53607
54357
|
} catch (e) {
|
|
53608
54358
|
return { success: false, error: e.message };
|
|
53609
54359
|
}
|
|
@@ -53658,7 +54408,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53658
54408
|
sessionCleanupMode,
|
|
53659
54409
|
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
53660
54410
|
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
53661
|
-
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0
|
|
54411
|
+
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0,
|
|
54412
|
+
worktreeCleanupFallback: typeof worktreeCleanup?.fallback === "string" ? worktreeCleanup.fallback : void 0,
|
|
54413
|
+
forced: worktreeCleanup?.forced === true ? true : void 0,
|
|
54414
|
+
forceFallbackReason: typeof worktreeCleanup?.reason === "string" ? worktreeCleanup.reason : void 0
|
|
53662
54415
|
}
|
|
53663
54416
|
});
|
|
53664
54417
|
} catch {
|
|
@@ -57555,6 +58308,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
57555
58308
|
apiKeyName: "OpenAI/Anthropic API key"
|
|
57556
58309
|
}
|
|
57557
58310
|
];
|
|
58311
|
+
init_cli_detector();
|
|
57558
58312
|
SessionRegistry = class {
|
|
57559
58313
|
bySessionId = /* @__PURE__ */ new Map();
|
|
57560
58314
|
byManagerKey = /* @__PURE__ */ new Map();
|
|
@@ -57825,6 +58579,8 @@ function readString(value) {
|
|
|
57825
58579
|
}
|
|
57826
58580
|
var DUPLICATE_DISPATCH_WINDOW_MS = 6e4;
|
|
57827
58581
|
var STALE_ASSIGNED_QUEUE_MS = 30 * 6e4;
|
|
58582
|
+
var ACTIVE_QUEUE_STATUSES = /* @__PURE__ */ new Set(["pending", "assigned"]);
|
|
58583
|
+
var HISTORICAL_QUEUE_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
57828
58584
|
async function refreshMeshFromDaemon(ctx) {
|
|
57829
58585
|
if (!(ctx.transport instanceof IpcTransport)) return;
|
|
57830
58586
|
try {
|
|
@@ -57950,30 +58706,126 @@ function buildMissingNodeReadChatRecovery(ctx, args) {
|
|
|
57950
58706
|
]
|
|
57951
58707
|
};
|
|
57952
58708
|
}
|
|
57953
|
-
function
|
|
58709
|
+
function readSessionRecordId(session) {
|
|
58710
|
+
return readString(session?.id) || readString(session?.sessionId) || readString(session?.session_id) || readString(session?.runtimeSessionId) || readString(session?.runtime_session_id) || readString(session?.instanceId) || readString(session?.instance_id);
|
|
58711
|
+
}
|
|
58712
|
+
function addSessionRecord(target, session) {
|
|
58713
|
+
if (!session || typeof session !== "object" || isTerminalSessionRecord(session)) return;
|
|
58714
|
+
const sessionId = readSessionRecordId(session);
|
|
58715
|
+
if (sessionId) target.add(sessionId);
|
|
58716
|
+
}
|
|
58717
|
+
function collectNodeSessionIds(node) {
|
|
58718
|
+
const sessions = /* @__PURE__ */ new Set();
|
|
58719
|
+
const sessionArrays = [
|
|
58720
|
+
node?.sessions,
|
|
58721
|
+
node?.activeSessions,
|
|
58722
|
+
node?.active_sessions,
|
|
58723
|
+
node?.lastProbe?.sessions,
|
|
58724
|
+
node?.last_probe?.sessions,
|
|
58725
|
+
node?.lastProbe?.status?.sessions,
|
|
58726
|
+
node?.last_probe?.status?.sessions
|
|
58727
|
+
];
|
|
58728
|
+
for (const value of sessionArrays) {
|
|
58729
|
+
if (Array.isArray(value)) value.forEach((session) => addSessionRecord(sessions, session));
|
|
58730
|
+
}
|
|
58731
|
+
const sessionRecords = [
|
|
58732
|
+
node?.activeSession,
|
|
58733
|
+
node?.active_session,
|
|
58734
|
+
node?.currentSession,
|
|
58735
|
+
node?.current_session,
|
|
58736
|
+
node?.runtimeSession,
|
|
58737
|
+
node?.runtime_session,
|
|
58738
|
+
node?.session,
|
|
58739
|
+
node?.lastProbe?.activeSession,
|
|
58740
|
+
node?.last_probe?.active_session,
|
|
58741
|
+
node?.lastProbe?.currentSession,
|
|
58742
|
+
node?.last_probe?.current_session,
|
|
58743
|
+
node?.lastProbe?.session,
|
|
58744
|
+
node?.last_probe?.session
|
|
58745
|
+
];
|
|
58746
|
+
sessionRecords.forEach((session) => addSessionRecord(sessions, session));
|
|
58747
|
+
return sessions;
|
|
58748
|
+
}
|
|
58749
|
+
function buildQueueLivenessIndex(mesh) {
|
|
58750
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
58751
|
+
const nodeSessionIds = /* @__PURE__ */ new Map();
|
|
58752
|
+
for (const node of Array.isArray(mesh?.nodes) ? mesh.nodes : []) {
|
|
58753
|
+
const nodeId = readString(node.id) || readString(node.nodeId) || readString(node.node_id);
|
|
58754
|
+
if (!nodeId) continue;
|
|
58755
|
+
nodeIds.add(nodeId);
|
|
58756
|
+
const sessions = collectNodeSessionIds(node);
|
|
58757
|
+
if (sessions.size > 0) nodeSessionIds.set(nodeId, sessions);
|
|
58758
|
+
}
|
|
58759
|
+
return { nodeIds, nodeSessionIds };
|
|
58760
|
+
}
|
|
58761
|
+
function queueAssignmentStaleReason(task, liveness) {
|
|
58762
|
+
if (task?.status !== "assigned") return void 0;
|
|
58763
|
+
const nodeId = readString(task.assignedNodeId) || readString(task.nodeId) || readString(task.node_id) || readString(task.targetNodeId);
|
|
58764
|
+
const sessionId = readString(task.assignedSessionId) || readString(task.sessionId) || readString(task.session_id) || readString(task.targetSessionId);
|
|
58765
|
+
if (nodeId && liveness.nodeIds.size > 0 && !liveness.nodeIds.has(nodeId)) {
|
|
58766
|
+
return "assigned node is not present in the current mesh snapshot";
|
|
58767
|
+
}
|
|
58768
|
+
if (nodeId && sessionId && liveness.nodeSessionIds.has(nodeId) && !liveness.nodeSessionIds.get(nodeId).has(sessionId)) {
|
|
58769
|
+
return "assigned session is not live on the assigned node";
|
|
58770
|
+
}
|
|
58771
|
+
const updatedAt = new Date(task.updatedAt).getTime();
|
|
58772
|
+
const ageMs = Number.isFinite(updatedAt) ? Date.now() - updatedAt : null;
|
|
58773
|
+
if (!nodeId && ageMs !== null && ageMs >= STALE_ASSIGNED_QUEUE_MS) {
|
|
58774
|
+
return "assigned task has no assigned node metadata";
|
|
58775
|
+
}
|
|
58776
|
+
return void 0;
|
|
58777
|
+
}
|
|
58778
|
+
function buildQueueStatusSummary(queue) {
|
|
58779
|
+
const counts = { pending: 0, assigned: 0, completed: 0, failed: 0, cancelled: 0 };
|
|
58780
|
+
for (const task of queue) {
|
|
58781
|
+
const status = typeof task?.status === "string" ? task.status : void 0;
|
|
58782
|
+
if (status && Object.prototype.hasOwnProperty.call(counts, status)) {
|
|
58783
|
+
counts[status] += 1;
|
|
58784
|
+
}
|
|
58785
|
+
}
|
|
58786
|
+
return {
|
|
58787
|
+
totalCount: queue.length,
|
|
58788
|
+
activeCount: counts.pending + counts.assigned,
|
|
58789
|
+
historicalCount: counts.completed + counts.failed + counts.cancelled,
|
|
58790
|
+
counts,
|
|
58791
|
+
activeCounts: {
|
|
58792
|
+
pending: counts.pending,
|
|
58793
|
+
assigned: counts.assigned
|
|
58794
|
+
},
|
|
58795
|
+
historicalCounts: {
|
|
58796
|
+
completed: counts.completed,
|
|
58797
|
+
failed: counts.failed,
|
|
58798
|
+
cancelled: counts.cancelled
|
|
58799
|
+
}
|
|
58800
|
+
};
|
|
58801
|
+
}
|
|
58802
|
+
function annotateQueueStaleness(queue, mesh) {
|
|
58803
|
+
const liveness = buildQueueLivenessIndex(mesh);
|
|
57954
58804
|
const now = Date.now();
|
|
57955
58805
|
return queue.map((task) => {
|
|
57956
58806
|
const taskStatus = typeof task?.status === "string" ? task.status : void 0;
|
|
57957
58807
|
const annotated = {
|
|
57958
58808
|
...task,
|
|
57959
58809
|
taskStatus,
|
|
58810
|
+
isActive: taskStatus ? ACTIVE_QUEUE_STATUSES.has(taskStatus) : false,
|
|
58811
|
+
isHistorical: taskStatus ? HISTORICAL_QUEUE_STATUSES.has(taskStatus) : false,
|
|
57960
58812
|
dispatchedAt: task?.createdAt,
|
|
57961
58813
|
...taskStatus === "assigned" ? { activeTaskId: task.id } : {},
|
|
57962
58814
|
...taskStatus === "completed" || taskStatus === "failed" ? {
|
|
57963
|
-
isHistorical: true,
|
|
57964
58815
|
completedAt: task.updatedAt
|
|
57965
58816
|
} : {}
|
|
57966
58817
|
};
|
|
57967
58818
|
if (taskStatus !== "assigned") return annotated;
|
|
57968
58819
|
const updatedAt = new Date(task.updatedAt).getTime();
|
|
57969
58820
|
const ageMs = Number.isFinite(updatedAt) ? now - updatedAt : null;
|
|
57970
|
-
|
|
58821
|
+
const staleReason = queueAssignmentStaleReason(task, liveness);
|
|
58822
|
+
if (!staleReason) return annotated;
|
|
57971
58823
|
return {
|
|
57972
58824
|
...annotated,
|
|
57973
58825
|
stale: true,
|
|
57974
58826
|
staleAssigned: true,
|
|
57975
|
-
staleReason
|
|
57976
|
-
assignedAgeMs: ageMs
|
|
58827
|
+
staleReason,
|
|
58828
|
+
...ageMs !== null ? { assignedAgeMs: ageMs } : {}
|
|
57977
58829
|
};
|
|
57978
58830
|
});
|
|
57979
58831
|
}
|
|
@@ -58040,16 +58892,38 @@ function extractLaunchPayload(value) {
|
|
|
58040
58892
|
function classifyMeshLaunchFailure(error48) {
|
|
58041
58893
|
const message = error48 instanceof Error ? error48.message : String(error48 || "launch failed");
|
|
58042
58894
|
const lower = message.toLowerCase();
|
|
58043
|
-
|
|
58044
|
-
|
|
58895
|
+
const p2pClassification = classifyP2pRelayFailure(error48, { command: "launch_cli" });
|
|
58896
|
+
if (p2pClassification.recoverable) {
|
|
58897
|
+
return p2pClassification;
|
|
58045
58898
|
}
|
|
58046
58899
|
if (lower.includes("cannot connect to daemon ipc") || lower.includes("daemon ipc command")) {
|
|
58047
|
-
return {
|
|
58900
|
+
return {
|
|
58901
|
+
code: "local_ipc_unavailable",
|
|
58902
|
+
reason: "local_daemon_ipc_unavailable",
|
|
58903
|
+
transport: "local_ipc",
|
|
58904
|
+
recoverable: true,
|
|
58905
|
+
retryRecommended: true,
|
|
58906
|
+
nextAction: "Check the local daemon IPC connection, then retry mesh_launch_session once after the daemon is reachable."
|
|
58907
|
+
};
|
|
58048
58908
|
}
|
|
58049
58909
|
if (lower.includes("timed out") || lower.includes("timeout")) {
|
|
58050
|
-
return {
|
|
58910
|
+
return {
|
|
58911
|
+
code: "mesh_transport_timeout",
|
|
58912
|
+
reason: "mesh_transport_timeout",
|
|
58913
|
+
transport: "mesh_transport",
|
|
58914
|
+
recoverable: true,
|
|
58915
|
+
retryRecommended: true,
|
|
58916
|
+
nextAction: "Check mesh transport health, then do one bounded retry before requeueing or relaunching the task."
|
|
58917
|
+
};
|
|
58051
58918
|
}
|
|
58052
|
-
return {
|
|
58919
|
+
return {
|
|
58920
|
+
code: "mesh_launch_failed",
|
|
58921
|
+
reason: "provider_launch_failed",
|
|
58922
|
+
transport: "mesh_transport",
|
|
58923
|
+
recoverable: false,
|
|
58924
|
+
retryRecommended: false,
|
|
58925
|
+
nextAction: "Inspect the provider launch error and fix the underlying provider/configuration issue before retrying."
|
|
58926
|
+
};
|
|
58053
58927
|
}
|
|
58054
58928
|
function buildWorktreeCleanupHint(node) {
|
|
58055
58929
|
if (!node.isLocalWorktree) return void 0;
|
|
@@ -58065,10 +58939,13 @@ function buildRecoverableLaunchFailure(ctx, node, providerType, error48) {
|
|
|
58065
58939
|
const cleanup = buildWorktreeCleanupHint(node);
|
|
58066
58940
|
return {
|
|
58067
58941
|
success: false,
|
|
58068
|
-
recoverable:
|
|
58942
|
+
recoverable: classified.recoverable,
|
|
58069
58943
|
code: classified.code,
|
|
58070
58944
|
reason: classified.reason,
|
|
58071
58945
|
transport: classified.transport,
|
|
58946
|
+
retryRecommended: classified.retryRecommended,
|
|
58947
|
+
nextAction: classified.nextAction,
|
|
58948
|
+
...classified.noFallbackReason ? { noFallbackReason: classified.noFallbackReason } : {},
|
|
58072
58949
|
error: message,
|
|
58073
58950
|
meshId: ctx.mesh.id,
|
|
58074
58951
|
nodeId: node.id,
|
|
@@ -58115,6 +58992,18 @@ function getLatestActiveLaunchFailure(meshId, nodeId) {
|
|
|
58115
58992
|
}
|
|
58116
58993
|
return null;
|
|
58117
58994
|
}
|
|
58995
|
+
function buildCoordinatorP2pRelayFailure(error48, context) {
|
|
58996
|
+
const payload = buildP2pRelayFailurePayload(error48, {
|
|
58997
|
+
command: context.command,
|
|
58998
|
+
targetDaemonId: context.targetDaemonId
|
|
58999
|
+
});
|
|
59000
|
+
return {
|
|
59001
|
+
...payload,
|
|
59002
|
+
...context.nodeId ? { nodeId: context.nodeId } : {},
|
|
59003
|
+
...context.sessionId ? { sessionId: context.sessionId } : {},
|
|
59004
|
+
retryHint: payload.retryRecommended ? payload.nextAction : "Do not retry as a P2P transport recovery; inspect the command/provider error first."
|
|
59005
|
+
};
|
|
59006
|
+
}
|
|
58118
59007
|
async function ipcDispatchToRemoteAgent(ctx, node, args) {
|
|
58119
59008
|
const transport = ctx.transport;
|
|
58120
59009
|
const daemonId = node.daemonId;
|
|
@@ -58150,11 +59039,32 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
|
|
|
58150
59039
|
});
|
|
58151
59040
|
const dispatchPayload = unwrapCommandPayload(dispatchResult);
|
|
58152
59041
|
if (dispatchPayload?.success === false || dispatchResult?.success === false) {
|
|
58153
|
-
|
|
59042
|
+
const source = dispatchPayload?.success === false ? dispatchPayload : dispatchResult;
|
|
59043
|
+
const errorMessage = dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task";
|
|
59044
|
+
return {
|
|
59045
|
+
...buildCoordinatorP2pRelayFailure(source?.error || errorMessage, {
|
|
59046
|
+
command: "agent_command",
|
|
59047
|
+
targetDaemonId: daemonId,
|
|
59048
|
+
nodeId: node.id,
|
|
59049
|
+
sessionId
|
|
59050
|
+
}),
|
|
59051
|
+
...source && typeof source === "object" ? source : {},
|
|
59052
|
+
success: false,
|
|
59053
|
+
error: `P2P dispatch failed: ${errorMessage}`
|
|
59054
|
+
};
|
|
58154
59055
|
}
|
|
58155
59056
|
return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType };
|
|
58156
59057
|
} catch (e) {
|
|
58157
|
-
|
|
59058
|
+
const errorMessage = e?.message || String(e);
|
|
59059
|
+
return {
|
|
59060
|
+
...buildCoordinatorP2pRelayFailure(e, {
|
|
59061
|
+
command: "agent_command",
|
|
59062
|
+
targetDaemonId: daemonId,
|
|
59063
|
+
nodeId: node.id,
|
|
59064
|
+
sessionId
|
|
59065
|
+
}),
|
|
59066
|
+
error: `P2P dispatch failed: ${errorMessage}`
|
|
59067
|
+
};
|
|
58158
59068
|
}
|
|
58159
59069
|
}
|
|
58160
59070
|
function resolveCoordinatorNode(ctx) {
|
|
@@ -58399,8 +59309,7 @@ async function commandForNode(ctx, node, command, args = {}) {
|
|
|
58399
59309
|
throw new Error(`Command '${command}' requires daemon IPC/local transport for node '${node.id}'`);
|
|
58400
59310
|
}
|
|
58401
59311
|
function isP2pTransportUnavailableError(error48) {
|
|
58402
|
-
|
|
58403
|
-
return /p2p|datachannel|mesh_relay_command|daemon_mesh_p2p_transport_unavailable/i.test(message) && /unavailable|failed|timeout|timed out|not connected|closed/i.test(message);
|
|
59312
|
+
return isP2pRelayTransportFailure(error48);
|
|
58404
59313
|
}
|
|
58405
59314
|
function buildRemoveNodeArgs(ctx, nodeId, sessionCleanupMode) {
|
|
58406
59315
|
return {
|
|
@@ -58847,11 +59756,17 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
58847
59756
|
}
|
|
58848
59757
|
async function meshViewQueue(ctx, args) {
|
|
58849
59758
|
try {
|
|
58850
|
-
const queue = annotateQueueStaleness(getQueue(ctx.mesh.id, { status: args.status }));
|
|
59759
|
+
const queue = annotateQueueStaleness(getQueue(ctx.mesh.id, { status: args.status }), ctx.mesh);
|
|
58851
59760
|
const staleAssignedTasks = queue.filter((task) => task?.status === "assigned" && task?.staleAssigned);
|
|
59761
|
+
const summary = buildQueueStatusSummary(queue);
|
|
58852
59762
|
return JSON.stringify({
|
|
58853
59763
|
success: true,
|
|
58854
59764
|
queue,
|
|
59765
|
+
summary,
|
|
59766
|
+
activeCounts: summary.activeCounts,
|
|
59767
|
+
historicalCounts: summary.historicalCounts,
|
|
59768
|
+
activeCount: summary.activeCount,
|
|
59769
|
+
historicalCount: summary.historicalCount,
|
|
58855
59770
|
staleAssignedTasks,
|
|
58856
59771
|
staleAssignedCount: staleAssignedTasks.length,
|
|
58857
59772
|
// Back-compat alias for callers already reading the first hardening payload.
|
|
@@ -58993,7 +59908,13 @@ async function meshSendTask(ctx, args) {
|
|
|
58993
59908
|
}
|
|
58994
59909
|
return JSON.stringify({ success: true, nodeId: args.node_id, taskId: task.id, status: task.status });
|
|
58995
59910
|
} catch (e) {
|
|
58996
|
-
|
|
59911
|
+
const failure2 = buildCoordinatorP2pRelayFailure(e, {
|
|
59912
|
+
command: "mesh_send_task",
|
|
59913
|
+
targetDaemonId: node.daemonId,
|
|
59914
|
+
nodeId: args.node_id,
|
|
59915
|
+
sessionId: args.session_id
|
|
59916
|
+
});
|
|
59917
|
+
return JSON.stringify(failure2);
|
|
58997
59918
|
}
|
|
58998
59919
|
}
|
|
58999
59920
|
async function meshReadChat(ctx, args) {
|