@adhdev/daemon-standalone 0.9.77-rc.3 → 0.9.77-rc.30

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 CHANGED
@@ -32530,22 +32530,47 @@ Follow these recovery rules:
32530
32530
  ].filter(Boolean);
32531
32531
  return parts.length > 0 ? ` (${parts.join("; ")})` : "";
32532
32532
  }
32533
+ function getMeshWithCache(components, meshId) {
32534
+ const localMesh = getMesh(meshId);
32535
+ if (localMesh) return localMesh;
32536
+ return components.router?.getCachedInlineMesh(meshId);
32537
+ }
32533
32538
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
32534
32539
  const task = claimNextTask(meshId, nodeId, sessionId);
32535
- if (!task) return false;
32540
+ if (!task) {
32541
+ return false;
32542
+ }
32536
32543
  LOG2.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
32544
+ const mesh = getMeshWithCache(components, meshId);
32545
+ const node = mesh?.nodes.find((n) => n.id === nodeId);
32546
+ if (node?.daemonId && components.dispatchMeshCommand) {
32547
+ const isLocalNode = components.cliManager.adapters.has(sessionId);
32548
+ if (!isLocalNode) {
32549
+ components.dispatchMeshCommand(node.daemonId, "agent_command", {
32550
+ targetSessionId: sessionId,
32551
+ cliType: providerType,
32552
+ action: "send_chat",
32553
+ message: task.message
32554
+ }).catch((e) => {
32555
+ LOG2.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
32556
+ updateTaskStatus(meshId, task.id, "failed");
32557
+ });
32558
+ return true;
32559
+ }
32560
+ }
32537
32561
  components.cliManager.handleCliCommand("agent_command", {
32538
32562
  targetSessionId: sessionId,
32539
32563
  cliType: providerType,
32540
32564
  action: "send_chat",
32541
- input: task.message
32565
+ message: task.message
32542
32566
  }).catch((e) => {
32543
- LOG2.error("MeshQueue", `Failed to dispatch task to node ${nodeId}: ${e?.message}`);
32567
+ LOG2.error("MeshQueue", `Failed to dispatch task locally to node ${nodeId}: ${e?.message}`);
32568
+ updateTaskStatus(meshId, task.id, "failed");
32544
32569
  });
32545
32570
  return true;
32546
32571
  }
32547
32572
  function triggerMeshQueue(components, meshId) {
32548
- const mesh = getMesh(meshId);
32573
+ const mesh = getMeshWithCache(components, meshId);
32549
32574
  if (!mesh) return;
32550
32575
  const cliInstances = components.instanceManager.getByCategory("cli");
32551
32576
  for (const inst of cliInstances) {
@@ -32562,6 +32587,15 @@ Follow these recovery rules:
32562
32587
  tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
32563
32588
  }
32564
32589
  }
32590
+ for (const [key, idle] of remoteIdleSessions.entries()) {
32591
+ const node = mesh.nodes.find((n) => n.id === idle.nodeId);
32592
+ if (node) {
32593
+ const assigned = tryAssignQueueTask(components, meshId, idle.nodeId, idle.sessionId, idle.providerType);
32594
+ if (assigned) {
32595
+ remoteIdleSessions.delete(key);
32596
+ }
32597
+ }
32598
+ }
32565
32599
  }
32566
32600
  function buildMeshSystemMessage(args) {
32567
32601
  const metadata = formatCompletionMetadata(args.metadataEvent);
@@ -32610,7 +32644,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
32610
32644
  function injectMeshSystemMessage(components, args) {
32611
32645
  if (args.event === "agent:generating_completed") {
32612
32646
  const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
32613
- const nodeId = readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
32647
+ const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
32614
32648
  const providerType = readNonEmptyString(args.metadataEvent.providerType);
32615
32649
  if (sessionId) {
32616
32650
  updateSessionTaskStatus(args.meshId, sessionId, "completed");
@@ -32620,8 +32654,31 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
32620
32654
  }, 500);
32621
32655
  }
32622
32656
  }
32657
+ } else if (args.event === "agent:ready") {
32658
+ const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
32659
+ const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
32660
+ const providerType = readNonEmptyString(args.metadataEvent.providerType);
32661
+ if (sessionId && nodeId && providerType) {
32662
+ remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
32663
+ setTimeout(() => {
32664
+ const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
32665
+ if (assigned) {
32666
+ remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
32667
+ }
32668
+ }, 500);
32669
+ }
32670
+ } else if (args.event === "agent:generating_started") {
32671
+ const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
32672
+ const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
32673
+ if (sessionId && nodeId) {
32674
+ remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
32675
+ }
32623
32676
  } else if (args.event === "agent:stopped") {
32624
32677
  const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
32678
+ const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
32679
+ if (sessionId && nodeId) {
32680
+ remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
32681
+ }
32625
32682
  if (sessionId) {
32626
32683
  updateSessionTaskStatus(args.meshId, sessionId, "failed");
32627
32684
  }
@@ -32631,7 +32688,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
32631
32688
  try {
32632
32689
  appendLedgerEntry(args.meshId, {
32633
32690
  kind: ledgerKind,
32634
- nodeId: readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
32691
+ nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
32635
32692
  sessionId: readNonEmptyString(args.metadataEvent.targetSessionId) || void 0,
32636
32693
  providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
32637
32694
  payload: {
@@ -32651,7 +32708,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
32651
32708
  const maxRetries = mesh?.policy?.maxTaskRetries ?? 1;
32652
32709
  recoveryContext = getSessionRecoveryContext(args.meshId, {
32653
32710
  sessionId: readNonEmptyString(args.metadataEvent.targetSessionId) || void 0,
32654
- nodeId: readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
32711
+ nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
32655
32712
  maxRetries
32656
32713
  });
32657
32714
  recoveryContext.failedProviderType = readNonEmptyString(args.metadataEvent.providerType) || null;
@@ -32746,6 +32803,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
32746
32803
  const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
32747
32804
  return injectMeshSystemMessage(components, {
32748
32805
  meshId,
32806
+ nodeId,
32749
32807
  nodeLabel,
32750
32808
  event: eventName,
32751
32809
  metadataEvent: {
@@ -32770,21 +32828,24 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
32770
32828
  const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
32771
32829
  const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
32772
32830
  if (!isMeshDelegate) return;
32773
- const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
32831
+ const mesh = meshIdFromRuntime ? getMeshWithCache(components, meshIdFromRuntime) : getMeshByRepo(workspace);
32774
32832
  const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
32775
32833
  if (!meshId) return;
32776
32834
  const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
32777
32835
  const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
32836
+ const resolvedNodeId = targetNode?.id || runtimeNodeId;
32778
32837
  const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
32779
32838
  injectMeshSystemMessage(components, {
32780
32839
  meshId,
32781
32840
  sourceInstanceId: instanceId,
32841
+ nodeId: resolvedNodeId,
32782
32842
  nodeLabel,
32783
32843
  event: event.event,
32784
32844
  metadataEvent: event
32785
32845
  });
32786
32846
  });
32787
32847
  }
32848
+ var remoteIdleSessions;
32788
32849
  var MAX_PENDING_EVENTS;
32789
32850
  var pendingMeshCoordinatorEvents;
32790
32851
  var MESH_COORDINATOR_EVENTS;
@@ -32796,12 +32857,14 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
32796
32857
  init_logger();
32797
32858
  init_mesh_ledger();
32798
32859
  init_mesh_work_queue();
32860
+ remoteIdleSessions = /* @__PURE__ */ new Map();
32799
32861
  MAX_PENDING_EVENTS = 50;
32800
32862
  pendingMeshCoordinatorEvents = [];
32801
32863
  MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
32802
32864
  "agent:generating_completed",
32803
32865
  "agent:waiting_approval",
32804
32866
  "agent:stopped",
32867
+ "agent:ready",
32805
32868
  "monitor:long_generating"
32806
32869
  ]);
32807
32870
  EVENT_TO_LEDGER_KIND = {
@@ -33914,6 +33977,8 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
33914
33977
  statusHistory = [];
33915
33978
  // ─── CLI Scripts (script-based parsing) ───
33916
33979
  cliScripts;
33980
+ /** Per-session opaque state object created by cliScripts.createState(), reset on stop. */
33981
+ scriptState = null;
33917
33982
  runtimeSettings = {};
33918
33983
  /** Full accumulated rendered PTY transcript for parser/readback use */
33919
33984
  accumulatedBuffer = "";
@@ -34095,6 +34160,7 @@ ${lastSnapshot}`;
34095
34160
  this.cliScripts = scripts;
34096
34161
  this.parsedStatusCache = null;
34097
34162
  this.parseErrorMessage = null;
34163
+ this.scriptState = typeof scripts.createState === "function" ? scripts.createState() : null;
34098
34164
  const scriptNames = listCliScriptNames(scripts);
34099
34165
  LOG2.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
34100
34166
  }
@@ -34212,6 +34278,7 @@ ${lastSnapshot}`;
34212
34278
  this.ready = false;
34213
34279
  this.startupParseGate = false;
34214
34280
  this.spawnAt = 0;
34281
+ this.scriptState = null;
34215
34282
  this.onStatusChange?.();
34216
34283
  });
34217
34284
  this.spawnAt = Date.now();
@@ -34985,7 +35052,7 @@ ${lastSnapshot}`;
34985
35052
  scope: this.currentTurnScope,
34986
35053
  runtimeSettings: this.runtimeSettings
34987
35054
  });
34988
- const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
35055
+ const session = this.cliScripts.parseSession(this.scriptState, { ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
34989
35056
  this.parseErrorMessage = null;
34990
35057
  return session && typeof session === "object" ? session : null;
34991
35058
  } catch (e) {
@@ -34999,7 +35066,7 @@ ${lastSnapshot}`;
34999
35066
  if (!this.cliScripts?.detectStatus) return null;
35000
35067
  try {
35001
35068
  const screenText = this.terminalScreen.getText();
35002
- const status = this.cliScripts.detectStatus({
35069
+ const status = this.cliScripts.detectStatus(this.scriptState, {
35003
35070
  tail: text.slice(-500),
35004
35071
  screenText,
35005
35072
  rawBuffer: this.accumulatedRawBuffer,
@@ -35018,7 +35085,7 @@ ${lastSnapshot}`;
35018
35085
  try {
35019
35086
  const screenText = this.terminalScreen.getText();
35020
35087
  const buffer = screenText || this.accumulatedBuffer;
35021
- return this.cliScripts.parseApproval({
35088
+ return this.cliScripts.parseApproval(this.scriptState, {
35022
35089
  buffer,
35023
35090
  screenText,
35024
35091
  rawBuffer: this.accumulatedRawBuffer,
@@ -35126,7 +35193,7 @@ ${lastSnapshot}`;
35126
35193
  scope: this.currentTurnScope,
35127
35194
  runtimeSettings: this.runtimeSettings
35128
35195
  });
35129
- return await Promise.resolve(fn2({
35196
+ return await Promise.resolve(fn2(this.scriptState, {
35130
35197
  ...input,
35131
35198
  args: args && typeof args === "object" ? { ...args } : {}
35132
35199
  }));
@@ -46296,11 +46363,13 @@ ${effect.notification.body || ""}`.trim();
46296
46363
  async function handlePtyInput(h, args) {
46297
46364
  const { cliType, data, targetSessionId } = args || {};
46298
46365
  if (!data) return { success: false, error: "data required" };
46366
+ const cleanData = typeof data === "string" ? data.replace(/\x1b\[[?>][0-9;]*c/g, "") : data;
46367
+ if (!cleanData) return { success: true };
46299
46368
  const adapter = h.getCliAdapter(targetSessionId || cliType);
46300
46369
  if (!adapter || typeof adapter.writeRaw !== "function") {
46301
46370
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
46302
46371
  }
46303
- await adapter.writeRaw(data);
46372
+ await adapter.writeRaw(cleanData);
46304
46373
  return { success: true };
46305
46374
  }
46306
46375
  function handlePtyResize(_h, args) {
@@ -47918,6 +47987,8 @@ ${effect.notification.body || ""}`.trim();
47918
47987
  this.completedDebounceTimer = null;
47919
47988
  }, 3e3);
47920
47989
  }
47990
+ } else if (newStatus === "idle" && this.lastStatus === "starting") {
47991
+ this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });
47921
47992
  } else if (newStatus === "stopped") {
47922
47993
  if (this.generatingDebounceTimer) {
47923
47994
  clearTimeout(this.generatingDebounceTimer);
@@ -49653,9 +49724,6 @@ ${rawInput}` : rawInput;
49653
49724
  const cliType = String(input.cliType || "").trim();
49654
49725
  const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
49655
49726
  const env2 = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
49656
- if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
49657
- cliArgs.unshift("--ignore-user-config");
49658
- }
49659
49727
  if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
49660
49728
  cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
49661
49729
  }
@@ -52970,6 +53038,22 @@ Run 'adhdev doctor' for detailed diagnostics.`
52970
53038
  if (!instructions || !template?.trim()) {
52971
53039
  return { kind: "unsupported", reason: "Provider manual MCP setup is missing instructions or template" };
52972
53040
  }
53041
+ const renderedTemplate = renderMeshCoordinatorTemplate(template, {
53042
+ meshId,
53043
+ workspace,
53044
+ serverName,
53045
+ adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
53046
+ });
53047
+ const isCliCommand = !renderedTemplate.trim().includes("\n") && !renderedTemplate.trim().startsWith("{");
53048
+ if (isCliCommand) {
53049
+ return {
53050
+ kind: "cli_command",
53051
+ serverName,
53052
+ command: renderedTemplate.trim(),
53053
+ requiresRestart: mcpConfig.requiresRestart === true,
53054
+ instructions
53055
+ };
53056
+ }
52973
53057
  return {
52974
53058
  kind: "manual",
52975
53059
  serverName,
@@ -52977,12 +53061,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
52977
53061
  configPathCommand: mcpConfig.configPathCommand,
52978
53062
  requiresRestart: mcpConfig.requiresRestart === true,
52979
53063
  instructions,
52980
- template: renderMeshCoordinatorTemplate(template, {
52981
- meshId,
52982
- workspace,
52983
- serverName,
52984
- adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
52985
- })
53064
+ template: renderedTemplate
52986
53065
  };
52987
53066
  }
52988
53067
  return {
@@ -55156,6 +55235,93 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
55156
55235
  meshCoordinatorSetup: coordinatorSetup
55157
55236
  };
55158
55237
  }
55238
+ if (coordinatorSetup.kind === "cli_command") {
55239
+ let cliCmdSystemPrompt = "";
55240
+ try {
55241
+ cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
55242
+ } catch (error48) {
55243
+ const message = error48?.message || String(error48);
55244
+ LOG2.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
55245
+ return {
55246
+ success: false,
55247
+ code: "mesh_coordinator_prompt_failed",
55248
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
55249
+ meshId,
55250
+ cliType,
55251
+ workspace
55252
+ };
55253
+ }
55254
+ try {
55255
+ const { execFileSync: execCmdSync } = await import("child_process");
55256
+ const cmdParts = coordinatorSetup.command.trim().split(/\s+/);
55257
+ const [regCmd, ...regArgs] = cmdParts;
55258
+ LOG2.info("MeshCoordinator", `Running MCP registration: ${coordinatorSetup.command}`);
55259
+ execCmdSync(regCmd, regArgs, { stdio: "pipe", timeout: 15e3 });
55260
+ } catch (error48) {
55261
+ LOG2.warn("MeshCoordinator", `MCP registration command failed (may be pre-registered): ${error48?.message || error48}`);
55262
+ }
55263
+ const cliCmdArgs = [];
55264
+ const cliCmdEnv = {};
55265
+ if (cliCmdSystemPrompt) {
55266
+ if (cliType === "codex-cli") {
55267
+ cliCmdArgs.push("-c", `developer_instructions=${JSON.stringify(cliCmdSystemPrompt)}`);
55268
+ } else if (cliType === "gemini-cli") {
55269
+ try {
55270
+ const { writeFileSync: wfs, existsSync: efs, readFileSync: rfs } = await import("fs");
55271
+ const geminiMdPath = `${workspace}/GEMINI.md`;
55272
+ const marker = "<!-- adhdev-mesh-coordinator-prompt -->";
55273
+ const markerEnd = "<!-- /adhdev-mesh-coordinator-prompt -->";
55274
+ const block = `${marker}
55275
+ ${cliCmdSystemPrompt}
55276
+ ${markerEnd}`;
55277
+ if (efs(geminiMdPath)) {
55278
+ const existing = rfs(geminiMdPath, "utf-8");
55279
+ const replaced = existing.replace(
55280
+ new RegExp(`${marker}[\\s\\S]*?${markerEnd}`, "g"),
55281
+ block
55282
+ );
55283
+ wfs(geminiMdPath, replaced.includes(marker) ? replaced : `${existing}
55284
+
55285
+ ${block}`);
55286
+ } else {
55287
+ wfs(geminiMdPath, block);
55288
+ }
55289
+ LOG2.info("MeshCoordinator", `Wrote coordinator prompt to ${workspace}/GEMINI.md`);
55290
+ } catch (e) {
55291
+ LOG2.warn("MeshCoordinator", `Could not write GEMINI.md: ${e?.message || e}`);
55292
+ }
55293
+ }
55294
+ }
55295
+ const cliCmdLaunch = await this.deps.cliManager.handleCliCommand("launch_cli", {
55296
+ cliType,
55297
+ dir: workspace,
55298
+ cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
55299
+ env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
55300
+ settings: { meshCoordinatorFor: meshId }
55301
+ });
55302
+ if (!cliCmdLaunch?.success) {
55303
+ return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
55304
+ }
55305
+ LOG2.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
55306
+ try {
55307
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
55308
+ appendLedgerEntry2(meshId, {
55309
+ kind: "coordinator_started",
55310
+ sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
55311
+ providerType: cliType,
55312
+ payload: { workspace }
55313
+ });
55314
+ } catch {
55315
+ }
55316
+ return {
55317
+ success: true,
55318
+ meshId,
55319
+ cliType,
55320
+ workspace,
55321
+ sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
55322
+ mcpRegistered: true
55323
+ };
55324
+ }
55159
55325
  const configFormat = coordinatorSetup.configFormat;
55160
55326
  if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
55161
55327
  return {
@@ -63202,7 +63368,8 @@ data: ${JSON.stringify(msg.data)}
63202
63368
  cdpManagers,
63203
63369
  sessionRegistry,
63204
63370
  detectedIdes: detectedIdesRef,
63205
- refreshProviderAvailability
63371
+ refreshProviderAvailability,
63372
+ dispatchMeshCommand: config2.dispatchMeshCommand
63206
63373
  };
63207
63374
  setupMeshEventForwarding(components);
63208
63375
  return components;