@adhdev/daemon-core 0.9.82-rc.18 → 0.9.82-rc.181

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.
Files changed (225) hide show
  1. package/dist/boot/process-hardening.d.ts +50 -0
  2. package/dist/chat/source-machine.d.ts +166 -0
  3. package/dist/chat/source-resolver.d.ts +104 -0
  4. package/dist/chat/subscription-updates.d.ts +1 -0
  5. package/dist/cli-adapter-types.d.ts +22 -2
  6. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  7. package/dist/cli-adapters/cli-state-engine.d.ts +178 -0
  8. package/dist/cli-adapters/provider-cli-adapter.d.ts +106 -63
  9. package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
  10. package/dist/cli-adapters/provider-cli-shared.d.ts +29 -0
  11. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  12. package/dist/commands/handler.d.ts +110 -0
  13. package/dist/commands/mesh-coordinator.d.ts +72 -1
  14. package/dist/commands/router.d.ts +22 -0
  15. package/dist/config/chat-history.d.ts +8 -0
  16. package/dist/config/config.d.ts +5 -0
  17. package/dist/config/mesh-config.d.ts +72 -1
  18. package/dist/git/git-commands.d.ts +5 -1
  19. package/dist/index.d.ts +35 -8
  20. package/dist/index.js +20754 -5387
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +20567 -5270
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/installer.d.ts +1 -4
  25. package/dist/ipc/local-ipc-server.d.ts +91 -0
  26. package/dist/launch.d.ts +1 -1
  27. package/dist/logging/async-batch-writer.d.ts +10 -0
  28. package/dist/mesh/beads-db.d.ts +72 -0
  29. package/dist/mesh/contracts.d.ts +164 -0
  30. package/dist/mesh/coordinator-prompt.d.ts +30 -0
  31. package/dist/mesh/coordinator-registry.d.ts +59 -0
  32. package/dist/mesh/mesh-active-work.d.ts +90 -0
  33. package/dist/mesh/mesh-events.d.ts +97 -5
  34. package/dist/mesh/mesh-fast-forward.d.ts +41 -0
  35. package/dist/mesh/mesh-host-ownership.d.ts +9 -0
  36. package/dist/mesh/mesh-ledger.d.ts +58 -1
  37. package/dist/mesh/mesh-refine-status.d.ts +26 -0
  38. package/dist/mesh/mesh-work-queue.d.ts +54 -6
  39. package/dist/mesh/preview-freshness.d.ts +18 -0
  40. package/dist/mesh/refine-config.d.ts +193 -0
  41. package/dist/mesh/worktree-bootstrap-config.d.ts +113 -0
  42. package/dist/providers/approval-utils.d.ts +13 -0
  43. package/dist/providers/cli-provider-instance.d.ts +35 -3
  44. package/dist/providers/contracts.d.ts +98 -5
  45. package/dist/providers/external-sources.d.ts +71 -0
  46. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
  47. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  48. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  49. package/dist/providers/native-history/dispatcher.d.ts +25 -0
  50. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  51. package/dist/providers/native-history/index.d.ts +13 -0
  52. package/dist/providers/provider-instance-manager.d.ts +12 -0
  53. package/dist/providers/provider-instance.d.ts +12 -0
  54. package/dist/providers/provider-loader.d.ts +26 -4
  55. package/dist/providers/provider-trust.d.ts +31 -0
  56. package/dist/providers/read-chat-contract.d.ts +29 -0
  57. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  58. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +85 -0
  59. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  60. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  61. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  62. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  63. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  64. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  65. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  66. package/dist/providers/sdk/v1/index.d.ts +30 -0
  67. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  68. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  69. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  70. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  71. package/dist/providers/sdk/v1/types/common/index.d.ts +169 -0
  72. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  73. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  74. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  75. package/dist/providers/spec/adapter.d.ts +56 -0
  76. package/dist/providers/spec/cli-adapter.d.ts +97 -0
  77. package/dist/providers/spec/driver.d.ts +159 -0
  78. package/dist/providers/spec/evaluator.d.ts +47 -0
  79. package/dist/providers/spec/loader.d.ts +14 -0
  80. package/dist/providers/spec/native-history-executor.d.ts +39 -0
  81. package/dist/providers/spec/route.d.ts +4 -0
  82. package/dist/providers/spec/schema.gen.d.ts +511 -0
  83. package/dist/providers/spec/types.d.ts +212 -0
  84. package/dist/providers/transcript-v2.d.ts +176 -0
  85. package/dist/providers/types/interactive-prompt.d.ts +48 -0
  86. package/dist/repo-mesh-types.d.ts +102 -1
  87. package/dist/sessions/registry.d.ts +3 -0
  88. package/dist/shared-types.d.ts +42 -1
  89. package/dist/status/reporter.d.ts +2 -0
  90. package/dist/status/snapshot.d.ts +1 -0
  91. package/dist/types.d.ts +5 -0
  92. package/package.json +7 -2
  93. package/src/agent-stream/poller.ts +2 -3
  94. package/src/boot/daemon-lifecycle.ts +17 -10
  95. package/src/boot/process-hardening.ts +89 -0
  96. package/src/chat/source-machine.ts +534 -0
  97. package/src/chat/source-resolver.ts +0 -0
  98. package/src/chat/subscription-updates.ts +14 -1
  99. package/src/cli-adapter-types.d.ts +1 -0
  100. package/src/cli-adapter-types.ts +21 -2
  101. package/src/cli-adapters/cli-script-runner.ts +421 -0
  102. package/src/cli-adapters/cli-state-engine.ts +1086 -0
  103. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  104. package/src/cli-adapters/provider-cli-adapter.ts +670 -1137
  105. package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
  106. package/src/cli-adapters/provider-cli-parse.ts +13 -0
  107. package/src/cli-adapters/provider-cli-runtime.ts +3 -1
  108. package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
  109. package/src/cli-adapters/provider-cli-shared.ts +59 -11
  110. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  111. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +17 -1
  112. package/src/cli-adapters/terminal-backends/xterm-backend.ts +8 -1
  113. package/src/commands/chat-commands.ts +1597 -60
  114. package/src/commands/cli-manager.ts +230 -3
  115. package/src/commands/handler.ts +809 -2
  116. package/src/commands/mesh-coordinator.ts +231 -127
  117. package/src/commands/router.ts +3495 -502
  118. package/src/config/chat-history.ts +91 -24
  119. package/src/config/config.ts +12 -0
  120. package/src/config/mesh-config.ts +280 -2
  121. package/src/config/recent-activity.ts +8 -2
  122. package/src/daemon/dev-cli-debug.ts +10 -1
  123. package/src/detection/ide-detector.ts +26 -16
  124. package/src/git/git-commands.ts +17 -5
  125. package/src/git/git-worktree.ts +8 -1
  126. package/src/index.ts +113 -7
  127. package/src/installer.d.ts +1 -1
  128. package/src/installer.ts +8 -6
  129. package/src/ipc/local-ipc-server.ts +278 -0
  130. package/src/launch.d.ts +1 -1
  131. package/src/launch.ts +37 -28
  132. package/src/logging/async-batch-writer.ts +55 -0
  133. package/src/logging/logger.ts +2 -1
  134. package/src/mesh/beads-db.ts +486 -0
  135. package/src/mesh/contracts.ts +329 -0
  136. package/src/mesh/coordinator-prompt.ts +204 -30
  137. package/src/mesh/coordinator-registry.ts +121 -0
  138. package/src/mesh/mesh-active-work.ts +437 -0
  139. package/src/mesh/mesh-events.ts +963 -67
  140. package/src/mesh/mesh-fast-forward.ts +438 -0
  141. package/src/mesh/mesh-host-ownership.ts +73 -0
  142. package/src/mesh/mesh-ledger.ts +457 -104
  143. package/src/mesh/mesh-refine-status.ts +144 -0
  144. package/src/mesh/mesh-work-queue.ts +263 -159
  145. package/src/mesh/preview-freshness.ts +118 -0
  146. package/src/mesh/refine-config.ts +366 -0
  147. package/src/mesh/worktree-bootstrap-config.ts +247 -0
  148. package/src/providers/approval-utils.d.ts +4 -0
  149. package/src/providers/approval-utils.ts +47 -5
  150. package/src/providers/chat-message-normalization.ts +4 -11
  151. package/src/providers/cli-provider-instance.ts +651 -57
  152. package/src/providers/contracts.ts +105 -5
  153. package/src/providers/external-sources.ts +218 -0
  154. package/src/providers/ide-provider-instance.ts +19 -5
  155. package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
  156. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  157. package/src/providers/native-history/codex-cli-transcript.ts +419 -0
  158. package/src/providers/native-history/dispatcher.ts +231 -0
  159. package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
  160. package/src/providers/native-history/index.ts +30 -0
  161. package/src/providers/provider-instance-manager.ts +30 -0
  162. package/src/providers/provider-instance.ts +9 -0
  163. package/src/providers/provider-loader.ts +585 -50
  164. package/src/providers/provider-schema.ts +31 -13
  165. package/src/providers/provider-trust.ts +114 -0
  166. package/src/providers/read-chat-contract.ts +76 -16
  167. package/src/providers/sdk/README.md +49 -0
  168. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  169. package/src/providers/sdk/v1/builders/cli/detect-status.ts +262 -0
  170. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  171. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  172. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  173. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  174. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  175. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  176. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  177. package/src/providers/sdk/v1/index.ts +152 -0
  178. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  179. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  180. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  181. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +458 -0
  182. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  183. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  184. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  185. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  186. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  187. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  188. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  189. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  190. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  191. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  192. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  193. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  194. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  195. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  196. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  197. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  198. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  199. package/src/providers/sdk/v1/types/common/index.ts +210 -0
  200. package/src/providers/sdk/v1/validators/index.ts +19 -0
  201. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  202. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  203. package/src/providers/spec/adapter.ts +168 -0
  204. package/src/providers/spec/cli-adapter.ts +507 -0
  205. package/src/providers/spec/driver.ts +540 -0
  206. package/src/providers/spec/evaluator.ts +298 -0
  207. package/src/providers/spec/loader.ts +130 -0
  208. package/src/providers/spec/native-history-executor.ts +706 -0
  209. package/src/providers/spec/route.ts +51 -0
  210. package/src/providers/spec/schema.gen.ts +511 -0
  211. package/src/providers/spec/schema.json +211 -0
  212. package/src/providers/spec/types.ts +231 -0
  213. package/src/providers/transcript-v2.ts +567 -0
  214. package/src/providers/types/interactive-prompt.ts +396 -0
  215. package/src/providers/version-archive.ts +38 -20
  216. package/src/repo-mesh-types.ts +112 -1
  217. package/src/sessions/registry.ts +3 -0
  218. package/src/shared-types.ts +45 -1
  219. package/src/status/builders.ts +24 -6
  220. package/src/status/reporter.ts +15 -0
  221. package/src/status/snapshot.ts +84 -25
  222. package/src/system/host-memory.ts +29 -12
  223. package/src/types.ts +5 -0
  224. package/dist/mesh/mesh-sync.d.ts +0 -53
  225. package/src/mesh/mesh-sync.ts +0 -111
@@ -7,8 +7,10 @@
7
7
  * Migrated from @adhdev/core — this is now the single source of truth.
8
8
  */
9
9
 
10
- import { execSync } from 'child_process';
11
- import { existsSync } from 'fs';
10
+ import { exec } from 'child_process';
11
+ import { promisify } from 'util';
12
+ const execAsync = promisify(exec);
13
+ import { existsSync, statSync } from 'fs';
12
14
  import { platform, homedir } from 'os';
13
15
  import * as path from 'path';
14
16
  import type { ProviderLoader } from '../providers/provider-loader.js';
@@ -73,25 +75,33 @@ function findCliCommand(command: string): string | null {
73
75
  const resolved = path.isAbsolute(candidate) ? candidate : path.resolve(candidate);
74
76
  return existsSync(resolved) ? resolved : null;
75
77
  }
76
- try {
77
- const result = execSync(
78
- platform() === 'win32' ? `where ${trimmed}` : `which ${trimmed}`,
79
- { encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }
80
- ).trim();
81
- return result.split('\n')[0] || null;
82
- } catch {
83
- return null;
78
+ const isWin = platform() === 'win32';
79
+ const paths = (process.env.PATH || '').split(isWin ? ';' : ':');
80
+ const exes = isWin ? ['.exe', '.cmd', '.bat', ''] : [''];
81
+ for (const p of paths) {
82
+ if (!p) continue;
83
+ for (const ext of exes) {
84
+ const fullPath = path.join(p, trimmed + ext);
85
+ try {
86
+ if (existsSync(fullPath)) {
87
+ const stat = statSync(fullPath);
88
+ if (stat.isFile() && (isWin || (stat.mode & 0o111))) {
89
+ return fullPath;
90
+ }
91
+ }
92
+ } catch { }
93
+ }
84
94
  }
95
+ return null;
85
96
  }
86
97
 
87
- function getIdeVersion(cliCommand: string): string | null {
98
+ async function getIdeVersion(cliCommand: string): Promise<string | null> {
88
99
  try {
89
- const result = execSync(`"${cliCommand}" --version`, {
100
+ const { stdout } = await execAsync(`"${cliCommand}" --version`, {
90
101
  encoding: 'utf-8',
91
102
  timeout: 10000,
92
- stdio: ['pipe', 'pipe', 'pipe'],
93
- }).trim();
94
- return result.split('\n')[0] || null;
103
+ });
104
+ return stdout.trim().split('\n')[0] || null;
95
105
  } catch {
96
106
  return null;
97
107
  }
@@ -152,7 +162,7 @@ export async function detectIDEs(providerLoader?: ProviderLoader): Promise<IDEIn
152
162
  const installed = os === 'darwin'
153
163
  ? !!(resolvedCli || appPath)
154
164
  : !!resolvedCli;
155
- const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
165
+ const version = resolvedCli ? await getIdeVersion(resolvedCli) : null;
156
166
 
157
167
  results.push({
158
168
  id: def.id,
@@ -42,8 +42,12 @@ export interface GitLogResult extends GitRepoIdentity {
42
42
  }
43
43
 
44
44
  export interface GitCheckpointResult extends GitRepoIdentity {
45
- commit: string;
45
+ commit?: string;
46
46
  message: string;
47
+ status?: 'created' | 'skipped';
48
+ skipped?: boolean;
49
+ noop?: boolean;
50
+ reason?: 'nothing_to_commit';
47
51
  lastCheckedAt: number;
48
52
  }
49
53
 
@@ -455,10 +459,17 @@ async function gitCheckpoint(
455
459
  } catch (err: any) {
456
460
  const output = (err?.stdout || '') + (err?.stderr || '');
457
461
  if (/nothing to commit/i.test(output)) {
458
- throw new GitCommandError('nothing_to_commit', 'Nothing to commit — working tree is clean.', {
459
- stdout: err?.stdout,
460
- stderr: err?.stderr,
461
- });
462
+ return {
463
+ workspace: repo.workspace,
464
+ repoRoot,
465
+ isGitRepo: true,
466
+ message: fullMsg,
467
+ status: 'skipped',
468
+ skipped: true,
469
+ noop: true,
470
+ reason: 'nothing_to_commit',
471
+ lastCheckedAt: Date.now(),
472
+ };
462
473
  }
463
474
  throw err;
464
475
  }
@@ -469,6 +480,7 @@ async function gitCheckpoint(
469
480
  isGitRepo: true,
470
481
  commit: commitSha,
471
482
  message: fullMsg,
483
+ status: 'created',
472
484
  lastCheckedAt: Date.now(),
473
485
  };
474
486
  }
@@ -116,8 +116,11 @@ export async function createWorktree(opts: WorktreeCreateOptions): Promise<Workt
116
116
  });
117
117
  } catch (error: any) {
118
118
  const stderr = typeof error.stderr === 'string' ? error.stderr : '';
119
- // Clean error messages for common failures
120
119
  if (/already exists/i.test(stderr)) {
120
+ // Distinguish directory-collision (TOCTOU race) from branch-already-exists
121
+ if (existsSync(targetDir)) {
122
+ throw new Error(`Worktree target directory was created concurrently: ${targetDir}`);
123
+ }
121
124
  throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
122
125
  }
123
126
  throw new Error(`git worktree add failed: ${stderr.trim() || error.message}`);
@@ -170,6 +173,10 @@ export async function removeWorktree(repoRoot: string, worktreePath: string, opt
170
173
  const stdout = typeof error.stdout === 'string' ? error.stdout : '';
171
174
  const detail = `${stderr}\n${stdout}\n${error.message || ''}`;
172
175
  if (opts.allowSubmoduleForceFallback && SUBMODULE_WORKTREE_REMOVE_RE.test(detail)) {
176
+ process.stderr.write(
177
+ `[adhdev-mesh] WARNING: git worktree remove --force fallback for submodule worktree '${worktreePath}'. `
178
+ + `Any uncommitted changes inside submodules will be lost.\n`,
179
+ );
173
180
  try {
174
181
  await execFileAsync('git', ['worktree', 'remove', '--force', worktreePath], {
175
182
  cwd: repoRoot,
package/src/index.ts CHANGED
@@ -85,9 +85,28 @@ export type {
85
85
  InputMediaType,
86
86
  } from './shared-types.js';
87
87
 
88
+ export type {
89
+ InteractivePrompt,
90
+ InteractiveQuestion,
91
+ InteractiveOption,
92
+ InteractivePromptResponse,
93
+ InteractiveAnswer,
94
+ } from './providers/types/interactive-prompt.js';
95
+ export {
96
+ normalizeInteractivePrompt,
97
+ normalizeInteractivePromptResponse,
98
+ buildClaudeInteractiveToolResult,
99
+ interactivePromptFromClaudeAskUserQuestion,
100
+ detectClaudeAskUserQuestionPromptFromJson,
101
+ } from './providers/types/interactive-prompt.js';
102
+
88
103
  // ── Repo Mesh Types (cross-package) ──
89
104
  export type {
90
105
  RepoMesh,
106
+ RepoMeshDaemonRole,
107
+ RepoMeshHostMetadata,
108
+ RepoMeshHostPairingMetadata,
109
+ RepoMeshHostStatus,
91
110
  RepoMeshNode,
92
111
  RepoMeshNodeHealth,
93
112
  RepoMeshPolicy,
@@ -111,6 +130,7 @@ export type {
111
130
  RepoMeshLedgerEntryStatus,
112
131
  RepoMeshLedgerSummaryStatus,
113
132
  RepoMeshLedgerStatus,
133
+ MeshAsyncJobLifecycle,
114
134
  } from './repo-mesh-types.js';
115
135
  export { DEFAULT_MESH_POLICY } from './repo-mesh-types.js';
116
136
 
@@ -138,7 +158,7 @@ export type RecentSessionBucket = 'needs_attention' | 'working' | 'task_complete
138
158
  export type { IDaemonCore, DaemonCoreOptions } from './daemon-core.js';
139
159
 
140
160
  // ── Config ──
141
- export { loadConfig, saveConfig, resetConfig, isSetupComplete, markSetupComplete, updateConfig } from './config/config.js';
161
+ export { loadConfig, saveConfig, resetConfig, isSetupComplete, markSetupComplete, updateConfig, getDaemonDataDir } from './config/config.js';
142
162
  export { getWorkspaceState } from './config/workspaces.js';
143
163
  export { appendRecentActivity, getRecentActivity } from './config/recent-activity.js';
144
164
  export type { RecentActivityEntry } from './config/recent-activity.js';
@@ -155,18 +175,51 @@ export type { CreateMeshOptions, UpdateMeshOptions, AddNodeOptions } from './con
155
175
  // ── Mesh Coordinator ──
156
176
  export { buildCoordinatorSystemPrompt } from './mesh/coordinator-prompt.js';
157
177
  export type { CoordinatorPromptContext } from './mesh/coordinator-prompt.js';
158
- export { syncMeshes } from './mesh/mesh-sync.js';
159
- export type { MeshSyncTransport, MeshSyncResult, RemoteMeshRecord } from './mesh/mesh-sync.js';
178
+ export { loadMeshCoordinatorRegistry, registerMeshCoordinator, unregisterMeshCoordinator, getCoordinatorForSession, listCoordinatorsForWorkspace } from './mesh/coordinator-registry.js';
179
+ export type { CoordinatorRegistryEntry } from './mesh/coordinator-registry.js';
180
+ export {
181
+ MESH_REFINE_CONFIG_LOCATIONS,
182
+ MESH_REFINE_CONFIG_SCHEMA,
183
+ loadMeshRefineConfig,
184
+ resolveMeshRefineValidationPlan,
185
+ suggestMeshRefineConfig,
186
+ validateMeshRefineConfig,
187
+ } from './mesh/refine-config.js';
188
+ export {
189
+ MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
190
+ MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
191
+ loadMeshWorktreeBootstrapConfig,
192
+ runMeshWorktreeBootstrap,
193
+ validateMeshWorktreeBootstrapConfig,
194
+ type RepoMeshWorktreeBootstrapConfig,
195
+ type WorktreeBootstrapState,
196
+ } from './mesh/worktree-bootstrap-config.js';
197
+ export type {
198
+ MeshRefineValidationCategory,
199
+ MeshRefineValidationCommandPlan,
200
+ MeshRefineValidationPlan,
201
+ RepoMeshRefineConfig,
202
+ RepoMeshRefineValidationCommandConfig,
203
+ } from './mesh/refine-config.js';
160
204
 
161
205
  // ── Mesh Task Ledger ──
162
- export { appendLedgerEntry, appendRemoteLedgerEntries, readLedgerEntries, readLedgerSlice, getLedgerSummary, getLedgerDir, getSessionRecoveryContext, MAX_LEDGER_SLICE_LIMIT } from './mesh/mesh-ledger.js';
163
- export type { AppendRemoteLedgerResult, MeshLedgerEntry, MeshLedgerKind, MeshLedgerSlice, MeshLedgerSummary, ReadLedgerOptions, ReadLedgerSliceOptions, SessionRecoveryContext } from './mesh/mesh-ledger.js';
206
+ export { appendLedgerEntry, appendRemoteLedgerEntries, buildTaskCompletionEvidence, normalizeMeshWorkerResult, readLedgerEntries, readLedgerSlice, getLedgerSummary, getLedgerDir, getSessionRecoveryContext, MAX_LEDGER_SLICE_LIMIT } from './mesh/mesh-ledger.js';
207
+ export type { AppendRemoteLedgerResult, MeshLedgerEntry, MeshLedgerKind, MeshLedgerSlice, MeshLedgerSummary, ReadLedgerOptions, ReadLedgerSliceOptions, SessionRecoveryContext, MeshTaskCompletionEvidence, MeshWorkerResultArtifact, MeshProcessArtifact, MeshValidationResultArtifact } from './mesh/mesh-ledger.js';
208
+ export { fastForwardMeshNode } from './mesh/mesh-fast-forward.js';
209
+ export type { MeshFastForwardNodeArgs, MeshFastForwardPlannedStep, MeshFastForwardResult } from './mesh/mesh-fast-forward.js';
164
210
  export { buildMeshLedgerReconciliationEvidence, buildMeshLedgerReplicaEvidence } from './mesh/mesh-ledger-reconciliation.js';
165
211
  export type { MeshLedgerReconciliationEvidence, MeshLedgerReplicaEvidence, MeshLedgerReplicaStatus } from './mesh/mesh-ledger-reconciliation.js';
166
212
 
167
213
  // ── Mesh Work Queue (GUPP) ──
168
- export { enqueueTask, getQueue, claimNextTask, updateTaskStatus, updateSessionTaskStatus, cancelTask, requeueTask, getMeshQueueStats } from './mesh/mesh-work-queue.js';
169
- export type { MeshWorkQueueEntry, MeshTaskStatus, MeshWorkQueueStats } from './mesh/mesh-work-queue.js';
214
+ export { enqueueTask, getQueue, claimNextTask, updateTaskStatus, updateSessionTaskStatus, cancelTask, requeueTask, getMeshQueueStats, getMeshQueueRevision, normalizeMeshTaskMode, validateMeshTaskModeRequest, buildMeshNodeCapabilityTags, nodeSatisfiesRequiredTags, normalizeMeshCapabilityTags, insertDirectDispatch, getActiveDirectDispatches, updateDirectDispatchStatus, cleanupTerminalDirectDispatches, markStaleDirectDispatches } from './mesh/mesh-work-queue.js';
215
+ export type { MeshWorkQueueEntry, MeshTaskStatus, MeshTaskMode, MeshWorkQueueStats, MeshQueueMutationOptions, MeshTaskModeValidationResult, DirectDispatchRecord } from './mesh/mesh-work-queue.js';
216
+ export { buildCompactStaleDirectWorkSummary, buildMeshActiveWork, buildMeshActiveWorkSummary } from './mesh/mesh-active-work.js';
217
+ export type { MeshActiveWorkRecord, MeshActiveWorkStatus, MeshActiveWorkSummary, MeshActiveWorkSource, MeshStaleDirectWorkSummary } from './mesh/mesh-active-work.js';
218
+ export { buildMeshAsyncRefineJobs } from './mesh/mesh-refine-status.js';
219
+ export type { MeshAsyncRefineJobStatus, MeshAsyncRefineJobSummary } from './mesh/mesh-refine-status.js';
220
+
221
+ // ── Mesh Host Ownership ──
222
+ export { buildMeshHostRequiredFailure, createDefaultMeshHostMetadata, isMeshHostOwner, normalizeMeshDaemonRole, requireMeshHostQueueOwner, resolveMeshHostStatus } from './mesh/mesh-host-ownership.js';
170
223
 
171
224
  // ── Mesh Visualization ──
172
225
  // buildMeshGraph and MeshGraph types moved to @adhdev/web-core to avoid
@@ -388,6 +441,13 @@ export type { CliAdapter } from './cli-adapter-types.js';
388
441
  export { NodePtyTransportFactory } from './cli-adapters/pty-transport.js';
389
442
  export type { PtyRuntimeTransport, PtyTransportFactory, PtySpawnOptions } from './cli-adapters/pty-transport.js';
390
443
  export { SessionHostPtyTransportFactory } from './cli-adapters/session-host-transport.js';
444
+ export {
445
+ RawTerminalAttachment,
446
+ namedKeyToAnsi,
447
+ namedKeysToAnsi,
448
+ withRawTerminalAttachment,
449
+ } from './cli-adapters/raw-terminal-io.js';
450
+ export type { NamedKey, RawTerminalAttachmentOptions, RawTerminalSessionHostClient } from './cli-adapters/raw-terminal-io.js';
391
451
  export type { HostedCliRuntimeDescriptor, CliTransportFactoryParams } from './commands/cli-manager.js';
392
452
  export {
393
453
  DEFAULT_SESSION_HOST_APP_NAME,
@@ -415,3 +475,49 @@ export type { ExtensionInfo as InstallerExtensionInfo } from './installer.js';
415
475
  // ── Boot / Lifecycle ──
416
476
  export { initDaemonComponents, startDaemonDevSupport, shutdownDaemonComponents } from './boot/daemon-lifecycle.js';
417
477
  export type { DaemonInitConfig, DaemonComponents, DaemonDevSupportOptions } from './boot/daemon-lifecycle.js';
478
+
479
+ // ── Local IPC server (shared between cloud + standalone daemons) ──
480
+ export {
481
+ startLocalIpcServer,
482
+ buildIpcStatusHttpResponse,
483
+ type LocalIpcServerOptions,
484
+ type LocalIpcServerHandle,
485
+ type IpcCommandContext,
486
+ type IpcCommandResult,
487
+ type IpcStatusPayload,
488
+ } from './ipc/local-ipc-server.js';
489
+
490
+ // ── CLI Spec (adhdev:cli/spec@1) ──
491
+ export { evaluate as evaluateSpec, evaluate } from './providers/spec/evaluator.js';
492
+ export { loadSpec, resolveSpecPath } from './providers/spec/loader.js';
493
+ export { createNativeHistoryDispatcher } from './providers/native-history/index.js';
494
+ export type { ReaderId } from './providers/native-history/index.js';
495
+ export {
496
+ readClaudeCliSession, readCodexCliSession,
497
+ readAntigravityCliSession, readHermesCliSession,
498
+ } from './providers/native-history/index.js';
499
+ export type {
500
+ CliSpec, SpecState, ControlAction, Control,
501
+ NotificationRule, DelegateTrigger, Section,
502
+ } from './providers/spec/types.js';
503
+ export type { SpecEvaluation, TraceEntry } from './providers/spec/evaluator.js';
504
+ export { SpecDriver } from './providers/spec/driver.js';
505
+ export type { DashboardEvent, DashboardCommand, SpecDriverOpts } from './providers/spec/driver.js';
506
+ export { TerminalAdapter } from './providers/spec/adapter.js';
507
+ export type { TerminalAdapterOpts, TerminalAdapterHandlers } from './providers/spec/adapter.js';
508
+
509
+ // ── Provider SDK (v1) — selective re-exports for external tooling ──
510
+ // Tooling (registry publish, dashboard validators, the e2e harness) needs
511
+ // the manifest validator, the builder catalog, and the contract version.
512
+ // We don't re-export *everything* from the SDK to keep the public surface
513
+ // stable; consumers that need internal SDK types still import from the
514
+ // sdk/v1 subpath.
515
+ export {
516
+ validateCliProviderManifest,
517
+ formatManifestValidationIssues,
518
+ type ManifestValidationIssue,
519
+ type ManifestValidationResult,
520
+ V1_CONTRACT_VERSION,
521
+ V1_PRIMITIVE_CATALOG,
522
+ V1_ALL_PRIMITIVES,
523
+ } from './providers/sdk/v1/index.js';
@@ -31,7 +31,7 @@ export interface InstallResult {
31
31
  /**
32
32
  * Check if an extension is already installed
33
33
  */
34
- export declare function isExtensionInstalled(ide: IDEInfo, marketplaceId: string): boolean;
34
+ export declare function isExtensionInstalled(ide: IDEInfo, marketplaceId: string): Promise<boolean>;
35
35
  /**
36
36
  * Install a single extension
37
37
  */
package/src/installer.ts CHANGED
@@ -122,20 +122,22 @@ export interface InstallResult {
122
122
  /**
123
123
  * Check if an extension is already installed
124
124
  */
125
- export function isExtensionInstalled(
125
+ import { promisify } from 'util';
126
+ const execAsync = promisify(exec);
127
+
128
+ export async function isExtensionInstalled(
126
129
  ide: IDEInfo,
127
130
  marketplaceId: string
128
- ): boolean {
131
+ ): Promise<boolean> {
129
132
  if (!ide.cliCommand) return false;
130
133
 
131
134
  try {
132
- const result = execSync(`"${ide.cliCommand}" --list-extensions`, {
135
+ const { stdout } = await execAsync(`"${ide.cliCommand}" --list-extensions`, {
133
136
  encoding: 'utf-8',
134
137
  timeout: 15000,
135
- stdio: ['pipe', 'pipe', 'pipe'],
136
138
  });
137
139
 
138
- const installed = result
140
+ const installed = stdout
139
141
  .trim()
140
142
  .split('\n')
141
143
  .map((e) => e.trim().toLowerCase());
@@ -163,7 +165,7 @@ export async function installExtension(
163
165
  }
164
166
 
165
167
  // Check if already installed
166
- const alreadyInstalled = isExtensionInstalled(ide, extension.marketplaceId);
168
+ const alreadyInstalled = await isExtensionInstalled(ide, extension.marketplaceId);
167
169
  if (alreadyInstalled) {
168
170
  return {
169
171
  extensionId: extension.id,
@@ -0,0 +1,278 @@
1
+ /**
2
+ * LocalIpcServer — generic HTTP + WebSocket IPC endpoint for daemon processes.
3
+ *
4
+ * Both daemon-cloud and daemon-standalone need a local IPC surface so
5
+ * external tools — the `adhdev mcp --mode ipc` MCP server and anything
6
+ * else that wants to issue commands without going through the cloud
7
+ * Worker — can connect over `ws://127.0.0.1:<port>/ipc`.
8
+ *
9
+ * Until now the implementation lived only in daemon-cloud. Standalone
10
+ * sessions therefore couldn't host MCP mesh tools — codex/claude config
11
+ * pointing at `--mode ipc` got `Cannot reach ipc daemon`. This module
12
+ * moves the transport into daemon-core so both daemons can mount it.
13
+ *
14
+ * The transport itself is daemon-agnostic. Cloud-specific behaviors
15
+ * (mesh relay, mandatory update gates) are injected via the caller's
16
+ * `handleCommand` hook; the IPC layer just frames/unframes JSON and
17
+ * routes messages.
18
+ */
19
+
20
+ import { createServer, type IncomingMessage, type Server as HttpServer } from 'http';
21
+ import { WebSocketServer, WebSocket } from 'ws';
22
+ import { LOG } from '../logging/logger.js';
23
+ import { DAEMON_WS_PATH } from '../ipc-protocol.js';
24
+
25
+ /** Parameters passed to `handleCommand` for each incoming ext:command frame. */
26
+ export interface IpcCommandContext {
27
+ /** The raw `command` field from the message — caller decides routing. */
28
+ command: string;
29
+ /** Args provided by the client; may have been normalized by the caller. */
30
+ args: Record<string, unknown>;
31
+ /** Stable id correlating the request and the eventual ext:command_result. */
32
+ requestId: string;
33
+ /** The connected WebSocket — only needed if the caller wants to send extra events. */
34
+ ws: WebSocket;
35
+ }
36
+
37
+ /** Result reported back to the client. `result` is optional context for success. */
38
+ export interface IpcCommandResult {
39
+ success: boolean;
40
+ result?: unknown;
41
+ error?: string;
42
+ /**
43
+ * Additional fields the caller wants merged into the response payload
44
+ * (e.g. the cloud daemon's mandatory-update-block fields). Reserved.
45
+ */
46
+ extra?: Record<string, unknown>;
47
+ }
48
+
49
+ /** Status payload returned from GET / on the IPC HTTP port. */
50
+ export interface IpcStatusPayload {
51
+ ok: true;
52
+ pid: number;
53
+ wsPath: string;
54
+ port: number;
55
+ /** Arbitrary daemon-specific summary. Cloud daemon includes mesh state, etc. */
56
+ status: Record<string, unknown> | null;
57
+ }
58
+
59
+ export interface LocalIpcServerOptions {
60
+ /** TCP port to listen on. 19222 is the conventional default. */
61
+ port: number;
62
+ /** Build the GET / status payload. Called on every health probe. */
63
+ buildStatusPayload: () => Record<string, unknown> | null;
64
+ /** Build the welcome message sent to a freshly-connected client. */
65
+ buildWelcomePayload: () => Record<string, unknown>;
66
+ /** Handle a single ext:command frame. Caller decides routing and returns the result. */
67
+ handleCommand: (ctx: IpcCommandContext) => Promise<IpcCommandResult>;
68
+ /** Optional notification when a new client connects (lets daemon track them for broadcasts). */
69
+ onClientConnected?: (ws: WebSocket) => void;
70
+ /** Optional notification when a client disconnects. */
71
+ onClientDisconnected?: (ws: WebSocket) => void;
72
+ /** Optional logger label (defaults to "IPC"). */
73
+ logCategory?: string;
74
+ }
75
+
76
+ /**
77
+ * Returned controller for stopping the server and broadcasting to clients.
78
+ * Stored by the daemon and torn down at shutdown.
79
+ */
80
+ export interface LocalIpcServerHandle {
81
+ /** True once `listen()` succeeded. */
82
+ isListening(): boolean;
83
+ /** Push a message to every connected client. */
84
+ broadcast(type: string, payload: unknown): void;
85
+ /** Close all client sockets + the HTTP server. */
86
+ close(): Promise<void>;
87
+ }
88
+
89
+ /**
90
+ * Build a JSON HTTP response describing the IPC endpoint. Exposed so caller
91
+ * code (and tests) can build the same shape without spinning a real server.
92
+ */
93
+ export function buildIpcStatusHttpResponse(
94
+ method: string | undefined,
95
+ url: string | undefined,
96
+ payload: IpcStatusPayload,
97
+ ): { statusCode: number; body: Record<string, unknown> } {
98
+ if (method && method.toUpperCase() !== 'GET') {
99
+ return { statusCode: 405, body: { ok: false, error: 'method not allowed' } };
100
+ }
101
+ // `/health` is the probe path used by the MCP IpcTransport ping —
102
+ // mirror cloud daemon behavior so `adhdev mcp --mode ipc` recognizes
103
+ // us as a live IPC host. `/` and `/status` return the same shape.
104
+ if (url && url !== '/' && url !== '/status' && url !== '/health') {
105
+ return { statusCode: 404, body: { ok: false, error: 'not found' } };
106
+ }
107
+ return { statusCode: 200, body: payload as unknown as Record<string, unknown> };
108
+ }
109
+
110
+ /**
111
+ * Start the local IPC server. Returns a handle the caller can use to broadcast
112
+ * events and tear down at shutdown.
113
+ */
114
+ export async function startLocalIpcServer(opts: LocalIpcServerOptions): Promise<LocalIpcServerHandle> {
115
+ const logCategory = opts.logCategory || 'IPC';
116
+ const clients = new Set<WebSocket>();
117
+ let httpServer: HttpServer | null = null;
118
+ let wss: WebSocketServer | null = null;
119
+ let listening = false;
120
+
121
+ httpServer = createServer((req, res) => {
122
+ const payload: IpcStatusPayload = {
123
+ ok: true,
124
+ pid: process.pid,
125
+ wsPath: DAEMON_WS_PATH,
126
+ port: opts.port,
127
+ status: opts.buildStatusPayload(),
128
+ };
129
+ const response = buildIpcStatusHttpResponse(req.method, req.url, payload);
130
+ const body = JSON.stringify(response.body);
131
+ res.writeHead(response.statusCode, {
132
+ 'Content-Type': 'application/json',
133
+ 'Content-Length': Buffer.byteLength(body),
134
+ 'Connection': 'close',
135
+ });
136
+ res.end(body);
137
+ });
138
+
139
+ wss = new WebSocketServer({ noServer: true });
140
+ wss.on('connection', (ws) => handleConnection(ws));
141
+
142
+ httpServer.on('upgrade', (req: IncomingMessage, socket, head) => {
143
+ const wsUrl = new URL(req.url || '/', `http://${req.headers.host || '127.0.0.1'}`);
144
+ if (wsUrl.pathname !== DAEMON_WS_PATH) {
145
+ socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
146
+ socket.destroy();
147
+ return;
148
+ }
149
+ wss!.handleUpgrade(req, socket, head, (ws) => {
150
+ wss!.emit('connection', ws, req);
151
+ });
152
+ });
153
+
154
+ function handleConnection(ws: WebSocket): void {
155
+ clients.add(ws);
156
+ sendWelcome(ws);
157
+ opts.onClientConnected?.(ws);
158
+
159
+ ws.on('message', (raw) => {
160
+ void handleMessage(ws, raw.toString());
161
+ });
162
+ ws.on('close', () => {
163
+ clients.delete(ws);
164
+ opts.onClientDisconnected?.(ws);
165
+ });
166
+ ws.on('error', () => {
167
+ clients.delete(ws);
168
+ opts.onClientDisconnected?.(ws);
169
+ });
170
+ }
171
+
172
+ function sendWelcome(ws: WebSocket): void {
173
+ try {
174
+ ws.send(JSON.stringify({
175
+ type: 'daemon:welcome',
176
+ payload: opts.buildWelcomePayload(),
177
+ }));
178
+ } catch (error: any) {
179
+ LOG.warn(logCategory, `Failed to send welcome: ${error?.message || error}`);
180
+ }
181
+ }
182
+
183
+ async function handleMessage(ws: WebSocket, raw: string): Promise<void> {
184
+ let msg: any;
185
+ try { msg = JSON.parse(raw); } catch { return; }
186
+ if (!msg || typeof msg !== 'object') return;
187
+
188
+ // Re-issue welcome on client request (used by reconnecting MCP servers).
189
+ if (msg.type === 'ext:register') {
190
+ sendWelcome(ws);
191
+ return;
192
+ }
193
+ if (msg.type !== 'ext:command') return;
194
+
195
+ const payload = msg.payload && typeof msg.payload === 'object' ? msg.payload : {};
196
+ const command = typeof payload.command === 'string' ? payload.command : '';
197
+ const args = payload.args && typeof payload.args === 'object'
198
+ ? payload.args as Record<string, unknown>
199
+ : {};
200
+ const requestId = typeof payload.requestId === 'string'
201
+ ? payload.requestId
202
+ : typeof payload.messageId === 'string'
203
+ ? payload.messageId
204
+ : `ipc-${Date.now()}`;
205
+
206
+ if (!command) {
207
+ ws.send(JSON.stringify({
208
+ type: 'ext:command_result',
209
+ payload: { requestId, success: false, error: 'command required' },
210
+ }));
211
+ return;
212
+ }
213
+
214
+ try {
215
+ const result = await opts.handleCommand({ command, args, requestId, ws });
216
+ ws.send(JSON.stringify({
217
+ type: 'ext:command_result',
218
+ payload: {
219
+ requestId,
220
+ success: result.success,
221
+ result: result.result,
222
+ error: result.error,
223
+ ...(result.extra || {}),
224
+ },
225
+ }));
226
+ } catch (error: any) {
227
+ ws.send(JSON.stringify({
228
+ type: 'ext:command_result',
229
+ payload: {
230
+ requestId,
231
+ success: false,
232
+ error: error?.message || String(error),
233
+ },
234
+ }));
235
+ }
236
+ }
237
+
238
+ await new Promise<void>((resolve, reject) => {
239
+ const onError = (error: Error) => {
240
+ httpServer?.off('listening', onListening);
241
+ reject(error);
242
+ };
243
+ const onListening = () => {
244
+ httpServer?.off('error', onError);
245
+ listening = true;
246
+ resolve();
247
+ };
248
+ httpServer!.once('error', onError);
249
+ httpServer!.once('listening', onListening);
250
+ httpServer!.listen(opts.port, '127.0.0.1');
251
+ });
252
+
253
+ LOG.info(logCategory, `Local IPC listening on ws://127.0.0.1:${opts.port}${DAEMON_WS_PATH}`);
254
+
255
+ return {
256
+ isListening: () => listening,
257
+ broadcast(type, payload) {
258
+ const message = JSON.stringify({ type, payload });
259
+ for (const client of clients) {
260
+ if (client.readyState !== WebSocket.OPEN) continue;
261
+ try { client.send(message); } catch { /* drop silently */ }
262
+ }
263
+ },
264
+ async close() {
265
+ for (const client of clients) {
266
+ try { client.close(); } catch { /* ignore */ }
267
+ }
268
+ clients.clear();
269
+ await new Promise<void>((resolve) => {
270
+ if (!httpServer) { resolve(); return; }
271
+ httpServer.close(() => resolve());
272
+ });
273
+ httpServer = null;
274
+ wss = null;
275
+ listening = false;
276
+ },
277
+ };
278
+ }
package/src/launch.d.ts CHANGED
@@ -18,7 +18,7 @@
18
18
  /** Kill IDE process (graceful → force) */
19
19
  export declare function killIdeProcess(ideId: string): Promise<boolean>;
20
20
  /** Check if IDE process is running */
21
- export declare function isIdeRunning(ideId: string): boolean;
21
+ export declare function isIdeRunning(ideId: string): Promise<boolean>;
22
22
  export interface LaunchOptions {
23
23
  ideId?: string;
24
24
  workspace?: string;