adhdev 0.9.55 → 0.9.57

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 CHANGED
@@ -14705,6 +14705,12 @@ var init_provider_cli_adapter = __esm({
14705
14705
  accumulatedRawBuffer = "";
14706
14706
  /** Current visible terminal screen snapshot */
14707
14707
  terminalScreen = new TerminalScreen(24, 80);
14708
+ static MAX_RESPONSE_BUFFER = 8e3;
14709
+ static MAX_RECENT_OUTPUT_BUFFER = 1e3;
14710
+ responseBufferDroppedChars = 0;
14711
+ recentOutputDroppedChars = 0;
14712
+ accumulatedBufferDroppedChars = 0;
14713
+ accumulatedRawBufferDroppedChars = 0;
14708
14714
  /** Max accumulated buffer size. Sized to comfortably hold a single long
14709
14715
  * Hermes turn (tool calls + reasoning + final bubble) without the
14710
14716
  * rolling window pushing the turn's ╭─ opening line out of view. */
@@ -14722,6 +14728,23 @@ var init_provider_cli_adapter = __esm({
14722
14728
  providerResolutionMeta;
14723
14729
  static FINISH_RETRY_DELAY_MS = 300;
14724
14730
  static MAX_FINISH_RETRIES = 2;
14731
+ getBufferState() {
14732
+ const build = (droppedChars, maxChars) => droppedChars > 0 ? { truncated: true, droppedChars, maxChars } : void 0;
14733
+ const responseBuffer = build(this.responseBufferDroppedChars, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
14734
+ const recentOutputBuffer = build(this.recentOutputDroppedChars, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
14735
+ const accumulatedBuffer = build(this.accumulatedBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
14736
+ const accumulatedRawBuffer = build(this.accumulatedRawBufferDroppedChars, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
14737
+ if (!responseBuffer && !recentOutputBuffer && !accumulatedBuffer && !accumulatedRawBuffer) return void 0;
14738
+ return {
14739
+ ...responseBuffer ? { responseBuffer } : {},
14740
+ ...recentOutputBuffer ? { recentOutputBuffer } : {},
14741
+ ...accumulatedBuffer ? { accumulatedBuffer } : {},
14742
+ ...accumulatedRawBuffer ? { accumulatedRawBuffer } : {}
14743
+ };
14744
+ }
14745
+ recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
14746
+ return Math.max(0, previousLength + appendedLength - nextLength);
14747
+ }
14725
14748
  buildCommittedMessagesActivitySignature() {
14726
14749
  const last = this.committedMessages[this.committedMessages.length - 1];
14727
14750
  return [
@@ -15087,7 +15110,9 @@ var init_provider_cli_adapter = __esm({
15087
15110
  this.scheduleStartupSettleCheck();
15088
15111
  }
15089
15112
  if (this.isWaitingForResponse && cleanData) {
15090
- this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, 8e3);
15113
+ const previousResponseLen = this.responseBuffer.length;
15114
+ this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, _ProviderCliAdapter.MAX_RESPONSE_BUFFER);
15115
+ this.responseBufferDroppedChars += this.recordBoundedAppendDrop(previousResponseLen, cleanData.length, this.responseBuffer.length);
15091
15116
  }
15092
15117
  if (cleanData.trim()) {
15093
15118
  if (this.serverConn) {
@@ -15096,14 +15121,19 @@ var init_provider_cli_adapter = __esm({
15096
15121
  this.logBuffer.push({ message: cleanData.trim(), level: "info" });
15097
15122
  }
15098
15123
  }
15124
+ const prevRecentLen = this.recentOutputBuffer.length;
15099
15125
  const prevAccumulatedLen = this.accumulatedBuffer.length;
15100
15126
  const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
15101
- this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, 1e3);
15127
+ this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
15102
15128
  this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
15103
15129
  this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
15130
+ const droppedRecent = this.recordBoundedAppendDrop(prevRecentLen, cleanData.length, this.recentOutputBuffer.length);
15131
+ const droppedClean = this.recordBoundedAppendDrop(prevAccumulatedLen, cleanData.length, this.accumulatedBuffer.length);
15132
+ const droppedRaw = this.recordBoundedAppendDrop(prevAccumulatedRawLen, rawData.length, this.accumulatedRawBuffer.length);
15133
+ this.recentOutputDroppedChars += droppedRecent;
15134
+ this.accumulatedBufferDroppedChars += droppedClean;
15135
+ this.accumulatedRawBufferDroppedChars += droppedRaw;
15104
15136
  if (this.currentTurnScope) {
15105
- const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
15106
- const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
15107
15137
  if (droppedClean > 0) {
15108
15138
  this.currentTurnScope.bufferStart = Math.max(0, this.currentTurnScope.bufferStart - droppedClean);
15109
15139
  }
@@ -15933,13 +15963,15 @@ var init_provider_cli_adapter = __esm({
15933
15963
  effectiveModal = parsedModal;
15934
15964
  }
15935
15965
  }
15966
+ const bufferState = this.getBufferState();
15936
15967
  return {
15937
15968
  status: effectiveStatus,
15938
15969
  messages: [...this.committedMessages],
15939
15970
  workingDir: this.workingDir,
15940
15971
  activeModal: effectiveModal,
15941
15972
  errorMessage: this.parseErrorMessage || void 0,
15942
- errorReason: this.parseErrorMessage ? "parse_error" : void 0
15973
+ errorReason: this.parseErrorMessage ? "parse_error" : void 0,
15974
+ ...bufferState ? { bufferState } : {}
15943
15975
  };
15944
15976
  }
15945
15977
  seedCommittedMessages(messages) {
@@ -16121,10 +16153,12 @@ var init_provider_cli_adapter = __esm({
16121
16153
  messages: hydratedMessages,
16122
16154
  activeModal: parsed.activeModal ?? this.activeModal,
16123
16155
  providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
16156
+ ...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
16124
16157
  ...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
16125
16158
  };
16126
16159
  } else {
16127
16160
  const messages = [...this.committedMessages];
16161
+ const bufferState = this.getBufferState();
16128
16162
  result = {
16129
16163
  id: "cli_session",
16130
16164
  status: this.currentStatus,
@@ -16135,7 +16169,8 @@ var init_provider_cli_adapter = __esm({
16135
16169
  index: typeof message.index === "number" ? message.index : index,
16136
16170
  receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
16137
16171
  })),
16138
- activeModal: this.activeModal
16172
+ activeModal: this.activeModal,
16173
+ ...bufferState ? { bufferState } : {}
16139
16174
  };
16140
16175
  }
16141
16176
  const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
@@ -35856,7 +35891,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
35856
35891
  resolvedDir,
35857
35892
  resolvedCliArgs,
35858
35893
  resolvedProvider,
35859
- {},
35894
+ this.providerLoader.getSettings(normalizedType),
35860
35895
  false,
35861
35896
  {
35862
35897
  providerSessionId: sessionBinding.providerSessionId,
@@ -38006,9 +38041,9 @@ function validateProviderDefinition(raw) {
38006
38041
  const typedProvider = provider;
38007
38042
  const controls = Array.isArray(provider.controls) ? provider.controls : [];
38008
38043
  if (category === "cli" || category === "acp") {
38009
- const spawn6 = provider.spawn;
38010
- const command = spawn6 && typeof spawn6 === "object" ? spawn6.command : void 0;
38011
- if (!spawn6 || typeof spawn6 !== "object") {
38044
+ const spawn7 = provider.spawn;
38045
+ const command = spawn7 && typeof spawn7 === "object" ? spawn7.command : void 0;
38046
+ if (!spawn7 || typeof spawn7 !== "object") {
38012
38047
  errors.push(`${String(category).toUpperCase()}/CLI providers must have spawn config`);
38013
38048
  } else if (typeof command !== "string" || !command.trim()) {
38014
38049
  errors.push("spawn.command is required");
@@ -46232,8 +46267,8 @@ async function handleAutoImplement(ctx, type, req, res) {
46232
46267
  fs14.writeFileSync(promptFile, prompt2, "utf-8");
46233
46268
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt2.length} chars)`);
46234
46269
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
46235
- const spawn6 = agentProvider?.spawn;
46236
- if (!spawn6?.command) {
46270
+ const spawn7 = agentProvider?.spawn;
46271
+ if (!spawn7?.command) {
46237
46272
  try {
46238
46273
  fs14.unlinkSync(promptFile);
46239
46274
  } catch {
@@ -46243,22 +46278,22 @@ async function handleAutoImplement(ctx, type, req, res) {
46243
46278
  }
46244
46279
  const agentCategory = agentProvider?.category;
46245
46280
  if (agentCategory === "acp") {
46246
- sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn6.command} ${(spawn6.args || []).join(" ")}` } });
46281
+ sendAutoImplSSE(ctx, { event: "progress", data: { function: "_init", status: "spawning", message: `Spawning ACP agent: ${spawn7.command} ${(spawn7.args || []).join(" ")}` } });
46247
46282
  ctx.autoImplStatus.running = true;
46248
46283
  ctx.autoImplStatus.type = type;
46249
46284
  const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
46250
46285
  const { Readable: Readable3, Writable: Writable3 } = await import("stream");
46251
46286
  const { spawn: spawnFn2 } = await import("child_process");
46252
- const acpArgs = [...spawn6.args || []];
46287
+ const acpArgs = [...spawn7.args || []];
46253
46288
  if (model) {
46254
46289
  acpArgs.push("--model", model);
46255
46290
  ctx.log(`Auto-implement ACP using model: ${model}`);
46256
46291
  }
46257
- const child2 = spawnFn2(spawn6.command, acpArgs, {
46292
+ const child2 = spawnFn2(spawn7.command, acpArgs, {
46258
46293
  cwd: providerDir,
46259
46294
  stdio: ["pipe", "pipe", "pipe"],
46260
- shell: spawn6.shell ?? false,
46261
- env: { ...process.env, ...spawn6.env || {} }
46295
+ shell: spawn7.shell ?? false,
46296
+ env: { ...process.env, ...spawn7.env || {} }
46262
46297
  });
46263
46298
  ctx.autoImplProcess = child2;
46264
46299
  child2.stderr?.on("data", (d) => {
@@ -46368,7 +46403,7 @@ async function handleAutoImplement(ctx, type, req, res) {
46368
46403
  ctx.json(res, 202, {
46369
46404
  started: true,
46370
46405
  type,
46371
- agent: spawn6.command,
46406
+ agent: spawn7.command,
46372
46407
  functions,
46373
46408
  providerDir,
46374
46409
  message: "ACP Auto-implement started. Connect to SSE for progress.",
@@ -46376,10 +46411,10 @@ async function handleAutoImplement(ctx, type, req, res) {
46376
46411
  });
46377
46412
  return;
46378
46413
  }
46379
- const command = spawn6.command;
46380
- const autoImpl = spawn6.autoImpl;
46414
+ const command = spawn7.command;
46415
+ const autoImpl = spawn7.autoImpl;
46381
46416
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
46382
- const baseArgs = [...spawn6.args || []].filter((a) => !interactiveFlags.includes(a));
46417
+ const baseArgs = [...spawn7.args || []].filter((a) => !interactiveFlags.includes(a));
46383
46418
  let shellCmd;
46384
46419
  const isWin = os24.platform() === "win32";
46385
46420
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
@@ -46426,7 +46461,7 @@ async function handleAutoImplement(ctx, type, req, res) {
46426
46461
  cols: 120,
46427
46462
  rows: 40,
46428
46463
  cwd: providerDir,
46429
- env: { ...process.env, ...spawn6.env || {} }
46464
+ env: { ...process.env, ...spawn7.env || {} }
46430
46465
  });
46431
46466
  isPty = true;
46432
46467
  } catch (err) {
@@ -46438,7 +46473,7 @@ async function handleAutoImplement(ctx, type, req, res) {
46438
46473
  stdio: ["pipe", "pipe", "pipe"],
46439
46474
  env: {
46440
46475
  ...process.env,
46441
- ...spawn6.env || {}
46476
+ ...spawn7.env || {}
46442
46477
  }
46443
46478
  });
46444
46479
  child.on("error", (err2) => {
@@ -47610,16 +47645,16 @@ var init_dev_server = __esm({
47610
47645
  this.json(res, 404, { error: `Provider not found: ${type}` });
47611
47646
  return;
47612
47647
  }
47613
- const spawn6 = provider.spawn;
47614
- if (!spawn6) {
47648
+ const spawn7 = provider.spawn;
47649
+ if (!spawn7) {
47615
47650
  this.json(res, 400, { error: `Provider ${type} has no spawn config` });
47616
47651
  return;
47617
47652
  }
47618
47653
  const { spawn: spawnFn } = await import("child_process");
47619
47654
  const start = Date.now();
47620
47655
  try {
47621
- const child = spawnFn(spawn6.command, [...spawn6.args || []], {
47622
- shell: spawn6.shell ?? false,
47656
+ const child = spawnFn(spawn7.command, [...spawn7.args || []], {
47657
+ shell: spawn7.shell ?? false,
47623
47658
  timeout: 5e3,
47624
47659
  stdio: ["pipe", "pipe", "pipe"]
47625
47660
  });
@@ -47651,7 +47686,7 @@ var init_dev_server = __esm({
47651
47686
  const elapsed = Date.now() - start;
47652
47687
  this.json(res, 200, {
47653
47688
  success: true,
47654
- command: `${spawn6.command} ${(spawn6.args || []).join(" ")}`,
47689
+ command: `${spawn7.command} ${(spawn7.args || []).join(" ")}`,
47655
47690
  elapsed,
47656
47691
  stdout: stdout.trim(),
47657
47692
  stderr: stderr.trim(),
@@ -47661,7 +47696,7 @@ var init_dev_server = __esm({
47661
47696
  const elapsed = Date.now() - start;
47662
47697
  this.json(res, 200, {
47663
47698
  success: false,
47664
- command: `${spawn6.command} ${(spawn6.args || []).join(" ")}`,
47699
+ command: `${spawn7.command} ${(spawn7.args || []).join(" ")}`,
47665
47700
  elapsed,
47666
47701
  error: e.message
47667
47702
  });
@@ -48124,20 +48159,20 @@ var init_dev_server = __esm({
48124
48159
  this.json(res, 404, { error: `Provider not found: ${type}` });
48125
48160
  return;
48126
48161
  }
48127
- const spawn6 = provider.spawn;
48128
- if (!spawn6) {
48162
+ const spawn7 = provider.spawn;
48163
+ if (!spawn7) {
48129
48164
  this.json(res, 400, { error: `Provider ${type} has no spawn config` });
48130
48165
  return;
48131
48166
  }
48132
48167
  const { spawn: spawnFn } = await import("child_process");
48133
48168
  const start = Date.now();
48134
48169
  try {
48135
- const args = [...spawn6.args || [], message];
48136
- const child = spawnFn(spawn6.command, args, {
48137
- shell: spawn6.shell ?? false,
48170
+ const args = [...spawn7.args || [], message];
48171
+ const child = spawnFn(spawn7.command, args, {
48172
+ shell: spawn7.shell ?? false,
48138
48173
  timeout,
48139
48174
  stdio: ["pipe", "pipe", "pipe"],
48140
- env: { ...process.env, ...spawn6.env || {} }
48175
+ env: { ...process.env, ...spawn7.env || {} }
48141
48176
  });
48142
48177
  let stdout = "";
48143
48178
  let stderr = "";
@@ -80944,6 +80979,58 @@ var init_server_connection = __esm({
80944
80979
  onStateChange(callback) {
80945
80980
  this.stateChangeCallbacks.push(callback);
80946
80981
  }
80982
+ /**
80983
+ * Send a command to another daemon owned by the same user, via server relay.
80984
+ * The server validates ownership before forwarding to the target daemon.
80985
+ *
80986
+ * Returns the command result or throws on timeout / auth failure.
80987
+ */
80988
+ sendMeshCommand(targetDaemonId, command, args = {}, timeoutMs = 3e4) {
80989
+ return new Promise((resolve21, reject) => {
80990
+ const requestId = `mesh_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
80991
+ const timer = setTimeout(() => {
80992
+ this.off("daemon_mesh_result", handler);
80993
+ reject(new Error(`Mesh command timed out after ${timeoutMs}ms`));
80994
+ }, timeoutMs);
80995
+ const handler = (msg) => {
80996
+ if (msg.payload?.requestId !== requestId) return;
80997
+ this.off("daemon_mesh_result", handler);
80998
+ clearTimeout(timer);
80999
+ if (msg.payload?.success === false) {
81000
+ reject(new Error(msg.payload?.error ?? "Mesh command failed"));
81001
+ } else {
81002
+ resolve21(msg.payload?.result);
81003
+ }
81004
+ };
81005
+ this.on("daemon_mesh_result", handler);
81006
+ const sent = this.ws?.readyState === 1 && (() => {
81007
+ try {
81008
+ this.ws.send(JSON.stringify({
81009
+ type: "daemon_mesh_command",
81010
+ requestId,
81011
+ targetDaemonId,
81012
+ command,
81013
+ args,
81014
+ timestamp: Date.now()
81015
+ }));
81016
+ return true;
81017
+ } catch {
81018
+ return false;
81019
+ }
81020
+ })();
81021
+ if (!sent) {
81022
+ clearTimeout(timer);
81023
+ this.off("daemon_mesh_result", handler);
81024
+ reject(new Error("Not connected to server"));
81025
+ }
81026
+ });
81027
+ }
81028
+ off(type, handler) {
81029
+ const handlers = this.messageHandlers.get(type);
81030
+ if (!handlers) return;
81031
+ const idx = handlers.indexOf(handler);
81032
+ if (idx !== -1) handlers.splice(idx, 1);
81033
+ }
80947
81034
  getState() {
80948
81035
  return this.state;
80949
81036
  }
@@ -81253,7 +81340,7 @@ function sendToPeer(peer, data) {
81253
81340
  return false;
81254
81341
  }
81255
81342
  const json2 = JSON.stringify(data);
81256
- if (messageType === "command_result" && json2.length > MAX_INLINE_JSON_MESSAGE_CHARS) {
81343
+ if (messageType === "command_result" && Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_CHARS) {
81257
81344
  return sendChunkedCommandResult(peer, peerId, requestId, json2);
81258
81345
  }
81259
81346
  try {
@@ -81266,21 +81353,51 @@ function sendToPeer(peer, data) {
81266
81353
  return false;
81267
81354
  }
81268
81355
  }
81356
+ function buildCommandResultChunkEnvelope(requestId, chunkId, index, total, data) {
81357
+ return JSON.stringify({
81358
+ type: "command_result_chunk",
81359
+ id: requestId,
81360
+ chunkId,
81361
+ index,
81362
+ total,
81363
+ data
81364
+ });
81365
+ }
81366
+ function splitJsonIntoCommandResultChunks(json2, requestId, chunkId) {
81367
+ const chunks = [];
81368
+ let offset = 0;
81369
+ while (offset < json2.length) {
81370
+ let end = Math.min(json2.length, offset + JSON_CHUNK_PAYLOAD_CHARS);
81371
+ while (end > offset) {
81372
+ const candidate = json2.slice(offset, end);
81373
+ const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, chunks.length, MAX_JSON_CHUNKS, candidate);
81374
+ if (Buffer.byteLength(envelope, "utf8") <= MAX_INLINE_JSON_MESSAGE_BYTES) break;
81375
+ end = offset + Math.max(1, Math.floor((end - offset) * 0.8));
81376
+ }
81377
+ chunks.push(json2.slice(offset, end));
81378
+ if (chunks.length > MAX_JSON_CHUNKS) return [];
81379
+ offset = end;
81380
+ }
81381
+ return chunks;
81382
+ }
81269
81383
  function sendChunkedCommandResult(peer, peerId, requestId, json2) {
81270
81384
  const chunkId = requestId || `command_result_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
81271
- const total = Math.ceil(json2.length / JSON_CHUNK_PAYLOAD_CHARS);
81385
+ const chunks = splitJsonIntoCommandResultChunks(json2, requestId, chunkId);
81386
+ const total = chunks.length;
81387
+ if (total === 0 || total > MAX_JSON_CHUNKS) {
81388
+ log(`command_result send failed: peer=${peerId} id=${requestId || "-"} reason=too_many_chunks chunks=${total || "unknown"}`);
81389
+ return false;
81390
+ }
81272
81391
  logDebug(`command_result chunked: peer=${peerId} id=${requestId || "-"} chars=${json2.length} chunks=${total}`);
81273
81392
  for (let index = 0; index < total; index += 1) {
81274
- const chunk = json2.slice(index * JSON_CHUNK_PAYLOAD_CHARS, (index + 1) * JSON_CHUNK_PAYLOAD_CHARS);
81393
+ const chunk = chunks[index] || "";
81275
81394
  try {
81276
- peer.dataChannel?.sendMessage(JSON.stringify({
81277
- type: "command_result_chunk",
81278
- id: requestId,
81279
- chunkId,
81280
- index,
81281
- total,
81282
- data: chunk
81283
- }));
81395
+ const envelope = buildCommandResultChunkEnvelope(requestId, chunkId, index, total, chunk);
81396
+ if (Buffer.byteLength(envelope, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES) {
81397
+ log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} reason=chunk_too_large`);
81398
+ return false;
81399
+ }
81400
+ peer.dataChannel?.sendMessage(envelope);
81284
81401
  } catch (error48) {
81285
81402
  log(`command_result send failed: peer=${peerId} id=${requestId || "-"} chunk=${index + 1}/${total} error=${error48?.message || error48}`);
81286
81403
  return false;
@@ -81288,10 +81405,58 @@ function sendChunkedCommandResult(peer, peerId, requestId, json2) {
81288
81405
  }
81289
81406
  return true;
81290
81407
  }
81408
+ function parseChunkedJsonMessage(peerId, parsed) {
81409
+ const chunkType = typeof parsed?.type === "string" ? parsed.type : "";
81410
+ if (!chunkType.endsWith("_chunk")) return parsed;
81411
+ const chunkId = typeof parsed?.chunkId === "string" ? parsed.chunkId : "";
81412
+ const id = typeof parsed?.id === "string" ? parsed.id : "";
81413
+ const index = Number(parsed?.index);
81414
+ const total = Number(parsed?.total);
81415
+ const data = typeof parsed?.data === "string" ? parsed.data : "";
81416
+ if (!chunkId || !Number.isInteger(index) || !Number.isInteger(total) || index < 0 || total <= 0 || total > MAX_JSON_CHUNKS || index >= total || !data) {
81417
+ log(`chunked JSON ignored: peer=${peerId} type=${chunkType || "unknown"} reason=malformed`);
81418
+ return null;
81419
+ }
81420
+ const now = Date.now();
81421
+ incomingJsonChunks.forEach((entry2, key2) => {
81422
+ if (now - entry2.createdAt > JSON_CHUNK_TTL_MS) incomingJsonChunks.delete(key2);
81423
+ });
81424
+ const key = `${peerId}:${chunkId}`;
81425
+ let entry = incomingJsonChunks.get(key);
81426
+ if (!entry || entry.total !== total || entry.type !== chunkType) {
81427
+ entry = { total, chunks: new Array(total).fill(""), received: 0, createdAt: now, type: chunkType, id };
81428
+ incomingJsonChunks.set(key, entry);
81429
+ }
81430
+ if (!entry.chunks[index]) {
81431
+ entry.chunks[index] = data;
81432
+ entry.received += 1;
81433
+ }
81434
+ if (entry.received < entry.total) return null;
81435
+ incomingJsonChunks.delete(key);
81436
+ try {
81437
+ return JSON.parse(entry.chunks.join(""));
81438
+ } catch (error48) {
81439
+ log(`chunked JSON parse failed: peer=${peerId} type=${chunkType} id=${entry.id || "-"} error=${error48?.message || error48}`);
81440
+ return CHUNK_PARSE_FAILED;
81441
+ }
81442
+ }
81291
81443
  function routeDataChannelMessage(peerId, msg, peers, handlers) {
81292
81444
  const text = typeof msg === "string" ? msg : msg.toString("utf-8");
81293
81445
  try {
81294
- const parsed = JSON.parse(text);
81446
+ let parsed = JSON.parse(text);
81447
+ const chunked = parseChunkedJsonMessage(peerId, parsed);
81448
+ if (chunked === null) return;
81449
+ if (chunked === CHUNK_PARSE_FAILED) {
81450
+ const peer = peers.get(peerId);
81451
+ const id = typeof parsed?.id === "string" ? parsed.id : "";
81452
+ if (parsed?.type === "command_chunk") {
81453
+ sendToPeer(peer, { type: "command_result", id, success: false, error: "Failed to reassemble chunked command" });
81454
+ } else if (id) {
81455
+ sendToPeer(peer, { id, type: "response", success: false, error: "Failed to reassemble chunked request" });
81456
+ }
81457
+ return;
81458
+ }
81459
+ parsed = chunked;
81295
81460
  if (parsed.type !== "command" && parsed.type !== "pty_input" && parsed.type !== "pty_resize" && parsed.type !== "ping" && parsed.type !== "pong") {
81296
81461
  logDebug(`Files message from peer ${peerId}: type=${parsed.type}`);
81297
81462
  }
@@ -81587,7 +81752,7 @@ async function handleFileRequest(peerId, req, peers, handlers) {
81587
81752
  }
81588
81753
  sendToPeer(peer, response);
81589
81754
  }
81590
- var MAX_INLINE_JSON_MESSAGE_CHARS, JSON_CHUNK_PAYLOAD_CHARS;
81755
+ var MAX_INLINE_JSON_MESSAGE_CHARS, MAX_INLINE_JSON_MESSAGE_BYTES, JSON_CHUNK_PAYLOAD_CHARS, JSON_CHUNK_TTL_MS, MAX_JSON_CHUNKS, CHUNK_PARSE_FAILED, incomingJsonChunks;
81591
81756
  var init_data_channel_router = __esm({
81592
81757
  "src/daemon-p2p/data-channel-router.ts"() {
81593
81758
  "use strict";
@@ -81595,18 +81760,23 @@ var init_data_channel_router = __esm({
81595
81760
  init_permission();
81596
81761
  init_log();
81597
81762
  MAX_INLINE_JSON_MESSAGE_CHARS = 6e4;
81598
- JSON_CHUNK_PAYLOAD_CHARS = 32e3;
81763
+ MAX_INLINE_JSON_MESSAGE_BYTES = 6e4;
81764
+ JSON_CHUNK_PAYLOAD_CHARS = 16e3;
81765
+ JSON_CHUNK_TTL_MS = 6e4;
81766
+ MAX_JSON_CHUNKS = 1024;
81767
+ CHUNK_PARSE_FAILED = /* @__PURE__ */ Symbol("chunk_parse_failed");
81768
+ incomingJsonChunks = /* @__PURE__ */ new Map();
81599
81769
  }
81600
81770
  });
81601
81771
 
81602
81772
  // src/daemon-p2p/screenshot-sender.ts
81603
- var CHUNK_SIZE, MAX_INLINE_JSON_MESSAGE_BYTES, JSON_CHUNK_PAYLOAD_CHARS2, ScreenshotSender;
81773
+ var CHUNK_SIZE, MAX_INLINE_JSON_MESSAGE_BYTES2, JSON_CHUNK_PAYLOAD_CHARS2, ScreenshotSender;
81604
81774
  var init_screenshot_sender = __esm({
81605
81775
  "src/daemon-p2p/screenshot-sender.ts"() {
81606
81776
  "use strict";
81607
81777
  init_log();
81608
81778
  CHUNK_SIZE = 6e4;
81609
- MAX_INLINE_JSON_MESSAGE_BYTES = 6e4;
81779
+ MAX_INLINE_JSON_MESSAGE_BYTES2 = 6e4;
81610
81780
  JSON_CHUNK_PAYLOAD_CHARS2 = 16e3;
81611
81781
  ScreenshotSender = class {
81612
81782
  _ssDebugDone = false;
@@ -81650,7 +81820,7 @@ var init_screenshot_sender = __esm({
81650
81820
  type: "topic_update",
81651
81821
  update
81652
81822
  });
81653
- if (Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES) {
81823
+ if (Buffer.byteLength(json2, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
81654
81824
  return this.sendChunkedTopicUpdate(peer, update, json2);
81655
81825
  }
81656
81826
  try {
@@ -81689,6 +81859,10 @@ var init_screenshot_sender = __esm({
81689
81859
  let sentAny = false;
81690
81860
  for (const peer of peers.values()) {
81691
81861
  if (peer.state !== "connected" || !peer.dataChannel?.isOpen()) continue;
81862
+ if (Buffer.byteLength(msg, "utf8") > MAX_INLINE_JSON_MESSAGE_BYTES2) {
81863
+ if (this.sendChunkedSessionOutput(peer, sessionId, msg)) sentAny = true;
81864
+ continue;
81865
+ }
81692
81866
  try {
81693
81867
  peer.dataChannel.sendMessage(msg);
81694
81868
  sentAny = true;
@@ -81697,6 +81871,27 @@ var init_screenshot_sender = __esm({
81697
81871
  }
81698
81872
  return sentAny;
81699
81873
  }
81874
+ sendChunkedSessionOutput(peer, sessionId, json2) {
81875
+ const chunkId = `session_output:${sessionId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`;
81876
+ const total = Math.ceil(json2.length / JSON_CHUNK_PAYLOAD_CHARS2);
81877
+ logDebug(`session_output chunked: peer=${peer.peerId || "unknown"} sessionId=${sessionId || "-"} chars=${json2.length} chunks=${total}`);
81878
+ for (let index = 0; index < total; index += 1) {
81879
+ const chunk = json2.slice(index * JSON_CHUNK_PAYLOAD_CHARS2, (index + 1) * JSON_CHUNK_PAYLOAD_CHARS2);
81880
+ try {
81881
+ peer.dataChannel?.sendMessage(JSON.stringify({
81882
+ type: "session_output_chunk",
81883
+ sessionId,
81884
+ chunkId,
81885
+ index,
81886
+ total,
81887
+ data: chunk
81888
+ }));
81889
+ } catch {
81890
+ return false;
81891
+ }
81892
+ }
81893
+ return true;
81894
+ }
81700
81895
  sendScreenshot(peers, base64Data, targetSessionId) {
81701
81896
  const buffer = Buffer.from(base64Data, "base64");
81702
81897
  return this.sendScreenshotBuffer(peers, buffer, targetSessionId);
@@ -89792,6 +89987,64 @@ var init_session_host_controller = __esm({
89792
89987
  }
89793
89988
  });
89794
89989
 
89990
+ // src/daemon-mesh-manager.ts
89991
+ var daemon_mesh_manager_exports = {};
89992
+ __export(daemon_mesh_manager_exports, {
89993
+ DaemonMeshManager: () => DaemonMeshManager
89994
+ });
89995
+ function interpolateArgs(args, context) {
89996
+ const result = {};
89997
+ for (const [k, v] of Object.entries(args)) {
89998
+ result[k] = typeof v === "string" ? interpolateString(v, context) : v;
89999
+ }
90000
+ return result;
90001
+ }
90002
+ function interpolateString(template, ctx) {
90003
+ return template.replace(/\{\{(\w+)\}\}/g, (_2, key) => {
90004
+ const val = ctx[key];
90005
+ return val !== void 0 ? String(val) : `{{${key}}}`;
90006
+ });
90007
+ }
90008
+ var DaemonMeshManager;
90009
+ var init_daemon_mesh_manager = __esm({
90010
+ "src/daemon-mesh-manager.ts"() {
90011
+ "use strict";
90012
+ init_src();
90013
+ DaemonMeshManager = class {
90014
+ rules = [];
90015
+ serverConn;
90016
+ constructor(serverConn) {
90017
+ this.serverConn = serverConn;
90018
+ }
90019
+ setRules(rules) {
90020
+ this.rules = rules;
90021
+ LOG.info("Mesh", `[Mesh] ${rules.length} rule(s) loaded`);
90022
+ }
90023
+ async emit(event) {
90024
+ const matching = this.rules.filter((r) => r.trigger === event.trigger);
90025
+ if (matching.length === 0) return;
90026
+ await Promise.allSettled(
90027
+ matching.map((rule) => this.executeRule(rule, event.context ?? {}))
90028
+ );
90029
+ }
90030
+ async executeRule(rule, context) {
90031
+ const args = interpolateArgs(rule.args ?? {}, context);
90032
+ try {
90033
+ LOG.info("Mesh", `[Mesh] Relaying '${rule.command}' \u2192 ${rule.targetDaemonId.slice(0, 12)}\u2026`);
90034
+ await this.serverConn.sendMeshCommand(rule.targetDaemonId, rule.command, args);
90035
+ LOG.info("Mesh", `[Mesh] Relay '${rule.command}' complete`);
90036
+ } catch (err) {
90037
+ LOG.warn("Mesh", `[Mesh] Relay '${rule.command}' failed: ${err?.message ?? err}`);
90038
+ }
90039
+ }
90040
+ /** Convenience: send a one-off mesh command without a rule. */
90041
+ async sendCommand(targetDaemonId, command, args = {}) {
90042
+ return this.serverConn.sendMeshCommand(targetDaemonId, command, args);
90043
+ }
90044
+ };
90045
+ }
90046
+ });
90047
+
89795
90048
  // src/adhdev-daemon.ts
89796
90049
  var adhdev_daemon_exports = {};
89797
90050
  __export(adhdev_daemon_exports, {
@@ -90036,13 +90289,14 @@ var init_adhdev_daemon = __esm({
90036
90289
  init_version();
90037
90290
  init_src();
90038
90291
  init_runtime_defaults();
90039
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.55" });
90292
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.57" });
90040
90293
  AdhdevDaemon = class _AdhdevDaemon {
90041
90294
  localHttpServer = null;
90042
90295
  localWss = null;
90043
90296
  localClients = /* @__PURE__ */ new Set();
90044
90297
  serverConn = null;
90045
90298
  p2p = null;
90299
+ meshManager = null;
90046
90300
  screenshotController = null;
90047
90301
  statusReporter = null;
90048
90302
  topicSubscriptionTimer = null;
@@ -90626,6 +90880,12 @@ ${err?.stack || ""}`);
90626
90880
  }
90627
90881
  });
90628
90882
  this.p2p = new DaemonP2PSender(this.serverConn);
90883
+ const { DaemonMeshManager: DaemonMeshManager2 } = await Promise.resolve().then(() => (init_daemon_mesh_manager(), daemon_mesh_manager_exports));
90884
+ this.meshManager = new DaemonMeshManager2(this.serverConn);
90885
+ const meshRules = config2.meshRules;
90886
+ if (Array.isArray(meshRules) && meshRules.length > 0) {
90887
+ this.meshManager.setRules(meshRules);
90888
+ }
90629
90889
  if (this.p2p.isAvailable) {
90630
90890
  console.log(source_default.green(" \u{1F517} P2P available (node-datachannel)"));
90631
90891
  this.p2p.onInput(async (event) => {
@@ -90964,6 +91224,16 @@ ${err?.stack || ""}`);
90964
91224
  if (cmdType.startsWith("git_")) {
90965
91225
  void this.flushP2PWorkspaceGitSubscriptions();
90966
91226
  }
91227
+ if (cmdType === "git_checkpoint" && routed.success && this.meshManager) {
91228
+ void this.meshManager.emit({
91229
+ trigger: "git_checkpoint_complete",
91230
+ context: {
91231
+ workspace: String(normalizedData.workspace ?? ""),
91232
+ checkpoint_message: routed.checkpoint?.message ?? String(normalizedData.message ?? ""),
91233
+ commit: routed.checkpoint?.commit ?? ""
91234
+ }
91235
+ });
91236
+ }
90967
91237
  return { ...routed, interactionId };
90968
91238
  } catch (e) {
90969
91239
  logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", interactionId, success: false, error: e.message, durationMs: Date.now() - cmdStart });
@@ -93674,9 +93944,9 @@ async function requestSessionHostDirect(request) {
93674
93944
  }
93675
93945
  }
93676
93946
  async function runRuntimeLaunchSpec(spec) {
93677
- const { spawn: spawn6 } = await import("child_process");
93947
+ const { spawn: spawn7 } = await import("child_process");
93678
93948
  return await new Promise((resolve21, reject) => {
93679
- const child = spawn6(spec.command, spec.args, {
93949
+ const child = spawn7(spec.command, spec.args, {
93680
93950
  stdio: "inherit",
93681
93951
  env: spec.env,
93682
93952
  shell: process.platform === "win32" && spec.command !== process.execPath
@@ -93945,7 +94215,7 @@ async function handleTraceCommand(options) {
93945
94215
  async function runDaemonUpgrade(options, pkgVersion3) {
93946
94216
  const { isDaemonRunning: isDaemonRunning2, stopDaemon: stopDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
93947
94217
  const { stopManagedSessionHostProcess: stopManagedSessionHostProcess2 } = await Promise.resolve().then(() => (init_session_host(), session_host_exports));
93948
- const { execSync: execSync8, spawn: spawn6 } = await import("child_process");
94218
+ const { execSync: execSync8, spawn: spawn7 } = await import("child_process");
93949
94219
  const fsMod = await import("fs");
93950
94220
  const pathMod = await import("path");
93951
94221
  console.log(source_default.bold("\n \u{1F504} ADHDev Upgrade\n"));
@@ -94029,7 +94299,7 @@ async function runDaemonUpgrade(options, pkgVersion3) {
94029
94299
  await new Promise((r) => setTimeout(r, 2e3));
94030
94300
  stopManagedSessionHostProcess2();
94031
94301
  await new Promise((r) => setTimeout(r, 500));
94032
- const child = spawn6(process.execPath, [process.argv[1], "daemon", "-p", DEFAULT_DAEMON_PORT_TEXT], {
94302
+ const child = spawn7(process.execPath, [process.argv[1], "daemon", "-p", DEFAULT_DAEMON_PORT_TEXT], {
94033
94303
  detached: true,
94034
94304
  stdio: "ignore",
94035
94305
  windowsHide: true,
@@ -94076,7 +94346,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
94076
94346
  }
94077
94347
  });
94078
94348
  program2.command("standalone").description("\u{1F5A5}\uFE0F Start ADHDev Standalone Server (Local Dashboard & Embedded Daemon)").option("-p, --port <port>", "Local HTTP/WS server port", "3847").option("--host <host>", "Bind to specific host (use 0.0.0.0 for LAN access)").option("--no-open", "Prevent opening browser automatically").option("--token <token>", "Require token authentication").option("--dev", "Enable Dev Mode").action(async (options) => {
94079
- const { spawn: spawn6, execSync: execSync8 } = await import("child_process");
94349
+ const { spawn: spawn7, execSync: execSync8 } = await import("child_process");
94080
94350
  const { DEFAULT_STANDALONE_SESSION_HOST_APP_NAME: DEFAULT_STANDALONE_SESSION_HOST_APP_NAME2, resolveSessionHostAppNameResolution: resolveSessionHostAppNameResolution2 } = await Promise.resolve().then(() => (init_src(), src_exports));
94081
94351
  console.log(source_default.cyan("\n Starting ADHDev Standalone Server..."));
94082
94352
  const args = [];
@@ -94105,7 +94375,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
94105
94375
  }
94106
94376
  console.log(source_default.gray(` Session host namespace: ${sessionHostName}${sessionHostResolution.source === "default" ? " (default isolated standalone namespace)" : sessionHostResolution.source === "explicit" ? " (from ADHDEV_SESSION_HOST_NAME)" : " (auto-corrected for standalone isolation)"}`));
94107
94377
  const spawnArgs = bin === "npx" ? npxArgs : args;
94108
- const child = spawn6(bin, spawnArgs, {
94378
+ const child = spawn7(bin, spawnArgs, {
94109
94379
  stdio: "inherit",
94110
94380
  shell: process.platform === "win32",
94111
94381
  env: standaloneEnv
@@ -94579,7 +94849,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
94579
94849
  hideCommand(program2.command("daemon:restart").description("Restart ADHDev Daemon (stop \u2192 start)").option("-p, --port <port>", "Local WS server port", DEFAULT_DAEMON_PORT_TEXT).option("--server <url>", "Override server URL").option("--dev", "Enable Dev Mode").action(async (options) => {
94580
94850
  const { stopDaemon: stopDaemon2, isDaemonRunning: isDaemonRunning2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
94581
94851
  const { stopManagedSessionHostProcess: stopManagedSessionHostProcess2 } = await Promise.resolve().then(() => (init_session_host(), session_host_exports));
94582
- const { spawn: spawn6 } = await import("child_process");
94852
+ const { spawn: spawn7 } = await import("child_process");
94583
94853
  if (isDaemonRunning2({ port: parseInt(options.port, 10) || DEFAULT_DAEMON_PORT })) {
94584
94854
  console.log(source_default.yellow("\n Stopping existing daemon..."));
94585
94855
  stopDaemon2({ port: parseInt(options.port, 10) || DEFAULT_DAEMON_PORT });
@@ -94591,7 +94861,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
94591
94861
  const args = ["daemon", "-p", options.port || DEFAULT_DAEMON_PORT_TEXT];
94592
94862
  if (options.server) args.push("--server", options.server);
94593
94863
  if (options.dev) args.push("--dev");
94594
- const child = spawn6(process.execPath, [process.argv[1], ...args], {
94864
+ const child = spawn7(process.execPath, [process.argv[1], ...args], {
94595
94865
  detached: true,
94596
94866
  stdio: "ignore",
94597
94867
  windowsHide: true,
@@ -96595,6 +96865,64 @@ function registerCdpCommands(program2) {
96595
96865
  });
96596
96866
  }
96597
96867
 
96868
+ // src/cli/mcp-commands.ts
96869
+ var import_node_child_process3 = require("child_process");
96870
+ var import_node_module3 = require("module");
96871
+ init_source();
96872
+ function registerMcpCommands(program2) {
96873
+ program2.command("mcp").description("Start an MCP server to expose IDE agents as tools (for Claude Desktop, etc.)").option("--api-key <key>", "ADHDev cloud API key (switches to cloud mode)").option("--port <n>", "Standalone daemon port (default: 3847)", "3847").option("--password <pass>", "Standalone daemon password (if set)").option("--base-url <url>", "Override cloud API base URL").addHelpText("after", `
96874
+ Examples:
96875
+ adhdev mcp Local mode (requires: adhdev standalone)
96876
+ adhdev mcp --api-key adk_xxx Cloud mode (no local daemon needed)
96877
+
96878
+ Claude Desktop config (~/.claude_desktop_config.json):
96879
+ {
96880
+ "mcpServers": {
96881
+ "adhdev": {
96882
+ "command": "adhdev",
96883
+ "args": ["mcp"]
96884
+ }
96885
+ }
96886
+ }
96887
+
96888
+ Tools available (local): list_sessions, read_chat, send_chat, approve, screenshot, git_status
96889
+ Tools available (cloud): list_sessions, read_chat, send_chat, approve
96890
+ `).action(async (opts) => {
96891
+ const mcpBin = resolveMcpBin();
96892
+ if (!mcpBin) {
96893
+ console.error(source_default.red("\u2717 @adhdev/mcp-server not found. Run: npm install -g @adhdev/mcp-server"));
96894
+ process.exit(1);
96895
+ }
96896
+ const args = [];
96897
+ if (opts.apiKey) args.push("--api-key", opts.apiKey);
96898
+ if (opts.port && opts.port !== "3847") args.push("--port", opts.port);
96899
+ if (opts.password) args.push("--password", opts.password);
96900
+ if (opts.baseUrl) args.push("--base-url", opts.baseUrl);
96901
+ const env3 = { ...process.env };
96902
+ if (opts.apiKey) env3.ADHDEV_API_KEY = opts.apiKey;
96903
+ if (opts.password) env3.ADHDEV_PASSWORD = opts.password;
96904
+ const child = (0, import_node_child_process3.spawn)(process.execPath, [mcpBin, ...args], {
96905
+ stdio: "inherit",
96906
+ env: env3
96907
+ });
96908
+ child.on("error", (err) => {
96909
+ console.error(source_default.red(`\u2717 MCP server error: ${err.message}`));
96910
+ process.exit(1);
96911
+ });
96912
+ child.on("exit", (code) => {
96913
+ process.exit(code ?? 0);
96914
+ });
96915
+ });
96916
+ }
96917
+ function resolveMcpBin() {
96918
+ try {
96919
+ const req = (0, import_node_module3.createRequire)(__filename);
96920
+ return req.resolve("@adhdev/mcp-server");
96921
+ } catch {
96922
+ return null;
96923
+ }
96924
+ }
96925
+
96598
96926
  // src/cli/index.ts
96599
96927
  init_version();
96600
96928
  var pkgVersion2 = resolvePackageVersion();
@@ -96614,6 +96942,7 @@ registerDoctorCommands(program, pkgVersion2);
96614
96942
  registerProviderCommands(program);
96615
96943
  registerCdpCommands(program);
96616
96944
  registerServiceCommands(program);
96945
+ registerMcpCommands(program);
96617
96946
  void (async () => {
96618
96947
  const helperMode = await maybeRunDaemonUpgradeHelperFromEnv();
96619
96948
  if (helperMode) {
@@ -96640,6 +96969,7 @@ void (async () => {
96640
96969
  console.log(source_default.gray(" Advanced tools:"));
96641
96970
  console.log(source_default.gray(" adhdev trace --category session_host \u2014 Inspect structured daemon trace"));
96642
96971
  console.log(source_default.gray(" adhdev service \u2014 Manage OS background auto-start service"));
96972
+ console.log(source_default.gray(" adhdev mcp \u2014 Start MCP server (expose agents to Claude Desktop, etc.)"));
96643
96973
  console.log(source_default.gray(" adhdev provider ... \u2014 Provider development commands"));
96644
96974
  console.log(source_default.gray(" adhdev cdp ... \u2014 CDP debugging tools"));
96645
96975
  console.log();