@adhdev/daemon-standalone 0.9.77-rc.43 → 0.9.77-rc.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +941 -180
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +1011 -195
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/index.js
CHANGED
|
@@ -22210,7 +22210,33 @@ var require_dist2 = __commonJS({
|
|
|
22210
22210
|
});
|
|
22211
22211
|
} catch (error48) {
|
|
22212
22212
|
const stderr = typeof error48.stderr === "string" ? error48.stderr : "";
|
|
22213
|
-
|
|
22213
|
+
const stdout = typeof error48.stdout === "string" ? error48.stdout : "";
|
|
22214
|
+
const detail = `${stderr}
|
|
22215
|
+
${stdout}
|
|
22216
|
+
${error48.message || ""}`;
|
|
22217
|
+
if (opts.allowSubmoduleForceFallback && SUBMODULE_WORKTREE_REMOVE_RE.test(detail)) {
|
|
22218
|
+
try {
|
|
22219
|
+
await execFileAsync2("git", ["worktree", "remove", "--force", worktreePath], {
|
|
22220
|
+
cwd: repoRoot,
|
|
22221
|
+
encoding: "utf8",
|
|
22222
|
+
timeout: GIT_TIMEOUT_MS,
|
|
22223
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
22224
|
+
windowsHide: true
|
|
22225
|
+
});
|
|
22226
|
+
} catch (forceError) {
|
|
22227
|
+
const forceStderr = typeof forceError.stderr === "string" ? forceError.stderr : "";
|
|
22228
|
+
const forceStdout = typeof forceError.stdout === "string" ? forceError.stdout : "";
|
|
22229
|
+
throw new Error(`git worktree remove --force fallback failed: ${forceStderr.trim() || forceStdout.trim() || forceError.message}`);
|
|
22230
|
+
}
|
|
22231
|
+
return {
|
|
22232
|
+
success: true,
|
|
22233
|
+
removedPath: worktreePath,
|
|
22234
|
+
fallback: "git_worktree_remove_force_submodule",
|
|
22235
|
+
forced: true,
|
|
22236
|
+
reason: "working_trees_containing_submodules"
|
|
22237
|
+
};
|
|
22238
|
+
}
|
|
22239
|
+
throw new Error(`git worktree remove failed: ${stderr.trim() || stdout.trim() || error48.message}`);
|
|
22214
22240
|
}
|
|
22215
22241
|
return { success: true, removedPath: worktreePath };
|
|
22216
22242
|
}
|
|
@@ -22269,6 +22295,7 @@ var require_dist2 = __commonJS({
|
|
|
22269
22295
|
var WORKTREE_DIR_NAME;
|
|
22270
22296
|
var GIT_TIMEOUT_MS;
|
|
22271
22297
|
var GIT_MAX_BUFFER;
|
|
22298
|
+
var SUBMODULE_WORKTREE_REMOVE_RE;
|
|
22272
22299
|
var init_git_worktree = __esm2({
|
|
22273
22300
|
"src/git/git-worktree.ts"() {
|
|
22274
22301
|
"use strict";
|
|
@@ -22281,6 +22308,7 @@ var require_dist2 = __commonJS({
|
|
|
22281
22308
|
WORKTREE_DIR_NAME = ".adhdev-worktrees";
|
|
22282
22309
|
GIT_TIMEOUT_MS = 3e4;
|
|
22283
22310
|
GIT_MAX_BUFFER = 4 * 1024 * 1024;
|
|
22311
|
+
SUBMODULE_WORKTREE_REMOVE_RE = /working trees containing submodules cannot be moved or removed/i;
|
|
22284
22312
|
}
|
|
22285
22313
|
});
|
|
22286
22314
|
var config_exports = {};
|
|
@@ -22787,7 +22815,8 @@ ${rules.join("\n")}`;
|
|
|
22787
22815
|
- **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
|
|
22788
22816
|
- **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to the queue or a node. Do not do it yourself.
|
|
22789
22817
|
- **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes \u2192 \`hermes-cli\`, Claude Code/Claude \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
|
|
22790
|
-
- **Front-load
|
|
22818
|
+
- **Front-load new task messages.** When calling \`mesh_enqueue_task\` or \`mesh_send_task\` for a new task, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
|
|
22819
|
+
- **Avoid context-wasting restarts.** For follow-up, retry, commit/push, preview, or cleanup work on the same issue, prefer the existing idle session and send only the delta from its last verified state. Start a fresh chat/session only for genuinely independent work, explicit provider/user request, unsafe transcript contamination, or required branch/worktree isolation.
|
|
22791
22820
|
- **Don't inspect code.** Treat delegated agent summaries as self-reports, not verification. Verify side effects via \`mesh_git_status\` (including related repo freshness when configured), not by reading source files.
|
|
22792
22821
|
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed. Never launch a duplicate session or second worker solely because \`mesh_read_chat\` has no final assistant message while the delegated session is still showing tool/terminal activity.
|
|
22793
22822
|
- **Handle failures with context.** If a task fails, check \`mesh_task_history\` first to see if this task was attempted before and how it failed. Read the chat to understand why, then decide: retry on the same node, reassign to a different node, or escalate to the user.
|
|
@@ -22810,18 +22839,24 @@ ${rules.join("\n")}`;
|
|
|
22810
22839
|
|
|
22811
22840
|
| Tool | Purpose |
|
|
22812
22841
|
|------|---------|
|
|
22813
|
-
| \`mesh_status\` | Check all nodes' health, git state,
|
|
22842
|
+
| \`mesh_status\` | Check all nodes' health, git state, active sessions, and branch convergence |
|
|
22814
22843
|
| \`mesh_list_nodes\` | List nodes with workspace paths |
|
|
22844
|
+
| \`mesh_enqueue_task\` | Add a task to the pull-based work queue; idle nodes auto-claim |
|
|
22845
|
+
| \`mesh_view_queue\` | View queue status \u2014 pending, assigned, completed, failed, cancelled tasks |
|
|
22846
|
+
| \`mesh_queue_cancel\` | Cancel a queue task without deleting audit history |
|
|
22847
|
+
| \`mesh_queue_requeue\` | Return a task to pending for retry; clears stale session targets |
|
|
22848
|
+
| \`mesh_send_task\` | Legacy push: enqueue a task targeted at a specific node |
|
|
22815
22849
|
| \`mesh_launch_session\` | Start a new agent session on a node |
|
|
22816
|
-
| \`
|
|
22817
|
-
| \`
|
|
22850
|
+
| \`mesh_read_chat\` | Read recent chat messages from a delegated agent session |
|
|
22851
|
+
| \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
|
|
22818
22852
|
| \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
|
|
22819
22853
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
22820
22854
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
22821
22855
|
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
22822
22856
|
| \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
|
|
22823
22857
|
| \`mesh_refine_node\` | Validate and merge a completed worktree node back into its base branch |
|
|
22824
|
-
| \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable)
|
|
22858
|
+
| \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |
|
|
22859
|
+
| \`mesh_cleanup_sessions\` | Manually clean up delegated session records for a node |`;
|
|
22825
22860
|
TOOL_EXPOSURE_PREFLIGHT_SECTION = `## Tool Exposure Preflight
|
|
22826
22861
|
|
|
22827
22862
|
Before doing any coordinator work, confirm that the actual callable tool list includes \`mesh_status\` and the other \`mesh_*\` tools from the table above. If this Repo Mesh coordinator prompt is present but the callable \`mesh_*\` tools are missing, the MCP server/tool manifest is stale or not injected yet. Do not substitute terminal/file/git tools, do not inspect or edit the repository directly, and do not continue as a non-mesh local coding agent. Stop immediately and tell the user to run \`/reload-mcp\` or start a fresh coordinator session so ADHDev can reconnect \`adhdev-mesh\`.`;
|
|
@@ -22831,9 +22866,10 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
22831
22866
|
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist. If \`mesh_task_history\` shows a recent failure for a task, decide whether to retry or reassign.
|
|
22832
22867
|
3. **Queue / Delegate** \u2014 The Mesh uses an autonomous pull-based Work Queue:
|
|
22833
22868
|
a. **General Tasks**: Enqueue tasks using \`mesh_enqueue_task\`. Idle node agents will automatically pull tasks from the queue and begin working.
|
|
22834
|
-
b. **Node Preparation**: Call \`mesh_launch_session\`
|
|
22869
|
+
b. **Node Preparation**: Reuse an existing idle session on the correct node/provider before launching a new chat/session. Call \`mesh_launch_session\` only when no suitable session exists, when the user explicitly asks for a fresh provider/session, or when branch/worktree isolation requires it. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
22835
22870
|
c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
|
|
22836
|
-
d.
|
|
22871
|
+
d. For the first dispatch of a new task, provide a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
|
|
22872
|
+
e. For a continuation of the same issue in an existing session, send a concise **delta instruction**: current verified state, the exact failed/blocked step, the newly approved action, and final reporting requirements. Do not resend the full original task or open a new chat solely to continue the same work; that wastes coordinator and worker context.
|
|
22837
22873
|
4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Use \`mesh_view_queue\` to see the status of all pending, assigned, completed, and failed tasks. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal. Handle approvals via \`mesh_approve\`.
|
|
22838
22874
|
5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
|
|
22839
22875
|
6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
|
|
@@ -22849,7 +22885,7 @@ When a node agent stops unexpectedly, the daemon automatically enriches the syst
|
|
|
22849
22885
|
- A recommendation: **retry**, **reassign**, or **escalate**
|
|
22850
22886
|
|
|
22851
22887
|
Follow these recovery rules:
|
|
22852
|
-
1. **If "Retry recommended"**:
|
|
22888
|
+
1. **If "Retry recommended"**: Check \`mesh_view_queue\` first \u2014 the daemon may have auto-requeued. If not, re-launch the session on the same node (\`mesh_launch_session\`), then resend the original task (\`mesh_send_task\`). The system message includes the original task text.
|
|
22853
22889
|
2. **If "Max retries exceeded"**: Do NOT retry on the same node. Either reassign the task to a different node, or inform the user that the task requires manual intervention.
|
|
22854
22890
|
3. **If no recovery context**: The stop may be intentional (normal completion). Use \`mesh_read_chat\` once to verify, then move on.
|
|
22855
22891
|
4. **Always record what happened**: After handling a failure, briefly note the outcome in your report to the user.`;
|
|
@@ -23104,6 +23140,7 @@ Follow these recovery rules:
|
|
|
23104
23140
|
enqueueTask: () => enqueueTask,
|
|
23105
23141
|
getMeshQueueStats: () => getMeshQueueStats,
|
|
23106
23142
|
getQueue: () => getQueue,
|
|
23143
|
+
recordTaskAutoLaunch: () => recordTaskAutoLaunch,
|
|
23107
23144
|
requeueTask: () => requeueTask,
|
|
23108
23145
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
23109
23146
|
updateTaskStatus: () => updateTaskStatus
|
|
@@ -23179,6 +23216,19 @@ Follow these recovery rules:
|
|
|
23179
23216
|
writeQueue(meshId, queue);
|
|
23180
23217
|
return queue[idx];
|
|
23181
23218
|
}
|
|
23219
|
+
function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
|
|
23220
|
+
const queue = readQueue(meshId);
|
|
23221
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
23222
|
+
if (idx === -1) return null;
|
|
23223
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23224
|
+
queue[idx].autoLaunch = {
|
|
23225
|
+
...autoLaunch,
|
|
23226
|
+
updatedAt: now
|
|
23227
|
+
};
|
|
23228
|
+
queue[idx].updatedAt = now;
|
|
23229
|
+
writeQueue(meshId, queue);
|
|
23230
|
+
return queue[idx];
|
|
23231
|
+
}
|
|
23182
23232
|
function cancelTask(meshId, taskId, opts) {
|
|
23183
23233
|
const queue = readQueue(meshId);
|
|
23184
23234
|
const idx = queue.findIndex((q) => q.id === taskId);
|
|
@@ -23253,6 +23303,142 @@ Follow these recovery rules:
|
|
|
23253
23303
|
init_mesh_ledger();
|
|
23254
23304
|
}
|
|
23255
23305
|
});
|
|
23306
|
+
function parseVersion(raw) {
|
|
23307
|
+
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
23308
|
+
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
23309
|
+
}
|
|
23310
|
+
function shellQuote(value) {
|
|
23311
|
+
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
23312
|
+
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
23313
|
+
}
|
|
23314
|
+
function expandHome(value) {
|
|
23315
|
+
const trimmed = value.trim();
|
|
23316
|
+
if (!trimmed.startsWith("~")) return trimmed;
|
|
23317
|
+
return path8.join(os22.homedir(), trimmed.slice(1));
|
|
23318
|
+
}
|
|
23319
|
+
function isExplicitCommandPath(command) {
|
|
23320
|
+
const trimmed = command.trim();
|
|
23321
|
+
return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
23322
|
+
}
|
|
23323
|
+
function resolveCommandPath(command) {
|
|
23324
|
+
const trimmed = command.trim();
|
|
23325
|
+
if (!trimmed) return null;
|
|
23326
|
+
if (isExplicitCommandPath(trimmed)) {
|
|
23327
|
+
const expanded = expandHome(trimmed);
|
|
23328
|
+
const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
|
|
23329
|
+
return (0, import_fs5.existsSync)(candidate) ? candidate : null;
|
|
23330
|
+
}
|
|
23331
|
+
return null;
|
|
23332
|
+
}
|
|
23333
|
+
function execAsync(cmd, timeoutMs = 5e3) {
|
|
23334
|
+
return new Promise((resolve16) => {
|
|
23335
|
+
const child = (0, import_child_process.exec)(cmd, {
|
|
23336
|
+
encoding: "utf-8",
|
|
23337
|
+
timeout: timeoutMs,
|
|
23338
|
+
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
23339
|
+
}, (err, stdout) => {
|
|
23340
|
+
if (err || !stdout?.trim()) {
|
|
23341
|
+
resolve16(null);
|
|
23342
|
+
} else {
|
|
23343
|
+
resolve16(stdout.trim());
|
|
23344
|
+
}
|
|
23345
|
+
});
|
|
23346
|
+
child.on("error", () => resolve16(null));
|
|
23347
|
+
});
|
|
23348
|
+
}
|
|
23349
|
+
async function detectCLIs(providerLoader, options) {
|
|
23350
|
+
const platform10 = os22.platform();
|
|
23351
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
23352
|
+
const includeVersion = options?.includeVersion !== false;
|
|
23353
|
+
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
23354
|
+
const results = await Promise.all(
|
|
23355
|
+
cliList.map(async (cli) => {
|
|
23356
|
+
try {
|
|
23357
|
+
const explicitPath = resolveCommandPath(cli.command);
|
|
23358
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
23359
|
+
if (!pathResult) return { ...cli, installed: false };
|
|
23360
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
23361
|
+
let version2;
|
|
23362
|
+
if (includeVersion) {
|
|
23363
|
+
const versionCommands = [
|
|
23364
|
+
`"${firstPath}" --version`,
|
|
23365
|
+
`"${firstPath}" -V`,
|
|
23366
|
+
`"${firstPath}" -v`,
|
|
23367
|
+
cli.versionCommand
|
|
23368
|
+
].filter((v) => !!v);
|
|
23369
|
+
try {
|
|
23370
|
+
for (const versionCommand of versionCommands) {
|
|
23371
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
23372
|
+
if (versionResult) {
|
|
23373
|
+
version2 = parseVersion(versionResult);
|
|
23374
|
+
break;
|
|
23375
|
+
}
|
|
23376
|
+
}
|
|
23377
|
+
} catch {
|
|
23378
|
+
}
|
|
23379
|
+
}
|
|
23380
|
+
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
23381
|
+
} catch {
|
|
23382
|
+
return { ...cli, installed: false };
|
|
23383
|
+
}
|
|
23384
|
+
})
|
|
23385
|
+
);
|
|
23386
|
+
return results;
|
|
23387
|
+
}
|
|
23388
|
+
async function detectCLI(cliId, providerLoader, options) {
|
|
23389
|
+
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
23390
|
+
if (providerLoader) {
|
|
23391
|
+
const cliList = providerLoader.getCliDetectionList();
|
|
23392
|
+
const target = cliList.find((c) => c.id === resolvedId);
|
|
23393
|
+
if (target) {
|
|
23394
|
+
const platform10 = os22.platform();
|
|
23395
|
+
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
23396
|
+
try {
|
|
23397
|
+
const explicitPath = resolveCommandPath(target.command);
|
|
23398
|
+
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
23399
|
+
if (!pathResult) return null;
|
|
23400
|
+
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
23401
|
+
let version2;
|
|
23402
|
+
if (options?.includeVersion !== false) {
|
|
23403
|
+
const versionCommands = [
|
|
23404
|
+
`"${firstPath}" --version`,
|
|
23405
|
+
`"${firstPath}" -V`,
|
|
23406
|
+
`"${firstPath}" -v`,
|
|
23407
|
+
target.versionCommand
|
|
23408
|
+
].filter((v) => !!v);
|
|
23409
|
+
try {
|
|
23410
|
+
for (const versionCommand of versionCommands) {
|
|
23411
|
+
const versionResult = await execAsync(versionCommand, 3e3);
|
|
23412
|
+
if (versionResult) {
|
|
23413
|
+
version2 = parseVersion(versionResult);
|
|
23414
|
+
break;
|
|
23415
|
+
}
|
|
23416
|
+
}
|
|
23417
|
+
} catch {
|
|
23418
|
+
}
|
|
23419
|
+
}
|
|
23420
|
+
return { ...target, installed: true, version: version2, path: firstPath };
|
|
23421
|
+
} catch {
|
|
23422
|
+
return null;
|
|
23423
|
+
}
|
|
23424
|
+
}
|
|
23425
|
+
}
|
|
23426
|
+
const all = await detectCLIs(providerLoader, options);
|
|
23427
|
+
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
23428
|
+
}
|
|
23429
|
+
var import_child_process;
|
|
23430
|
+
var os22;
|
|
23431
|
+
var path8;
|
|
23432
|
+
var import_fs5;
|
|
23433
|
+
var init_cli_detector = __esm2({
|
|
23434
|
+
"src/detection/cli-detector.ts"() {
|
|
23435
|
+
"use strict";
|
|
23436
|
+
import_child_process = require("child_process");
|
|
23437
|
+
os22 = __toESM2(require("os"));
|
|
23438
|
+
path8 = __toESM2(require("path"));
|
|
23439
|
+
import_fs5 = require("fs");
|
|
23440
|
+
}
|
|
23441
|
+
});
|
|
23256
23442
|
function setLogLevel(level) {
|
|
23257
23443
|
currentLevel = level;
|
|
23258
23444
|
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
@@ -23267,13 +23453,13 @@ Follow these recovery rules:
|
|
|
23267
23453
|
return LOG_DIR;
|
|
23268
23454
|
}
|
|
23269
23455
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
23270
|
-
return
|
|
23456
|
+
return path9.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
23271
23457
|
}
|
|
23272
23458
|
function checkDateRotation() {
|
|
23273
23459
|
const today = getDateStr();
|
|
23274
23460
|
if (today !== currentDate) {
|
|
23275
23461
|
currentDate = today;
|
|
23276
|
-
currentLogFile =
|
|
23462
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
23277
23463
|
cleanOldLogs();
|
|
23278
23464
|
}
|
|
23279
23465
|
}
|
|
@@ -23287,7 +23473,7 @@ Follow these recovery rules:
|
|
|
23287
23473
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
23288
23474
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
23289
23475
|
try {
|
|
23290
|
-
fs22.unlinkSync(
|
|
23476
|
+
fs22.unlinkSync(path9.join(LOG_DIR, file2));
|
|
23291
23477
|
} catch {
|
|
23292
23478
|
}
|
|
23293
23479
|
}
|
|
@@ -23404,8 +23590,8 @@ Follow these recovery rules:
|
|
|
23404
23590
|
writeToFile(`Log level: ${currentLevel}`);
|
|
23405
23591
|
}
|
|
23406
23592
|
var fs22;
|
|
23407
|
-
var
|
|
23408
|
-
var
|
|
23593
|
+
var path9;
|
|
23594
|
+
var os32;
|
|
23409
23595
|
var LEVEL_NUM;
|
|
23410
23596
|
var LEVEL_LABEL;
|
|
23411
23597
|
var currentLevel;
|
|
@@ -23427,12 +23613,12 @@ Follow these recovery rules:
|
|
|
23427
23613
|
"src/logging/logger.ts"() {
|
|
23428
23614
|
"use strict";
|
|
23429
23615
|
fs22 = __toESM2(require("fs"));
|
|
23430
|
-
|
|
23431
|
-
|
|
23616
|
+
path9 = __toESM2(require("path"));
|
|
23617
|
+
os32 = __toESM2(require("os"));
|
|
23432
23618
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
23433
23619
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
23434
23620
|
currentLevel = "info";
|
|
23435
|
-
LOG_DIR = process.platform === "win32" ?
|
|
23621
|
+
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");
|
|
23436
23622
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
23437
23623
|
MAX_LOG_DAYS = 7;
|
|
23438
23624
|
try {
|
|
@@ -23440,16 +23626,16 @@ Follow these recovery rules:
|
|
|
23440
23626
|
} catch {
|
|
23441
23627
|
}
|
|
23442
23628
|
currentDate = getDateStr();
|
|
23443
|
-
currentLogFile =
|
|
23629
|
+
currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
23444
23630
|
cleanOldLogs();
|
|
23445
23631
|
try {
|
|
23446
|
-
const oldLog =
|
|
23632
|
+
const oldLog = path9.join(LOG_DIR, "daemon.log");
|
|
23447
23633
|
if (fs22.existsSync(oldLog)) {
|
|
23448
23634
|
const stat2 = fs22.statSync(oldLog);
|
|
23449
23635
|
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
23450
|
-
fs22.renameSync(oldLog,
|
|
23636
|
+
fs22.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
23451
23637
|
}
|
|
23452
|
-
const oldLogBackup =
|
|
23638
|
+
const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
|
|
23453
23639
|
if (fs22.existsSync(oldLogBackup)) {
|
|
23454
23640
|
fs22.unlinkSync(oldLogBackup);
|
|
23455
23641
|
}
|
|
@@ -23481,7 +23667,7 @@ Follow these recovery rules:
|
|
|
23481
23667
|
}
|
|
23482
23668
|
};
|
|
23483
23669
|
interceptorInstalled = false;
|
|
23484
|
-
LOG_PATH =
|
|
23670
|
+
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
23485
23671
|
}
|
|
23486
23672
|
});
|
|
23487
23673
|
var mesh_events_exports = {};
|
|
@@ -23551,7 +23737,235 @@ Follow these recovery rules:
|
|
|
23551
23737
|
});
|
|
23552
23738
|
return true;
|
|
23553
23739
|
}
|
|
23554
|
-
function
|
|
23740
|
+
function normalizeProviderPriority(policy) {
|
|
23741
|
+
const raw = policy && typeof policy === "object" && !Array.isArray(policy) ? policy.providerPriority : void 0;
|
|
23742
|
+
if (!Array.isArray(raw)) return [];
|
|
23743
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23744
|
+
return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
|
|
23745
|
+
if (seen.has(type)) return false;
|
|
23746
|
+
seen.add(type);
|
|
23747
|
+
return true;
|
|
23748
|
+
});
|
|
23749
|
+
}
|
|
23750
|
+
function isTerminalSessionStatus(status) {
|
|
23751
|
+
return ["stopped", "failed", "terminated", "exited", "closed"].includes(status);
|
|
23752
|
+
}
|
|
23753
|
+
function isIdleSessionState(state) {
|
|
23754
|
+
const status = readNonEmptyString(state?.status).toLowerCase();
|
|
23755
|
+
if (isTerminalSessionStatus(status)) return false;
|
|
23756
|
+
return status === "idle" || state?.activeChat?.status === "waiting_input";
|
|
23757
|
+
}
|
|
23758
|
+
function isDirtyNode(node) {
|
|
23759
|
+
return node?.health === "dirty" || node?.git?.dirty === true;
|
|
23760
|
+
}
|
|
23761
|
+
function isLaunchableNode(node) {
|
|
23762
|
+
if (!node || node.status === "disabled" || node.status === "removed") return false;
|
|
23763
|
+
const health = readNonEmptyString(node.health).toLowerCase();
|
|
23764
|
+
if (!health) return true;
|
|
23765
|
+
return health === "online" || health === "unknown";
|
|
23766
|
+
}
|
|
23767
|
+
function localAutoLaunchSkipReason(node) {
|
|
23768
|
+
const daemonId = readNonEmptyString(node?.daemonId);
|
|
23769
|
+
const machineId = readNonEmptyString(node?.machineId);
|
|
23770
|
+
const appConfig = loadConfig2();
|
|
23771
|
+
const localMachineId = readNonEmptyString(appConfig.machineId) || readNonEmptyString(appConfig.registeredMachineId);
|
|
23772
|
+
const cloudDaemonId = localMachineId ? `daemon_${localMachineId}` : "";
|
|
23773
|
+
const standaloneDaemonId = localMachineId ? `standalone_${localMachineId}` : "";
|
|
23774
|
+
const daemonMatchesLocal = !daemonId || daemonId === cloudDaemonId || daemonId === standaloneDaemonId;
|
|
23775
|
+
const machineMatchesLocal = !machineId || localMachineId && machineId === localMachineId;
|
|
23776
|
+
if (node?.isLocalWorktree === true) {
|
|
23777
|
+
return daemonMatchesLocal && machineMatchesLocal ? null : "remote_auto_launch_unsupported";
|
|
23778
|
+
}
|
|
23779
|
+
if (daemonId || machineId) {
|
|
23780
|
+
return daemonMatchesLocal && machineMatchesLocal ? null : "remote_auto_launch_unsupported";
|
|
23781
|
+
}
|
|
23782
|
+
return null;
|
|
23783
|
+
}
|
|
23784
|
+
function activeAssignedCount(meshId) {
|
|
23785
|
+
return getQueue(meshId, { status: ["assigned"] }).length;
|
|
23786
|
+
}
|
|
23787
|
+
function nodeHasActiveAssignment(meshId, nodeId) {
|
|
23788
|
+
return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
|
|
23789
|
+
}
|
|
23790
|
+
function liveSessionCountForNode(components, meshId, nodeId) {
|
|
23791
|
+
return components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
23792
|
+
const state = inst.getState();
|
|
23793
|
+
const settings = state.settings || {};
|
|
23794
|
+
if (readNonEmptyString(settings.meshNodeFor) !== meshId) return false;
|
|
23795
|
+
const instNodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
23796
|
+
if (instNodeId !== nodeId) return false;
|
|
23797
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
23798
|
+
return !isTerminalSessionStatus(status);
|
|
23799
|
+
}).length;
|
|
23800
|
+
}
|
|
23801
|
+
function recordAutoLaunchEvent(meshId, args) {
|
|
23802
|
+
try {
|
|
23803
|
+
appendLedgerEntry(meshId, {
|
|
23804
|
+
kind: "session_auto_launch",
|
|
23805
|
+
nodeId: args.nodeId,
|
|
23806
|
+
sessionId: args.sessionId,
|
|
23807
|
+
providerType: args.providerType,
|
|
23808
|
+
payload: {
|
|
23809
|
+
phase: args.phase,
|
|
23810
|
+
taskId: args.taskId,
|
|
23811
|
+
reason: args.reason,
|
|
23812
|
+
error: args.error
|
|
23813
|
+
}
|
|
23814
|
+
});
|
|
23815
|
+
} catch (e) {
|
|
23816
|
+
LOG2.warn("MeshQueue", `Failed to record auto-launch ledger event: ${e?.message || e}`);
|
|
23817
|
+
}
|
|
23818
|
+
}
|
|
23819
|
+
function markAutoLaunch(meshId, taskId, args) {
|
|
23820
|
+
recordTaskAutoLaunch(meshId, taskId, {
|
|
23821
|
+
status: args.status,
|
|
23822
|
+
reason: args.reason || args.error,
|
|
23823
|
+
nodeId: args.nodeId,
|
|
23824
|
+
providerType: args.providerType,
|
|
23825
|
+
sessionId: args.sessionId
|
|
23826
|
+
});
|
|
23827
|
+
recordAutoLaunchEvent(meshId, {
|
|
23828
|
+
phase: args.status,
|
|
23829
|
+
taskId,
|
|
23830
|
+
nodeId: args.nodeId,
|
|
23831
|
+
providerType: args.providerType,
|
|
23832
|
+
sessionId: args.sessionId,
|
|
23833
|
+
reason: args.reason,
|
|
23834
|
+
error: args.error
|
|
23835
|
+
});
|
|
23836
|
+
}
|
|
23837
|
+
async function resolveUsableProvider(components, nodeId, node) {
|
|
23838
|
+
const providerPriority = normalizeProviderPriority(node?.policy);
|
|
23839
|
+
if (!providerPriority.length) return { reason: "missing_provider_priority" };
|
|
23840
|
+
const providerLoader = components.providerLoader;
|
|
23841
|
+
if (!providerLoader) return { reason: "provider_loader_unavailable" };
|
|
23842
|
+
const failed = [];
|
|
23843
|
+
for (const requestedType of providerPriority) {
|
|
23844
|
+
const normalizedType = typeof providerLoader.resolveAlias === "function" ? providerLoader.resolveAlias(requestedType) : requestedType;
|
|
23845
|
+
if (typeof providerLoader.isMachineProviderEnabled === "function" && !providerLoader.isMachineProviderEnabled(normalizedType)) {
|
|
23846
|
+
failed.push(`${requestedType}: disabled`);
|
|
23847
|
+
continue;
|
|
23848
|
+
}
|
|
23849
|
+
let detected;
|
|
23850
|
+
try {
|
|
23851
|
+
detected = await detectCLI(normalizedType, providerLoader, { includeVersion: false });
|
|
23852
|
+
} catch (e) {
|
|
23853
|
+
failed.push(`${requestedType}: detect failed: ${e?.message || e}`);
|
|
23854
|
+
continue;
|
|
23855
|
+
}
|
|
23856
|
+
if (typeof providerLoader.setCliDetectionResults === "function") {
|
|
23857
|
+
providerLoader.setCliDetectionResults([{
|
|
23858
|
+
id: normalizedType,
|
|
23859
|
+
installed: !!detected,
|
|
23860
|
+
path: detected?.path
|
|
23861
|
+
}], false);
|
|
23862
|
+
}
|
|
23863
|
+
components.onStatusChange?.();
|
|
23864
|
+
if (detected) return { providerType: normalizedType };
|
|
23865
|
+
failed.push(`${requestedType}: not detected`);
|
|
23866
|
+
}
|
|
23867
|
+
return { reason: `provider_priority_unusable: ${failed.join("; ") || nodeId}` };
|
|
23868
|
+
}
|
|
23869
|
+
async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
23870
|
+
const queue = getQueue(meshId);
|
|
23871
|
+
const pending = queue.filter((task) => task.status === "pending");
|
|
23872
|
+
if (!pending.length) return false;
|
|
23873
|
+
const maxParallelTasks = Math.max(1, Math.floor(Number(mesh?.policy?.maxParallelTasks) || 2));
|
|
23874
|
+
for (const task of pending) {
|
|
23875
|
+
if (activeAssignedCount(meshId) >= maxParallelTasks) {
|
|
23876
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_parallel_tasks_reached" });
|
|
23877
|
+
return false;
|
|
23878
|
+
}
|
|
23879
|
+
if (task.targetSessionId) {
|
|
23880
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_constraint" });
|
|
23881
|
+
continue;
|
|
23882
|
+
}
|
|
23883
|
+
const candidateNodes = Array.isArray(mesh?.nodes) ? mesh.nodes.filter((node) => task.targetNodeId ? node?.id === task.targetNodeId : true) : [];
|
|
23884
|
+
if (!candidateNodes.length) {
|
|
23885
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "no_matching_node", nodeId: task.targetNodeId });
|
|
23886
|
+
continue;
|
|
23887
|
+
}
|
|
23888
|
+
for (const node of candidateNodes) {
|
|
23889
|
+
const nodeId = readNonEmptyString(node?.id);
|
|
23890
|
+
if (!nodeId) continue;
|
|
23891
|
+
const launchKey = `${meshId}:${nodeId}`;
|
|
23892
|
+
const cooldownUntil = autoLaunchCooldownUntil.get(launchKey) || 0;
|
|
23893
|
+
if (autoLaunchInProgress.has(launchKey)) {
|
|
23894
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_in_progress", nodeId });
|
|
23895
|
+
continue;
|
|
23896
|
+
}
|
|
23897
|
+
if (Date.now() < cooldownUntil) {
|
|
23898
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_cooldown", nodeId });
|
|
23899
|
+
continue;
|
|
23900
|
+
}
|
|
23901
|
+
if (isDirtyNode(node)) {
|
|
23902
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "dirty_workspace", nodeId });
|
|
23903
|
+
continue;
|
|
23904
|
+
}
|
|
23905
|
+
if (!isLaunchableNode(node)) {
|
|
23906
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_not_launch_ready", nodeId });
|
|
23907
|
+
continue;
|
|
23908
|
+
}
|
|
23909
|
+
const localSkipReason = localAutoLaunchSkipReason(node);
|
|
23910
|
+
if (localSkipReason) {
|
|
23911
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: localSkipReason, nodeId });
|
|
23912
|
+
continue;
|
|
23913
|
+
}
|
|
23914
|
+
if (nodeHasActiveAssignment(meshId, nodeId)) {
|
|
23915
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
|
|
23916
|
+
continue;
|
|
23917
|
+
}
|
|
23918
|
+
const maxConcurrentSessions = Number(node?.policy?.maxConcurrentSessions);
|
|
23919
|
+
if (Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0 && liveSessionCountForNode(components, meshId, nodeId) >= maxConcurrentSessions) {
|
|
23920
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_concurrent_sessions_reached", nodeId });
|
|
23921
|
+
continue;
|
|
23922
|
+
}
|
|
23923
|
+
autoLaunchInProgress.add(launchKey);
|
|
23924
|
+
try {
|
|
23925
|
+
const resolved = await resolveUsableProvider(components, nodeId, node);
|
|
23926
|
+
if (!resolved.providerType) {
|
|
23927
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: resolved.reason || "provider_unusable", nodeId });
|
|
23928
|
+
continue;
|
|
23929
|
+
}
|
|
23930
|
+
markAutoLaunch(meshId, task.id, { status: "started", nodeId, providerType: resolved.providerType });
|
|
23931
|
+
const launchResult = await components.cliManager.handleCliCommand("launch_cli", {
|
|
23932
|
+
cliType: resolved.providerType,
|
|
23933
|
+
dir: node.workspace,
|
|
23934
|
+
settings: {
|
|
23935
|
+
meshNodeFor: meshId,
|
|
23936
|
+
meshNodeId: nodeId,
|
|
23937
|
+
spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
|
|
23938
|
+
launchedByCoordinator: true,
|
|
23939
|
+
autoLaunchedForQueueTaskId: task.id
|
|
23940
|
+
}
|
|
23941
|
+
});
|
|
23942
|
+
if (!launchResult?.success) {
|
|
23943
|
+
const reason = launchResult?.error || "launch_cli_failed";
|
|
23944
|
+
markAutoLaunch(meshId, task.id, { status: "failed", reason, nodeId, providerType: resolved.providerType });
|
|
23945
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
23946
|
+
return false;
|
|
23947
|
+
}
|
|
23948
|
+
const sessionId = readNonEmptyString(launchResult.sessionId) || readNonEmptyString(launchResult.id) || readNonEmptyString(launchResult.runtimeSessionId);
|
|
23949
|
+
if (!sessionId) {
|
|
23950
|
+
markAutoLaunch(meshId, task.id, { status: "failed", reason: "launch_missing_session_id", nodeId, providerType: resolved.providerType });
|
|
23951
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
23952
|
+
return false;
|
|
23953
|
+
}
|
|
23954
|
+
markAutoLaunch(meshId, task.id, { status: "completed", nodeId, providerType: resolved.providerType, sessionId });
|
|
23955
|
+
tryAssignQueueTask(components, meshId, nodeId, sessionId, resolved.providerType);
|
|
23956
|
+
return true;
|
|
23957
|
+
} catch (e) {
|
|
23958
|
+
markAutoLaunch(meshId, task.id, { status: "failed", error: e?.message || String(e), nodeId });
|
|
23959
|
+
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
|
|
23960
|
+
return false;
|
|
23961
|
+
} finally {
|
|
23962
|
+
autoLaunchInProgress.delete(launchKey);
|
|
23963
|
+
}
|
|
23964
|
+
}
|
|
23965
|
+
}
|
|
23966
|
+
return false;
|
|
23967
|
+
}
|
|
23968
|
+
async function triggerMeshQueue(components, meshId) {
|
|
23555
23969
|
const mesh = getMeshWithCache(components, meshId);
|
|
23556
23970
|
if (!mesh) return;
|
|
23557
23971
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
@@ -23562,9 +23976,7 @@ Follow these recovery rules:
|
|
|
23562
23976
|
if (instMeshId !== meshId) continue;
|
|
23563
23977
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
23564
23978
|
if (!nodeId) continue;
|
|
23565
|
-
|
|
23566
|
-
if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
|
|
23567
|
-
if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
|
|
23979
|
+
if (!isIdleSessionState(state)) continue;
|
|
23568
23980
|
const sessionId = state.instanceId;
|
|
23569
23981
|
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
23570
23982
|
if (providerType) {
|
|
@@ -23580,6 +23992,7 @@ Follow these recovery rules:
|
|
|
23580
23992
|
}
|
|
23581
23993
|
}
|
|
23582
23994
|
}
|
|
23995
|
+
await maybeAutoLaunchOneQueueSession(components, meshId, mesh);
|
|
23583
23996
|
}
|
|
23584
23997
|
function buildMeshSystemMessage(args) {
|
|
23585
23998
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
@@ -23861,10 +24274,15 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
|
|
|
23861
24274
|
var pendingMeshCoordinatorEvents;
|
|
23862
24275
|
var MESH_COORDINATOR_EVENTS;
|
|
23863
24276
|
var EVENT_TO_LEDGER_KIND;
|
|
24277
|
+
var autoLaunchInProgress;
|
|
24278
|
+
var autoLaunchCooldownUntil;
|
|
24279
|
+
var AUTO_LAUNCH_COOLDOWN_MS;
|
|
23864
24280
|
var init_mesh_events = __esm2({
|
|
23865
24281
|
"src/mesh/mesh-events.ts"() {
|
|
23866
24282
|
"use strict";
|
|
24283
|
+
init_config();
|
|
23867
24284
|
init_mesh_config();
|
|
24285
|
+
init_cli_detector();
|
|
23868
24286
|
init_logger();
|
|
23869
24287
|
init_mesh_ledger();
|
|
23870
24288
|
init_mesh_work_queue();
|
|
@@ -23885,6 +24303,9 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
|
|
|
23885
24303
|
"agent:stopped": "task_failed",
|
|
23886
24304
|
"monitor:long_generating": "task_stalled"
|
|
23887
24305
|
};
|
|
24306
|
+
autoLaunchInProgress = /* @__PURE__ */ new Set();
|
|
24307
|
+
autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
|
|
24308
|
+
AUTO_LAUNCH_COOLDOWN_MS = 5e3;
|
|
23888
24309
|
}
|
|
23889
24310
|
});
|
|
23890
24311
|
function normalizeCategories(categories) {
|
|
@@ -27003,6 +27424,7 @@ ${lastSnapshot}`;
|
|
|
27003
27424
|
MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS2,
|
|
27004
27425
|
MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS2,
|
|
27005
27426
|
NodePtyTransportFactory: () => NodePtyTransportFactory,
|
|
27427
|
+
P2pRelayFailureError: () => P2pRelayFailureError,
|
|
27006
27428
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
27007
27429
|
ProviderInstanceManager: () => ProviderInstanceManager,
|
|
27008
27430
|
ProviderLoader: () => ProviderLoader,
|
|
@@ -27019,6 +27441,7 @@ ${lastSnapshot}`;
|
|
|
27019
27441
|
buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
|
|
27020
27442
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
|
|
27021
27443
|
buildMachineInfo: () => buildMachineInfo2,
|
|
27444
|
+
buildP2pRelayFailurePayload: () => buildP2pRelayFailurePayload,
|
|
27022
27445
|
buildPinnedGlobalInstallCommand: () => buildPinnedGlobalInstallCommand,
|
|
27023
27446
|
buildRuntimeSystemChatMessage: () => buildRuntimeSystemChatMessage,
|
|
27024
27447
|
buildSessionEntries: () => buildSessionEntries,
|
|
@@ -27033,6 +27456,7 @@ ${lastSnapshot}`;
|
|
|
27033
27456
|
claimNextTask: () => claimNextTask,
|
|
27034
27457
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
27035
27458
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush2,
|
|
27459
|
+
classifyP2pRelayFailure: () => classifyP2pRelayFailure,
|
|
27036
27460
|
clearDebugTrace: () => clearDebugTrace,
|
|
27037
27461
|
compareGitSnapshots: () => compareGitSnapshots,
|
|
27038
27462
|
configureDebugTraceStore: () => configureDebugTraceStore,
|
|
@@ -27100,6 +27524,7 @@ ${lastSnapshot}`;
|
|
|
27100
27524
|
isInternalChatMessage: () => isInternalChatMessage,
|
|
27101
27525
|
isManagedStatusWaiting: () => isManagedStatusWaiting,
|
|
27102
27526
|
isManagedStatusWorking: () => isManagedStatusWorking,
|
|
27527
|
+
isP2pRelayTransportFailure: () => isP2pRelayTransportFailure,
|
|
27103
27528
|
isPathInside: () => isPathInside,
|
|
27104
27529
|
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
|
|
27105
27530
|
isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
|
|
@@ -29028,7 +29453,115 @@ ${lastSnapshot}`;
|
|
|
29028
29453
|
init_mesh_ledger();
|
|
29029
29454
|
init_mesh_work_queue();
|
|
29030
29455
|
init_mesh_events();
|
|
29031
|
-
var
|
|
29456
|
+
var NO_FALLBACK_REASON = "Repo Mesh command/data-plane is P2P-only; WS/REST command fallback is intentionally disabled to preserve the transport boundary.";
|
|
29457
|
+
var 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.";
|
|
29458
|
+
var NON_P2P_NEXT_ACTION = "Inspect the provider/command error and fix the underlying logic or configuration before retrying.";
|
|
29459
|
+
function messageFromError(error48) {
|
|
29460
|
+
if (error48 instanceof Error) return error48.message;
|
|
29461
|
+
if (typeof error48 === "string") return error48;
|
|
29462
|
+
if (error48 && typeof error48 === "object") {
|
|
29463
|
+
const candidate = error48.error ?? error48.message ?? error48.reason;
|
|
29464
|
+
if (typeof candidate === "string") return candidate;
|
|
29465
|
+
}
|
|
29466
|
+
return String(error48 || "mesh relay command failed");
|
|
29467
|
+
}
|
|
29468
|
+
function classifyP2pRelayFailure(error48, _context = {}) {
|
|
29469
|
+
const message = messageFromError(error48);
|
|
29470
|
+
const lower = message.toLowerCase();
|
|
29471
|
+
const hasP2pSignal = /p2p|datachannel|node-datachannel|webrtc|ice|mesh_relay_command|daemon_mesh_p2p_transport/i.test(message);
|
|
29472
|
+
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);
|
|
29473
|
+
if (/requires targetdaemonid and command|providerpriority|no inference provider|permission denied|read-only|not a member/i.test(message)) {
|
|
29474
|
+
return {
|
|
29475
|
+
code: "mesh_logic_or_provider_failure",
|
|
29476
|
+
reason: "mesh_logic_or_provider_failure",
|
|
29477
|
+
transport: "unknown",
|
|
29478
|
+
recoverable: false,
|
|
29479
|
+
retryRecommended: false,
|
|
29480
|
+
nextAction: NON_P2P_NEXT_ACTION,
|
|
29481
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29482
|
+
};
|
|
29483
|
+
}
|
|
29484
|
+
let code = null;
|
|
29485
|
+
let reason = "";
|
|
29486
|
+
if (/timeout|timed out/i.test(message) && (hasP2pSignal || /mesh transport/i.test(message))) {
|
|
29487
|
+
code = "p2p_timeout";
|
|
29488
|
+
reason = "daemon_mesh_p2p_timeout";
|
|
29489
|
+
} else if (/no route|route unavailable/i.test(message)) {
|
|
29490
|
+
code = "p2p_no_route";
|
|
29491
|
+
reason = "daemon_mesh_p2p_no_route";
|
|
29492
|
+
} else if (/offline|not owned|not found|not connected to server/i.test(message) && /daemon|peer|target/i.test(message)) {
|
|
29493
|
+
code = "p2p_daemon_offline";
|
|
29494
|
+
reason = "daemon_mesh_target_offline";
|
|
29495
|
+
} else if (/closed|disconnected/i.test(message) && (hasP2pSignal || /state changed/i.test(message))) {
|
|
29496
|
+
code = "p2p_datachannel_closed";
|
|
29497
|
+
reason = "daemon_mesh_p2p_datachannel_closed";
|
|
29498
|
+
} else if (/not connected|cannot send|cannot establish/i.test(message) && hasP2pSignal) {
|
|
29499
|
+
code = "p2p_not_connected";
|
|
29500
|
+
reason = "daemon_mesh_p2p_not_connected";
|
|
29501
|
+
} else if (hasP2pSignal && hasFailureSignal) {
|
|
29502
|
+
code = "p2p_unavailable";
|
|
29503
|
+
reason = "daemon_mesh_p2p_transport_unavailable";
|
|
29504
|
+
}
|
|
29505
|
+
if (!code) {
|
|
29506
|
+
return {
|
|
29507
|
+
code: "mesh_logic_or_provider_failure",
|
|
29508
|
+
reason: "mesh_logic_or_provider_failure",
|
|
29509
|
+
transport: "unknown",
|
|
29510
|
+
recoverable: false,
|
|
29511
|
+
retryRecommended: false,
|
|
29512
|
+
nextAction: NON_P2P_NEXT_ACTION,
|
|
29513
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29514
|
+
};
|
|
29515
|
+
}
|
|
29516
|
+
return {
|
|
29517
|
+
code,
|
|
29518
|
+
reason,
|
|
29519
|
+
transport: "p2p",
|
|
29520
|
+
recoverable: true,
|
|
29521
|
+
retryRecommended: true,
|
|
29522
|
+
nextAction: P2P_NEXT_ACTION,
|
|
29523
|
+
noFallbackReason: NO_FALLBACK_REASON
|
|
29524
|
+
};
|
|
29525
|
+
}
|
|
29526
|
+
function isP2pRelayTransportFailure(error48) {
|
|
29527
|
+
return classifyP2pRelayFailure(error48).recoverable === true;
|
|
29528
|
+
}
|
|
29529
|
+
function buildP2pRelayFailurePayload(error48, context = {}) {
|
|
29530
|
+
const classification = classifyP2pRelayFailure(error48, context);
|
|
29531
|
+
return {
|
|
29532
|
+
success: false,
|
|
29533
|
+
...classification,
|
|
29534
|
+
error: messageFromError(error48),
|
|
29535
|
+
...context.command ? { command: context.command } : {},
|
|
29536
|
+
...context.targetDaemonId ? { targetDaemonId: context.targetDaemonId } : {}
|
|
29537
|
+
};
|
|
29538
|
+
}
|
|
29539
|
+
var P2pRelayFailureError = class extends Error {
|
|
29540
|
+
code;
|
|
29541
|
+
reason;
|
|
29542
|
+
transport;
|
|
29543
|
+
recoverable;
|
|
29544
|
+
retryRecommended;
|
|
29545
|
+
nextAction;
|
|
29546
|
+
noFallbackReason;
|
|
29547
|
+
command;
|
|
29548
|
+
targetDaemonId;
|
|
29549
|
+
constructor(message, context = {}) {
|
|
29550
|
+
super(message);
|
|
29551
|
+
this.name = "P2pRelayFailureError";
|
|
29552
|
+
const payload = buildP2pRelayFailurePayload(message, context);
|
|
29553
|
+
this.code = payload.code;
|
|
29554
|
+
this.reason = payload.reason;
|
|
29555
|
+
this.transport = payload.transport;
|
|
29556
|
+
this.recoverable = payload.recoverable;
|
|
29557
|
+
this.retryRecommended = payload.retryRecommended;
|
|
29558
|
+
this.nextAction = payload.nextAction;
|
|
29559
|
+
this.noFallbackReason = payload.noFallbackReason;
|
|
29560
|
+
this.command = context.command;
|
|
29561
|
+
this.targetDaemonId = context.targetDaemonId;
|
|
29562
|
+
}
|
|
29563
|
+
};
|
|
29564
|
+
var import_fs6 = require("fs");
|
|
29032
29565
|
var import_path5 = require("path");
|
|
29033
29566
|
init_config();
|
|
29034
29567
|
var DEFAULT_STATE = {
|
|
@@ -29079,11 +29612,11 @@ ${lastSnapshot}`;
|
|
|
29079
29612
|
}
|
|
29080
29613
|
function loadState() {
|
|
29081
29614
|
const statePath = getStatePath();
|
|
29082
|
-
if (!(0,
|
|
29615
|
+
if (!(0, import_fs6.existsSync)(statePath)) {
|
|
29083
29616
|
return { ...DEFAULT_STATE };
|
|
29084
29617
|
}
|
|
29085
29618
|
try {
|
|
29086
|
-
const raw = (0,
|
|
29619
|
+
const raw = (0, import_fs6.readFileSync)(statePath, "utf-8");
|
|
29087
29620
|
return normalizeState(JSON.parse(raw));
|
|
29088
29621
|
} catch {
|
|
29089
29622
|
return { ...DEFAULT_STATE };
|
|
@@ -29092,15 +29625,15 @@ ${lastSnapshot}`;
|
|
|
29092
29625
|
function saveState(state) {
|
|
29093
29626
|
const statePath = getStatePath();
|
|
29094
29627
|
const normalized = normalizeState(state);
|
|
29095
|
-
(0,
|
|
29628
|
+
(0, import_fs6.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
29096
29629
|
}
|
|
29097
29630
|
function resetState() {
|
|
29098
29631
|
saveState({ ...DEFAULT_STATE });
|
|
29099
29632
|
}
|
|
29100
|
-
var
|
|
29101
|
-
var
|
|
29633
|
+
var import_child_process2 = require("child_process");
|
|
29634
|
+
var import_fs7 = require("fs");
|
|
29102
29635
|
var import_os22 = require("os");
|
|
29103
|
-
var
|
|
29636
|
+
var path10 = __toESM2(require("path"));
|
|
29104
29637
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
29105
29638
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
29106
29639
|
function registerIDEDefinition(def) {
|
|
@@ -29119,13 +29652,13 @@ ${lastSnapshot}`;
|
|
|
29119
29652
|
function findCliCommand(command) {
|
|
29120
29653
|
const trimmed = String(command || "").trim();
|
|
29121
29654
|
if (!trimmed) return null;
|
|
29122
|
-
if (
|
|
29123
|
-
const candidate = trimmed.startsWith("~") ?
|
|
29124
|
-
const resolved =
|
|
29125
|
-
return (0,
|
|
29655
|
+
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
29656
|
+
const candidate = trimmed.startsWith("~") ? path10.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
|
|
29657
|
+
const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
|
|
29658
|
+
return (0, import_fs7.existsSync)(resolved) ? resolved : null;
|
|
29126
29659
|
}
|
|
29127
29660
|
try {
|
|
29128
|
-
const result = (0,
|
|
29661
|
+
const result = (0, import_child_process2.execSync)(
|
|
29129
29662
|
(0, import_os22.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
|
|
29130
29663
|
{ encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
|
|
29131
29664
|
).trim();
|
|
@@ -29136,7 +29669,7 @@ ${lastSnapshot}`;
|
|
|
29136
29669
|
}
|
|
29137
29670
|
function getIdeVersion(cliCommand) {
|
|
29138
29671
|
try {
|
|
29139
|
-
const result = (0,
|
|
29672
|
+
const result = (0, import_child_process2.execSync)(`"${cliCommand}" --version`, {
|
|
29140
29673
|
encoding: "utf-8",
|
|
29141
29674
|
timeout: 1e4,
|
|
29142
29675
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -29149,13 +29682,13 @@ ${lastSnapshot}`;
|
|
|
29149
29682
|
function checkPathExists(paths) {
|
|
29150
29683
|
const home = (0, import_os22.homedir)();
|
|
29151
29684
|
for (const p of paths) {
|
|
29152
|
-
const normalized = p.startsWith("~") ?
|
|
29685
|
+
const normalized = p.startsWith("~") ? path10.join(home, p.slice(1)) : p;
|
|
29153
29686
|
if (normalized.includes("*")) {
|
|
29154
29687
|
const username = home.split(/[\\/]/).pop() || "";
|
|
29155
29688
|
const resolved = normalized.replace("*", username);
|
|
29156
|
-
if ((0,
|
|
29689
|
+
if ((0, import_fs7.existsSync)(resolved)) return resolved;
|
|
29157
29690
|
} else {
|
|
29158
|
-
if ((0,
|
|
29691
|
+
if ((0, import_fs7.existsSync)(normalized)) return normalized;
|
|
29159
29692
|
}
|
|
29160
29693
|
}
|
|
29161
29694
|
return null;
|
|
@@ -29169,7 +29702,7 @@ ${lastSnapshot}`;
|
|
|
29169
29702
|
let resolvedCli = cliPath;
|
|
29170
29703
|
if (!resolvedCli && appPath && os222 === "darwin") {
|
|
29171
29704
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
29172
|
-
if ((0,
|
|
29705
|
+
if ((0, import_fs7.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
29173
29706
|
}
|
|
29174
29707
|
if (!resolvedCli && appPath && os222 === "win32") {
|
|
29175
29708
|
const { dirname: dirname9 } = await import("path");
|
|
@@ -29182,7 +29715,7 @@ ${lastSnapshot}`;
|
|
|
29182
29715
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
29183
29716
|
];
|
|
29184
29717
|
for (const c of candidates) {
|
|
29185
|
-
if ((0,
|
|
29718
|
+
if ((0, import_fs7.existsSync)(c)) {
|
|
29186
29719
|
resolvedCli = c;
|
|
29187
29720
|
break;
|
|
29188
29721
|
}
|
|
@@ -29203,133 +29736,7 @@ ${lastSnapshot}`;
|
|
|
29203
29736
|
}
|
|
29204
29737
|
return results;
|
|
29205
29738
|
}
|
|
29206
|
-
|
|
29207
|
-
var os32 = __toESM2(require("os"));
|
|
29208
|
-
var path10 = __toESM2(require("path"));
|
|
29209
|
-
var import_fs7 = require("fs");
|
|
29210
|
-
function parseVersion(raw) {
|
|
29211
|
-
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
29212
|
-
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
29213
|
-
}
|
|
29214
|
-
function shellQuote(value) {
|
|
29215
|
-
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
29216
|
-
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
29217
|
-
}
|
|
29218
|
-
function expandHome(value) {
|
|
29219
|
-
const trimmed = value.trim();
|
|
29220
|
-
if (!trimmed.startsWith("~")) return trimmed;
|
|
29221
|
-
return path10.join(os32.homedir(), trimmed.slice(1));
|
|
29222
|
-
}
|
|
29223
|
-
function isExplicitCommandPath(command) {
|
|
29224
|
-
const trimmed = command.trim();
|
|
29225
|
-
return path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
29226
|
-
}
|
|
29227
|
-
function resolveCommandPath(command) {
|
|
29228
|
-
const trimmed = command.trim();
|
|
29229
|
-
if (!trimmed) return null;
|
|
29230
|
-
if (isExplicitCommandPath(trimmed)) {
|
|
29231
|
-
const expanded = expandHome(trimmed);
|
|
29232
|
-
const candidate = path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
|
|
29233
|
-
return (0, import_fs7.existsSync)(candidate) ? candidate : null;
|
|
29234
|
-
}
|
|
29235
|
-
return null;
|
|
29236
|
-
}
|
|
29237
|
-
function execAsync(cmd, timeoutMs = 5e3) {
|
|
29238
|
-
return new Promise((resolve16) => {
|
|
29239
|
-
const child = (0, import_child_process2.exec)(cmd, {
|
|
29240
|
-
encoding: "utf-8",
|
|
29241
|
-
timeout: timeoutMs,
|
|
29242
|
-
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
29243
|
-
}, (err, stdout) => {
|
|
29244
|
-
if (err || !stdout?.trim()) {
|
|
29245
|
-
resolve16(null);
|
|
29246
|
-
} else {
|
|
29247
|
-
resolve16(stdout.trim());
|
|
29248
|
-
}
|
|
29249
|
-
});
|
|
29250
|
-
child.on("error", () => resolve16(null));
|
|
29251
|
-
});
|
|
29252
|
-
}
|
|
29253
|
-
async function detectCLIs(providerLoader, options) {
|
|
29254
|
-
const platform10 = os32.platform();
|
|
29255
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
29256
|
-
const includeVersion = options?.includeVersion !== false;
|
|
29257
|
-
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
29258
|
-
const results = await Promise.all(
|
|
29259
|
-
cliList.map(async (cli) => {
|
|
29260
|
-
try {
|
|
29261
|
-
const explicitPath = resolveCommandPath(cli.command);
|
|
29262
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
|
|
29263
|
-
if (!pathResult) return { ...cli, installed: false };
|
|
29264
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29265
|
-
let version2;
|
|
29266
|
-
if (includeVersion) {
|
|
29267
|
-
const versionCommands = [
|
|
29268
|
-
`"${firstPath}" --version`,
|
|
29269
|
-
`"${firstPath}" -V`,
|
|
29270
|
-
`"${firstPath}" -v`,
|
|
29271
|
-
cli.versionCommand
|
|
29272
|
-
].filter((v) => !!v);
|
|
29273
|
-
try {
|
|
29274
|
-
for (const versionCommand of versionCommands) {
|
|
29275
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29276
|
-
if (versionResult) {
|
|
29277
|
-
version2 = parseVersion(versionResult);
|
|
29278
|
-
break;
|
|
29279
|
-
}
|
|
29280
|
-
}
|
|
29281
|
-
} catch {
|
|
29282
|
-
}
|
|
29283
|
-
}
|
|
29284
|
-
return { ...cli, installed: true, version: version2, path: firstPath };
|
|
29285
|
-
} catch {
|
|
29286
|
-
return { ...cli, installed: false };
|
|
29287
|
-
}
|
|
29288
|
-
})
|
|
29289
|
-
);
|
|
29290
|
-
return results;
|
|
29291
|
-
}
|
|
29292
|
-
async function detectCLI(cliId, providerLoader, options) {
|
|
29293
|
-
const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
|
|
29294
|
-
if (providerLoader) {
|
|
29295
|
-
const cliList = providerLoader.getCliDetectionList();
|
|
29296
|
-
const target = cliList.find((c) => c.id === resolvedId);
|
|
29297
|
-
if (target) {
|
|
29298
|
-
const platform10 = os32.platform();
|
|
29299
|
-
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
29300
|
-
try {
|
|
29301
|
-
const explicitPath = resolveCommandPath(target.command);
|
|
29302
|
-
const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
|
|
29303
|
-
if (!pathResult) return null;
|
|
29304
|
-
const firstPath = explicitPath || pathResult.split("\n")[0];
|
|
29305
|
-
let version2;
|
|
29306
|
-
if (options?.includeVersion !== false) {
|
|
29307
|
-
const versionCommands = [
|
|
29308
|
-
`"${firstPath}" --version`,
|
|
29309
|
-
`"${firstPath}" -V`,
|
|
29310
|
-
`"${firstPath}" -v`,
|
|
29311
|
-
target.versionCommand
|
|
29312
|
-
].filter((v) => !!v);
|
|
29313
|
-
try {
|
|
29314
|
-
for (const versionCommand of versionCommands) {
|
|
29315
|
-
const versionResult = await execAsync(versionCommand, 3e3);
|
|
29316
|
-
if (versionResult) {
|
|
29317
|
-
version2 = parseVersion(versionResult);
|
|
29318
|
-
break;
|
|
29319
|
-
}
|
|
29320
|
-
}
|
|
29321
|
-
} catch {
|
|
29322
|
-
}
|
|
29323
|
-
}
|
|
29324
|
-
return { ...target, installed: true, version: version2, path: firstPath };
|
|
29325
|
-
} catch {
|
|
29326
|
-
return null;
|
|
29327
|
-
}
|
|
29328
|
-
}
|
|
29329
|
-
}
|
|
29330
|
-
const all = await detectCLIs(providerLoader, options);
|
|
29331
|
-
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
29332
|
-
}
|
|
29739
|
+
init_cli_detector();
|
|
29333
29740
|
var os42 = __toESM2(require("os"));
|
|
29334
29741
|
var import_child_process3 = require("child_process");
|
|
29335
29742
|
function parseDarwinAvailableBytes(totalMem) {
|
|
@@ -38353,6 +38760,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
38353
38760
|
var import_child_process6 = require("child_process");
|
|
38354
38761
|
var import_chalk = __toESM2((init_source(), __toCommonJS(source_exports)));
|
|
38355
38762
|
init_provider_cli_adapter();
|
|
38763
|
+
init_cli_detector();
|
|
38356
38764
|
init_config();
|
|
38357
38765
|
var os12 = __toESM2(require("os"));
|
|
38358
38766
|
var path16 = __toESM2(require("path"));
|
|
@@ -43906,6 +44314,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
43906
44314
|
return getProviderLoader().getAvailableIdeTypes();
|
|
43907
44315
|
}
|
|
43908
44316
|
init_config();
|
|
44317
|
+
init_cli_detector();
|
|
43909
44318
|
init_logger();
|
|
43910
44319
|
var fs8 = __toESM2(require("fs"));
|
|
43911
44320
|
var path21 = __toESM2(require("path"));
|
|
@@ -45038,6 +45447,209 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
45038
45447
|
}
|
|
45039
45448
|
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
|
|
45040
45449
|
}
|
|
45450
|
+
var REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
|
|
45451
|
+
var REFINE_VALIDATION_TIMEOUT_MS = 12e4;
|
|
45452
|
+
var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
45453
|
+
var REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
|
|
45454
|
+
var REFINE_VALIDATION_MAX_COMMANDS = 4;
|
|
45455
|
+
function truncateValidationOutput(value) {
|
|
45456
|
+
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
45457
|
+
if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
|
|
45458
|
+
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
45459
|
+
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
45460
|
+
}
|
|
45461
|
+
function readPackageScripts(workspace) {
|
|
45462
|
+
try {
|
|
45463
|
+
const packageJsonPath = (0, import_path6.join)(workspace, "package.json");
|
|
45464
|
+
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
45465
|
+
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
45466
|
+
} catch {
|
|
45467
|
+
return {};
|
|
45468
|
+
}
|
|
45469
|
+
}
|
|
45470
|
+
function tokenizeValidationCommand(command) {
|
|
45471
|
+
const trimmed = command.trim();
|
|
45472
|
+
if (!trimmed) return null;
|
|
45473
|
+
if (/[;&|<>`$\\\n\r'\"]/.test(trimmed)) return null;
|
|
45474
|
+
const tokens = trimmed.split(/\s+/).filter(Boolean);
|
|
45475
|
+
if (!tokens.length) return null;
|
|
45476
|
+
if (tokens.some((token) => !/^[A-Za-z0-9_@./:=+-]+$/.test(token))) return null;
|
|
45477
|
+
return tokens;
|
|
45478
|
+
}
|
|
45479
|
+
function scriptMatchesValidationCategory(scriptName, category) {
|
|
45480
|
+
return scriptName === category || scriptName.startsWith(`${category}:`);
|
|
45481
|
+
}
|
|
45482
|
+
function parsePackageManagerValidationCommand(rawCommand, category, scripts, source) {
|
|
45483
|
+
const tokens = tokenizeValidationCommand(rawCommand);
|
|
45484
|
+
if (!tokens) {
|
|
45485
|
+
return { rejected: { command: rawCommand, category, source, reason: "unsafe command string is not allowlisted" } };
|
|
45486
|
+
}
|
|
45487
|
+
const [binary, second, third, ...rest] = tokens;
|
|
45488
|
+
let scriptName = "";
|
|
45489
|
+
let command = binary;
|
|
45490
|
+
let args = [];
|
|
45491
|
+
if ((binary === "npm" || binary === "pnpm" || binary === "bun") && second === "run" && third) {
|
|
45492
|
+
scriptName = third;
|
|
45493
|
+
args = ["run", scriptName, ...rest];
|
|
45494
|
+
} else if (binary === "npm" && second === "test" && !third) {
|
|
45495
|
+
scriptName = "test";
|
|
45496
|
+
args = ["test"];
|
|
45497
|
+
} else if (binary === "yarn" && second === "run" && third) {
|
|
45498
|
+
scriptName = third;
|
|
45499
|
+
args = ["run", scriptName, ...rest];
|
|
45500
|
+
} else if (binary === "yarn" && second && !third) {
|
|
45501
|
+
scriptName = second;
|
|
45502
|
+
args = [scriptName];
|
|
45503
|
+
} else {
|
|
45504
|
+
return { rejected: { command: rawCommand, category, source, reason: "command is not a supported package-manager script invocation" } };
|
|
45505
|
+
}
|
|
45506
|
+
if (!scriptName || !Object.prototype.hasOwnProperty.call(scripts, scriptName)) {
|
|
45507
|
+
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script is not declared in package.json" } };
|
|
45508
|
+
}
|
|
45509
|
+
if (!scriptMatchesValidationCategory(scriptName, category)) {
|
|
45510
|
+
return { rejected: { command: rawCommand, category, source, script: scriptName, reason: "script name is outside the validation category allowlist" } };
|
|
45511
|
+
}
|
|
45512
|
+
return {
|
|
45513
|
+
command: {
|
|
45514
|
+
command,
|
|
45515
|
+
args,
|
|
45516
|
+
displayCommand: [command, ...args].join(" "),
|
|
45517
|
+
category,
|
|
45518
|
+
source
|
|
45519
|
+
}
|
|
45520
|
+
};
|
|
45521
|
+
}
|
|
45522
|
+
function collectProjectContextValidationCandidates(mesh) {
|
|
45523
|
+
const commands = mesh?.projectContext?.commands;
|
|
45524
|
+
if (!commands || typeof commands !== "object" || Array.isArray(commands)) return [];
|
|
45525
|
+
const candidates = [];
|
|
45526
|
+
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
45527
|
+
const entries = Array.isArray(commands[category]) ? commands[category] : [];
|
|
45528
|
+
for (const entry of entries) {
|
|
45529
|
+
if (typeof entry?.command !== "string") continue;
|
|
45530
|
+
candidates.push({
|
|
45531
|
+
command: entry.command,
|
|
45532
|
+
category,
|
|
45533
|
+
source: typeof entry.sourcePath === "string" ? entry.sourcePath : "projectContext.commands",
|
|
45534
|
+
confidence: typeof entry.confidence === "string" ? entry.confidence : void 0
|
|
45535
|
+
});
|
|
45536
|
+
}
|
|
45537
|
+
}
|
|
45538
|
+
return candidates.sort((a, b) => {
|
|
45539
|
+
const rank = (value) => value === "high" ? 0 : value === "medium" ? 1 : 2;
|
|
45540
|
+
return rank(a.confidence) - rank(b.confidence);
|
|
45541
|
+
});
|
|
45542
|
+
}
|
|
45543
|
+
function collectPolicyValidationCandidates(mesh) {
|
|
45544
|
+
const policy = mesh?.policy && typeof mesh.policy === "object" && !Array.isArray(mesh.policy) ? mesh.policy : {};
|
|
45545
|
+
const configured = Array.isArray(policy.validationCommands) ? policy.validationCommands : Array.isArray(policy.validationGate?.commands) ? policy.validationGate.commands : [];
|
|
45546
|
+
return configured.map((entry) => typeof entry === "string" ? { command: entry, category: "", source: "mesh.policy.validationCommands" } : entry).filter((entry) => entry && typeof entry.command === "string").map((entry) => {
|
|
45547
|
+
const commandText = entry.command.trim();
|
|
45548
|
+
const category = REFINE_VALIDATION_CATEGORIES.find((cat) => commandText.includes(` ${cat}`)) ?? "";
|
|
45549
|
+
return { command: commandText, category, source: "mesh.policy.validationCommands" };
|
|
45550
|
+
}).filter((entry) => !!entry.category);
|
|
45551
|
+
}
|
|
45552
|
+
function selectMeshRefineValidationCommands(mesh, workspace) {
|
|
45553
|
+
const scripts = readPackageScripts(workspace);
|
|
45554
|
+
const rejectedCommands = [];
|
|
45555
|
+
const selected = [];
|
|
45556
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45557
|
+
const candidates = [
|
|
45558
|
+
...collectPolicyValidationCandidates(mesh),
|
|
45559
|
+
...collectProjectContextValidationCandidates(mesh)
|
|
45560
|
+
];
|
|
45561
|
+
for (const candidate of candidates) {
|
|
45562
|
+
const parsed = parsePackageManagerValidationCommand(candidate.command, candidate.category, scripts, candidate.source);
|
|
45563
|
+
if (parsed.rejected) {
|
|
45564
|
+
rejectedCommands.push(parsed.rejected);
|
|
45565
|
+
continue;
|
|
45566
|
+
}
|
|
45567
|
+
if (!parsed.command || seen.has(parsed.command.displayCommand)) continue;
|
|
45568
|
+
selected.push(parsed.command);
|
|
45569
|
+
seen.add(parsed.command.displayCommand);
|
|
45570
|
+
if (selected.length >= REFINE_VALIDATION_MAX_COMMANDS) break;
|
|
45571
|
+
}
|
|
45572
|
+
if (!selected.length && candidates.length === 0) {
|
|
45573
|
+
for (const category of REFINE_VALIDATION_CATEGORIES) {
|
|
45574
|
+
if (!Object.prototype.hasOwnProperty.call(scripts, category)) continue;
|
|
45575
|
+
const fallback = parsePackageManagerValidationCommand(`npm run ${category}`, category, scripts, "package.json:scripts");
|
|
45576
|
+
if (fallback.command && !seen.has(fallback.command.displayCommand)) {
|
|
45577
|
+
selected.push(fallback.command);
|
|
45578
|
+
seen.add(fallback.command.displayCommand);
|
|
45579
|
+
} else if (fallback.rejected) {
|
|
45580
|
+
rejectedCommands.push(fallback.rejected);
|
|
45581
|
+
}
|
|
45582
|
+
if (selected.length >= 2) break;
|
|
45583
|
+
}
|
|
45584
|
+
}
|
|
45585
|
+
return {
|
|
45586
|
+
commands: selected,
|
|
45587
|
+
rejectedCommands,
|
|
45588
|
+
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"
|
|
45589
|
+
};
|
|
45590
|
+
}
|
|
45591
|
+
async function runMeshRefineValidationGate(mesh, workspace) {
|
|
45592
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
45593
|
+
const { promisify: promisify3 } = await import("util");
|
|
45594
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
45595
|
+
const selection = selectMeshRefineValidationCommands(mesh, workspace);
|
|
45596
|
+
const summary = {
|
|
45597
|
+
status: "skipped",
|
|
45598
|
+
required: true,
|
|
45599
|
+
commandsRun: [],
|
|
45600
|
+
rejectedCommands: selection.rejectedCommands,
|
|
45601
|
+
skippedReason: void 0,
|
|
45602
|
+
timeoutMs: REFINE_VALIDATION_TIMEOUT_MS,
|
|
45603
|
+
outputLimitBytes: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES
|
|
45604
|
+
};
|
|
45605
|
+
if (!selection.commands.length) {
|
|
45606
|
+
summary.skippedReason = "validation_unavailable: no allowlisted projectContext, mesh policy, or package.json build/test/typecheck/lint command was available";
|
|
45607
|
+
return summary;
|
|
45608
|
+
}
|
|
45609
|
+
for (const candidate of selection.commands) {
|
|
45610
|
+
const startedAt = Date.now();
|
|
45611
|
+
try {
|
|
45612
|
+
const result = await execFileAsync3(candidate.command, candidate.args, {
|
|
45613
|
+
cwd: workspace,
|
|
45614
|
+
encoding: "utf8",
|
|
45615
|
+
timeout: REFINE_VALIDATION_TIMEOUT_MS,
|
|
45616
|
+
maxBuffer: REFINE_VALIDATION_OUTPUT_LIMIT_BYTES,
|
|
45617
|
+
env: { ...process.env, CI: process.env.CI || "1" }
|
|
45618
|
+
});
|
|
45619
|
+
summary.commandsRun.push({
|
|
45620
|
+
command: candidate.command,
|
|
45621
|
+
args: candidate.args,
|
|
45622
|
+
displayCommand: candidate.displayCommand,
|
|
45623
|
+
category: candidate.category,
|
|
45624
|
+
source: candidate.source,
|
|
45625
|
+
passed: true,
|
|
45626
|
+
exitCode: 0,
|
|
45627
|
+
durationMs: Date.now() - startedAt,
|
|
45628
|
+
stdout: truncateValidationOutput(result.stdout),
|
|
45629
|
+
stderr: truncateValidationOutput(result.stderr)
|
|
45630
|
+
});
|
|
45631
|
+
} catch (error48) {
|
|
45632
|
+
summary.commandsRun.push({
|
|
45633
|
+
command: candidate.command,
|
|
45634
|
+
args: candidate.args,
|
|
45635
|
+
displayCommand: candidate.displayCommand,
|
|
45636
|
+
category: candidate.category,
|
|
45637
|
+
source: candidate.source,
|
|
45638
|
+
passed: false,
|
|
45639
|
+
exitCode: typeof error48?.code === "number" ? error48.code : null,
|
|
45640
|
+
signal: typeof error48?.signal === "string" ? error48.signal : null,
|
|
45641
|
+
timedOut: error48?.killed === true || /timed out/i.test(String(error48?.message || "")),
|
|
45642
|
+
durationMs: Date.now() - startedAt,
|
|
45643
|
+
stdout: truncateValidationOutput(error48?.stdout),
|
|
45644
|
+
stderr: truncateValidationOutput(error48?.stderr || error48?.message)
|
|
45645
|
+
});
|
|
45646
|
+
summary.status = "failed";
|
|
45647
|
+
return summary;
|
|
45648
|
+
}
|
|
45649
|
+
}
|
|
45650
|
+
summary.status = "passed";
|
|
45651
|
+
return summary;
|
|
45652
|
+
}
|
|
45041
45653
|
function loadYamlModule() {
|
|
45042
45654
|
return yaml;
|
|
45043
45655
|
}
|
|
@@ -45321,20 +45933,98 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
45321
45933
|
recoveryHint: "Inspect the worktree branch and mesh metadata before retrying cleanup."
|
|
45322
45934
|
};
|
|
45323
45935
|
}
|
|
45936
|
+
const forceFallbackConvergence = await this.getWorktreeForceCleanupConvergence({
|
|
45937
|
+
repoRoot,
|
|
45938
|
+
workspace,
|
|
45939
|
+
node: args.node
|
|
45940
|
+
});
|
|
45324
45941
|
try {
|
|
45325
|
-
const result = await removeWorktree2(repoRoot, workspace, {
|
|
45326
|
-
|
|
45942
|
+
const result = await removeWorktree2(repoRoot, workspace, {
|
|
45943
|
+
requireClean: true,
|
|
45944
|
+
allowSubmoduleForceFallback: forceFallbackConvergence.allow
|
|
45945
|
+
});
|
|
45946
|
+
return {
|
|
45947
|
+
success: true,
|
|
45948
|
+
removedPath: result.removedPath,
|
|
45949
|
+
repoRoot,
|
|
45950
|
+
...result.fallback ? {
|
|
45951
|
+
fallback: result.fallback,
|
|
45952
|
+
forced: result.forced,
|
|
45953
|
+
reason: result.reason,
|
|
45954
|
+
convergence: forceFallbackConvergence
|
|
45955
|
+
} : {}
|
|
45956
|
+
};
|
|
45327
45957
|
} catch (e) {
|
|
45328
45958
|
const message = String(e?.message || e || "worktree cleanup failed");
|
|
45329
45959
|
const dirty = message.includes("dirty worktree") || message.includes("local changes");
|
|
45960
|
+
const submoduleForceBlocked = /working trees containing submodules cannot be moved or removed/i.test(message) && !forceFallbackConvergence.allow;
|
|
45330
45961
|
return {
|
|
45331
45962
|
success: false,
|
|
45332
|
-
code: dirty ? "mesh_worktree_cleanup_dirty" : "mesh_worktree_cleanup_failed",
|
|
45333
|
-
error: message,
|
|
45334
|
-
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."
|
|
45963
|
+
code: dirty ? "mesh_worktree_cleanup_dirty" : submoduleForceBlocked ? "mesh_worktree_cleanup_force_fallback_blocked" : "mesh_worktree_cleanup_failed",
|
|
45964
|
+
error: submoduleForceBlocked ? `${message}; refusing --force fallback because convergence could not be verified: ${forceFallbackConvergence.error || "unknown convergence state"}` : message,
|
|
45965
|
+
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.",
|
|
45966
|
+
...submoduleForceBlocked ? { convergence: forceFallbackConvergence } : {}
|
|
45335
45967
|
};
|
|
45336
45968
|
}
|
|
45337
45969
|
}
|
|
45970
|
+
async getWorktreeForceCleanupConvergence(args) {
|
|
45971
|
+
const metadataStatus = typeof args.node?.branchConvergence?.status === "string" ? args.node.branchConvergence.status : "";
|
|
45972
|
+
if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate") {
|
|
45973
|
+
return { allow: true, status: metadataStatus, source: "node_branch_convergence" };
|
|
45974
|
+
}
|
|
45975
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
45976
|
+
const { promisify: promisify3 } = await import("util");
|
|
45977
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
45978
|
+
const runGit2 = async (gitArgs, cwd) => {
|
|
45979
|
+
const { stdout } = await execFileAsync3("git", gitArgs, {
|
|
45980
|
+
cwd,
|
|
45981
|
+
encoding: "utf8",
|
|
45982
|
+
timeout: 3e4,
|
|
45983
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
45984
|
+
windowsHide: true
|
|
45985
|
+
});
|
|
45986
|
+
return String(stdout || "").trim();
|
|
45987
|
+
};
|
|
45988
|
+
let head = "";
|
|
45989
|
+
try {
|
|
45990
|
+
head = await runGit2(["rev-parse", "HEAD"], args.workspace);
|
|
45991
|
+
} catch (e) {
|
|
45992
|
+
return { allow: false, error: `could not resolve worktree HEAD: ${e?.message || e}` };
|
|
45993
|
+
}
|
|
45994
|
+
if (!head) return { allow: false, error: "worktree HEAD is empty" };
|
|
45995
|
+
const candidateRefs = [];
|
|
45996
|
+
try {
|
|
45997
|
+
const defaultBranch = await runGit2(["branch", "--show-current"], args.repoRoot);
|
|
45998
|
+
if (defaultBranch) {
|
|
45999
|
+
candidateRefs.push(defaultBranch, `origin/${defaultBranch}`);
|
|
46000
|
+
}
|
|
46001
|
+
} catch {
|
|
46002
|
+
}
|
|
46003
|
+
candidateRefs.push("origin/main", "origin/master", "main", "master");
|
|
46004
|
+
const seen = /* @__PURE__ */ new Set();
|
|
46005
|
+
const checkedRefs = [];
|
|
46006
|
+
for (const ref of candidateRefs) {
|
|
46007
|
+
if (!ref || seen.has(ref)) continue;
|
|
46008
|
+
seen.add(ref);
|
|
46009
|
+
let commit = "";
|
|
46010
|
+
try {
|
|
46011
|
+
commit = await runGit2(["rev-parse", "--verify", `${ref}^{commit}`], args.repoRoot);
|
|
46012
|
+
} catch {
|
|
46013
|
+
continue;
|
|
46014
|
+
}
|
|
46015
|
+
checkedRefs.push(ref);
|
|
46016
|
+
try {
|
|
46017
|
+
await runGit2(["merge-base", "--is-ancestor", head, commit], args.repoRoot);
|
|
46018
|
+
return { allow: true, status: "merged_to_default_ref", source: "git_merge_base", ref };
|
|
46019
|
+
} catch {
|
|
46020
|
+
}
|
|
46021
|
+
}
|
|
46022
|
+
return {
|
|
46023
|
+
allow: false,
|
|
46024
|
+
status: metadataStatus || void 0,
|
|
46025
|
+
error: checkedRefs.length ? `worktree HEAD is not contained in checked refs: ${checkedRefs.join(", ")}` : "no default/main refs were available for convergence verification"
|
|
46026
|
+
};
|
|
46027
|
+
}
|
|
45338
46028
|
isCompletedHostedSession(record2) {
|
|
45339
46029
|
return record2?.lifecycle === "stopped" || record2?.lifecycle === "failed" || record2?.lifecycle === "interrupted";
|
|
45340
46030
|
}
|
|
@@ -46294,10 +46984,61 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46294
46984
|
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
46295
46985
|
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
46296
46986
|
const baseBranch = baseBranchStdout.trim();
|
|
46987
|
+
const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
|
|
46988
|
+
if (validationSummary.status === "failed") {
|
|
46989
|
+
return {
|
|
46990
|
+
success: false,
|
|
46991
|
+
code: "validation_failed",
|
|
46992
|
+
convergenceStatus: "blocked_review",
|
|
46993
|
+
error: "Refinery validation gate failed; merge/refine was not attempted.",
|
|
46994
|
+
branch,
|
|
46995
|
+
into: baseBranch,
|
|
46996
|
+
validationSummary,
|
|
46997
|
+
finalBranchConvergenceState: {
|
|
46998
|
+
branch,
|
|
46999
|
+
baseBranch,
|
|
47000
|
+
merged: false,
|
|
47001
|
+
removed: false,
|
|
47002
|
+
validation: "failed",
|
|
47003
|
+
status: "blocked_review"
|
|
47004
|
+
}
|
|
47005
|
+
};
|
|
47006
|
+
}
|
|
47007
|
+
if (validationSummary.status === "skipped") {
|
|
47008
|
+
return {
|
|
47009
|
+
success: false,
|
|
47010
|
+
code: "validation_unavailable",
|
|
47011
|
+
convergenceStatus: "blocked_review",
|
|
47012
|
+
error: "Refinery validation gate is required but no allowlisted validation command was available; merge/refine was not attempted.",
|
|
47013
|
+
branch,
|
|
47014
|
+
into: baseBranch,
|
|
47015
|
+
validationSummary,
|
|
47016
|
+
finalBranchConvergenceState: {
|
|
47017
|
+
branch,
|
|
47018
|
+
baseBranch,
|
|
47019
|
+
merged: false,
|
|
47020
|
+
removed: false,
|
|
47021
|
+
validation: "unavailable",
|
|
47022
|
+
status: "blocked_review"
|
|
47023
|
+
}
|
|
47024
|
+
};
|
|
47025
|
+
}
|
|
46297
47026
|
try {
|
|
46298
47027
|
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
46299
47028
|
} catch (e) {
|
|
46300
|
-
return {
|
|
47029
|
+
return {
|
|
47030
|
+
success: false,
|
|
47031
|
+
error: `Merge failed (conflicts?): ${e.message}`,
|
|
47032
|
+
validationSummary,
|
|
47033
|
+
finalBranchConvergenceState: {
|
|
47034
|
+
branch,
|
|
47035
|
+
baseBranch,
|
|
47036
|
+
merged: false,
|
|
47037
|
+
removed: false,
|
|
47038
|
+
validation: "passed",
|
|
47039
|
+
status: "not_mergeable"
|
|
47040
|
+
}
|
|
47041
|
+
};
|
|
46301
47042
|
}
|
|
46302
47043
|
const removeResult = await this.execute("remove_mesh_node", {
|
|
46303
47044
|
meshId,
|
|
@@ -46310,11 +47051,27 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46310
47051
|
appendLedgerEntry2(meshId, {
|
|
46311
47052
|
kind: "node_removed",
|
|
46312
47053
|
nodeId,
|
|
46313
|
-
payload: { refined: true, mergedBranch: branch, into: baseBranch }
|
|
47054
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
|
|
46314
47055
|
});
|
|
46315
47056
|
} catch {
|
|
46316
47057
|
}
|
|
46317
|
-
return {
|
|
47058
|
+
return {
|
|
47059
|
+
success: true,
|
|
47060
|
+
merged: true,
|
|
47061
|
+
branch,
|
|
47062
|
+
into: baseBranch,
|
|
47063
|
+
removeResult,
|
|
47064
|
+
validationSummary,
|
|
47065
|
+
finalBranchConvergenceState: {
|
|
47066
|
+
branch: baseBranch,
|
|
47067
|
+
mergedBranch: branch,
|
|
47068
|
+
baseBranch,
|
|
47069
|
+
merged: true,
|
|
47070
|
+
removed: removeResult?.success !== false,
|
|
47071
|
+
validation: "passed",
|
|
47072
|
+
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
47073
|
+
}
|
|
47074
|
+
};
|
|
46318
47075
|
} catch (e) {
|
|
46319
47076
|
return { success: false, error: e.message };
|
|
46320
47077
|
}
|
|
@@ -46369,7 +47126,10 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46369
47126
|
sessionCleanupMode,
|
|
46370
47127
|
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
46371
47128
|
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
46372
|
-
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0
|
|
47129
|
+
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0,
|
|
47130
|
+
worktreeCleanupFallback: typeof worktreeCleanup?.fallback === "string" ? worktreeCleanup.fallback : void 0,
|
|
47131
|
+
forced: worktreeCleanup?.forced === true ? true : void 0,
|
|
47132
|
+
forceFallbackReason: typeof worktreeCleanup?.reason === "string" ? worktreeCleanup.reason : void 0
|
|
46373
47133
|
}
|
|
46374
47134
|
});
|
|
46375
47135
|
} catch {
|
|
@@ -54452,6 +55212,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
54452
55212
|
return false;
|
|
54453
55213
|
}
|
|
54454
55214
|
}
|
|
55215
|
+
init_cli_detector();
|
|
54455
55216
|
var SessionRegistry = class {
|
|
54456
55217
|
bySessionId = /* @__PURE__ */ new Map();
|
|
54457
55218
|
byManagerKey = /* @__PURE__ */ new Map();
|