@adhdev/daemon-core 0.9.82-rc.116 → 0.9.82-rc.118

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
@@ -14843,6 +14843,10 @@ var DEFAULT_APPROVAL_POSITIVE_HINTS = [
14843
14843
  function normalizeApprovalLabel(value) {
14844
14844
  return String(value || "").toLowerCase().replace(/^[\s\[(<{]*\d+(?:\s*[.)\]}>:-]|\s)+/, "").replace(/[^\p{L}\p{N}]+/gu, " ").trim();
14845
14845
  }
14846
+ function isNegativeApprovalLabel(value) {
14847
+ const label = normalizeApprovalLabel(value);
14848
+ return /^(no|deny|reject|cancel|skip|exit|stop)\b/.test(label) || /\bwithout\b/.test(label) || /\bdo not\b/.test(label);
14849
+ }
14846
14850
  function getApprovalPositiveHints(provider) {
14847
14851
  const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
14848
14852
  return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
@@ -14850,19 +14854,19 @@ function getApprovalPositiveHints(provider) {
14850
14854
  function pickApprovalButton(buttons, provider) {
14851
14855
  const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
14852
14856
  if (labels.length === 0) {
14853
- return { index: 0, label: "Approve" };
14857
+ return { index: -1, label: "" };
14854
14858
  }
14855
14859
  const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
14856
14860
  const hints = getApprovalPositiveHints(provider);
14857
14861
  for (const hint of hints) {
14858
- const exactIndex = normalizedButtons.findIndex((label) => label === hint);
14862
+ const exactIndex = normalizedButtons.findIndex((label, index) => label === hint && !isNegativeApprovalLabel(labels[index]));
14859
14863
  if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
14860
- const prefixIndex = normalizedButtons.findIndex((label) => label.startsWith(hint));
14864
+ const prefixIndex = normalizedButtons.findIndex((label, index) => label.startsWith(hint) && !isNegativeApprovalLabel(labels[index]));
14861
14865
  if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
14862
- const includeIndex = normalizedButtons.findIndex((label) => label.includes(hint));
14866
+ const includeIndex = normalizedButtons.findIndex((label, index) => label.includes(hint) && !isNegativeApprovalLabel(labels[index]));
14863
14867
  if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
14864
14868
  }
14865
- return { index: 0, label: labels[0] };
14869
+ return { index: -1, label: "" };
14866
14870
  }
14867
14871
  function formatAutoApprovalMessage(modalMessage, buttonLabel) {
14868
14872
  const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
@@ -16916,6 +16920,7 @@ function buildCliMessageSourceProvenance(args) {
16916
16920
  }
16917
16921
  function buildNativeHistoryFallbackReason(args) {
16918
16922
  if (!supportsCliNativeTranscript(args.providerType, args.provider)) return "provider_native_transcript_not_supported";
16923
+ if (args.unavailableReason) return `native_history_unavailable:${args.unavailableReason}`;
16919
16924
  if (args.nativeSource === "native-unavailable") return "native_history_unavailable";
16920
16925
  if (args.nativeHistoryCoverage === "partial") return "native_history_partial";
16921
16926
  if (args.nativeHistoryCoverage === "unavailable") return "native_history_unavailable";
@@ -16990,6 +16995,15 @@ function hasSafeNativeHistoryMapping(args) {
16990
16995
  return hasOverlappingVisibleConversationText(args.nativeMessages, args.ptyMessages || []);
16991
16996
  }
16992
16997
  function readCliProviderNativeHistory(agentStr, args) {
16998
+ if (!args.historySessionId) {
16999
+ return {
17000
+ messages: [],
17001
+ hasMore: false,
17002
+ source: "native-unavailable",
17003
+ unavailableReason: "native_history_workspace_only_lookup_unsafe",
17004
+ lookup: "session"
17005
+ };
17006
+ }
16993
17007
  const sessionHistory = readProviderChatHistory(agentStr, {
16994
17008
  canonicalHistory: args.canonicalHistory,
16995
17009
  historySessionId: args.historySessionId,
@@ -17000,20 +17014,7 @@ function readCliProviderNativeHistory(agentStr, args) {
17000
17014
  historyBehavior: args.historyBehavior,
17001
17015
  scripts: args.scripts
17002
17016
  });
17003
- if (sessionHistory.source !== "native-unavailable" || args.exactSessionScoped || !args.historySessionId || !args.workspace) {
17004
- return { ...sessionHistory, lookup: args.historySessionId ? "session" : "workspace" };
17005
- }
17006
- const workspaceHistory = readProviderChatHistory(agentStr, {
17007
- canonicalHistory: args.canonicalHistory,
17008
- historySessionId: void 0,
17009
- workspace: args.workspace,
17010
- offset: args.offset,
17011
- limit: args.limit,
17012
- excludeRecentCount: args.excludeRecentCount,
17013
- historyBehavior: args.historyBehavior,
17014
- scripts: args.scripts
17015
- });
17016
- return { ...workspaceHistory, lookup: "workspace" };
17017
+ return { ...sessionHistory, lookup: "session" };
17017
17018
  }
17018
17019
  function isNativeHistoryFreshEnough(args) {
17019
17020
  const nativeNewest = getMessageNewestReceivedAt(args.nativeMessages);
@@ -17756,6 +17757,7 @@ async function handleReadChat(h, args) {
17756
17757
  provider,
17757
17758
  nativeSource: nativeHistory.source,
17758
17759
  nativeHistoryCoverage,
17760
+ unavailableReason,
17759
17761
  nativeMessageCount: nativeMessages.length,
17760
17762
  safeMapping,
17761
17763
  freshEnough
@@ -17855,6 +17857,7 @@ async function handleReadChat(h, args) {
17855
17857
  provider,
17856
17858
  nativeSource: history.source,
17857
17859
  nativeHistoryCoverage,
17860
+ unavailableReason,
17858
17861
  nativeMessageCount: historyMessages.length,
17859
17862
  safeMapping,
17860
17863
  freshEnough: true
@@ -27865,6 +27868,12 @@ function finalizeMeshNodeStatus(args) {
27865
27868
  status.launchBlockedMessage = readStringValue(bootstrap.error) || "Required worktree bootstrap failed; resolve it before launching an agent into this node.";
27866
27869
  return;
27867
27870
  }
27871
+ if (bootstrap.status === "running" && bootstrap.required !== false) {
27872
+ status.launchReady = false;
27873
+ status.launchBlockedReason = "worktree_bootstrap_running";
27874
+ status.launchBlockedMessage = "Required worktree bootstrap is still running; wait for it to finish before launching an agent into this node.";
27875
+ return;
27876
+ }
27868
27877
  }
27869
27878
  const connectionState = readStringValue(readObjectRecord(status.connection).state);
27870
27879
  status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
@@ -27965,9 +27974,12 @@ function summarizeMeshSessionRecord(record) {
27965
27974
  isCached: false
27966
27975
  };
27967
27976
  }
27968
- function liveSessionRecordMatchesMeshNode(record, meshId, nodeId) {
27977
+ function liveSessionRecordMatchesMeshNode(record, meshId, nodeId, nodeWorkspace = "", nodeIsMissingLocalWorktree = false) {
27969
27978
  const recordNodeId = readStringValue(record?.meta?.meshNodeId);
27970
27979
  if (!recordNodeId || recordNodeId !== nodeId) return false;
27980
+ if (nodeIsMissingLocalWorktree) return false;
27981
+ const recordWorkspace = readStringValue(record?.workspace);
27982
+ if (nodeWorkspace && recordWorkspace && recordWorkspace !== nodeWorkspace) return false;
27971
27983
  const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
27972
27984
  return !recordMeshId || recordMeshId === meshId;
27973
27985
  }
@@ -27992,9 +28004,13 @@ function readLiveMeshNodeWorkspace(args) {
27992
28004
  return "";
27993
28005
  }
27994
28006
  function collectLiveMeshSessionRecords(args) {
28007
+ const nodeWorkspace = readStringValue(args.node?.workspace);
28008
+ const nodeIsMissingLocalWorktree = args.node?.isLocalWorktree === true && !!nodeWorkspace && !fs11.existsSync(nodeWorkspace);
27995
28009
  const matches = args.liveSessionRecords.filter((record) => {
27996
- const nodeWorkspace = readStringValue(args.node?.workspace);
27997
- if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId)) return true;
28010
+ const recordNodeId = readStringValue(record?.meta?.meshNodeId);
28011
+ if (recordNodeId && recordNodeId !== args.nodeId) return false;
28012
+ if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId, nodeWorkspace || "", nodeIsMissingLocalWorktree)) return true;
28013
+ if (nodeIsMissingLocalWorktree) return false;
27998
28014
  return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record, args.meshId, nodeWorkspace);
27999
28015
  });
28000
28016
  if (args.allowCoordinatorSession) {
@@ -28010,11 +28026,15 @@ function collectLiveMeshSessionRecords(args) {
28010
28026
  function buildHistoricalMeshSessions(args) {
28011
28027
  const liveNodeIds = /* @__PURE__ */ new Set();
28012
28028
  const liveWorkspaces = /* @__PURE__ */ new Set();
28029
+ const missingLocalWorktreeNodeIds = /* @__PURE__ */ new Set();
28013
28030
  for (const node of args.nodes || []) {
28014
28031
  const nodeId = readStringValue(node?.id, node?.nodeId);
28015
28032
  const workspace = readStringValue(node?.workspace);
28016
28033
  if (nodeId) liveNodeIds.add(nodeId);
28017
28034
  if (workspace) liveWorkspaces.add(workspace);
28035
+ if (nodeId && node?.isLocalWorktree === true && workspace && !fs11.existsSync(workspace)) {
28036
+ missingLocalWorktreeNodeIds.add(nodeId);
28037
+ }
28018
28038
  }
28019
28039
  const sessions = [];
28020
28040
  for (const record of args.liveSessionRecords || []) {
@@ -28023,7 +28043,7 @@ function buildHistoricalMeshSessions(args) {
28023
28043
  if (recordMeshId !== args.meshId) continue;
28024
28044
  const recordNodeId = readStringValue(meta.meshNodeId);
28025
28045
  const workspace = readStringValue(record?.workspace);
28026
- const removedNode = !!recordNodeId && !liveNodeIds.has(recordNodeId);
28046
+ const removedNode = !!recordNodeId && (!liveNodeIds.has(recordNodeId) || missingLocalWorktreeNodeIds.has(recordNodeId));
28027
28047
  const orphanedWorkspace = !!workspace && !liveWorkspaces.has(workspace) && meta.meshCoordinatorFor !== args.meshId;
28028
28048
  if (!removedNode && !orphanedWorkspace) continue;
28029
28049
  sessions.push({
@@ -31214,56 +31234,113 @@ var DaemonCommandRouter = class {
31214
31234
  if (!node) return { success: false, error: "Failed to register worktree node" };
31215
31235
  this.invalidateAggregateMeshStatus(meshId);
31216
31236
  }
31217
- const initSubmodules = sourceNode.policy?.initSubmodulesOnClone !== false;
31218
- if (initSubmodules) {
31219
- try {
31220
- const { runGit: runGit3 } = await Promise.resolve().then(() => (init_git_executor(), git_executor_exports));
31221
- await runGit3(
31222
- { workspace: result.worktreePath, repoRoot: result.worktreePath, isGitRepo: true },
31223
- ["submodule", "update", "--init", "--recursive"],
31224
- { timeoutMs: 12e4 }
31225
- );
31226
- } catch (subErr) {
31227
- console.warn("[mesh] Submodule init failed for worktree:", subErr.message);
31237
+ const persistWorktreeSetupState = async (bootstrapState2) => {
31238
+ node.worktreeBootstrap = bootstrapState2;
31239
+ if (meshRecord.inline) {
31240
+ this.updateInlineMeshNode(meshId, mesh, node);
31241
+ return;
31228
31242
  }
31229
- }
31230
- const bootstrapState = await runMeshWorktreeBootstrap(mesh, result.worktreePath);
31231
- node.worktreeBootstrap = bootstrapState;
31232
- if (!meshRecord.inline) {
31233
31243
  try {
31234
31244
  const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
31235
- updateNode2(meshId, node.id, { worktreeBootstrap: bootstrapState });
31245
+ updateNode2(meshId, node.id, { worktreeBootstrap: bootstrapState2 });
31236
31246
  this.invalidateAggregateMeshStatus(meshId);
31237
31247
  } catch {
31238
31248
  }
31239
- }
31240
- try {
31241
- const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
31242
- appendLedgerEntry2(meshId, {
31243
- kind: "node_cloned",
31244
- nodeId: node.id,
31245
- payload: {
31246
- sourceNodeId,
31247
- branch: result.branch,
31248
- worktreePath: result.worktreePath,
31249
- submodulesInitialized: initSubmodules,
31250
- worktreeBootstrap: {
31251
- status: bootstrapState.status,
31252
- required: bootstrapState.required,
31253
- configSource: bootstrapState.configSource,
31254
- configSourceType: bootstrapState.configSourceType,
31255
- lastCommand: bootstrapState.lastCommand,
31256
- exitCode: bootstrapState.exitCode
31249
+ };
31250
+ const appendCloneLedger = async (initSubmodules2, bootstrapState2) => {
31251
+ try {
31252
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
31253
+ appendLedgerEntry2(meshId, {
31254
+ kind: "node_cloned",
31255
+ nodeId: node.id,
31256
+ payload: {
31257
+ sourceNodeId,
31258
+ branch: result.branch,
31259
+ worktreePath: result.worktreePath,
31260
+ submodulesInitialized: initSubmodules2,
31261
+ worktreeBootstrap: {
31262
+ status: bootstrapState2.status,
31263
+ required: bootstrapState2.required,
31264
+ configSource: bootstrapState2.configSource,
31265
+ configSourceType: bootstrapState2.configSourceType,
31266
+ lastCommand: bootstrapState2.lastCommand,
31267
+ exitCode: bootstrapState2.exitCode
31268
+ }
31257
31269
  }
31270
+ });
31271
+ } catch {
31272
+ }
31273
+ };
31274
+ const initSubmodules = sourceNode.policy?.initSubmodulesOnClone !== false;
31275
+ const loadedBootstrap = loadMeshWorktreeBootstrapConfig(mesh, result.worktreePath);
31276
+ const runningBootstrapState = {
31277
+ status: "running",
31278
+ required: loadedBootstrap.config?.required !== false,
31279
+ configSource: loadedBootstrap.path || loadedBootstrap.source,
31280
+ configSourceType: loadedBootstrap.sourceType,
31281
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
31282
+ };
31283
+ await persistWorktreeSetupState(runningBootstrapState);
31284
+ const finishWorktreeSetup = async () => {
31285
+ let submodulesInitialized2 = false;
31286
+ if (initSubmodules) {
31287
+ try {
31288
+ const { runGit: runGit3 } = await Promise.resolve().then(() => (init_git_executor(), git_executor_exports));
31289
+ await runGit3(
31290
+ { workspace: result.worktreePath, repoRoot: result.worktreePath, isGitRepo: true },
31291
+ ["submodule", "update", "--init", "--recursive"],
31292
+ { timeoutMs: 12e4 }
31293
+ );
31294
+ submodulesInitialized2 = true;
31295
+ } catch (subErr) {
31296
+ console.warn("[mesh] Submodule init failed for worktree:", subErr.message);
31258
31297
  }
31298
+ }
31299
+ const bootstrapState2 = await runMeshWorktreeBootstrap(mesh, result.worktreePath);
31300
+ await persistWorktreeSetupState(bootstrapState2);
31301
+ await appendCloneLedger(submodulesInitialized2, bootstrapState2);
31302
+ return { submodulesInitialized: submodulesInitialized2, bootstrapState: bootstrapState2 };
31303
+ };
31304
+ const requestedSetupWaitMs = Number(args?.setupWaitMs ?? args?.bootstrapWaitMs ?? 8e3);
31305
+ const setupWaitMs = Number.isFinite(requestedSetupWaitMs) ? Math.min(Math.max(requestedSetupWaitMs, 0), 14e3) : 8e3;
31306
+ const setupPromise = finishWorktreeSetup();
31307
+ const setupResult = await Promise.race([
31308
+ setupPromise.then((value) => ({ completed: true, value })),
31309
+ new Promise((resolve17) => setTimeout(() => resolve17({ completed: false }), setupWaitMs))
31310
+ ]);
31311
+ if (!setupResult.completed) {
31312
+ setupPromise.catch((error) => {
31313
+ const failedState = {
31314
+ ...runningBootstrapState,
31315
+ status: "failed",
31316
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
31317
+ error: error?.message || String(error)
31318
+ };
31319
+ void persistWorktreeSetupState(failedState);
31320
+ void appendCloneLedger(false, failedState);
31259
31321
  });
31260
- } catch {
31322
+ return {
31323
+ success: true,
31324
+ async: true,
31325
+ status: "accepted",
31326
+ node,
31327
+ worktreePath: result.worktreePath,
31328
+ branch: result.branch,
31329
+ worktreeBootstrap: runningBootstrapState,
31330
+ worktreeSetup: {
31331
+ status: "running",
31332
+ setupWaitMs,
31333
+ message: "Worktree node is registered; submodule/bootstrap setup is continuing in the background."
31334
+ }
31335
+ };
31261
31336
  }
31337
+ const { submodulesInitialized, bootstrapState } = setupResult.value;
31262
31338
  return {
31263
31339
  success: true,
31264
31340
  node,
31265
31341
  worktreePath: result.worktreePath,
31266
31342
  branch: result.branch,
31343
+ submodulesInitialized,
31267
31344
  worktreeBootstrap: bootstrapState
31268
31345
  };
31269
31346
  } catch (e) {
@@ -31720,12 +31797,18 @@ ${block2}`);
31720
31797
  for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
31721
31798
  const nodeId = String(node.id || node.nodeId || "");
31722
31799
  const daemonId = readStringValue(node.daemonId);
31800
+ const nodeMachineId = readMeshNodeMachineId(node);
31801
+ const nodeHostname = readMeshNodeHostname(node);
31723
31802
  const providerPriority = readProviderPriorityFromPolicy(node.policy);
31803
+ const configuredCoordinatorNode = Boolean(
31804
+ nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
31805
+ );
31806
+ const sparseConfiguredCoordinatorNode = configuredCoordinatorNode && !daemonId && !nodeMachineId && !nodeHostname;
31724
31807
  const isSelfNode = Boolean(
31725
31808
  nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
31726
31809
  ) || Boolean(
31727
31810
  daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
31728
- ) || Boolean(meshRecord?.inline && nodeIndex === 0);
31811
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0) || sparseConfiguredCoordinatorNode;
31729
31812
  const machineIdentity = buildMeshNodeMachineIdentity(node, {
31730
31813
  localMachineId,
31731
31814
  localDaemonId: this.deps.statusInstanceId,
@@ -31742,7 +31825,7 @@ ${block2}`);
31742
31825
  worktreeBranch: node.worktreeBranch,
31743
31826
  role: normalizeMeshDaemonRole(node.role) || (meshHost.hostNodeId && nodeId === meshHost.hostNodeId ? "host" : void 0),
31744
31827
  daemonId,
31745
- machineId: readMeshNodeMachineId(node) || node.machineId,
31828
+ machineId: nodeMachineId || node.machineId,
31746
31829
  machine: machineIdentity,
31747
31830
  machineStatus: node.machineStatus,
31748
31831
  health: "unknown",