adhdev 0.9.60 → 0.9.62
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/cli/index.js +3 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/vendor/mcp-server/index.js +193 -40
- package/vendor/mcp-server/index.js.map +1 -1
package/dist/index.js
CHANGED
|
@@ -59187,7 +59187,7 @@ var init_adhdev_daemon = __esm({
|
|
|
59187
59187
|
init_version();
|
|
59188
59188
|
init_src();
|
|
59189
59189
|
init_runtime_defaults();
|
|
59190
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.
|
|
59190
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.62" });
|
|
59191
59191
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
59192
59192
|
localHttpServer = null;
|
|
59193
59193
|
localWss = null;
|
package/package.json
CHANGED
|
@@ -129,6 +129,18 @@ var CloudTransport = class {
|
|
|
129
129
|
if (!res.ok) throw new Error(`Git status failed: ${res.status}`);
|
|
130
130
|
return res.json();
|
|
131
131
|
}
|
|
132
|
+
async stop(daemonId, opts) {
|
|
133
|
+
const res = await fetch(
|
|
134
|
+
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/stop`,
|
|
135
|
+
{
|
|
136
|
+
method: "POST",
|
|
137
|
+
headers: this.headers(),
|
|
138
|
+
body: JSON.stringify(opts)
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
if (!res.ok) throw new Error(`Stop failed: ${res.status}`);
|
|
142
|
+
return res.json();
|
|
143
|
+
}
|
|
132
144
|
async launch(daemonId, opts) {
|
|
133
145
|
const res = await fetch(
|
|
134
146
|
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/launch`,
|
|
@@ -161,10 +173,14 @@ var FORMAT_PROP = {
|
|
|
161
173
|
};
|
|
162
174
|
var LIST_SESSIONS_TOOL = {
|
|
163
175
|
name: "list_sessions",
|
|
164
|
-
description: "List all
|
|
176
|
+
description: "List all connected agent sessions. In cloud mode, fetches session state from each daemon (data is sourced from daemon WS status reports, up to 30s stale). Pass daemon_id to scope to a single daemon.",
|
|
165
177
|
inputSchema: {
|
|
166
178
|
type: "object",
|
|
167
179
|
properties: {
|
|
180
|
+
daemon_id: {
|
|
181
|
+
type: "string",
|
|
182
|
+
description: "Daemon ID (cloud mode only). Omit to list sessions across all daemons."
|
|
183
|
+
},
|
|
168
184
|
...FORMAT_PROP
|
|
169
185
|
},
|
|
170
186
|
required: []
|
|
@@ -187,46 +203,122 @@ async function listSessions(transport, args = {}) {
|
|
|
187
203
|
}, null, 2);
|
|
188
204
|
}
|
|
189
205
|
if (sessions.length === 0) return "No active sessions.";
|
|
190
|
-
const
|
|
206
|
+
const lines = sessions.map((s) => {
|
|
191
207
|
const parts = [`id: ${s.id}`, `type: ${s.providerType ?? s.type ?? "unknown"}`];
|
|
192
208
|
if (s.label) parts.push(`label: ${s.label}`);
|
|
193
|
-
if (s.agentStatus) parts.push(`status: ${s.agentStatus}`);
|
|
209
|
+
if (s.status ?? s.agentStatus) parts.push(`status: ${s.status ?? s.agentStatus}`);
|
|
194
210
|
if (s.workspace) parts.push(`workspace: ${s.workspace}`);
|
|
195
211
|
return parts.join(", ");
|
|
196
212
|
});
|
|
197
213
|
return `Sessions (${sessions.length}):
|
|
198
|
-
${
|
|
214
|
+
${lines.join("\n")}`;
|
|
199
215
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
id: s.id,
|
|
209
|
-
type: s.providerType ?? "unknown",
|
|
210
|
-
status: s.status ?? s.agentStatus ?? null,
|
|
211
|
-
workspace: s.workspace ?? null
|
|
212
|
-
});
|
|
213
|
-
}
|
|
216
|
+
return listSessionsCloud(transport, args.daemon_id, asJson);
|
|
217
|
+
}
|
|
218
|
+
async function listSessionsCloud(transport, daemonId, asJson) {
|
|
219
|
+
const collected = [];
|
|
220
|
+
if (daemonId) {
|
|
221
|
+
const daemonStatus = await transport.getDaemonStatus(daemonId);
|
|
222
|
+
for (const s of daemonStatus?.sessions ?? []) {
|
|
223
|
+
collected.push({ daemonId, session: s });
|
|
214
224
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
225
|
+
} else {
|
|
226
|
+
const data = await transport.listDaemons();
|
|
227
|
+
const daemons = data?.daemons ?? [];
|
|
228
|
+
for (let i = 0; i < daemons.length; i += 5) {
|
|
229
|
+
await Promise.allSettled(
|
|
230
|
+
daemons.slice(i, i + 5).map(async (d) => {
|
|
231
|
+
try {
|
|
232
|
+
const daemonStatus = await transport.getDaemonStatus(d.id);
|
|
233
|
+
for (const s of daemonStatus?.sessions ?? []) {
|
|
234
|
+
collected.push({ daemonId: d.id, session: s });
|
|
235
|
+
}
|
|
236
|
+
} catch {
|
|
237
|
+
}
|
|
238
|
+
})
|
|
224
239
|
);
|
|
225
240
|
}
|
|
226
|
-
if (sessions.length === 0) lines.push(`daemon: ${d.id} (no sessions)`);
|
|
227
241
|
}
|
|
228
|
-
|
|
229
|
-
|
|
242
|
+
if (asJson) {
|
|
243
|
+
return JSON.stringify({
|
|
244
|
+
sessions: collected.map(({ daemonId: dId, session: s }) => ({
|
|
245
|
+
daemon_id: dId,
|
|
246
|
+
id: s.id,
|
|
247
|
+
type: s.providerType ?? "unknown",
|
|
248
|
+
status: s.status ?? null,
|
|
249
|
+
workspace: s.workspace ?? null
|
|
250
|
+
}))
|
|
251
|
+
}, null, 2);
|
|
252
|
+
}
|
|
253
|
+
if (collected.length === 0) return "No active sessions.";
|
|
254
|
+
const lines = collected.map(({ daemonId: dId, session: s }) => {
|
|
255
|
+
const parts = [
|
|
256
|
+
`daemon: ${dId}`,
|
|
257
|
+
`session: ${s.id}`,
|
|
258
|
+
`type: ${s.providerType ?? "unknown"}`
|
|
259
|
+
];
|
|
260
|
+
if (s.status) parts.push(`status: ${s.status}`);
|
|
261
|
+
if (s.workspace) parts.push(`workspace: ${s.workspace}`);
|
|
262
|
+
return parts.join(", ");
|
|
263
|
+
});
|
|
264
|
+
return `Sessions (${collected.length}):
|
|
265
|
+
${lines.join("\n")}`;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/tools/list-daemons.ts
|
|
269
|
+
var LIST_DAEMONS_TOOL = {
|
|
270
|
+
name: "list_daemons",
|
|
271
|
+
description: "List all connected daemons (machines running the ADHDev agent). Use this to discover daemon IDs before calling launch_session, git_status, or other tools that require daemon_id. In local mode returns the single standalone daemon info.",
|
|
272
|
+
inputSchema: {
|
|
273
|
+
type: "object",
|
|
274
|
+
properties: {
|
|
275
|
+
...FORMAT_PROP
|
|
276
|
+
},
|
|
277
|
+
required: []
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
async function listDaemons(transport, args = {}) {
|
|
281
|
+
const asJson = args.format === "json";
|
|
282
|
+
if ("getStatus" in transport) {
|
|
283
|
+
const status = await transport.getStatus();
|
|
284
|
+
const daemon = {
|
|
285
|
+
id: status?.id ?? status?.instanceId ?? "standalone",
|
|
286
|
+
hostname: status?.hostname ?? status?.machine?.hostname ?? "localhost",
|
|
287
|
+
platform: status?.platform ?? status?.machine?.platform ?? "unknown",
|
|
288
|
+
version: status?.version ?? null,
|
|
289
|
+
sessions: (status?.sessions ?? []).length
|
|
290
|
+
};
|
|
291
|
+
if (asJson) return JSON.stringify({ daemons: [daemon] }, null, 2);
|
|
292
|
+
return `Daemons (1):
|
|
293
|
+
id: ${daemon.id}, hostname: ${daemon.hostname}, platform: ${daemon.platform}${daemon.version ? `, version: ${daemon.version}` : ""}, sessions: ${daemon.sessions}`;
|
|
294
|
+
}
|
|
295
|
+
const data = await transport.listDaemons();
|
|
296
|
+
const daemons = data?.daemons ?? [];
|
|
297
|
+
if (asJson) {
|
|
298
|
+
return JSON.stringify({
|
|
299
|
+
daemons: daemons.map((d) => ({
|
|
300
|
+
id: d.id,
|
|
301
|
+
hostname: d.hostname ?? null,
|
|
302
|
+
platform: d.platform ?? null,
|
|
303
|
+
nickname: d.nickname ?? null,
|
|
304
|
+
version: d.version ?? null,
|
|
305
|
+
p2p_available: d.p2p?.available ?? null,
|
|
306
|
+
cdp_connected: d.cdpConnected ?? null
|
|
307
|
+
}))
|
|
308
|
+
}, null, 2);
|
|
309
|
+
}
|
|
310
|
+
if (daemons.length === 0) return "No connected daemons.";
|
|
311
|
+
const lines = daemons.map((d) => {
|
|
312
|
+
const parts = [`id: ${d.id}`];
|
|
313
|
+
if (d.nickname) parts.push(`nickname: ${d.nickname}`);
|
|
314
|
+
if (d.hostname) parts.push(`hostname: ${d.hostname}`);
|
|
315
|
+
if (d.platform) parts.push(`platform: ${d.platform}`);
|
|
316
|
+
if (d.version) parts.push(`version: ${d.version}`);
|
|
317
|
+
if (d.p2p?.available != null) parts.push(`p2p: ${d.p2p.available ? "yes" : "no"}`);
|
|
318
|
+
return parts.join(", ");
|
|
319
|
+
});
|
|
320
|
+
return `Daemons (${daemons.length}):
|
|
321
|
+
${lines.join("\n")}`;
|
|
230
322
|
}
|
|
231
323
|
|
|
232
324
|
// src/tools/read-chat.ts
|
|
@@ -380,17 +472,13 @@ async function approve(transport, args) {
|
|
|
380
472
|
// src/tools/screenshot.ts
|
|
381
473
|
var SCREENSHOT_TOOL = {
|
|
382
474
|
name: "screenshot",
|
|
383
|
-
description: "Capture a screenshot of the current IDE window. Returns the image.",
|
|
475
|
+
description: "Capture a screenshot of the current IDE window. Returns the image. Local mode only \u2014 screenshots require direct P2P access to the daemon and are not available in cloud mode.",
|
|
384
476
|
inputSchema: {
|
|
385
477
|
type: "object",
|
|
386
478
|
properties: {
|
|
387
479
|
session_id: {
|
|
388
480
|
type: "string",
|
|
389
481
|
description: "Target session ID. Omit to use the active session."
|
|
390
|
-
},
|
|
391
|
-
daemon_id: {
|
|
392
|
-
type: "string",
|
|
393
|
-
description: "Daemon ID (cloud mode only)."
|
|
394
482
|
}
|
|
395
483
|
},
|
|
396
484
|
required: []
|
|
@@ -579,6 +667,57 @@ async function launchSession(transport, args) {
|
|
|
579
667
|
return id ? `Session launched. id: ${id}, type: ${args.type}` : `Launched: ${JSON.stringify(result)}`;
|
|
580
668
|
}
|
|
581
669
|
|
|
670
|
+
// src/tools/stop-session.ts
|
|
671
|
+
var STOP_SESSION_TOOL = {
|
|
672
|
+
name: "stop_session",
|
|
673
|
+
description: "Stop a running agent session. For CLI agents (hermes-cli, claude-cli, etc.) this sends a graceful stop signal. Use list_sessions to find the session_id.",
|
|
674
|
+
inputSchema: {
|
|
675
|
+
type: "object",
|
|
676
|
+
properties: {
|
|
677
|
+
session_id: {
|
|
678
|
+
type: "string",
|
|
679
|
+
description: "Session ID to stop (from list_sessions)."
|
|
680
|
+
},
|
|
681
|
+
daemon_id: {
|
|
682
|
+
type: "string",
|
|
683
|
+
description: "Daemon ID (cloud mode only, required)."
|
|
684
|
+
},
|
|
685
|
+
type: {
|
|
686
|
+
type: "string",
|
|
687
|
+
description: "Provider type (e.g. hermes-cli, claude-cli). Cloud mode: auto-resolved from session_id if omitted."
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
required: ["session_id"]
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
async function stopSession(transport, args) {
|
|
694
|
+
if ("command" in transport) {
|
|
695
|
+
const local = transport;
|
|
696
|
+
let resolvedType = args.type;
|
|
697
|
+
if (!resolvedType) {
|
|
698
|
+
const status = await local.getStatus();
|
|
699
|
+
const session = (status?.sessions ?? []).find((s) => s.id === args.session_id);
|
|
700
|
+
resolvedType = session?.providerType ?? session?.type;
|
|
701
|
+
}
|
|
702
|
+
if (!resolvedType) {
|
|
703
|
+
return `Error: could not resolve session type for ${args.session_id}. Pass type= explicitly.`;
|
|
704
|
+
}
|
|
705
|
+
const result2 = await local.command("stop_cli", {
|
|
706
|
+
targetSessionId: args.session_id,
|
|
707
|
+
cliType: resolvedType
|
|
708
|
+
});
|
|
709
|
+
if (result2?.success === false) return `Error: ${result2.error ?? "stop failed"}`;
|
|
710
|
+
return `Session ${args.session_id} stopped.`;
|
|
711
|
+
}
|
|
712
|
+
if (!args.daemon_id) throw new Error("daemon_id is required in cloud mode");
|
|
713
|
+
const result = await transport.stop(args.daemon_id, {
|
|
714
|
+
id: args.session_id,
|
|
715
|
+
...args.type ? { type: args.type } : {}
|
|
716
|
+
});
|
|
717
|
+
if (result?.success === false || result?.error) return `Error: ${result.error ?? "stop failed"}`;
|
|
718
|
+
return `Session ${args.session_id} stopped.`;
|
|
719
|
+
}
|
|
720
|
+
|
|
582
721
|
// src/tools/check-pending.ts
|
|
583
722
|
var CHECK_PENDING_TOOL = {
|
|
584
723
|
name: "check_pending",
|
|
@@ -695,8 +834,10 @@ async function startMcpServer(opts) {
|
|
|
695
834
|
}
|
|
696
835
|
const isLocal = opts.mode === "local";
|
|
697
836
|
const allTools = [
|
|
837
|
+
LIST_DAEMONS_TOOL,
|
|
698
838
|
LIST_SESSIONS_TOOL,
|
|
699
839
|
LAUNCH_SESSION_TOOL,
|
|
840
|
+
STOP_SESSION_TOOL,
|
|
700
841
|
CHECK_PENDING_TOOL,
|
|
701
842
|
READ_CHAT_TOOL,
|
|
702
843
|
SEND_CHAT_TOOL,
|
|
@@ -705,7 +846,7 @@ async function startMcpServer(opts) {
|
|
|
705
846
|
...isLocal ? [SCREENSHOT_TOOL] : []
|
|
706
847
|
];
|
|
707
848
|
const server = new import_server.Server(
|
|
708
|
-
{ name: "adhdev-mcp-server", version: "0.9.
|
|
849
|
+
{ name: "adhdev-mcp-server", version: "0.9.62" },
|
|
709
850
|
{ capabilities: { tools: {} } }
|
|
710
851
|
);
|
|
711
852
|
server.setRequestHandler(import_types.ListToolsRequestSchema, async () => ({ tools: allTools }));
|
|
@@ -714,8 +855,12 @@ async function startMcpServer(opts) {
|
|
|
714
855
|
const a = args ?? {};
|
|
715
856
|
try {
|
|
716
857
|
switch (name) {
|
|
858
|
+
case "list_daemons": {
|
|
859
|
+
const text = await listDaemons(transport, { format: a.format });
|
|
860
|
+
return { content: [{ type: "text", text }] };
|
|
861
|
+
}
|
|
717
862
|
case "list_sessions": {
|
|
718
|
-
const text = await listSessions(transport, { format: a.format });
|
|
863
|
+
const text = await listSessions(transport, { format: a.format, daemon_id: a.daemon_id });
|
|
719
864
|
return { content: [{ type: "text", text }] };
|
|
720
865
|
}
|
|
721
866
|
case "read_chat": {
|
|
@@ -732,7 +877,7 @@ async function startMcpServer(opts) {
|
|
|
732
877
|
return { content: [{ type: "text", text }] };
|
|
733
878
|
}
|
|
734
879
|
case "screenshot": {
|
|
735
|
-
const result = await screenshot(transport, { session_id: a.session_id
|
|
880
|
+
const result = await screenshot(transport, { session_id: a.session_id });
|
|
736
881
|
if (result.type === "image") {
|
|
737
882
|
return {
|
|
738
883
|
content: [{ type: "image", data: result.data, mimeType: result.mimeType }]
|
|
@@ -753,6 +898,14 @@ async function startMcpServer(opts) {
|
|
|
753
898
|
});
|
|
754
899
|
return { content: [{ type: "text", text }] };
|
|
755
900
|
}
|
|
901
|
+
case "stop_session": {
|
|
902
|
+
const text = await stopSession(transport, {
|
|
903
|
+
session_id: a.session_id,
|
|
904
|
+
daemon_id: a.daemon_id,
|
|
905
|
+
type: a.type
|
|
906
|
+
});
|
|
907
|
+
return { content: [{ type: "text", text }] };
|
|
908
|
+
}
|
|
756
909
|
case "check_pending": {
|
|
757
910
|
const text = await checkPending(transport, { daemon_id: a.daemon_id, format: a.format });
|
|
758
911
|
return { content: [{ type: "text", text }] };
|
|
@@ -823,8 +976,8 @@ Environment variables:
|
|
|
823
976
|
ADHDEV_API_KEY API key (cloud mode)
|
|
824
977
|
ADHDEV_PASSWORD Daemon password (local mode)
|
|
825
978
|
|
|
826
|
-
Local mode tools: list_sessions, launch_session, check_pending, read_chat, send_chat, approve, git_status, screenshot
|
|
827
|
-
Cloud mode tools: list_sessions, launch_session, check_pending, read_chat, send_chat, approve, git_status
|
|
979
|
+
Local mode tools: list_daemons, list_sessions, launch_session, stop_session, check_pending, read_chat, send_chat, approve, git_status, screenshot
|
|
980
|
+
Cloud mode tools: list_daemons, list_sessions, launch_session, stop_session, check_pending, read_chat, send_chat, approve, git_status
|
|
828
981
|
`.trim());
|
|
829
982
|
}
|
|
830
983
|
startMcpServer(parseArgs(process.argv)).catch((err) => {
|