@adhdev/daemon-standalone 0.9.82-rc.231 → 0.9.82-rc.233
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 +11 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +296 -1234
- package/vendor/mcp-server/index.js.map +1 -1
|
@@ -224,11 +224,6 @@ var IpcTransport = class {
|
|
|
224
224
|
}
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
// src/transports/mode.ts
|
|
228
|
-
function isLocalTransport(transport) {
|
|
229
|
-
return typeof transport.command === "function";
|
|
230
|
-
}
|
|
231
|
-
|
|
232
227
|
// src/tools/chat-compact.ts
|
|
233
228
|
function messageContent(message) {
|
|
234
229
|
const content = message?.content;
|
|
@@ -410,7 +405,6 @@ var OLD_HISTORICAL_QUEUE_RECORD_MS = 7 * 24 * 60 * 6e4;
|
|
|
410
405
|
var ACTIVE_QUEUE_STATUSES = /* @__PURE__ */ new Set(["pending", "assigned"]);
|
|
411
406
|
var HISTORICAL_QUEUE_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
412
407
|
async function refreshMeshFromDaemon(ctx) {
|
|
413
|
-
if (!isLocalTransport(ctx.transport)) return;
|
|
414
408
|
try {
|
|
415
409
|
const result = await ctx.transport.command("get_mesh", { meshId: ctx.mesh.id });
|
|
416
410
|
if (!result?.success || !Array.isArray(result.mesh?.nodes)) return;
|
|
@@ -934,15 +928,12 @@ async function reconcileDirectDispatchesFromTranscriptEvidence(ctx, liveNodes, d
|
|
|
934
928
|
return { attempted, reconciled, skipped };
|
|
935
929
|
}
|
|
936
930
|
async function triggerMeshQueueAndReport(ctx, node, opts) {
|
|
937
|
-
if (!(isLocalTransport(ctx.transport) || ctx.transport instanceof IpcTransport)) return void 0;
|
|
938
931
|
try {
|
|
939
932
|
let raw;
|
|
940
933
|
if (ctx.transport instanceof IpcTransport && node?.daemonId && opts?.localNode === false) {
|
|
941
934
|
raw = await ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id });
|
|
942
|
-
} else if (isLocalTransport(ctx.transport)) {
|
|
943
|
-
raw = await ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id });
|
|
944
935
|
} else {
|
|
945
|
-
|
|
936
|
+
raw = await ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id });
|
|
946
937
|
}
|
|
947
938
|
const payload = unwrapCommandPayload(raw);
|
|
948
939
|
const trigger = payload?.trigger && typeof payload.trigger === "object" ? payload.trigger : payload;
|
|
@@ -1592,7 +1583,7 @@ async function collectRelatedRepoStatuses(ctx, node) {
|
|
|
1592
1583
|
const results = [];
|
|
1593
1584
|
for (const repo of relatedRepos) {
|
|
1594
1585
|
try {
|
|
1595
|
-
const statusResult =
|
|
1586
|
+
const statusResult = await commandForNode(ctx, node, "git_status", { workspace: repo.workspace, refreshUpstream: true });
|
|
1596
1587
|
const status = extractGitStatus(statusResult);
|
|
1597
1588
|
results.push(summarizeRelatedRepoStatus(repo, status));
|
|
1598
1589
|
} catch (e) {
|
|
@@ -1811,11 +1802,7 @@ async function commandForNode(ctx, node, command, args = {}) {
|
|
|
1811
1802
|
if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
|
|
1812
1803
|
return ctx.transport.meshCommand(node.daemonId, command, args);
|
|
1813
1804
|
}
|
|
1814
|
-
|
|
1815
|
-
return ctx.transport.command(command, args);
|
|
1816
|
-
}
|
|
1817
|
-
const identity = buildNodeMachineIdentity(ctx, node);
|
|
1818
|
-
throw new Error(`Command '${command}' requires daemon IPC/local transport for node '${node.id}' (hostname=${identity.hostname || "unknown"}, coordinatorHostname=${identity.coordinatorHostname || "unknown"}, sameMachine=${identity.sameMachine})`);
|
|
1805
|
+
return ctx.transport.command(command, args);
|
|
1819
1806
|
}
|
|
1820
1807
|
function normalizePendingMeshCoordinatorEvents(value) {
|
|
1821
1808
|
const payload = unwrapCommandPayload(value);
|
|
@@ -1893,12 +1880,9 @@ async function drainCoordinatorPendingEvents(ctx, opts) {
|
|
|
1893
1880
|
}
|
|
1894
1881
|
return surfacedEvents;
|
|
1895
1882
|
}
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
return events;
|
|
1900
|
-
}
|
|
1901
|
-
return [];
|
|
1883
|
+
const events = (0, import_daemon_core.drainPendingMeshCoordinatorEvents)(ctx.mesh.id, ctx.localDaemonId).filter(matchesCurrentMesh);
|
|
1884
|
+
events.forEach(rememberMeshSessionProviderMetadataFromEvent);
|
|
1885
|
+
return events;
|
|
1902
1886
|
}
|
|
1903
1887
|
function isP2pTransportUnavailableError(error) {
|
|
1904
1888
|
return (0, import_daemon_core.isP2pRelayTransportFailure)(error);
|
|
@@ -2299,47 +2283,26 @@ async function meshStatus(ctx, args = {}) {
|
|
|
2299
2283
|
...getNodeLaunchReadiness(node)
|
|
2300
2284
|
};
|
|
2301
2285
|
try {
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
refreshUpstream: true,
|
|
2323
|
-
includeSubmodules: autoDiscover,
|
|
2324
|
-
submoduleIgnorePaths: node.policy?.submoduleIgnorePaths || void 0
|
|
2325
|
-
});
|
|
2326
|
-
const status = extractGitStatus(statusResult);
|
|
2327
|
-
const uncommittedChanges = countUncommittedChanges(status);
|
|
2328
|
-
const dirty = isGitStatusDirty(status);
|
|
2329
|
-
entry.health = status?.isGitRepo ? dirty ? "dirty" : "online" : "degraded";
|
|
2330
|
-
assignFullGitSnapshot(entry, status);
|
|
2331
|
-
entry.branch = status?.branch;
|
|
2332
|
-
entry.isDirty = dirty;
|
|
2333
|
-
entry.uncommittedChanges = uncommittedChanges;
|
|
2334
|
-
entry.branchConvergence = buildBranchConvergence(mesh, node, status, dirty, uncommittedChanges);
|
|
2335
|
-
const submodules = extractSubmodules(statusResult, node.policy?.submoduleIgnorePaths || []);
|
|
2336
|
-
if (submodules && submodules.some((s) => s?.outOfSync)) {
|
|
2337
|
-
entry.submoduleWarning = "One or more submodules are out of sync with the parent repo. Run `git submodule update` or check deployment readiness.";
|
|
2338
|
-
entry.outOfSyncSubmodules = submodules.filter((s) => s?.outOfSync).map((s) => s.path);
|
|
2339
|
-
}
|
|
2340
|
-
} else {
|
|
2341
|
-
entry.health = "unknown";
|
|
2342
|
-
entry.note = "No daemonId available for cloud status probe";
|
|
2286
|
+
const autoDiscover = node.policy?.autoDiscoverSubmodules !== false;
|
|
2287
|
+
const statusResult = await commandForNode(ctx, node, "git_status", {
|
|
2288
|
+
workspace: node.workspace,
|
|
2289
|
+
refreshUpstream: true,
|
|
2290
|
+
includeSubmodules: autoDiscover,
|
|
2291
|
+
submoduleIgnorePaths: node.policy?.submoduleIgnorePaths || void 0
|
|
2292
|
+
});
|
|
2293
|
+
const status = extractGitStatus(statusResult);
|
|
2294
|
+
const uncommittedChanges = countUncommittedChanges(status);
|
|
2295
|
+
const dirty = isGitStatusDirty(status);
|
|
2296
|
+
entry.health = status?.isGitRepo ? dirty ? "dirty" : "online" : "degraded";
|
|
2297
|
+
assignFullGitSnapshot(entry, status);
|
|
2298
|
+
entry.branch = status?.branch;
|
|
2299
|
+
entry.isDirty = dirty;
|
|
2300
|
+
entry.uncommittedChanges = uncommittedChanges;
|
|
2301
|
+
entry.branchConvergence = buildBranchConvergence(mesh, node, status, dirty, uncommittedChanges);
|
|
2302
|
+
const submodules = extractSubmodules(statusResult, node.policy?.submoduleIgnorePaths || []);
|
|
2303
|
+
if (submodules && submodules.some((s) => s?.outOfSync)) {
|
|
2304
|
+
entry.submoduleWarning = "One or more submodules are out of sync with the parent repo. Run `git submodule update` or check deployment readiness.";
|
|
2305
|
+
entry.outOfSyncSubmodules = submodules.filter((s) => s?.outOfSync).map((s) => s.path);
|
|
2343
2306
|
}
|
|
2344
2307
|
} catch (e) {
|
|
2345
2308
|
const failure = buildCoordinatorP2pRelayFailure(e, {
|
|
@@ -2671,7 +2634,7 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
2671
2634
|
const missionId = readString(args.missionId) || readString(args.mission_id) || void 0;
|
|
2672
2635
|
try {
|
|
2673
2636
|
const task = (0, import_daemon_core.enqueueTask)(ctx.mesh.id, args.message, { taskMode, requiredTags, dependsOn, missionId });
|
|
2674
|
-
if (
|
|
2637
|
+
if (!(ctx.transport instanceof IpcTransport)) {
|
|
2675
2638
|
const queueTrigger = await triggerMeshQueueAndReport(ctx);
|
|
2676
2639
|
return JSON.stringify({
|
|
2677
2640
|
success: true,
|
|
@@ -2684,7 +2647,7 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
2684
2647
|
...buildQueueTriggerGuidance(queueTrigger)
|
|
2685
2648
|
});
|
|
2686
2649
|
}
|
|
2687
|
-
|
|
2650
|
+
{
|
|
2688
2651
|
const queueTrigger = await triggerMeshQueueAndReport(ctx);
|
|
2689
2652
|
const dispatchPromises = [];
|
|
2690
2653
|
for (const node of ctx.mesh.nodes) {
|
|
@@ -2748,7 +2711,6 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
2748
2711
|
...buildQueueTriggerGuidance(queueTrigger)
|
|
2749
2712
|
});
|
|
2750
2713
|
}
|
|
2751
|
-
return JSON.stringify({ success: true, source: "queue", taskId: task.id, status: task.status, taskMode: task.taskMode, requiredTags: task.requiredTags });
|
|
2752
2714
|
} catch (e) {
|
|
2753
2715
|
const message = e?.message || String(e);
|
|
2754
2716
|
if (message.includes("live_debug_readonly_guardrail_violation")) {
|
|
@@ -2864,10 +2826,8 @@ async function meshQueueCancel(ctx, args) {
|
|
|
2864
2826
|
if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
|
|
2865
2827
|
const task = (0, import_daemon_core.cancelTask)(ctx.mesh.id, taskId, { reason: args.reason });
|
|
2866
2828
|
if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
});
|
|
2870
|
-
}
|
|
2829
|
+
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
2830
|
+
});
|
|
2871
2831
|
return JSON.stringify({ success: true, task }, null, 2);
|
|
2872
2832
|
} catch (e) {
|
|
2873
2833
|
return JSON.stringify({ success: false, error: e.message });
|
|
@@ -2898,10 +2858,8 @@ async function meshQueueRequeue(ctx, args) {
|
|
|
2898
2858
|
hint: "Use force=true to bypass the retry cap for explicit operator recovery."
|
|
2899
2859
|
}, null, 2);
|
|
2900
2860
|
}
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
});
|
|
2904
|
-
}
|
|
2861
|
+
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
2862
|
+
});
|
|
2905
2863
|
return JSON.stringify({ success: true, task }, null, 2);
|
|
2906
2864
|
} catch (e) {
|
|
2907
2865
|
return JSON.stringify({ success: false, error: e.message });
|
|
@@ -2926,7 +2884,7 @@ async function meshSendTask(ctx, args) {
|
|
|
2926
2884
|
return JSON.stringify({ error: `Node '${args.node_id}' is read-only` });
|
|
2927
2885
|
}
|
|
2928
2886
|
let explicitTargetSession;
|
|
2929
|
-
if (args.session_id && isWorkerTaskMode(taskMode)
|
|
2887
|
+
if (args.session_id && isWorkerTaskMode(taskMode)) {
|
|
2930
2888
|
try {
|
|
2931
2889
|
const statusResult = await commandForNode(ctx, node, "get_status_metadata", {});
|
|
2932
2890
|
const sessions = extractStatusMetadataSessions(statusResult);
|
|
@@ -2981,15 +2939,6 @@ async function meshSendTask(ctx, args) {
|
|
|
2981
2939
|
});
|
|
2982
2940
|
}
|
|
2983
2941
|
try {
|
|
2984
|
-
if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
2985
|
-
const res = await ctx.transport.meshEnqueueTask(node.daemonId, {
|
|
2986
|
-
meshId: ctx.mesh.id,
|
|
2987
|
-
message: args.message,
|
|
2988
|
-
targetNodeId: args.node_id,
|
|
2989
|
-
...taskMode ? { taskMode } : {}
|
|
2990
|
-
});
|
|
2991
|
-
return JSON.stringify(res);
|
|
2992
|
-
}
|
|
2993
2942
|
const isLocalNode = isLocalControlPlaneNode(ctx, node);
|
|
2994
2943
|
if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
|
|
2995
2944
|
const cached = getSessionMetadata(meshSessionCacheKey(args.node_id, args.session_id || ""));
|
|
@@ -3047,7 +2996,7 @@ async function meshSendTask(ctx, args) {
|
|
|
3047
2996
|
dispatched: result2.success === true
|
|
3048
2997
|
});
|
|
3049
2998
|
}
|
|
3050
|
-
if (args.session_id
|
|
2999
|
+
if (args.session_id) {
|
|
3051
3000
|
const cached = getSessionMetadata(meshSessionCacheKey(args.node_id, args.session_id));
|
|
3052
3001
|
let resolvedProviderType = cached?.providerType || "";
|
|
3053
3002
|
if (!resolvedProviderType) {
|
|
@@ -3244,8 +3193,8 @@ async function meshSendTask(ctx, args) {
|
|
|
3244
3193
|
targetSessionId: args.session_id,
|
|
3245
3194
|
taskMode
|
|
3246
3195
|
});
|
|
3247
|
-
const queueTrigger =
|
|
3248
|
-
const pendingEvents =
|
|
3196
|
+
const queueTrigger = await triggerMeshQueueAndReport(ctx);
|
|
3197
|
+
const pendingEvents = (0, import_daemon_core.drainPendingMeshCoordinatorEvents)(ctx.mesh.id, ctx.localDaemonId);
|
|
3249
3198
|
const result = {
|
|
3250
3199
|
success: true,
|
|
3251
3200
|
source: "queue",
|
|
@@ -3275,91 +3224,59 @@ async function meshReadChat(ctx, args) {
|
|
|
3275
3224
|
if (!node) {
|
|
3276
3225
|
return JSON.stringify(buildMissingNodeReadChatRecovery(ctx, args), null, 2);
|
|
3277
3226
|
}
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3227
|
+
await drainCoordinatorPendingEvents(ctx, { nodeIds: [args.node_id] });
|
|
3228
|
+
const cached = resolveMeshSessionProviderMetadata(ctx, args.node_id, args.session_id);
|
|
3229
|
+
const providerSessionId = typeof args.provider_session_id === "string" && args.provider_session_id.trim() ? args.provider_session_id.trim() : cached?.providerSessionId;
|
|
3230
|
+
const result = await commandForNode(ctx, node, "read_chat", {
|
|
3231
|
+
sessionId: args.session_id,
|
|
3232
|
+
targetSessionId: args.session_id,
|
|
3233
|
+
workspace: node.workspace,
|
|
3234
|
+
...cached?.providerType ? { agentType: cached.providerType, providerType: cached.providerType } : {},
|
|
3235
|
+
...providerSessionId ? { providerSessionId } : {},
|
|
3236
|
+
tailLimit: args.tail ?? 10
|
|
3237
|
+
});
|
|
3238
|
+
const payload = annotateRapidReadChatAdvisory(unwrapCommandPayload(result), {
|
|
3239
|
+
key: `mesh:${args.node_id}:${args.session_id}`,
|
|
3240
|
+
toolName: "mesh_read_chat",
|
|
3241
|
+
completionCallbackExpected: true
|
|
3242
|
+
});
|
|
3243
|
+
const useCompact = args.compact !== false;
|
|
3244
|
+
if (useCompact) {
|
|
3245
|
+
const compactPayload = compactChatPayload(payload, {
|
|
3246
|
+
nodeId: args.node_id,
|
|
3285
3247
|
sessionId: args.session_id,
|
|
3286
|
-
|
|
3287
|
-
workspace: node.workspace,
|
|
3288
|
-
...cached?.providerType ? { agentType: cached.providerType, providerType: cached.providerType } : {},
|
|
3289
|
-
...providerSessionId ? { providerSessionId } : {},
|
|
3290
|
-
tailLimit: args.tail ?? 10
|
|
3291
|
-
});
|
|
3292
|
-
const payload = annotateRapidReadChatAdvisory(unwrapCommandPayload(result), {
|
|
3293
|
-
key: `mesh:${args.node_id}:${args.session_id}`,
|
|
3294
|
-
toolName: "mesh_read_chat",
|
|
3295
|
-
completionCallbackExpected: true
|
|
3248
|
+
limit: args.tail ?? 10
|
|
3296
3249
|
});
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
limit: args.tail ?? 10
|
|
3303
|
-
});
|
|
3304
|
-
return JSON.stringify(
|
|
3305
|
-
payload.pollingAdvisory ? { ...compactPayload, pollingAdvisory: payload.pollingAdvisory } : compactPayload,
|
|
3306
|
-
null,
|
|
3307
|
-
2
|
|
3308
|
-
);
|
|
3309
|
-
}
|
|
3310
|
-
return JSON.stringify(payload, null, 2);
|
|
3311
|
-
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
3312
|
-
try {
|
|
3313
|
-
const targetId = `${node.daemonId}:session:${args.session_id}`;
|
|
3314
|
-
const res = await ctx.transport.readChat(targetId, {
|
|
3315
|
-
limit: args.tail ?? 10,
|
|
3316
|
-
sessionId: args.session_id
|
|
3317
|
-
});
|
|
3318
|
-
return JSON.stringify(res, null, 2);
|
|
3319
|
-
} catch (e) {
|
|
3320
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3321
|
-
}
|
|
3322
|
-
} else {
|
|
3323
|
-
return JSON.stringify({ error: "Cloud mesh read_chat requires node daemonId" });
|
|
3250
|
+
return JSON.stringify(
|
|
3251
|
+
payload.pollingAdvisory ? { ...compactPayload, pollingAdvisory: payload.pollingAdvisory } : compactPayload,
|
|
3252
|
+
null,
|
|
3253
|
+
2
|
|
3254
|
+
);
|
|
3324
3255
|
}
|
|
3256
|
+
return JSON.stringify(payload, null, 2);
|
|
3325
3257
|
}
|
|
3326
3258
|
async function meshReadDebug(ctx, args) {
|
|
3327
3259
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
return JSON.stringify(payload, null, 2);
|
|
3343
|
-
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
3344
|
-
try {
|
|
3345
|
-
const targetId = `${node.daemonId}:session:${args.session_id}`;
|
|
3346
|
-
const res = await ctx.transport.getChatDebugBundle(targetId, {
|
|
3347
|
-
sessionId: args.session_id,
|
|
3348
|
-
tailLimit: args.tail ?? 40,
|
|
3349
|
-
delivery: args.delivery
|
|
3350
|
-
});
|
|
3351
|
-
return JSON.stringify(res, null, 2);
|
|
3352
|
-
} catch (e) {
|
|
3353
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3354
|
-
}
|
|
3355
|
-
}
|
|
3356
|
-
return JSON.stringify({ error: "Cloud mesh read_debug requires node daemonId" });
|
|
3260
|
+
const cached = resolveMeshSessionProviderMetadata(ctx, args.node_id, args.session_id);
|
|
3261
|
+
const providerSessionId = typeof args.provider_session_id === "string" && args.provider_session_id.trim() ? args.provider_session_id.trim() : cached?.providerSessionId;
|
|
3262
|
+
const delivery = args.delivery === "inline" ? void 0 : "daemon_file";
|
|
3263
|
+
const result = await commandForNode(ctx, node, "get_chat_debug_bundle", {
|
|
3264
|
+
sessionId: args.session_id,
|
|
3265
|
+
targetSessionId: args.session_id,
|
|
3266
|
+
workspace: node.workspace,
|
|
3267
|
+
...cached?.providerType ? { agentType: cached.providerType, providerType: cached.providerType } : {},
|
|
3268
|
+
...providerSessionId ? { providerSessionId } : {},
|
|
3269
|
+
tailLimit: args.tail ?? 40,
|
|
3270
|
+
...delivery ? { delivery } : {}
|
|
3271
|
+
});
|
|
3272
|
+
const payload = unwrapCommandPayload(result);
|
|
3273
|
+
return JSON.stringify(payload, null, 2);
|
|
3357
3274
|
}
|
|
3358
3275
|
async function meshLaunchSession(ctx, args) {
|
|
3359
3276
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
3360
3277
|
const bootstrapBlock = getWorktreeBootstrapLaunchBlock(node, ctx.mesh.policy);
|
|
3361
3278
|
if (bootstrapBlock) return JSON.stringify(bootstrapBlock, null, 2);
|
|
3362
|
-
|
|
3279
|
+
{
|
|
3363
3280
|
let resolvedProviderType = typeof args.type === "string" && args.type.trim() ? args.type : "";
|
|
3364
3281
|
if (!resolvedProviderType) {
|
|
3365
3282
|
const providerPriority = readProviderPriority(node.policy);
|
|
@@ -3439,51 +3356,6 @@ async function meshLaunchSession(ctx, args) {
|
|
|
3439
3356
|
queueTrigger,
|
|
3440
3357
|
...buildQueueTriggerGuidance(queueTrigger)
|
|
3441
3358
|
}, null, 2);
|
|
3442
|
-
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
3443
|
-
let resolvedProviderType = typeof args.type === "string" && args.type.trim() ? args.type : "";
|
|
3444
|
-
if (!resolvedProviderType) {
|
|
3445
|
-
const providerPriority = readProviderPriority(node.policy);
|
|
3446
|
-
if (!providerPriority.length) {
|
|
3447
|
-
return JSON.stringify({ success: false, error: missingProviderPriorityMessage(args.node_id) });
|
|
3448
|
-
}
|
|
3449
|
-
resolvedProviderType = providerPriority[0];
|
|
3450
|
-
}
|
|
3451
|
-
const coordinatorNode = resolveCoordinatorNode(ctx);
|
|
3452
|
-
const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
|
|
3453
|
-
const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
|
|
3454
|
-
if (!coordinatorDaemonId) {
|
|
3455
|
-
return JSON.stringify(buildMissingCoordinatorDaemonIdFailure(ctx, node, resolvedProviderType), null, 2);
|
|
3456
|
-
}
|
|
3457
|
-
try {
|
|
3458
|
-
const res = await ctx.transport.launch(node.daemonId, {
|
|
3459
|
-
type: resolvedProviderType,
|
|
3460
|
-
dir: node.workspace,
|
|
3461
|
-
settings: {
|
|
3462
|
-
meshNodeFor: ctx.mesh.id,
|
|
3463
|
-
meshNodeId: args.node_id,
|
|
3464
|
-
spawnedSessionVisibility,
|
|
3465
|
-
...coordinatorDaemonId ? { meshCoordinatorDaemonId: coordinatorDaemonId } : {},
|
|
3466
|
-
...coordinatorNode?.id ? { meshCoordinatorNodeId: coordinatorNode.id } : {},
|
|
3467
|
-
launchedByCoordinator: true
|
|
3468
|
-
}
|
|
3469
|
-
});
|
|
3470
|
-
const runtimeSessionId = typeof res?.sessionId === "string" ? res.sessionId : typeof res?.id === "string" ? res.id : "";
|
|
3471
|
-
try {
|
|
3472
|
-
(0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
|
|
3473
|
-
kind: "session_launched",
|
|
3474
|
-
nodeId: args.node_id,
|
|
3475
|
-
sessionId: runtimeSessionId || void 0,
|
|
3476
|
-
providerType: resolvedProviderType,
|
|
3477
|
-
payload: {}
|
|
3478
|
-
});
|
|
3479
|
-
} catch {
|
|
3480
|
-
}
|
|
3481
|
-
return JSON.stringify({ ...res, resolvedProviderType }, null, 2);
|
|
3482
|
-
} catch (e) {
|
|
3483
|
-
return JSON.stringify(recordRecoverableLaunchFailure(ctx, node, resolvedProviderType, e), null, 2);
|
|
3484
|
-
}
|
|
3485
|
-
} else {
|
|
3486
|
-
return JSON.stringify({ error: "Cloud mesh launch_session requires node daemonId" });
|
|
3487
3359
|
}
|
|
3488
3360
|
}
|
|
3489
3361
|
async function meshGitStatus(ctx, args) {
|
|
@@ -3491,37 +3363,23 @@ async function meshGitStatus(ctx, args) {
|
|
|
3491
3363
|
const autoDiscoverSubmodules = node.policy?.autoDiscoverSubmodules !== false;
|
|
3492
3364
|
const submoduleIgnorePaths = node.policy?.submoduleIgnorePaths || [];
|
|
3493
3365
|
try {
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
const diffResult = await commandForNode(ctx, node, "git_diff_summary", {
|
|
3512
|
-
workspace: node.workspace
|
|
3513
|
-
});
|
|
3514
|
-
return JSON.stringify({
|
|
3515
|
-
nodeId: args.node_id,
|
|
3516
|
-
workspace: node.workspace,
|
|
3517
|
-
status: extractGitStatus(statusResult),
|
|
3518
|
-
diff: extractGitDiff(diffResult),
|
|
3519
|
-
submodules: autoDiscoverSubmodules ? extractSubmodules(statusResult, submoduleIgnorePaths) : void 0,
|
|
3520
|
-
relatedRepos: await collectRelatedRepoStatuses(ctx, node)
|
|
3521
|
-
}, null, 2);
|
|
3522
|
-
} else {
|
|
3523
|
-
return JSON.stringify({ error: "No daemonId available for cloud git_status probe" });
|
|
3524
|
-
}
|
|
3366
|
+
const statusResult = await commandForNode(ctx, node, "git_status", {
|
|
3367
|
+
workspace: node.workspace,
|
|
3368
|
+
refreshUpstream: true,
|
|
3369
|
+
includeSubmodules: autoDiscoverSubmodules,
|
|
3370
|
+
submoduleIgnorePaths: submoduleIgnorePaths.length > 0 ? submoduleIgnorePaths : void 0
|
|
3371
|
+
});
|
|
3372
|
+
const diffResult = await commandForNode(ctx, node, "git_diff_summary", {
|
|
3373
|
+
workspace: node.workspace
|
|
3374
|
+
});
|
|
3375
|
+
return JSON.stringify({
|
|
3376
|
+
nodeId: args.node_id,
|
|
3377
|
+
workspace: node.workspace,
|
|
3378
|
+
status: extractGitStatus(statusResult),
|
|
3379
|
+
diff: extractGitDiff(diffResult),
|
|
3380
|
+
submodules: autoDiscoverSubmodules ? extractSubmodules(statusResult, submoduleIgnorePaths) : void 0,
|
|
3381
|
+
relatedRepos: await collectRelatedRepoStatuses(ctx, node)
|
|
3382
|
+
}, null, 2);
|
|
3525
3383
|
} catch (e) {
|
|
3526
3384
|
const failure = buildCoordinatorP2pRelayFailure(e, {
|
|
3527
3385
|
command: "git_status",
|
|
@@ -3584,211 +3442,104 @@ async function meshCheckpoint(ctx, args) {
|
|
|
3584
3442
|
if (node.policy?.readOnly) {
|
|
3585
3443
|
return JSON.stringify({ error: `Node '${args.node_id}' is read-only \u2014 cannot checkpoint` });
|
|
3586
3444
|
}
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
payload: {
|
|
3598
|
-
message: args.message,
|
|
3599
|
-
commit: result?.checkpoint?.commit,
|
|
3600
|
-
outcome: result?.checkpoint?.status || (result?.checkpoint?.noop ? "skipped" : void 0),
|
|
3601
|
-
noop: result?.checkpoint?.noop === true,
|
|
3602
|
-
reason: result?.checkpoint?.reason
|
|
3603
|
-
}
|
|
3604
|
-
});
|
|
3605
|
-
} catch {
|
|
3606
|
-
}
|
|
3607
|
-
return JSON.stringify(result, null, 2);
|
|
3608
|
-
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
3609
|
-
try {
|
|
3610
|
-
const res = await ctx.transport.gitCheckpoint(node.daemonId, {
|
|
3611
|
-
workspace: node.workspace,
|
|
3445
|
+
const result = await commandForNode(ctx, node, "git_checkpoint", {
|
|
3446
|
+
workspace: node.workspace,
|
|
3447
|
+
message: args.message,
|
|
3448
|
+
includeUntracked: true
|
|
3449
|
+
});
|
|
3450
|
+
try {
|
|
3451
|
+
(0, import_daemon_core.appendLedgerEntry)(ctx.mesh.id, {
|
|
3452
|
+
kind: "checkpoint_created",
|
|
3453
|
+
nodeId: args.node_id,
|
|
3454
|
+
payload: {
|
|
3612
3455
|
message: args.message,
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
kind: "checkpoint_created",
|
|
3618
|
-
nodeId: args.node_id,
|
|
3619
|
-
payload: {
|
|
3620
|
-
message: args.message,
|
|
3621
|
-
commit: res?.checkpoint?.commit,
|
|
3622
|
-
outcome: res?.checkpoint?.status || (res?.checkpoint?.noop ? "skipped" : void 0),
|
|
3623
|
-
noop: res?.checkpoint?.noop === true,
|
|
3624
|
-
reason: res?.checkpoint?.reason
|
|
3625
|
-
}
|
|
3626
|
-
});
|
|
3627
|
-
} catch {
|
|
3456
|
+
commit: result?.checkpoint?.commit,
|
|
3457
|
+
outcome: result?.checkpoint?.status || (result?.checkpoint?.noop ? "skipped" : void 0),
|
|
3458
|
+
noop: result?.checkpoint?.noop === true,
|
|
3459
|
+
reason: result?.checkpoint?.reason
|
|
3628
3460
|
}
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3632
|
-
}
|
|
3633
|
-
} else {
|
|
3634
|
-
return JSON.stringify({ error: "Cloud mesh checkpoint requires node daemonId" });
|
|
3461
|
+
});
|
|
3462
|
+
} catch {
|
|
3635
3463
|
}
|
|
3464
|
+
return JSON.stringify(result, null, 2);
|
|
3636
3465
|
}
|
|
3637
3466
|
async function meshApprove(ctx, args) {
|
|
3638
3467
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
return JSON.stringify(result, null, 2);
|
|
3651
|
-
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
3652
|
-
try {
|
|
3653
|
-
const targetId = `${node.daemonId}:session:${args.session_id}`;
|
|
3654
|
-
const res = await ctx.transport.approve(targetId, args.action === "reject" ? "reject" : "approve");
|
|
3655
|
-
return JSON.stringify(res, null, 2);
|
|
3656
|
-
} catch (e) {
|
|
3657
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3658
|
-
}
|
|
3659
|
-
} else {
|
|
3660
|
-
return JSON.stringify({ error: "Cloud mesh approve requires node daemonId" });
|
|
3661
|
-
}
|
|
3468
|
+
const cached = getSessionMetadata(meshSessionCacheKey(args.node_id, args.session_id));
|
|
3469
|
+
const providerSessionId = cached?.providerSessionId;
|
|
3470
|
+
const result = await commandForNode(ctx, node, "resolve_action", {
|
|
3471
|
+
sessionId: args.session_id,
|
|
3472
|
+
targetSessionId: args.session_id,
|
|
3473
|
+
workspace: node.workspace,
|
|
3474
|
+
...cached?.providerType ? { agentType: cached.providerType, providerType: cached.providerType } : {},
|
|
3475
|
+
...providerSessionId ? { providerSessionId } : {},
|
|
3476
|
+
action: args.action === "reject" ? "reject" : "approve"
|
|
3477
|
+
});
|
|
3478
|
+
return JSON.stringify(result, null, 2);
|
|
3662
3479
|
}
|
|
3663
3480
|
async function meshCloneNode(ctx, args) {
|
|
3664
3481
|
const sourceNode = await findNodeWithRefresh(ctx, args.source_node_id);
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
await syncCoordinatorDaemonMeshCache(ctx);
|
|
3680
|
-
}
|
|
3681
|
-
return JSON.stringify(result, null, 2);
|
|
3682
|
-
} else if (!isLocalTransport(ctx.transport) && sourceNode.daemonId) {
|
|
3683
|
-
try {
|
|
3684
|
-
const res = await ctx.transport.meshCloneNode(sourceNode.daemonId, {
|
|
3685
|
-
meshId: ctx.mesh.id,
|
|
3686
|
-
sourceNodeId: args.source_node_id,
|
|
3687
|
-
branch: args.branch,
|
|
3688
|
-
baseBranch: args.base_branch,
|
|
3689
|
-
inlineMesh: ctx.mesh
|
|
3690
|
-
});
|
|
3691
|
-
const clonePayload = extractCloneNodePayload(res);
|
|
3692
|
-
if (clonePayload?.success && clonePayload.node?.id) {
|
|
3693
|
-
const existingIndex = ctx.mesh.nodes.findIndex((n) => n.id === clonePayload.node.id);
|
|
3694
|
-
if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
|
|
3695
|
-
else ctx.mesh.nodes.push(clonePayload.node);
|
|
3696
|
-
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3697
|
-
await syncCoordinatorDaemonMeshCache(ctx);
|
|
3698
|
-
}
|
|
3699
|
-
return JSON.stringify(res, null, 2);
|
|
3700
|
-
} catch (e) {
|
|
3701
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3702
|
-
}
|
|
3703
|
-
} else {
|
|
3704
|
-
return JSON.stringify({ error: "Cloud mesh clone_node requires source node daemonId" });
|
|
3482
|
+
const result = await commandForNode(ctx, sourceNode, "clone_mesh_node", {
|
|
3483
|
+
meshId: ctx.mesh.id,
|
|
3484
|
+
sourceNodeId: args.source_node_id,
|
|
3485
|
+
branch: args.branch,
|
|
3486
|
+
baseBranch: args.base_branch,
|
|
3487
|
+
inlineMesh: ctx.mesh
|
|
3488
|
+
});
|
|
3489
|
+
const clonePayload = extractCloneNodePayload(result);
|
|
3490
|
+
if (clonePayload?.success && clonePayload.node?.id) {
|
|
3491
|
+
const existingIndex = ctx.mesh.nodes.findIndex((n) => n.id === clonePayload.node.id);
|
|
3492
|
+
if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
|
|
3493
|
+
else ctx.mesh.nodes.push(clonePayload.node);
|
|
3494
|
+
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3495
|
+
await syncCoordinatorDaemonMeshCache(ctx);
|
|
3705
3496
|
}
|
|
3497
|
+
return JSON.stringify(result, null, 2);
|
|
3706
3498
|
}
|
|
3707
3499
|
async function meshCleanupSessions(ctx, args) {
|
|
3708
3500
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
return JSON.stringify(result, null, 2);
|
|
3719
|
-
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
3720
|
-
try {
|
|
3721
|
-
const res = await ctx.transport.meshCleanupSessions(node.daemonId, {
|
|
3722
|
-
meshId: ctx.mesh.id,
|
|
3723
|
-
nodeId: args.node_id,
|
|
3724
|
-
mode: args.mode,
|
|
3725
|
-
sessionIds: args.session_ids,
|
|
3726
|
-
dryRun: args.dry_run === true,
|
|
3727
|
-
inlineMesh: ctx.mesh
|
|
3728
|
-
});
|
|
3729
|
-
return JSON.stringify(res, null, 2);
|
|
3730
|
-
} catch (e) {
|
|
3731
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3732
|
-
}
|
|
3733
|
-
} else {
|
|
3734
|
-
return JSON.stringify({ error: "Cloud mesh cleanup_sessions requires node daemonId" });
|
|
3735
|
-
}
|
|
3501
|
+
const result = await commandForNode(ctx, node, "cleanup_mesh_sessions", {
|
|
3502
|
+
meshId: ctx.mesh.id,
|
|
3503
|
+
nodeId: args.node_id,
|
|
3504
|
+
mode: args.mode,
|
|
3505
|
+
sessionIds: args.session_ids,
|
|
3506
|
+
dryRun: args.dry_run === true,
|
|
3507
|
+
inlineMesh: ctx.mesh
|
|
3508
|
+
});
|
|
3509
|
+
return JSON.stringify(result, null, 2);
|
|
3736
3510
|
}
|
|
3737
3511
|
async function meshRemoveNode(ctx, args) {
|
|
3738
3512
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
}, null, 2);
|
|
3760
|
-
}
|
|
3761
|
-
}
|
|
3762
|
-
if (result?.success && result.removed !== false) {
|
|
3763
|
-
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
3764
|
-
if (idx >= 0) {
|
|
3765
|
-
ctx.mesh.nodes.splice(idx, 1);
|
|
3766
|
-
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3767
|
-
}
|
|
3513
|
+
const removeArgs = buildRemoveNodeArgs(ctx, args.node_id, args.session_cleanup_mode);
|
|
3514
|
+
let result;
|
|
3515
|
+
let transportFallback;
|
|
3516
|
+
try {
|
|
3517
|
+
result = await commandForNode(ctx, node, "remove_mesh_node", removeArgs);
|
|
3518
|
+
} catch (e) {
|
|
3519
|
+
if (ctx.transport instanceof IpcTransport && node.isLocalWorktree && isP2pTransportUnavailableError(e)) {
|
|
3520
|
+
result = await ctx.transport.command("remove_mesh_node", removeArgs);
|
|
3521
|
+
transportFallback = {
|
|
3522
|
+
from: "p2p_mesh_relay",
|
|
3523
|
+
to: "local_control_plane",
|
|
3524
|
+
reason: e?.message || String(e)
|
|
3525
|
+
};
|
|
3526
|
+
} else {
|
|
3527
|
+
return JSON.stringify({
|
|
3528
|
+
success: false,
|
|
3529
|
+
code: isP2pTransportUnavailableError(e) ? "p2p_unavailable" : "mesh_remove_node_failed",
|
|
3530
|
+
error: e?.message || String(e),
|
|
3531
|
+
recoveryHint: isP2pTransportUnavailableError(e) ? "If this is an ADHDev-managed local worktree, retry from a coordinator connected to the daemon that owns the worktree; dashboard command/data-plane traffic still requires P2P." : "Inspect mesh_status and retry after resolving the reported failure."
|
|
3532
|
+
}, null, 2);
|
|
3768
3533
|
}
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
...args.session_cleanup_mode ? { sessionCleanupMode: args.session_cleanup_mode } : {},
|
|
3776
|
-
inlineMesh: ctx.mesh
|
|
3777
|
-
});
|
|
3778
|
-
if (res?.success && res.removed !== false) {
|
|
3779
|
-
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
3780
|
-
if (idx >= 0) {
|
|
3781
|
-
ctx.mesh.nodes.splice(idx, 1);
|
|
3782
|
-
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3783
|
-
}
|
|
3784
|
-
}
|
|
3785
|
-
return JSON.stringify(res, null, 2);
|
|
3786
|
-
} catch (e) {
|
|
3787
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3534
|
+
}
|
|
3535
|
+
if (result?.success && result.removed !== false) {
|
|
3536
|
+
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
3537
|
+
if (idx >= 0) {
|
|
3538
|
+
ctx.mesh.nodes.splice(idx, 1);
|
|
3539
|
+
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3788
3540
|
}
|
|
3789
|
-
} else {
|
|
3790
|
-
return JSON.stringify({ error: "Cloud mesh remove_node requires node daemonId" });
|
|
3791
3541
|
}
|
|
3542
|
+
return JSON.stringify({ ...result || {}, ...transportFallback ? { transportFallback } : {} }, null, 2);
|
|
3792
3543
|
}
|
|
3793
3544
|
function resolveRefineConfigNode(ctx, nodeId) {
|
|
3794
3545
|
if (nodeId) return findNode(ctx.mesh, nodeId);
|
|
@@ -3829,46 +3580,21 @@ async function meshRefinePlan(ctx, args) {
|
|
|
3829
3580
|
}
|
|
3830
3581
|
async function meshRefineNode(ctx, args) {
|
|
3831
3582
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3843
|
-
}
|
|
3844
|
-
}
|
|
3845
|
-
return JSON.stringify(result, null, 2);
|
|
3846
|
-
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
3847
|
-
try {
|
|
3848
|
-
const res = await ctx.transport.meshRefineNode(node.daemonId, {
|
|
3849
|
-
meshId: ctx.mesh.id,
|
|
3850
|
-
nodeId: args.node_id,
|
|
3851
|
-
inlineMesh: ctx.mesh
|
|
3852
|
-
});
|
|
3853
|
-
if (res?.success && res.async !== true && res.removeResult?.removed !== false) {
|
|
3854
|
-
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
3855
|
-
if (idx >= 0) {
|
|
3856
|
-
ctx.mesh.nodes.splice(idx, 1);
|
|
3857
|
-
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3858
|
-
}
|
|
3859
|
-
}
|
|
3860
|
-
return JSON.stringify(res, null, 2);
|
|
3861
|
-
} catch (e) {
|
|
3862
|
-
return JSON.stringify({ success: false, error: e.message });
|
|
3583
|
+
const result = await commandForNode(ctx, node, "refine_mesh_node", {
|
|
3584
|
+
meshId: ctx.mesh.id,
|
|
3585
|
+
nodeId: args.node_id,
|
|
3586
|
+
inlineMesh: ctx.mesh
|
|
3587
|
+
});
|
|
3588
|
+
if (result?.success && result.async !== true && result.removeResult?.removed !== false) {
|
|
3589
|
+
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
3590
|
+
if (idx >= 0) {
|
|
3591
|
+
ctx.mesh.nodes.splice(idx, 1);
|
|
3592
|
+
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3863
3593
|
}
|
|
3864
|
-
} else {
|
|
3865
|
-
return JSON.stringify({ error: "Cloud mesh refine_node requires node daemonId" });
|
|
3866
3594
|
}
|
|
3595
|
+
return JSON.stringify(result, null, 2);
|
|
3867
3596
|
}
|
|
3868
3597
|
async function meshReviewInbox(ctx, args = {}) {
|
|
3869
|
-
if (!isLocalTransport(ctx.transport)) {
|
|
3870
|
-
return JSON.stringify({ error: "mesh_review_inbox requires a local daemon transport (M4.0 scope: local nodes only)" });
|
|
3871
|
-
}
|
|
3872
3598
|
await refreshMeshFromDaemon(ctx);
|
|
3873
3599
|
const meshId = (args.mesh_id ?? ctx.mesh.id).trim();
|
|
3874
3600
|
const result = await commandForNode(ctx, ctx.mesh.nodes[0], "get_mesh_review_inbox", {
|
|
@@ -3903,24 +3629,20 @@ ADHDev MCP Server
|
|
|
3903
3629
|
|
|
3904
3630
|
Usage:
|
|
3905
3631
|
adhdev mcp Local mode (requires standalone daemon)
|
|
3906
|
-
adhdev mcp --api-key <key> Cloud mode (ADHDev cloud API)
|
|
3907
3632
|
adhdev mcp --mode ipc --repo-mesh <mesh_id> Cloud daemon IPC mesh mode
|
|
3908
3633
|
adhdev-mcp --help Compatibility bin (same server, legacy package entrypoint)
|
|
3909
3634
|
|
|
3910
3635
|
Options:
|
|
3911
|
-
--mode <mode> Transport: local
|
|
3636
|
+
--mode <mode> Transport: local or ipc
|
|
3912
3637
|
--port <n> Standalone or IPC daemon port (defaults: local 3847, ipc 19222)
|
|
3913
3638
|
--password <pass> Standalone daemon password (if set)
|
|
3914
|
-
--api-key <key> ADHDev cloud API key (switches to cloud mode)
|
|
3915
|
-
--base-url <url> Override cloud API base URL
|
|
3916
3639
|
--repo-mesh <mesh_id> Enable mesh mode \u2014 exposes only mesh-scoped coordinator tools
|
|
3917
3640
|
--help Show this help
|
|
3918
3641
|
|
|
3919
3642
|
Environment variables:
|
|
3920
|
-
ADHDEV_API_KEY API key (cloud mode)
|
|
3921
3643
|
ADHDEV_PASSWORD Daemon password (local mode)
|
|
3922
3644
|
ADHDEV_MESH_ID Mesh ID (mesh mode)
|
|
3923
|
-
ADHDEV_MCP_TRANSPORT Transport: local
|
|
3645
|
+
ADHDEV_MCP_TRANSPORT Transport: local or ipc
|
|
3924
3646
|
|
|
3925
3647
|
Standard tools: ${STANDARD_TOOLS.join(", ")}
|
|
3926
3648
|
Mesh tools: ${meshTools.join(", ")}
|
|
@@ -3974,269 +3696,6 @@ var LocalTransport = class {
|
|
|
3974
3696
|
}
|
|
3975
3697
|
};
|
|
3976
3698
|
|
|
3977
|
-
// src/transports/cloud.ts
|
|
3978
|
-
var DEFAULT_BASE_URL = "https://api.adhf.dev";
|
|
3979
|
-
var CloudTransport = class {
|
|
3980
|
-
baseUrl;
|
|
3981
|
-
apiKey;
|
|
3982
|
-
constructor(opts) {
|
|
3983
|
-
this.apiKey = opts.apiKey;
|
|
3984
|
-
this.baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL;
|
|
3985
|
-
}
|
|
3986
|
-
headers() {
|
|
3987
|
-
return {
|
|
3988
|
-
"Content-Type": "application/json",
|
|
3989
|
-
"Authorization": `Bearer ${this.apiKey}`
|
|
3990
|
-
};
|
|
3991
|
-
}
|
|
3992
|
-
async listRemoteMeshes() {
|
|
3993
|
-
const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes`, { headers: this.headers() });
|
|
3994
|
-
if (!res.ok) throw new Error(`List remote meshes failed: ${res.status}`);
|
|
3995
|
-
return res.json();
|
|
3996
|
-
}
|
|
3997
|
-
async createRemoteMesh(data) {
|
|
3998
|
-
const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes`, {
|
|
3999
|
-
method: "POST",
|
|
4000
|
-
headers: this.headers(),
|
|
4001
|
-
body: JSON.stringify(data)
|
|
4002
|
-
});
|
|
4003
|
-
if (!res.ok) throw new Error(`Create remote mesh failed: ${res.status}`);
|
|
4004
|
-
return res.json();
|
|
4005
|
-
}
|
|
4006
|
-
async deleteRemoteMesh(meshId) {
|
|
4007
|
-
const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes/${encodeURIComponent(meshId)}`, {
|
|
4008
|
-
method: "DELETE",
|
|
4009
|
-
headers: this.headers()
|
|
4010
|
-
});
|
|
4011
|
-
if (!res.ok) throw new Error(`Delete remote mesh failed: ${res.status}`);
|
|
4012
|
-
}
|
|
4013
|
-
async listDaemons() {
|
|
4014
|
-
const res = await fetch(`${this.baseUrl}/api/v1/daemons`, { headers: this.headers() });
|
|
4015
|
-
if (!res.ok) throw new Error(`List daemons failed: ${res.status}`);
|
|
4016
|
-
return res.json();
|
|
4017
|
-
}
|
|
4018
|
-
async getStatus(targetId) {
|
|
4019
|
-
const res = await fetch(
|
|
4020
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(targetId)}/status`,
|
|
4021
|
-
{ headers: this.headers() }
|
|
4022
|
-
);
|
|
4023
|
-
if (!res.ok) throw new Error(`Status failed: ${res.status}`);
|
|
4024
|
-
return res.json();
|
|
4025
|
-
}
|
|
4026
|
-
/** Get all sessions for a daemon (returns CompactSessionEntry[]). */
|
|
4027
|
-
async getDaemonStatus(daemonId) {
|
|
4028
|
-
const res = await fetch(
|
|
4029
|
-
`${this.baseUrl}/api/v1/daemons/${encodeURIComponent(daemonId)}/status`,
|
|
4030
|
-
{ headers: this.headers() }
|
|
4031
|
-
);
|
|
4032
|
-
if (!res.ok) throw new Error(`Daemon status failed: ${res.status}`);
|
|
4033
|
-
return res.json();
|
|
4034
|
-
}
|
|
4035
|
-
async readChat(targetId, opts = {}) {
|
|
4036
|
-
const params = new URLSearchParams();
|
|
4037
|
-
if (opts.limit) params.set("limit", String(opts.limit));
|
|
4038
|
-
if (opts.sessionId) params.set("sessionId", opts.sessionId);
|
|
4039
|
-
const qs = params.toString() ? `?${params}` : "";
|
|
4040
|
-
const res = await fetch(
|
|
4041
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(targetId)}/chat${qs}`,
|
|
4042
|
-
{ headers: this.headers() }
|
|
4043
|
-
);
|
|
4044
|
-
if (!res.ok) throw new Error(`Read chat failed: ${res.status}`);
|
|
4045
|
-
return res.json();
|
|
4046
|
-
}
|
|
4047
|
-
async getChatDebugBundle(targetId, opts = {}) {
|
|
4048
|
-
const res = await fetch(
|
|
4049
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(targetId)}/chat/debug`,
|
|
4050
|
-
{
|
|
4051
|
-
method: "POST",
|
|
4052
|
-
headers: this.headers(),
|
|
4053
|
-
body: JSON.stringify({
|
|
4054
|
-
...opts.agentType ? { agentType: opts.agentType } : {},
|
|
4055
|
-
...opts.sessionId ? { sessionId: opts.sessionId } : {},
|
|
4056
|
-
...opts.tailLimit ? { tailLimit: opts.tailLimit } : {},
|
|
4057
|
-
...opts.delivery ? { delivery: opts.delivery } : {}
|
|
4058
|
-
})
|
|
4059
|
-
}
|
|
4060
|
-
);
|
|
4061
|
-
if (!res.ok) throw new Error(`Chat debug bundle failed: ${res.status}`);
|
|
4062
|
-
return res.json();
|
|
4063
|
-
}
|
|
4064
|
-
async sendChat(targetId, message, opts = {}) {
|
|
4065
|
-
const res = await fetch(
|
|
4066
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(targetId)}/chat`,
|
|
4067
|
-
{
|
|
4068
|
-
method: "POST",
|
|
4069
|
-
headers: this.headers(),
|
|
4070
|
-
body: JSON.stringify({ message, ...opts })
|
|
4071
|
-
}
|
|
4072
|
-
);
|
|
4073
|
-
if (!res.ok) throw new Error(`Send chat failed: ${res.status}`);
|
|
4074
|
-
return res.json();
|
|
4075
|
-
}
|
|
4076
|
-
async approve(targetId, action, agentType) {
|
|
4077
|
-
const res = await fetch(
|
|
4078
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(targetId)}/approve`,
|
|
4079
|
-
{
|
|
4080
|
-
method: "POST",
|
|
4081
|
-
headers: this.headers(),
|
|
4082
|
-
body: JSON.stringify({ action, ...agentType ? { agentType } : {} })
|
|
4083
|
-
}
|
|
4084
|
-
);
|
|
4085
|
-
if (!res.ok) throw new Error(`Approve failed: ${res.status}`);
|
|
4086
|
-
return res.json();
|
|
4087
|
-
}
|
|
4088
|
-
async gitStatus(daemonId, workspace, includeDiff = true, refreshUpstream = false) {
|
|
4089
|
-
const params = new URLSearchParams({ workspace, includeDiff: String(includeDiff), refreshUpstream: String(refreshUpstream) });
|
|
4090
|
-
const res = await fetch(
|
|
4091
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/git-status?${params}`,
|
|
4092
|
-
{ headers: this.headers() }
|
|
4093
|
-
);
|
|
4094
|
-
if (!res.ok) throw new Error(`Git status failed: ${res.status}`);
|
|
4095
|
-
return res.json();
|
|
4096
|
-
}
|
|
4097
|
-
async stop(daemonId, opts) {
|
|
4098
|
-
const res = await fetch(
|
|
4099
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/stop`,
|
|
4100
|
-
{
|
|
4101
|
-
method: "POST",
|
|
4102
|
-
headers: this.headers(),
|
|
4103
|
-
body: JSON.stringify(opts)
|
|
4104
|
-
}
|
|
4105
|
-
);
|
|
4106
|
-
if (!res.ok) throw new Error(`Stop failed: ${res.status}`);
|
|
4107
|
-
return res.json();
|
|
4108
|
-
}
|
|
4109
|
-
async launch(daemonId, opts) {
|
|
4110
|
-
const res = await fetch(
|
|
4111
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/launch`,
|
|
4112
|
-
{
|
|
4113
|
-
method: "POST",
|
|
4114
|
-
headers: this.headers(),
|
|
4115
|
-
body: JSON.stringify(opts)
|
|
4116
|
-
}
|
|
4117
|
-
);
|
|
4118
|
-
if (!res.ok) throw new Error(`Launch failed: ${res.status}`);
|
|
4119
|
-
return res.json();
|
|
4120
|
-
}
|
|
4121
|
-
async gitLog(daemonId, workspace, opts = {}) {
|
|
4122
|
-
const params = new URLSearchParams({ workspace });
|
|
4123
|
-
if (opts.limit) params.set("limit", String(opts.limit));
|
|
4124
|
-
if (opts.file) params.set("file", opts.file);
|
|
4125
|
-
if (opts.since) params.set("since", opts.since);
|
|
4126
|
-
if (opts.until) params.set("until", opts.until);
|
|
4127
|
-
const res = await fetch(
|
|
4128
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/git-log?${params}`,
|
|
4129
|
-
{ headers: this.headers() }
|
|
4130
|
-
);
|
|
4131
|
-
if (!res.ok) throw new Error(`Git log failed: ${res.status}`);
|
|
4132
|
-
return res.json();
|
|
4133
|
-
}
|
|
4134
|
-
async gitDiff(daemonId, workspace, opts = {}) {
|
|
4135
|
-
const params = new URLSearchParams({ workspace });
|
|
4136
|
-
if (opts.file) params.set("file", opts.file);
|
|
4137
|
-
if (opts.maxLines) params.set("maxLines", String(opts.maxLines));
|
|
4138
|
-
if (opts.staged) params.set("staged", "true");
|
|
4139
|
-
const res = await fetch(
|
|
4140
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/git-diff?${params}`,
|
|
4141
|
-
{ headers: this.headers() }
|
|
4142
|
-
);
|
|
4143
|
-
if (!res.ok) throw new Error(`Git diff failed: ${res.status}`);
|
|
4144
|
-
return res.json();
|
|
4145
|
-
}
|
|
4146
|
-
async gitPush(daemonId, opts) {
|
|
4147
|
-
const res = await fetch(
|
|
4148
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/git-push`,
|
|
4149
|
-
{
|
|
4150
|
-
method: "POST",
|
|
4151
|
-
headers: this.headers(),
|
|
4152
|
-
body: JSON.stringify(opts)
|
|
4153
|
-
}
|
|
4154
|
-
);
|
|
4155
|
-
if (!res.ok) throw new Error(`Git push failed: ${res.status}`);
|
|
4156
|
-
return res.json();
|
|
4157
|
-
}
|
|
4158
|
-
async gitCheckpoint(daemonId, opts) {
|
|
4159
|
-
const res = await fetch(
|
|
4160
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/git-checkpoint`,
|
|
4161
|
-
{
|
|
4162
|
-
method: "POST",
|
|
4163
|
-
headers: this.headers(),
|
|
4164
|
-
body: JSON.stringify(opts)
|
|
4165
|
-
}
|
|
4166
|
-
);
|
|
4167
|
-
if (!res.ok) throw new Error(`Git checkpoint failed: ${res.status}`);
|
|
4168
|
-
return res.json();
|
|
4169
|
-
}
|
|
4170
|
-
async meshCloneNode(daemonId, payload) {
|
|
4171
|
-
const res = await fetch(
|
|
4172
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/clone-node`,
|
|
4173
|
-
{
|
|
4174
|
-
method: "POST",
|
|
4175
|
-
headers: this.headers(),
|
|
4176
|
-
body: JSON.stringify(payload)
|
|
4177
|
-
}
|
|
4178
|
-
);
|
|
4179
|
-
if (!res.ok) throw new Error(`Mesh clone node failed: ${res.status}`);
|
|
4180
|
-
return res.json();
|
|
4181
|
-
}
|
|
4182
|
-
async meshRemoveNode(daemonId, payload) {
|
|
4183
|
-
const res = await fetch(
|
|
4184
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/remove-node`,
|
|
4185
|
-
{
|
|
4186
|
-
method: "POST",
|
|
4187
|
-
headers: this.headers(),
|
|
4188
|
-
body: JSON.stringify(payload)
|
|
4189
|
-
}
|
|
4190
|
-
);
|
|
4191
|
-
if (!res.ok) throw new Error(`Mesh remove node failed: ${res.status}`);
|
|
4192
|
-
return res.json();
|
|
4193
|
-
}
|
|
4194
|
-
async meshCleanupSessions(daemonId, payload) {
|
|
4195
|
-
const res = await fetch(
|
|
4196
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/cleanup-sessions`,
|
|
4197
|
-
{
|
|
4198
|
-
method: "POST",
|
|
4199
|
-
headers: this.headers(),
|
|
4200
|
-
body: JSON.stringify(payload)
|
|
4201
|
-
}
|
|
4202
|
-
);
|
|
4203
|
-
if (!res.ok) throw new Error(`Mesh cleanup sessions failed: ${res.status}`);
|
|
4204
|
-
return res.json();
|
|
4205
|
-
}
|
|
4206
|
-
async meshEnqueueTask(daemonId, payload) {
|
|
4207
|
-
const res = await fetch(
|
|
4208
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/enqueue`,
|
|
4209
|
-
{
|
|
4210
|
-
method: "POST",
|
|
4211
|
-
headers: this.headers(),
|
|
4212
|
-
body: JSON.stringify(payload)
|
|
4213
|
-
}
|
|
4214
|
-
);
|
|
4215
|
-
if (!res.ok) throw new Error(`Mesh enqueue task failed: ${res.status}`);
|
|
4216
|
-
return res.json();
|
|
4217
|
-
}
|
|
4218
|
-
async meshRefineNode(daemonId, payload) {
|
|
4219
|
-
const res = await fetch(
|
|
4220
|
-
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/refine-node`,
|
|
4221
|
-
{
|
|
4222
|
-
method: "POST",
|
|
4223
|
-
headers: this.headers(),
|
|
4224
|
-
body: JSON.stringify(payload)
|
|
4225
|
-
}
|
|
4226
|
-
);
|
|
4227
|
-
if (!res.ok) throw new Error(`Mesh refine node failed: ${res.status}`);
|
|
4228
|
-
return res.json();
|
|
4229
|
-
}
|
|
4230
|
-
async ping() {
|
|
4231
|
-
try {
|
|
4232
|
-
await this.listDaemons();
|
|
4233
|
-
return true;
|
|
4234
|
-
} catch {
|
|
4235
|
-
return false;
|
|
4236
|
-
}
|
|
4237
|
-
}
|
|
4238
|
-
};
|
|
4239
|
-
|
|
4240
3699
|
// src/tools/list-sessions.ts
|
|
4241
3700
|
var FORMAT_PROP = {
|
|
4242
3701
|
format: {
|
|
@@ -4247,14 +3706,10 @@ var FORMAT_PROP = {
|
|
|
4247
3706
|
};
|
|
4248
3707
|
var LIST_SESSIONS_TOOL = {
|
|
4249
3708
|
name: "list_sessions",
|
|
4250
|
-
description: "List all connected agent sessions.
|
|
3709
|
+
description: "List all connected agent sessions.",
|
|
4251
3710
|
inputSchema: {
|
|
4252
3711
|
type: "object",
|
|
4253
3712
|
properties: {
|
|
4254
|
-
daemon_id: {
|
|
4255
|
-
type: "string",
|
|
4256
|
-
description: "Daemon ID (cloud mode only). Omit to list sessions across all daemons."
|
|
4257
|
-
},
|
|
4258
3713
|
...FORMAT_PROP
|
|
4259
3714
|
},
|
|
4260
3715
|
required: []
|
|
@@ -4262,87 +3717,35 @@ var LIST_SESSIONS_TOOL = {
|
|
|
4262
3717
|
};
|
|
4263
3718
|
async function listSessions(transport, args = {}) {
|
|
4264
3719
|
const asJson = args.format === "json";
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
const sessions = status?.sessions ?? [];
|
|
4268
|
-
if (asJson) {
|
|
4269
|
-
return JSON.stringify({
|
|
4270
|
-
sessions: sessions.map((s) => ({
|
|
4271
|
-
id: s.id,
|
|
4272
|
-
type: s.providerType ?? s.type ?? "unknown",
|
|
4273
|
-
label: s.label ?? null,
|
|
4274
|
-
status: s.status ?? s.agentStatus ?? null,
|
|
4275
|
-
workspace: s.workspace ?? null
|
|
4276
|
-
}))
|
|
4277
|
-
}, null, 2);
|
|
4278
|
-
}
|
|
4279
|
-
if (sessions.length === 0) return "No active sessions.";
|
|
4280
|
-
const lines = sessions.map((s) => {
|
|
4281
|
-
const parts = [`id: ${s.id}`, `type: ${s.providerType ?? s.type ?? "unknown"}`];
|
|
4282
|
-
if (s.label) parts.push(`label: ${s.label}`);
|
|
4283
|
-
if (s.status ?? s.agentStatus) parts.push(`status: ${s.status ?? s.agentStatus}`);
|
|
4284
|
-
if (s.workspace) parts.push(`workspace: ${s.workspace}`);
|
|
4285
|
-
return parts.join(", ");
|
|
4286
|
-
});
|
|
4287
|
-
return `Sessions (${sessions.length}):
|
|
4288
|
-
${lines.join("\n")}`;
|
|
4289
|
-
}
|
|
4290
|
-
return listSessionsCloud(transport, args.daemon_id, asJson);
|
|
4291
|
-
}
|
|
4292
|
-
async function listSessionsCloud(transport, daemonId, asJson) {
|
|
4293
|
-
const collected = [];
|
|
4294
|
-
if (daemonId) {
|
|
4295
|
-
const daemonStatus = await transport.getDaemonStatus(daemonId);
|
|
4296
|
-
for (const s of daemonStatus?.sessions ?? []) {
|
|
4297
|
-
collected.push({ daemonId, session: s });
|
|
4298
|
-
}
|
|
4299
|
-
} else {
|
|
4300
|
-
const data = await transport.listDaemons();
|
|
4301
|
-
const daemons = data?.daemons ?? [];
|
|
4302
|
-
for (let i = 0; i < daemons.length; i += 5) {
|
|
4303
|
-
await Promise.allSettled(
|
|
4304
|
-
daemons.slice(i, i + 5).map(async (d) => {
|
|
4305
|
-
try {
|
|
4306
|
-
const daemonStatus = await transport.getDaemonStatus(d.id);
|
|
4307
|
-
for (const s of daemonStatus?.sessions ?? []) {
|
|
4308
|
-
collected.push({ daemonId: d.id, session: s });
|
|
4309
|
-
}
|
|
4310
|
-
} catch {
|
|
4311
|
-
}
|
|
4312
|
-
})
|
|
4313
|
-
);
|
|
4314
|
-
}
|
|
4315
|
-
}
|
|
3720
|
+
const status = await transport.getStatus();
|
|
3721
|
+
const sessions = status?.sessions ?? [];
|
|
4316
3722
|
if (asJson) {
|
|
4317
3723
|
return JSON.stringify({
|
|
4318
|
-
sessions:
|
|
4319
|
-
daemon_id: dId,
|
|
3724
|
+
sessions: sessions.map((s) => ({
|
|
4320
3725
|
id: s.id,
|
|
4321
|
-
type: s.providerType ?? "unknown",
|
|
4322
|
-
|
|
3726
|
+
type: s.providerType ?? s.type ?? "unknown",
|
|
3727
|
+
label: s.label ?? null,
|
|
3728
|
+
status: s.status ?? s.agentStatus ?? null,
|
|
4323
3729
|
workspace: s.workspace ?? null
|
|
4324
3730
|
}))
|
|
4325
3731
|
}, null, 2);
|
|
4326
3732
|
}
|
|
4327
|
-
if (
|
|
4328
|
-
const lines =
|
|
4329
|
-
const parts = [
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
`type: ${s.providerType ?? "unknown"}`
|
|
4333
|
-
];
|
|
4334
|
-
if (s.status) parts.push(`status: ${s.status}`);
|
|
3733
|
+
if (sessions.length === 0) return "No active sessions.";
|
|
3734
|
+
const lines = sessions.map((s) => {
|
|
3735
|
+
const parts = [`id: ${s.id}`, `type: ${s.providerType ?? s.type ?? "unknown"}`];
|
|
3736
|
+
if (s.label) parts.push(`label: ${s.label}`);
|
|
3737
|
+
if (s.status ?? s.agentStatus) parts.push(`status: ${s.status ?? s.agentStatus}`);
|
|
4335
3738
|
if (s.workspace) parts.push(`workspace: ${s.workspace}`);
|
|
4336
3739
|
return parts.join(", ");
|
|
4337
3740
|
});
|
|
4338
|
-
return `Sessions (${
|
|
3741
|
+
return `Sessions (${sessions.length}):
|
|
4339
3742
|
${lines.join("\n")}`;
|
|
4340
3743
|
}
|
|
4341
3744
|
|
|
4342
3745
|
// src/tools/list-daemons.ts
|
|
4343
3746
|
var LIST_DAEMONS_TOOL = {
|
|
4344
3747
|
name: "list_daemons",
|
|
4345
|
-
description: "List
|
|
3748
|
+
description: "List the connected daemon (machine running the ADHDev agent). Returns the daemon identity extracted from its status report.",
|
|
4346
3749
|
inputSchema: {
|
|
4347
3750
|
type: "object",
|
|
4348
3751
|
properties: {
|
|
@@ -4353,46 +3756,17 @@ var LIST_DAEMONS_TOOL = {
|
|
|
4353
3756
|
};
|
|
4354
3757
|
async function listDaemons(transport, args = {}) {
|
|
4355
3758
|
const asJson = args.format === "json";
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
return `Daemons (1):
|
|
3759
|
+
const status = await transport.getStatus();
|
|
3760
|
+
const daemon = {
|
|
3761
|
+
id: status?.id ?? status?.instanceId ?? "standalone",
|
|
3762
|
+
hostname: status?.hostname ?? status?.machine?.hostname ?? "localhost",
|
|
3763
|
+
platform: status?.platform ?? status?.machine?.platform ?? "unknown",
|
|
3764
|
+
version: status?.version ?? null,
|
|
3765
|
+
sessions: (status?.sessions ?? []).length
|
|
3766
|
+
};
|
|
3767
|
+
if (asJson) return JSON.stringify({ daemons: [daemon] }, null, 2);
|
|
3768
|
+
return `Daemons (1):
|
|
4367
3769
|
id: ${daemon.id}, hostname: ${daemon.hostname}, platform: ${daemon.platform}${daemon.version ? `, version: ${daemon.version}` : ""}, sessions: ${daemon.sessions}`;
|
|
4368
|
-
}
|
|
4369
|
-
const data = await transport.listDaemons();
|
|
4370
|
-
const daemons = data?.daemons ?? [];
|
|
4371
|
-
if (asJson) {
|
|
4372
|
-
return JSON.stringify({
|
|
4373
|
-
daemons: daemons.map((d) => ({
|
|
4374
|
-
id: d.id,
|
|
4375
|
-
hostname: d.hostname ?? null,
|
|
4376
|
-
platform: d.platform ?? null,
|
|
4377
|
-
nickname: d.nickname ?? null,
|
|
4378
|
-
version: d.version ?? null,
|
|
4379
|
-
p2p_available: d.p2p?.available ?? null,
|
|
4380
|
-
cdp_connected: d.cdpConnected ?? null
|
|
4381
|
-
}))
|
|
4382
|
-
}, null, 2);
|
|
4383
|
-
}
|
|
4384
|
-
if (daemons.length === 0) return "No connected daemons.";
|
|
4385
|
-
const lines = daemons.map((d) => {
|
|
4386
|
-
const parts = [`id: ${d.id}`];
|
|
4387
|
-
if (d.nickname) parts.push(`nickname: ${d.nickname}`);
|
|
4388
|
-
if (d.hostname) parts.push(`hostname: ${d.hostname}`);
|
|
4389
|
-
if (d.platform) parts.push(`platform: ${d.platform}`);
|
|
4390
|
-
if (d.version) parts.push(`version: ${d.version}`);
|
|
4391
|
-
if (d.p2p?.available != null) parts.push(`p2p: ${d.p2p.available ? "yes" : "no"}`);
|
|
4392
|
-
return parts.join(", ");
|
|
4393
|
-
});
|
|
4394
|
-
return `Daemons (${daemons.length}):
|
|
4395
|
-
${lines.join("\n")}`;
|
|
4396
3770
|
}
|
|
4397
3771
|
|
|
4398
3772
|
// src/tools/read-chat.ts
|
|
@@ -4410,10 +3784,6 @@ var READ_CHAT_TOOL = {
|
|
|
4410
3784
|
type: "number",
|
|
4411
3785
|
description: "Max messages to return (default: 50)."
|
|
4412
3786
|
},
|
|
4413
|
-
daemon_id: {
|
|
4414
|
-
type: "string",
|
|
4415
|
-
description: "Daemon ID (cloud mode only). Omit for local mode."
|
|
4416
|
-
},
|
|
4417
3787
|
compact: {
|
|
4418
3788
|
type: "boolean",
|
|
4419
3789
|
description: "Opt-in compact mode: filters tool/terminal/system/internal/control/debug/status chatter and returns user-visible messages plus lightweight summary metadata."
|
|
@@ -4425,23 +3795,12 @@ var READ_CHAT_TOOL = {
|
|
|
4425
3795
|
};
|
|
4426
3796
|
async function readChat(transport, args) {
|
|
4427
3797
|
const limit = args.limit ?? 50;
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
});
|
|
4433
|
-
const annotated2 = annotateRapidReadChatAdvisory(result2, {
|
|
4434
|
-
key: `local:${args.session_id ?? "__active__"}`,
|
|
4435
|
-
toolName: "read_chat",
|
|
4436
|
-
completionCallbackExpected: false
|
|
4437
|
-
});
|
|
4438
|
-
return formatChatResult(annotated2, args.session_id, args.format, limit, args.compact);
|
|
4439
|
-
}
|
|
4440
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
4441
|
-
const targetId = args.session_id ? `${args.daemon_id}:session:${args.session_id}` : args.daemon_id;
|
|
4442
|
-
const result = await transport.readChat(targetId, { limit, sessionId: args.session_id });
|
|
3798
|
+
const result = await transport.command("read_chat", {
|
|
3799
|
+
...args.session_id ? { targetSessionId: args.session_id } : {},
|
|
3800
|
+
tailLimit: limit
|
|
3801
|
+
});
|
|
4443
3802
|
const annotated = annotateRapidReadChatAdvisory(result, {
|
|
4444
|
-
key: `
|
|
3803
|
+
key: `local:${args.session_id ?? "__active__"}`,
|
|
4445
3804
|
toolName: "read_chat",
|
|
4446
3805
|
completionCallbackExpected: false
|
|
4447
3806
|
});
|
|
@@ -4531,10 +3890,6 @@ var READ_CHAT_DEBUG_TOOL = {
|
|
|
4531
3890
|
type: "string",
|
|
4532
3891
|
description: "Target session ID (from list_sessions). Required for reliable routing."
|
|
4533
3892
|
},
|
|
4534
|
-
daemon_id: {
|
|
4535
|
-
type: "string",
|
|
4536
|
-
description: "Daemon ID (cloud mode only). Omit for local mode."
|
|
4537
|
-
},
|
|
4538
3893
|
agent_type: {
|
|
4539
3894
|
type: "string",
|
|
4540
3895
|
description: "Optional provider/agent type hint, e.g. hermes-cli, claude-cli, codex-cli."
|
|
@@ -4564,19 +3919,7 @@ async function readChatDebug(transport, args) {
|
|
|
4564
3919
|
...args.agent_type ? { agentType: args.agent_type, providerType: args.agent_type } : {},
|
|
4565
3920
|
...delivery === "daemon_file" ? { delivery: "daemon_file" } : {}
|
|
4566
3921
|
};
|
|
4567
|
-
|
|
4568
|
-
if (isLocalTransport(transport)) {
|
|
4569
|
-
result = await transport.command("get_chat_debug_bundle", commandArgs);
|
|
4570
|
-
} else {
|
|
4571
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
4572
|
-
const targetId = `${args.daemon_id}:session:${sessionId}`;
|
|
4573
|
-
result = await transport.getChatDebugBundle(targetId, {
|
|
4574
|
-
sessionId,
|
|
4575
|
-
agentType: args.agent_type,
|
|
4576
|
-
tailLimit,
|
|
4577
|
-
delivery
|
|
4578
|
-
});
|
|
4579
|
-
}
|
|
3922
|
+
const result = await transport.command("get_chat_debug_bundle", commandArgs);
|
|
4580
3923
|
return formatChatDebugResult(result, { sessionId, delivery, format: args.format });
|
|
4581
3924
|
}
|
|
4582
3925
|
function formatChatDebugResult(result, options) {
|
|
@@ -4618,10 +3961,6 @@ var SPEC_DEBUG_TOOL = {
|
|
|
4618
3961
|
type: "string",
|
|
4619
3962
|
description: "Target session ID (from list_sessions)."
|
|
4620
3963
|
},
|
|
4621
|
-
daemon_id: {
|
|
4622
|
-
type: "string",
|
|
4623
|
-
description: "Daemon ID (cloud mode only). Omit for local mode."
|
|
4624
|
-
},
|
|
4625
3964
|
...FORMAT_PROP
|
|
4626
3965
|
},
|
|
4627
3966
|
required: ["session_id"]
|
|
@@ -4630,14 +3969,7 @@ var SPEC_DEBUG_TOOL = {
|
|
|
4630
3969
|
async function specDebug(transport, args) {
|
|
4631
3970
|
const sessionId = typeof args.session_id === "string" ? args.session_id.trim() : "";
|
|
4632
3971
|
if (!sessionId) throw new Error("session_id is required");
|
|
4633
|
-
|
|
4634
|
-
if (isLocalTransport(transport)) {
|
|
4635
|
-
result = await transport.command("get_spec_debug", { targetSessionId: sessionId });
|
|
4636
|
-
} else {
|
|
4637
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
4638
|
-
const targetId = `${args.daemon_id}:session:${sessionId}`;
|
|
4639
|
-
result = await transport.sendCommand(targetId, "get_spec_debug", { targetSessionId: sessionId });
|
|
4640
|
-
}
|
|
3972
|
+
const result = await transport.command("get_spec_debug", { targetSessionId: sessionId });
|
|
4641
3973
|
return formatSpecDebugResult(result, { sessionId, format: args.format });
|
|
4642
3974
|
}
|
|
4643
3975
|
function formatSpecDebugResult(result, options) {
|
|
@@ -4705,10 +4037,6 @@ var SEND_CHAT_TOOL = {
|
|
|
4705
4037
|
session_id: {
|
|
4706
4038
|
type: "string",
|
|
4707
4039
|
description: "Target session ID (from list_sessions). Omit to use the active session."
|
|
4708
|
-
},
|
|
4709
|
-
daemon_id: {
|
|
4710
|
-
type: "string",
|
|
4711
|
-
description: "Daemon ID (cloud mode only). Omit for local mode."
|
|
4712
4040
|
}
|
|
4713
4041
|
},
|
|
4714
4042
|
required: ["message"]
|
|
@@ -4716,18 +4044,9 @@ var SEND_CHAT_TOOL = {
|
|
|
4716
4044
|
};
|
|
4717
4045
|
async function sendChat(transport, args) {
|
|
4718
4046
|
if (!args.message?.trim()) throw new Error("message is required");
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
...args.session_id ? { targetSessionId: args.session_id } : {}
|
|
4723
|
-
});
|
|
4724
|
-
if (result2?.success === false) return `Error: ${result2.error ?? "send_chat failed"}`;
|
|
4725
|
-
return "Message sent.";
|
|
4726
|
-
}
|
|
4727
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
4728
|
-
const targetId = args.session_id ? `${args.daemon_id}:session:${args.session_id}` : args.daemon_id;
|
|
4729
|
-
const result = await transport.sendChat(targetId, args.message, {
|
|
4730
|
-
...args.session_id ? { sessionId: args.session_id } : {}
|
|
4047
|
+
const result = await transport.command("send_chat", {
|
|
4048
|
+
message: args.message,
|
|
4049
|
+
...args.session_id ? { targetSessionId: args.session_id } : {}
|
|
4731
4050
|
});
|
|
4732
4051
|
if (result?.success === false) return `Error: ${result.error ?? "send_chat failed"}`;
|
|
4733
4052
|
return "Message sent.";
|
|
@@ -4748,10 +4067,6 @@ var APPROVE_TOOL = {
|
|
|
4748
4067
|
session_id: {
|
|
4749
4068
|
type: "string",
|
|
4750
4069
|
description: "Target session ID. Omit to use the active session."
|
|
4751
|
-
},
|
|
4752
|
-
daemon_id: {
|
|
4753
|
-
type: "string",
|
|
4754
|
-
description: "Daemon ID (cloud mode only)."
|
|
4755
4070
|
}
|
|
4756
4071
|
},
|
|
4757
4072
|
required: ["action"]
|
|
@@ -4759,25 +4074,18 @@ var APPROVE_TOOL = {
|
|
|
4759
4074
|
};
|
|
4760
4075
|
async function approve(transport, args) {
|
|
4761
4076
|
const action = args.action === "reject" ? "reject" : "approve";
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
if (result2?.success === false) return `Error: ${result2.error ?? "resolve_action failed"}`;
|
|
4768
|
-
return `Action ${action}d.`;
|
|
4769
|
-
}
|
|
4770
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
4771
|
-
const targetId = args.session_id ? `${args.daemon_id}:session:${args.session_id}` : args.daemon_id;
|
|
4772
|
-
const result = await transport.approve(targetId, action);
|
|
4773
|
-
if (result?.success === false) return `Error: ${result.error ?? "approve failed"}`;
|
|
4077
|
+
const result = await transport.command("resolve_action", {
|
|
4078
|
+
action,
|
|
4079
|
+
...args.session_id ? { targetSessionId: args.session_id } : {}
|
|
4080
|
+
});
|
|
4081
|
+
if (result?.success === false) return `Error: ${result.error ?? "resolve_action failed"}`;
|
|
4774
4082
|
return `Action ${action}d.`;
|
|
4775
4083
|
}
|
|
4776
4084
|
|
|
4777
4085
|
// src/tools/screenshot.ts
|
|
4778
4086
|
var SCREENSHOT_TOOL = {
|
|
4779
4087
|
name: "screenshot",
|
|
4780
|
-
description: "Capture a screenshot of the current IDE window. Returns the image.
|
|
4088
|
+
description: "Capture a screenshot of the current IDE window. Returns the image.",
|
|
4781
4089
|
inputSchema: {
|
|
4782
4090
|
type: "object",
|
|
4783
4091
|
properties: {
|
|
@@ -4790,14 +4098,9 @@ var SCREENSHOT_TOOL = {
|
|
|
4790
4098
|
}
|
|
4791
4099
|
};
|
|
4792
4100
|
async function screenshot(transport, args) {
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
...args.session_id ? { targetSessionId: args.session_id } : {}
|
|
4797
|
-
});
|
|
4798
|
-
} else {
|
|
4799
|
-
return { type: "text", text: "Screenshots are not available in cloud mode. Run adhdev mcp in local mode (requires standalone daemon)." };
|
|
4800
|
-
}
|
|
4101
|
+
const result = await transport.command("screenshot", {
|
|
4102
|
+
...args.session_id ? { targetSessionId: args.session_id } : {}
|
|
4103
|
+
});
|
|
4801
4104
|
if (result?.success === false) {
|
|
4802
4105
|
return { type: "text", text: `Error: ${result.error ?? "screenshot failed"}` };
|
|
4803
4106
|
}
|
|
@@ -4824,42 +4127,22 @@ var GIT_STATUS_TOOL = {
|
|
|
4824
4127
|
type: "boolean",
|
|
4825
4128
|
description: "Include changed file list (default: true)."
|
|
4826
4129
|
},
|
|
4827
|
-
daemon_id: {
|
|
4828
|
-
type: "string",
|
|
4829
|
-
description: "Daemon ID (cloud mode only)."
|
|
4830
|
-
},
|
|
4831
4130
|
...FORMAT_PROP
|
|
4832
4131
|
},
|
|
4833
4132
|
required: ["workspace"]
|
|
4834
4133
|
}
|
|
4835
4134
|
};
|
|
4836
4135
|
async function gitStatus(transport, args) {
|
|
4837
|
-
let status;
|
|
4838
4136
|
let diffSummary;
|
|
4839
|
-
|
|
4840
|
-
|
|
4137
|
+
const statusResult = await transport.command("git_status", {
|
|
4138
|
+
workspace: args.workspace
|
|
4139
|
+
});
|
|
4140
|
+
const status = statusResult?.status ?? statusResult;
|
|
4141
|
+
if (args.include_diff !== false) {
|
|
4142
|
+
const diffResult = await transport.command("git_diff_summary", {
|
|
4841
4143
|
workspace: args.workspace
|
|
4842
4144
|
});
|
|
4843
|
-
|
|
4844
|
-
if (args.include_diff !== false) {
|
|
4845
|
-
const diffResult = await transport.command("git_diff_summary", {
|
|
4846
|
-
workspace: args.workspace
|
|
4847
|
-
});
|
|
4848
|
-
diffSummary = diffResult?.diffSummary ?? diffResult;
|
|
4849
|
-
}
|
|
4850
|
-
} else {
|
|
4851
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
4852
|
-
const result = await transport.gitStatus(
|
|
4853
|
-
args.daemon_id,
|
|
4854
|
-
args.workspace,
|
|
4855
|
-
args.include_diff !== false
|
|
4856
|
-
);
|
|
4857
|
-
if (result?.error) {
|
|
4858
|
-
if (args.format === "json") return JSON.stringify({ error: result.error }, null, 2);
|
|
4859
|
-
return `Error: ${result.error}`;
|
|
4860
|
-
}
|
|
4861
|
-
status = result?.status;
|
|
4862
|
-
diffSummary = result?.diff;
|
|
4145
|
+
diffSummary = diffResult?.diffSummary ?? diffResult;
|
|
4863
4146
|
}
|
|
4864
4147
|
if (status?.success === false || status?.reason) {
|
|
4865
4148
|
const msg = status?.error ?? status?.reason ?? "unknown";
|
|
@@ -4951,10 +4234,6 @@ var GIT_LOG_TOOL = {
|
|
|
4951
4234
|
type: "string",
|
|
4952
4235
|
description: "Only commits before this date (ISO 8601 or git date string, optional)."
|
|
4953
4236
|
},
|
|
4954
|
-
daemon_id: {
|
|
4955
|
-
type: "string",
|
|
4956
|
-
description: "Daemon ID (cloud mode only, required)."
|
|
4957
|
-
},
|
|
4958
4237
|
...FORMAT_PROP
|
|
4959
4238
|
},
|
|
4960
4239
|
required: ["workspace"]
|
|
@@ -4962,26 +4241,14 @@ var GIT_LOG_TOOL = {
|
|
|
4962
4241
|
};
|
|
4963
4242
|
async function gitLog(transport, args) {
|
|
4964
4243
|
const limit = Math.max(1, Math.min(100, args.limit ?? 20));
|
|
4965
|
-
let raw
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
});
|
|
4974
|
-
raw = raw?.log ?? raw;
|
|
4975
|
-
} else {
|
|
4976
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
4977
|
-
const result = await transport.gitLog(args.daemon_id, args.workspace, {
|
|
4978
|
-
limit,
|
|
4979
|
-
file: args.file,
|
|
4980
|
-
since: args.since,
|
|
4981
|
-
until: args.until
|
|
4982
|
-
});
|
|
4983
|
-
raw = result?.log ?? result;
|
|
4984
|
-
}
|
|
4244
|
+
let raw = await transport.command("git_log", {
|
|
4245
|
+
workspace: args.workspace,
|
|
4246
|
+
limit,
|
|
4247
|
+
...args.file ? { path: args.file } : {},
|
|
4248
|
+
...args.since ? { since: args.since } : {},
|
|
4249
|
+
...args.until ? { until: args.until } : {}
|
|
4250
|
+
});
|
|
4251
|
+
raw = raw?.log ?? raw;
|
|
4985
4252
|
if (raw?.success === false || raw?.reason) {
|
|
4986
4253
|
const msg = raw?.error ?? raw?.reason ?? "unknown";
|
|
4987
4254
|
if (args.format === "json") return JSON.stringify({ error: msg }, null, 2);
|
|
@@ -5044,10 +4311,6 @@ var GIT_DIFF_TOOL = {
|
|
|
5044
4311
|
type: "boolean",
|
|
5045
4312
|
description: "Show staged changes instead of unstaged (default: false)."
|
|
5046
4313
|
},
|
|
5047
|
-
daemon_id: {
|
|
5048
|
-
type: "string",
|
|
5049
|
-
description: "Daemon ID (cloud mode only, required)."
|
|
5050
|
-
},
|
|
5051
4314
|
...FORMAT_PROP
|
|
5052
4315
|
},
|
|
5053
4316
|
required: ["workspace"]
|
|
@@ -5056,20 +4319,7 @@ var GIT_DIFF_TOOL = {
|
|
|
5056
4319
|
async function gitDiff(transport, args) {
|
|
5057
4320
|
const maxLines = Math.max(10, Math.min(2e3, args.max_lines ?? 300));
|
|
5058
4321
|
const staged = args.staged ?? false;
|
|
5059
|
-
|
|
5060
|
-
return localGitDiff(transport, args.workspace, args.file, maxLines, staged, args.format);
|
|
5061
|
-
}
|
|
5062
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
5063
|
-
const result = await transport.gitDiff(args.daemon_id, args.workspace, {
|
|
5064
|
-
file: args.file,
|
|
5065
|
-
maxLines,
|
|
5066
|
-
staged
|
|
5067
|
-
});
|
|
5068
|
-
if (result?.error) {
|
|
5069
|
-
if (args.format === "json") return JSON.stringify({ error: result.error }, null, 2);
|
|
5070
|
-
return `Git diff error: ${result.error}`;
|
|
5071
|
-
}
|
|
5072
|
-
return formatDiffResult(result, args.format);
|
|
4322
|
+
return localGitDiff(transport, args.workspace, args.file, maxLines, staged, args.format);
|
|
5073
4323
|
}
|
|
5074
4324
|
async function localGitDiff(transport, workspace, file, maxLines, staged, format) {
|
|
5075
4325
|
if (file) {
|
|
@@ -5191,10 +4441,6 @@ var GIT_CHECKPOINT_TOOL = {
|
|
|
5191
4441
|
include_untracked: {
|
|
5192
4442
|
type: "boolean",
|
|
5193
4443
|
description: "Also stage and commit untracked files (default: false)."
|
|
5194
|
-
},
|
|
5195
|
-
daemon_id: {
|
|
5196
|
-
type: "string",
|
|
5197
|
-
description: "Daemon ID (cloud mode only, required)."
|
|
5198
4444
|
}
|
|
5199
4445
|
},
|
|
5200
4446
|
required: ["workspace", "message"]
|
|
@@ -5204,23 +4450,12 @@ async function gitCheckpoint(transport, args) {
|
|
|
5204
4450
|
const message = args.message?.trim();
|
|
5205
4451
|
if (!message) return "Error: message is required";
|
|
5206
4452
|
if (message.length > 200) return "Error: message must be 200 characters or fewer";
|
|
5207
|
-
let raw
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
});
|
|
5214
|
-
raw = raw?.checkpoint ?? raw;
|
|
5215
|
-
} else {
|
|
5216
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
5217
|
-
const result = await transport.gitCheckpoint(args.daemon_id, {
|
|
5218
|
-
workspace: args.workspace,
|
|
5219
|
-
message,
|
|
5220
|
-
includeUntracked: args.include_untracked ?? false
|
|
5221
|
-
});
|
|
5222
|
-
raw = result?.checkpoint ?? result;
|
|
5223
|
-
}
|
|
4453
|
+
let raw = await transport.command("git_checkpoint", {
|
|
4454
|
+
workspace: args.workspace,
|
|
4455
|
+
message,
|
|
4456
|
+
includeUntracked: args.include_untracked ?? false
|
|
4457
|
+
});
|
|
4458
|
+
raw = raw?.checkpoint ?? raw;
|
|
5224
4459
|
if (raw?.success === false || raw?.reason) {
|
|
5225
4460
|
const msg = raw?.error ?? raw?.reason ?? "unknown";
|
|
5226
4461
|
if (msg.includes("Nothing to commit") || msg.includes("nothing to commit")) {
|
|
@@ -5251,33 +4486,18 @@ var GIT_PUSH_TOOL = {
|
|
|
5251
4486
|
branch: {
|
|
5252
4487
|
type: "string",
|
|
5253
4488
|
description: "Branch to push (default: current branch)."
|
|
5254
|
-
},
|
|
5255
|
-
daemon_id: {
|
|
5256
|
-
type: "string",
|
|
5257
|
-
description: "Daemon ID (cloud mode only, required)."
|
|
5258
4489
|
}
|
|
5259
4490
|
},
|
|
5260
4491
|
required: ["workspace"]
|
|
5261
4492
|
}
|
|
5262
4493
|
};
|
|
5263
4494
|
async function gitPush(transport, args) {
|
|
5264
|
-
let raw
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
});
|
|
5271
|
-
raw = raw?.push ?? raw;
|
|
5272
|
-
} else {
|
|
5273
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
5274
|
-
const result = await transport.gitPush(args.daemon_id, {
|
|
5275
|
-
workspace: args.workspace,
|
|
5276
|
-
remote: args.remote,
|
|
5277
|
-
branch: args.branch
|
|
5278
|
-
});
|
|
5279
|
-
raw = result?.push ?? result;
|
|
5280
|
-
}
|
|
4495
|
+
let raw = await transport.command("git_push", {
|
|
4496
|
+
workspace: args.workspace,
|
|
4497
|
+
remote: args.remote ?? "origin",
|
|
4498
|
+
...args.branch ? { branch: args.branch } : {}
|
|
4499
|
+
});
|
|
4500
|
+
raw = raw?.push ?? raw;
|
|
5281
4501
|
if (raw?.success === false || raw?.reason) {
|
|
5282
4502
|
const msg = raw?.error ?? raw?.reason ?? "unknown";
|
|
5283
4503
|
return `Git push error: ${msg}`;
|
|
@@ -5308,32 +4528,17 @@ var LAUNCH_SESSION_TOOL = {
|
|
|
5308
4528
|
model: {
|
|
5309
4529
|
type: "string",
|
|
5310
4530
|
description: "Model override for ACP agents (e.g. claude-opus-4-7)."
|
|
5311
|
-
},
|
|
5312
|
-
daemon_id: {
|
|
5313
|
-
type: "string",
|
|
5314
|
-
description: "Daemon ID (cloud mode only). Required in cloud mode."
|
|
5315
4531
|
}
|
|
5316
4532
|
},
|
|
5317
4533
|
required: ["type"]
|
|
5318
4534
|
}
|
|
5319
4535
|
};
|
|
5320
4536
|
async function launchSession(transport, args) {
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
if (result2?.success === false) return `Error: ${result2.error ?? "launch failed"}`;
|
|
5327
|
-
const id2 = result2?.id ?? result2?.sessionId;
|
|
5328
|
-
return id2 ? `Session launched. id: ${id2}, type: ${args.type}` : `Launched: ${JSON.stringify(result2)}`;
|
|
5329
|
-
}
|
|
5330
|
-
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
5331
|
-
const result = await transport.launch(args.daemon_id, {
|
|
5332
|
-
type: args.type,
|
|
5333
|
-
dir: args.workspace,
|
|
5334
|
-
model: args.model
|
|
5335
|
-
});
|
|
5336
|
-
if (result?.success === false || result?.error) return `Error: ${result.error ?? "launch failed"}`;
|
|
4537
|
+
const isCliOrAcp = args.type.includes("-cli") || args.type.includes("-acp") || args.type === "codex";
|
|
4538
|
+
const commandType = isCliOrAcp ? "launch_cli" : "launch_ide";
|
|
4539
|
+
const payload = isCliOrAcp ? { cliType: args.type, dir: args.workspace ?? "~", ...args.model ? { model: args.model } : {} } : { ideType: args.type, enableCdp: true };
|
|
4540
|
+
const result = await transport.command(commandType, payload);
|
|
4541
|
+
if (result?.success === false) return `Error: ${result.error ?? "launch failed"}`;
|
|
5337
4542
|
const id = result?.id ?? result?.sessionId;
|
|
5338
4543
|
return id ? `Session launched. id: ${id}, type: ${args.type}` : `Launched: ${JSON.stringify(result)}`;
|
|
5339
4544
|
}
|
|
@@ -5349,43 +4554,29 @@ var STOP_SESSION_TOOL = {
|
|
|
5349
4554
|
type: "string",
|
|
5350
4555
|
description: "Session ID to stop (from list_sessions)."
|
|
5351
4556
|
},
|
|
5352
|
-
daemon_id: {
|
|
5353
|
-
type: "string",
|
|
5354
|
-
description: "Daemon ID (cloud mode only, required)."
|
|
5355
|
-
},
|
|
5356
4557
|
type: {
|
|
5357
4558
|
type: "string",
|
|
5358
|
-
description: "Provider type (e.g. hermes-cli, claude-cli).
|
|
4559
|
+
description: "Provider type (e.g. hermes-cli, claude-cli). Auto-resolved from session_id if omitted."
|
|
5359
4560
|
}
|
|
5360
4561
|
},
|
|
5361
4562
|
required: ["session_id"]
|
|
5362
4563
|
}
|
|
5363
4564
|
};
|
|
5364
4565
|
async function stopSession(transport, args) {
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
}
|
|
5373
|
-
if (!resolvedType) {
|
|
5374
|
-
return `Error: could not resolve session type for ${args.session_id}. Pass type= explicitly.`;
|
|
5375
|
-
}
|
|
5376
|
-
const result2 = await local.command("stop_cli", {
|
|
5377
|
-
targetSessionId: args.session_id,
|
|
5378
|
-
cliType: resolvedType
|
|
5379
|
-
});
|
|
5380
|
-
if (result2?.success === false) return `Error: ${result2.error ?? "stop failed"}`;
|
|
5381
|
-
return `Session ${args.session_id} stopped.`;
|
|
4566
|
+
let resolvedType = args.type;
|
|
4567
|
+
if (!resolvedType) {
|
|
4568
|
+
const status = await transport.getStatus();
|
|
4569
|
+
const session = (status?.sessions ?? []).find((s) => s.id === args.session_id);
|
|
4570
|
+
resolvedType = session?.providerType ?? session?.type;
|
|
4571
|
+
}
|
|
4572
|
+
if (!resolvedType) {
|
|
4573
|
+
return `Error: could not resolve session type for ${args.session_id}. Pass type= explicitly.`;
|
|
5382
4574
|
}
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
...args.type ? { type: args.type } : {}
|
|
4575
|
+
const result = await transport.command("stop_cli", {
|
|
4576
|
+
targetSessionId: args.session_id,
|
|
4577
|
+
cliType: resolvedType
|
|
5387
4578
|
});
|
|
5388
|
-
if (result?.success === false
|
|
4579
|
+
if (result?.success === false) return `Error: ${result.error ?? "stop failed"}`;
|
|
5389
4580
|
return `Session ${args.session_id} stopped.`;
|
|
5390
4581
|
}
|
|
5391
4582
|
|
|
@@ -5396,28 +4587,18 @@ var CHECK_PENDING_TOOL = {
|
|
|
5396
4587
|
inputSchema: {
|
|
5397
4588
|
type: "object",
|
|
5398
4589
|
properties: {
|
|
5399
|
-
daemon_id: {
|
|
5400
|
-
type: "string",
|
|
5401
|
-
description: "Daemon ID to check (cloud mode). Omit to check all daemons."
|
|
5402
|
-
},
|
|
5403
4590
|
...FORMAT_PROP
|
|
5404
4591
|
},
|
|
5405
4592
|
required: []
|
|
5406
4593
|
}
|
|
5407
4594
|
};
|
|
5408
4595
|
async function checkPending(transport, args) {
|
|
5409
|
-
if (isLocalTransport(transport)) {
|
|
5410
|
-
return checkPendingLocal(transport, args.format);
|
|
5411
|
-
}
|
|
5412
|
-
return checkPendingCloud(transport, args.daemon_id, args.format);
|
|
5413
|
-
}
|
|
5414
|
-
async function checkPendingLocal(transport, format) {
|
|
5415
4596
|
const status = await transport.getStatus();
|
|
5416
4597
|
const sessions = status?.sessions ?? [];
|
|
5417
4598
|
const pending = sessions.filter(
|
|
5418
4599
|
(s) => s.status === "waiting_approval" || s.agentStatus === "waiting_approval"
|
|
5419
4600
|
);
|
|
5420
|
-
if (format === "json") {
|
|
4601
|
+
if (args.format === "json") {
|
|
5421
4602
|
return JSON.stringify({
|
|
5422
4603
|
pending: pending.map((s) => ({
|
|
5423
4604
|
session_id: s.id,
|
|
@@ -5440,56 +4621,6 @@ async function checkPendingLocal(transport, format) {
|
|
|
5440
4621
|
});
|
|
5441
4622
|
return `Pending approvals (${pending.length}):
|
|
5442
4623
|
|
|
5443
|
-
${lines.join("\n\n")}`;
|
|
5444
|
-
}
|
|
5445
|
-
async function checkPendingCloud(transport, daemonId, format) {
|
|
5446
|
-
const pending = [];
|
|
5447
|
-
if (daemonId) {
|
|
5448
|
-
const daemonStatus = await transport.getDaemonStatus(daemonId);
|
|
5449
|
-
const sessions = daemonStatus?.sessions ?? [];
|
|
5450
|
-
for (const s of sessions) {
|
|
5451
|
-
if (s.status === "waiting_approval") pending.push({ daemonId, session: s });
|
|
5452
|
-
}
|
|
5453
|
-
} else {
|
|
5454
|
-
const data = await transport.listDaemons();
|
|
5455
|
-
const daemons = data?.daemons ?? [];
|
|
5456
|
-
for (let i = 0; i < daemons.length; i += 5) {
|
|
5457
|
-
await Promise.allSettled(
|
|
5458
|
-
daemons.slice(i, i + 5).map(async (d) => {
|
|
5459
|
-
try {
|
|
5460
|
-
const daemonStatus = await transport.getDaemonStatus(d.id);
|
|
5461
|
-
const sessions = daemonStatus?.sessions ?? [];
|
|
5462
|
-
for (const s of sessions) {
|
|
5463
|
-
if (s.status === "waiting_approval") pending.push({ daemonId: d.id, session: s });
|
|
5464
|
-
}
|
|
5465
|
-
} catch {
|
|
5466
|
-
}
|
|
5467
|
-
})
|
|
5468
|
-
);
|
|
5469
|
-
}
|
|
5470
|
-
}
|
|
5471
|
-
if (format === "json") {
|
|
5472
|
-
return JSON.stringify({
|
|
5473
|
-
pending: pending.map(({ daemonId: dId, session: s }) => ({
|
|
5474
|
-
daemon_id: dId,
|
|
5475
|
-
session_id: s.id,
|
|
5476
|
-
workspace: s.workspace ?? null,
|
|
5477
|
-
type: s.providerType ?? null,
|
|
5478
|
-
modal_message: null,
|
|
5479
|
-
buttons: []
|
|
5480
|
-
}))
|
|
5481
|
-
}, null, 2);
|
|
5482
|
-
}
|
|
5483
|
-
if (pending.length === 0) return "No sessions waiting for approval.";
|
|
5484
|
-
const lines = pending.map(({ daemonId: dId, session: s }) => {
|
|
5485
|
-
const parts = [`daemon_id: ${dId}`, `session_id: ${s.id}`];
|
|
5486
|
-
if (s.workspace) parts.push(`workspace: ${s.workspace}`);
|
|
5487
|
-
if (s.providerType) parts.push(`type: ${s.providerType}`);
|
|
5488
|
-
parts.push("(use read_chat to see the approval prompt)");
|
|
5489
|
-
return parts.join("\n ");
|
|
5490
|
-
});
|
|
5491
|
-
return `Pending approvals (${pending.length}):
|
|
5492
|
-
|
|
5493
4624
|
${lines.join("\n\n")}`;
|
|
5494
4625
|
}
|
|
5495
4626
|
|
|
@@ -5503,10 +4634,10 @@ async function buildMeshModeCoordinatorPrompt(mesh) {
|
|
|
5503
4634
|
}
|
|
5504
4635
|
}
|
|
5505
4636
|
async function startMcpServer(opts) {
|
|
5506
|
-
const transport = opts.mode === "
|
|
4637
|
+
const transport = opts.mode === "ipc" ? new IpcTransport({ port: opts.port }) : new LocalTransport({ port: opts.port, password: opts.password });
|
|
5507
4638
|
const alive = await transport.ping();
|
|
5508
4639
|
if (!alive) {
|
|
5509
|
-
const hint = opts.mode === "local" ? `Make sure the standalone daemon is running (adhdev standalone or npx @adhdev/daemon-standalone).` :
|
|
4640
|
+
const hint = opts.mode === "local" ? `Make sure the standalone daemon is running (adhdev standalone or npx @adhdev/daemon-standalone).` : `Make sure the cloud daemon is running with local IPC enabled (adhdev daemon).`;
|
|
5510
4641
|
process.stderr.write(`[adhdev-mcp] Cannot reach ${opts.mode} daemon. ${hint}
|
|
5511
4642
|
`);
|
|
5512
4643
|
process.exit(1);
|
|
@@ -5521,64 +4652,6 @@ async function startMcpServer(opts) {
|
|
|
5521
4652
|
`);
|
|
5522
4653
|
} catch (e) {
|
|
5523
4654
|
process.stderr.write(`[adhdev-mcp] Failed to parse ADHDEV_INLINE_MESH: ${e.message}
|
|
5524
|
-
`);
|
|
5525
|
-
}
|
|
5526
|
-
}
|
|
5527
|
-
if (!mesh && opts.mode === "cloud" && opts.apiKey) {
|
|
5528
|
-
try {
|
|
5529
|
-
const base = opts.baseUrl || "https://api.adhf.dev";
|
|
5530
|
-
const res = await fetch(`${base}/api/v1/repo-meshes/${opts.meshId}`, {
|
|
5531
|
-
headers: { "Authorization": `Bearer ${opts.apiKey}`, "Content-Type": "application/json" }
|
|
5532
|
-
});
|
|
5533
|
-
if (res.ok) {
|
|
5534
|
-
const data = await res.json();
|
|
5535
|
-
const rm = data.mesh;
|
|
5536
|
-
const nodes = data.nodes || [];
|
|
5537
|
-
let policy = {};
|
|
5538
|
-
try {
|
|
5539
|
-
policy = JSON.parse(rm.policy_json || rm.policy || "{}");
|
|
5540
|
-
} catch {
|
|
5541
|
-
}
|
|
5542
|
-
let coordinator = {};
|
|
5543
|
-
try {
|
|
5544
|
-
coordinator = JSON.parse(rm.coordinator_json || rm.coordinator_config || "{}");
|
|
5545
|
-
} catch {
|
|
5546
|
-
}
|
|
5547
|
-
mesh = {
|
|
5548
|
-
id: rm.id,
|
|
5549
|
-
name: rm.name,
|
|
5550
|
-
repoIdentity: rm.repo_identity,
|
|
5551
|
-
repoRemoteUrl: rm.repo_remote_url,
|
|
5552
|
-
defaultBranch: rm.default_branch,
|
|
5553
|
-
policy: {
|
|
5554
|
-
requirePreTaskCheckpoint: false,
|
|
5555
|
-
requirePostTaskCheckpoint: true,
|
|
5556
|
-
requireApprovalForPush: true,
|
|
5557
|
-
allowAutoPublishSubmoduleMainCommits: false,
|
|
5558
|
-
requireApprovalForDestructiveGit: true,
|
|
5559
|
-
dirtyWorkspaceBehavior: "warn",
|
|
5560
|
-
maxParallelTasks: 2,
|
|
5561
|
-
spawnedSessionVisibility: "visible",
|
|
5562
|
-
...policy
|
|
5563
|
-
},
|
|
5564
|
-
coordinator,
|
|
5565
|
-
nodes: nodes.map((n) => ({
|
|
5566
|
-
id: n.id,
|
|
5567
|
-
workspace: n.workspace,
|
|
5568
|
-
repoRoot: n.repo_root,
|
|
5569
|
-
daemonId: n.daemon_id,
|
|
5570
|
-
userOverrides: {},
|
|
5571
|
-
policy: {},
|
|
5572
|
-
isLocalWorktree: false
|
|
5573
|
-
})),
|
|
5574
|
-
createdAt: rm.created_at,
|
|
5575
|
-
updatedAt: rm.updated_at
|
|
5576
|
-
};
|
|
5577
|
-
process.stderr.write(`[adhdev-mcp] Loaded mesh config from cloud API
|
|
5578
|
-
`);
|
|
5579
|
-
}
|
|
5580
|
-
} catch (e) {
|
|
5581
|
-
process.stderr.write(`[adhdev-mcp] Cloud mesh fetch failed, falling back to local: ${e.message}
|
|
5582
4655
|
`);
|
|
5583
4656
|
}
|
|
5584
4657
|
}
|
|
@@ -5605,7 +4678,7 @@ async function startMcpServer(opts) {
|
|
|
5605
4678
|
}
|
|
5606
4679
|
}
|
|
5607
4680
|
if (!mesh) {
|
|
5608
|
-
process.stderr.write(`[adhdev-mcp] Mesh '${opts.meshId}' not found in
|
|
4681
|
+
process.stderr.write(`[adhdev-mcp] Mesh '${opts.meshId}' not found in local config. Use 'adhdev mesh list' to see available meshes.
|
|
5609
4682
|
`);
|
|
5610
4683
|
process.exit(1);
|
|
5611
4684
|
}
|
|
@@ -5784,7 +4857,7 @@ async function startMcpServer(opts) {
|
|
|
5784
4857
|
return { content: [{ type: "text", text }] };
|
|
5785
4858
|
}
|
|
5786
4859
|
case "list_sessions": {
|
|
5787
|
-
const text = await listSessions(transport, { format: a.format
|
|
4860
|
+
const text = await listSessions(transport, { format: a.format });
|
|
5788
4861
|
return { content: [{ type: "text", text }] };
|
|
5789
4862
|
}
|
|
5790
4863
|
case "read_chat": {
|
|
@@ -5800,12 +4873,12 @@ async function startMcpServer(opts) {
|
|
|
5800
4873
|
return { content: [{ type: "text", text }] };
|
|
5801
4874
|
}
|
|
5802
4875
|
case "send_chat": {
|
|
5803
|
-
const text = await sendChat(transport, { message: a.message, session_id: a.session_id
|
|
4876
|
+
const text = await sendChat(transport, { message: a.message, session_id: a.session_id });
|
|
5804
4877
|
return { content: [{ type: "text", text }] };
|
|
5805
4878
|
}
|
|
5806
4879
|
case "approve": {
|
|
5807
4880
|
const action = a.action === "reject" ? "reject" : "approve";
|
|
5808
|
-
const text = await approve(transport, { action, session_id: a.session_id
|
|
4881
|
+
const text = await approve(transport, { action, session_id: a.session_id });
|
|
5809
4882
|
return { content: [{ type: "text", text }] };
|
|
5810
4883
|
}
|
|
5811
4884
|
case "screenshot": {
|
|
@@ -5818,44 +4891,42 @@ async function startMcpServer(opts) {
|
|
|
5818
4891
|
return { content: [{ type: "text", text: result.text }] };
|
|
5819
4892
|
}
|
|
5820
4893
|
case "git_status": {
|
|
5821
|
-
const text = await gitStatus(transport, { workspace: a.workspace, include_diff: a.include_diff,
|
|
4894
|
+
const text = await gitStatus(transport, { workspace: a.workspace, include_diff: a.include_diff, format: a.format });
|
|
5822
4895
|
return { content: [{ type: "text", text }] };
|
|
5823
4896
|
}
|
|
5824
4897
|
case "git_log": {
|
|
5825
|
-
const text = await gitLog(transport, { workspace: a.workspace, limit: a.limit, file: a.file, since: a.since, until: a.until,
|
|
4898
|
+
const text = await gitLog(transport, { workspace: a.workspace, limit: a.limit, file: a.file, since: a.since, until: a.until, format: a.format });
|
|
5826
4899
|
return { content: [{ type: "text", text }] };
|
|
5827
4900
|
}
|
|
5828
4901
|
case "git_diff": {
|
|
5829
|
-
const text = await gitDiff(transport, { workspace: a.workspace, file: a.file, max_lines: a.max_lines, staged: a.staged,
|
|
4902
|
+
const text = await gitDiff(transport, { workspace: a.workspace, file: a.file, max_lines: a.max_lines, staged: a.staged, format: a.format });
|
|
5830
4903
|
return { content: [{ type: "text", text }] };
|
|
5831
4904
|
}
|
|
5832
4905
|
case "git_checkpoint": {
|
|
5833
|
-
const text = await gitCheckpoint(transport, { workspace: a.workspace, message: a.message, include_untracked: a.include_untracked
|
|
4906
|
+
const text = await gitCheckpoint(transport, { workspace: a.workspace, message: a.message, include_untracked: a.include_untracked });
|
|
5834
4907
|
return { content: [{ type: "text", text }] };
|
|
5835
4908
|
}
|
|
5836
4909
|
case "git_push": {
|
|
5837
|
-
const text = await gitPush(transport, { workspace: a.workspace, remote: a.remote, branch: a.branch
|
|
4910
|
+
const text = await gitPush(transport, { workspace: a.workspace, remote: a.remote, branch: a.branch });
|
|
5838
4911
|
return { content: [{ type: "text", text }] };
|
|
5839
4912
|
}
|
|
5840
4913
|
case "launch_session": {
|
|
5841
4914
|
const text = await launchSession(transport, {
|
|
5842
4915
|
type: a.type,
|
|
5843
4916
|
workspace: a.workspace,
|
|
5844
|
-
model: a.model
|
|
5845
|
-
daemon_id: a.daemon_id
|
|
4917
|
+
model: a.model
|
|
5846
4918
|
});
|
|
5847
4919
|
return { content: [{ type: "text", text }] };
|
|
5848
4920
|
}
|
|
5849
4921
|
case "stop_session": {
|
|
5850
4922
|
const text = await stopSession(transport, {
|
|
5851
4923
|
session_id: a.session_id,
|
|
5852
|
-
daemon_id: a.daemon_id,
|
|
5853
4924
|
type: a.type
|
|
5854
4925
|
});
|
|
5855
4926
|
return { content: [{ type: "text", text }] };
|
|
5856
4927
|
}
|
|
5857
4928
|
case "check_pending": {
|
|
5858
|
-
const text = await checkPending(transport, {
|
|
4929
|
+
const text = await checkPending(transport, { format: a.format });
|
|
5859
4930
|
return { content: [{ type: "text", text }] };
|
|
5860
4931
|
}
|
|
5861
4932
|
default:
|
|
@@ -5877,26 +4948,18 @@ async function startMcpServer(opts) {
|
|
|
5877
4948
|
// src/index.ts
|
|
5878
4949
|
function parseArgs(argv, env = process.env) {
|
|
5879
4950
|
const args = argv.slice(2);
|
|
5880
|
-
let apiKey;
|
|
5881
|
-
let baseUrl;
|
|
5882
4951
|
let port;
|
|
5883
4952
|
let password;
|
|
5884
4953
|
let meshId;
|
|
5885
4954
|
let explicitMode;
|
|
5886
4955
|
for (let i = 0; i < args.length; i++) {
|
|
5887
4956
|
const arg = args[i];
|
|
5888
|
-
if (
|
|
5889
|
-
apiKey = args[++i];
|
|
5890
|
-
} else if (arg?.startsWith("--api-key=")) {
|
|
5891
|
-
apiKey = arg.slice("--api-key=".length);
|
|
5892
|
-
} else if (arg === "--base-url" && args[i + 1]) {
|
|
5893
|
-
baseUrl = args[++i];
|
|
5894
|
-
} else if (arg === "--mode" && args[i + 1]) {
|
|
4957
|
+
if (arg === "--mode" && args[i + 1]) {
|
|
5895
4958
|
const value = String(args[++i]).trim();
|
|
5896
|
-
if (value === "local" || value === "
|
|
4959
|
+
if (value === "local" || value === "ipc") explicitMode = value;
|
|
5897
4960
|
} else if (arg?.startsWith("--mode=")) {
|
|
5898
4961
|
const value = arg.slice("--mode=".length).trim();
|
|
5899
|
-
if (value === "local" || value === "
|
|
4962
|
+
if (value === "local" || value === "ipc") explicitMode = value;
|
|
5900
4963
|
} else if (arg === "--port" && args[i + 1]) {
|
|
5901
4964
|
port = Number(args[++i]);
|
|
5902
4965
|
} else if (arg?.startsWith("--port=")) {
|
|
@@ -5912,15 +4975,14 @@ function parseArgs(argv, env = process.env) {
|
|
|
5912
4975
|
process.exit(0);
|
|
5913
4976
|
}
|
|
5914
4977
|
}
|
|
5915
|
-
if (!apiKey && env.ADHDEV_API_KEY) apiKey = env.ADHDEV_API_KEY;
|
|
5916
4978
|
if (!password && env.ADHDEV_PASSWORD) password = env.ADHDEV_PASSWORD;
|
|
5917
4979
|
if (!meshId && env.ADHDEV_MESH_ID) meshId = env.ADHDEV_MESH_ID;
|
|
5918
4980
|
if (!explicitMode && env.ADHDEV_MCP_TRANSPORT) {
|
|
5919
4981
|
const value = env.ADHDEV_MCP_TRANSPORT.trim();
|
|
5920
|
-
if (value === "local" || value === "
|
|
4982
|
+
if (value === "local" || value === "ipc") explicitMode = value;
|
|
5921
4983
|
}
|
|
5922
|
-
const mode = explicitMode || (
|
|
5923
|
-
return { mode, port, password,
|
|
4984
|
+
const mode = explicitMode || (meshId && env.ADHDEV_INLINE_MESH ? "ipc" : "local");
|
|
4985
|
+
return { mode, port, password, meshId };
|
|
5924
4986
|
}
|
|
5925
4987
|
function printHelp() {
|
|
5926
4988
|
console.error(buildMcpHelpText());
|