@adhdev/daemon-core 0.9.82-rc.222 → 0.9.82-rc.224

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
@@ -25116,7 +25116,9 @@ async function handleReadChat(h, args) {
25116
25116
  const historyLimit = normalizeReadChatTailLimit(args);
25117
25117
  try {
25118
25118
  const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h);
25119
- const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
25119
+ const targetSid = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
25120
+ const registrySessionWorkspace = targetSid ? h.ctx?.sessionRegistry?.get?.(targetSid)?.workspace : void 0;
25121
+ const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : typeof registrySessionWorkspace === "string" ? registrySessionWorkspace : void 0;
25120
25122
  const intendedWorkspace = typeof args?.workspace === "string" ? args.workspace : void 0;
25121
25123
  const supportsNative = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.nativeHistory);
25122
25124
  const history = supportsNative ? readCliProviderNativeHistory(agentStr, {
@@ -39671,7 +39673,12 @@ function applyInlineMeshBranchConvergence(mesh, node, status) {
39671
39673
  }
39672
39674
  }
39673
39675
  function summarizeInlineMeshBranchConvergence(nodes) {
39674
- const followUps = nodes.filter((node) => readObjectRecord(node.branchConvergence).needsConvergence === true).map((node) => {
39676
+ const followUps = nodes.filter((node) => {
39677
+ if (readObjectRecord(node.branchConvergence).needsConvergence !== true) return false;
39678
+ const workspace = typeof node.workspace === "string" ? node.workspace : "";
39679
+ if (workspace && !fs23.existsSync(workspace)) return false;
39680
+ return true;
39681
+ }).map((node) => {
39675
39682
  const convergence = readObjectRecord(node.branchConvergence);
39676
39683
  return {
39677
39684
  nodeId: node.nodeId,
@@ -41182,7 +41189,66 @@ var DaemonCommandRouter = class {
41182
41189
  } catch (e) {
41183
41190
  const message = String(e?.message || e || "worktree cleanup failed");
41184
41191
  const dirty = message.includes("dirty worktree") || message.includes("local changes");
41185
- const submoduleForceBlocked = /working trees containing submodules cannot be moved or removed/i.test(message) && !forceFallbackConvergence.allow;
41192
+ const isSubmoduleGuard = /working trees containing submodules cannot be moved or removed/i.test(message);
41193
+ const submoduleForceBlocked = isSubmoduleGuard && !forceFallbackConvergence.allow;
41194
+ if (isSubmoduleGuard && forceFallbackConvergence.allow) {
41195
+ const { execFile: execFile4 } = await import("child_process");
41196
+ const { promisify: promisify7 } = await import("util");
41197
+ const execFileAsync3 = promisify7(execFile4);
41198
+ const GIT_TIMEOUT_CLEANUP = 3e4;
41199
+ const GIT_MAX_BUFFER_CLEANUP = 4 * 1024 * 1024;
41200
+ try {
41201
+ await execFileAsync3("git", ["-C", workspace, "submodule", "deinit", "--all", "-f"], {
41202
+ encoding: "utf8",
41203
+ timeout: GIT_TIMEOUT_CLEANUP,
41204
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
41205
+ windowsHide: true
41206
+ });
41207
+ await execFileAsync3("git", ["worktree", "remove", "--force", workspace], {
41208
+ cwd: repoRoot,
41209
+ encoding: "utf8",
41210
+ timeout: GIT_TIMEOUT_CLEANUP,
41211
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
41212
+ windowsHide: true
41213
+ });
41214
+ return {
41215
+ success: true,
41216
+ removedPath: workspace,
41217
+ repoRoot,
41218
+ fallback: "git_worktree_remove_submodule_deinit",
41219
+ forced: true,
41220
+ reason: "working_trees_containing_submodules",
41221
+ convergence: forceFallbackConvergence
41222
+ };
41223
+ } catch (deinitError) {
41224
+ try {
41225
+ fs23.rmSync(workspace, { recursive: true, force: true });
41226
+ await execFileAsync3("git", ["worktree", "prune"], {
41227
+ cwd: repoRoot,
41228
+ encoding: "utf8",
41229
+ timeout: GIT_TIMEOUT_CLEANUP,
41230
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
41231
+ windowsHide: true
41232
+ });
41233
+ return {
41234
+ success: true,
41235
+ removedPath: workspace,
41236
+ repoRoot,
41237
+ fallback: "fs_rm_worktree_prune",
41238
+ forced: true,
41239
+ reason: "working_trees_containing_submodules",
41240
+ convergence: forceFallbackConvergence
41241
+ };
41242
+ } catch (rmError) {
41243
+ return {
41244
+ success: false,
41245
+ code: "mesh_worktree_cleanup_failed",
41246
+ error: `All removal fallbacks exhausted. deinit+remove: ${deinitError?.message || deinitError}; rmSync+prune: ${rmError?.message || rmError}`,
41247
+ recoveryHint: "Manually remove the worktree directory and run git worktree prune from the source repo."
41248
+ };
41249
+ }
41250
+ }
41251
+ }
41186
41252
  return {
41187
41253
  success: false,
41188
41254
  code: dirty ? "mesh_worktree_cleanup_dirty" : submoduleForceBlocked ? "mesh_worktree_cleanup_force_fallback_blocked" : "mesh_worktree_cleanup_failed",
@@ -41194,9 +41260,13 @@ var DaemonCommandRouter = class {
41194
41260
  }
41195
41261
  async getWorktreeForceCleanupConvergence(args) {
41196
41262
  const metadataStatus = typeof args.node?.branchConvergence?.status === "string" ? args.node.branchConvergence.status : "";
41197
- if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate") {
41263
+ if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate" || metadataStatus === "merged_pushed") {
41198
41264
  return { allow: true, status: metadataStatus, source: "node_branch_convergence" };
41199
41265
  }
41266
+ const refinedConvergence = typeof args.node?.refineState?.finalBranchConvergenceState?.status === "string" ? args.node.refineState.finalBranchConvergenceState.status : typeof args.node?.lastRefineResult?.finalBranchConvergenceState?.status === "string" ? args.node.lastRefineResult.finalBranchConvergenceState.status : "";
41267
+ if (refinedConvergence === "merged_pushed" || refinedConvergence === "merged_to_main") {
41268
+ return { allow: true, status: refinedConvergence, source: "node_refine_state" };
41269
+ }
41200
41270
  const { execFile: execFile4 } = await import("child_process");
41201
41271
  const { promisify: promisify7 } = await import("util");
41202
41272
  const execFileAsync3 = promisify7(execFile4);
@@ -41682,11 +41752,24 @@ var DaemonCommandRouter = class {
41682
41752
  if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
41683
41753
  const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
41684
41754
  const baseBranch = baseBranchStdout.trim();
41685
- const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
41755
+ let fetchWarning;
41756
+ try {
41757
+ await execFileAsync3("git", ["fetch", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
41758
+ } catch (e) {
41759
+ fetchWarning = `git fetch origin ${baseBranch} failed (proceeding with local HEAD): ${e?.message}`;
41760
+ }
41761
+ let baseHeadRaw;
41762
+ try {
41763
+ const { stdout } = await execFileAsync3("git", ["rev-parse", `origin/${baseBranch}`], { cwd: repoRoot, encoding: "utf8" });
41764
+ baseHeadRaw = stdout.trim();
41765
+ } catch {
41766
+ const { stdout: localHead } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
41767
+ baseHeadRaw = localHead.trim();
41768
+ }
41686
41769
  const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
41687
- const baseHead = baseHeadStdout.trim();
41770
+ const baseHead = baseHeadRaw;
41688
41771
  let branchHead = branchHeadStdout.trim();
41689
- recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
41772
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead, ...fetchWarning ? { fetchWarning } : {} });
41690
41773
  const validationStarted = Date.now();
41691
41774
  const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace, {
41692
41775
  // M2-2: consume the node's persisted bootstrap state; persist re-runs.
@@ -41705,11 +41788,25 @@ var DaemonCommandRouter = class {
41705
41788
  { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
41706
41789
  );
41707
41790
  if (validationSummary.status === "failed") {
41791
+ const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
41792
+ const buildValidationFailedError = () => {
41793
+ const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
41794
+ if (!firstFailedCmd) return base;
41795
+ const cmdName = typeof firstFailedCmd.displayCommand === "string" ? firstFailedCmd.displayCommand : typeof firstFailedCmd.command === "string" ? [firstFailedCmd.command, ...Array.isArray(firstFailedCmd.args) ? firstFailedCmd.args : []].join(" ").trim() : typeof firstFailedCmd.cmd === "string" ? firstFailedCmd.cmd : "";
41796
+ const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
41797
+ const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
41798
+ return [
41799
+ base,
41800
+ cmdName ? `First failing command: ${cmdName}` : "",
41801
+ tail ? `Output (tail):
41802
+ ${tail}` : ""
41803
+ ].filter(Boolean).join("\n");
41804
+ };
41708
41805
  return {
41709
41806
  success: false,
41710
41807
  code: validationSummary.failureCode || "validation_failed",
41711
41808
  convergenceStatus: "blocked_review",
41712
- error: validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.",
41809
+ error: buildValidationFailedError(),
41713
41810
  branch,
41714
41811
  into: baseBranch,
41715
41812
  validationSummary,
@@ -42311,13 +42408,54 @@ var DaemonCommandRouter = class {
42311
42408
  this.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", response);
42312
42409
  return { success: true };
42313
42410
  }
42314
- case "launch_cli":
42411
+ case "launch_cli": {
42412
+ const launchResult = await this.deps.cliManager.handleCliCommand(cmd, args);
42413
+ const meshNodeId = readStringValue(args?.settings?.meshNodeId);
42414
+ const meshId = readStringValue(args?.settings?.meshNodeFor);
42415
+ if (meshNodeId && meshId && launchResult?.success !== false) {
42416
+ try {
42417
+ const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
42418
+ const meshObj = getMesh2(meshId) ?? this.getCachedInlineMesh(meshId);
42419
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === meshNodeId || n.nodeId === meshNodeId) : void 0;
42420
+ const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
42421
+ if (bootstrapStatus === "running") {
42422
+ return { success: true, ...launchResult, bootstrapPending: true };
42423
+ }
42424
+ } catch {
42425
+ }
42426
+ }
42427
+ return launchResult;
42428
+ }
42315
42429
  case "stop_cli":
42316
42430
  case "set_cli_view_mode":
42317
- case "record_provider_pty":
42318
- case "agent_command": {
42431
+ case "record_provider_pty": {
42319
42432
  return this.deps.cliManager.handleCliCommand(cmd, args);
42320
42433
  }
42434
+ case "agent_command": {
42435
+ const agentResult = await this.deps.cliManager.handleCliCommand(cmd, args);
42436
+ const meshCtx = args?.meshContext;
42437
+ const dispatchNodeId = readStringValue(meshCtx?.nodeId);
42438
+ const dispatchMeshId = readStringValue(meshCtx?.meshId);
42439
+ if (dispatchNodeId && dispatchMeshId && agentResult?.success !== false) {
42440
+ try {
42441
+ const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
42442
+ const meshObj = getMesh2(dispatchMeshId) ?? this.getCachedInlineMesh(dispatchMeshId);
42443
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === dispatchNodeId || n.nodeId === dispatchNodeId) : void 0;
42444
+ const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
42445
+ if (bootstrapStatus === "running") {
42446
+ return {
42447
+ success: true,
42448
+ ...agentResult,
42449
+ dispatchAcknowledgementRisk: true,
42450
+ dispatchAcknowledgementRiskReason: "bootstrap_still_running",
42451
+ nextAction: "Wait for worktree_bootstrap_complete event before dispatching work to this node."
42452
+ };
42453
+ }
42454
+ } catch {
42455
+ }
42456
+ }
42457
+ return agentResult;
42458
+ }
42321
42459
  // ─── Logs ───
42322
42460
  case "get_logs": {
42323
42461
  const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
@@ -43702,9 +43840,11 @@ var DaemonCommandRouter = class {
43702
43840
  if (meshRecord?.inline) {
43703
43841
  removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
43704
43842
  if (removed) this.invalidateAggregateMeshStatus(meshId);
43843
+ if (!removed && !node) removed = true;
43705
43844
  } else {
43706
43845
  const { removeNode: removeNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
43707
43846
  removed = removeNode2(meshId, nodeId);
43847
+ if (!removed && !node) removed = true;
43708
43848
  if (removed) this.invalidateAggregateMeshStatus(meshId);
43709
43849
  }
43710
43850
  if (removed) {
@@ -43888,8 +44028,37 @@ var DaemonCommandRouter = class {
43888
44028
  setupPromise.then((value) => ({ completed: true, value })),
43889
44029
  new Promise((resolve23) => setTimeout(() => resolve23({ completed: false }), setupWaitMs))
43890
44030
  ]);
44031
+ const emitBootstrapEvent = (eventStatus2, bootstrapState2, startedAtMs, extraPayload) => {
44032
+ try {
44033
+ const durationMs = Date.now() - startedAtMs;
44034
+ const eventPayload = {
44035
+ event: `worktree_${eventStatus2}`,
44036
+ meshId,
44037
+ nodeLabel: node.id,
44038
+ nodeId: node.id,
44039
+ workspace: result.worktreePath,
44040
+ metadataEvent: {
44041
+ source: "clone_mesh_node_bootstrap",
44042
+ nodeId: node.id,
44043
+ status: eventStatus2,
44044
+ worktreePath: result.worktreePath,
44045
+ durationMs,
44046
+ bootstrapStatus: bootstrapState2.status,
44047
+ ...bootstrapState2.error ? { error: bootstrapState2.error } : {},
44048
+ ...bootstrapState2.exitCode !== void 0 ? { exitCode: bootstrapState2.exitCode } : {},
44049
+ ...extraPayload || {}
44050
+ },
44051
+ queuedAt: Date.now()
44052
+ };
44053
+ queuePendingMeshCoordinatorEvent(eventPayload);
44054
+ } catch {
44055
+ }
44056
+ };
44057
+ const bootstrapStartedMs = Date.now();
43891
44058
  if (!setupResult.completed) {
43892
- setupPromise.catch((error) => {
44059
+ setupPromise.then(({ bootstrapState: bootstrapState2 }) => {
44060
+ emitBootstrapEvent("bootstrap_complete", bootstrapState2, bootstrapStartedMs);
44061
+ }).catch((error) => {
43893
44062
  const failedState = {
43894
44063
  ...runningBootstrapState,
43895
44064
  status: "failed",
@@ -43898,6 +44067,7 @@ var DaemonCommandRouter = class {
43898
44067
  };
43899
44068
  void persistWorktreeSetupState(failedState);
43900
44069
  void appendCloneLedger(false, failedState);
44070
+ emitBootstrapEvent("bootstrap_failed", failedState, bootstrapStartedMs, { error: error?.message || String(error) });
43901
44071
  });
43902
44072
  return {
43903
44073
  success: true,
@@ -43915,6 +44085,7 @@ var DaemonCommandRouter = class {
43915
44085
  };
43916
44086
  }
43917
44087
  const { submodulesInitialized, bootstrapState } = setupResult.value;
44088
+ emitBootstrapEvent("bootstrap_complete", bootstrapState, bootstrapStartedMs);
43918
44089
  return {
43919
44090
  success: true,
43920
44091
  node,
@@ -43982,7 +44153,34 @@ var DaemonCommandRouter = class {
43982
44153
  const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue trigger");
43983
44154
  if (ownerFailure) return ownerFailure;
43984
44155
  try {
43985
- const { triggerMeshQueue: triggerMeshQueue2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
44156
+ const { triggerMeshQueue: triggerMeshQueue2, tryAssignQueueTask: tryAssignQueueTask2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
44157
+ const preferredNodeId = typeof args?.preferredNodeId === "string" ? args.preferredNodeId.trim() : "";
44158
+ if (preferredNodeId) {
44159
+ const cliInstances = this.deps.instanceManager.getByCategory("cli");
44160
+ const sorted = [...cliInstances].sort((a, b) => {
44161
+ const aSettings = a.getState().settings || {};
44162
+ const bSettings = b.getState().settings || {};
44163
+ const aNode = readStringValue(aSettings.meshNodeId, aSettings.nodeId);
44164
+ const bNode = readStringValue(bSettings.meshNodeId, bSettings.nodeId);
44165
+ return (aNode === preferredNodeId ? -1 : 0) - (bNode === preferredNodeId ? -1 : 0);
44166
+ });
44167
+ for (const inst of sorted) {
44168
+ const state = inst.getState();
44169
+ const settings = state.settings || {};
44170
+ const nodeId = readStringValue(settings.meshNodeId, settings.nodeId);
44171
+ if (!nodeId || nodeId !== preferredNodeId) continue;
44172
+ const meshNodeFor = readStringValue(settings.meshNodeFor);
44173
+ if (meshNodeFor !== meshId) continue;
44174
+ const status = (readStringValue(state.status) || "").toLowerCase();
44175
+ if (status !== "idle") continue;
44176
+ const sessionId = typeof state.instanceId === "string" ? state.instanceId : "";
44177
+ const providerType = readStringValue(state.type, settings.providerType) || "";
44178
+ if (sessionId && providerType) {
44179
+ tryAssignQueueTask2(this.deps, meshId, nodeId, sessionId, providerType);
44180
+ break;
44181
+ }
44182
+ }
44183
+ }
43986
44184
  const trigger = await triggerMeshQueue2(this.deps, meshId);
43987
44185
  return { success: true, trigger };
43988
44186
  } catch (e) {