@adhdev/daemon-core 1.0.18-rc.18 → 1.0.18-rc.2

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 (82) hide show
  1. package/dist/cli-adapters/cli-state-engine.d.ts +0 -77
  2. package/dist/cli-adapters/provider-cli-shared.d.ts +0 -33
  3. package/dist/cli-adapters/pty-transport.d.ts +1 -2
  4. package/dist/commands/cli-manager.d.ts +0 -9
  5. package/dist/commands/upgrade-helper.d.ts +0 -1
  6. package/dist/commands/windows-atomic-upgrade.d.ts +1 -17
  7. package/dist/config/mesh-json-config.d.ts +0 -62
  8. package/dist/index.d.ts +2 -4
  9. package/dist/index.js +4143 -6578
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +4138 -6570
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/mesh/coordinator-prompt.d.ts +0 -76
  14. package/dist/mesh/mesh-active-work.d.ts +1 -1
  15. package/dist/mesh/mesh-ledger.d.ts +1 -28
  16. package/dist/mesh/mesh-node-identity.d.ts +0 -23
  17. package/dist/mesh/mesh-refine-gates.d.ts +0 -89
  18. package/dist/mesh/mesh-remote-event-pull.d.ts +0 -3
  19. package/dist/mesh/mesh-runtime-store.d.ts +0 -11
  20. package/dist/mesh/mesh-work-queue.d.ts +1 -24
  21. package/dist/providers/chat-message-normalization.d.ts +0 -22
  22. package/dist/providers/cli-provider-instance-types.d.ts +0 -4
  23. package/dist/providers/cli-provider-instance.d.ts +0 -78
  24. package/dist/providers/contracts.d.ts +0 -17
  25. package/dist/providers/provider-schema.d.ts +0 -1
  26. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +0 -14
  27. package/dist/providers/types/interactive-prompt.d.ts +0 -18
  28. package/dist/repo-mesh-types.d.ts +6 -38
  29. package/dist/shared-types.d.ts +2 -4
  30. package/package.json +3 -3
  31. package/src/boot/daemon-lifecycle.ts +0 -10
  32. package/src/cli-adapters/cli-state-engine.ts +3 -220
  33. package/src/cli-adapters/provider-cli-adapter.ts +11 -41
  34. package/src/cli-adapters/provider-cli-shared.ts +0 -41
  35. package/src/cli-adapters/pty-transport.d.ts +1 -2
  36. package/src/cli-adapters/pty-transport.ts +1 -1
  37. package/src/cli-adapters/session-host-transport.ts +3 -8
  38. package/src/commands/cli-manager.ts +8 -72
  39. package/src/commands/high-family/mesh-coordinator-launch.ts +2 -17
  40. package/src/commands/high-family/mesh-events.ts +2 -13
  41. package/src/commands/med-family/mesh-crud.ts +0 -155
  42. package/src/commands/med-family/mesh-queue.ts +1 -74
  43. package/src/commands/router-refine.ts +4 -71
  44. package/src/commands/router.ts +0 -8
  45. package/src/commands/upgrade-helper.ts +82 -106
  46. package/src/commands/windows-atomic-upgrade.ts +35 -281
  47. package/src/config/mesh-json-config.ts +0 -111
  48. package/src/index.ts +1 -21
  49. package/src/mesh/coordinator-prompt.ts +11 -258
  50. package/src/mesh/mesh-active-work.ts +1 -11
  51. package/src/mesh/mesh-completion-synthesis.ts +1 -12
  52. package/src/mesh/mesh-event-classify.ts +0 -19
  53. package/src/mesh/mesh-event-forwarding.ts +6 -64
  54. package/src/mesh/mesh-events-utils.ts +0 -42
  55. package/src/mesh/mesh-ledger.ts +0 -77
  56. package/src/mesh/mesh-node-identity.ts +0 -49
  57. package/src/mesh/mesh-queue-assignment.ts +11 -210
  58. package/src/mesh/mesh-reconcile-loop.ts +3 -306
  59. package/src/mesh/mesh-refine-gates.ts +0 -300
  60. package/src/mesh/mesh-remote-event-pull.ts +47 -68
  61. package/src/mesh/mesh-runtime-store.ts +0 -21
  62. package/src/mesh/mesh-work-queue.ts +2 -85
  63. package/src/providers/chat-message-normalization.ts +0 -53
  64. package/src/providers/cli-provider-instance-types.ts +0 -53
  65. package/src/providers/cli-provider-instance.ts +15 -497
  66. package/src/providers/contracts.ts +1 -25
  67. package/src/providers/provider-schema.ts +0 -83
  68. package/src/providers/sdk/v1/builders/cli/detect-status.ts +0 -23
  69. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +0 -20
  70. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +0 -44
  71. package/src/providers/types/interactive-prompt.ts +0 -77
  72. package/src/repo-mesh-types.ts +12 -112
  73. package/src/session-host/managed-host.ts +0 -34
  74. package/src/shared-types.ts +1 -9
  75. package/src/status/reporter.ts +0 -1
  76. package/src/status/snapshot.ts +0 -2
  77. package/dist/commands/process-lifecycle.d.ts +0 -43
  78. package/dist/mesh/mesh-disk-retention.d.ts +0 -105
  79. package/dist/providers/auto-approve-modes.d.ts +0 -14
  80. package/src/commands/process-lifecycle.ts +0 -248
  81. package/src/mesh/mesh-disk-retention.ts +0 -370
  82. package/src/providers/auto-approve-modes.ts +0 -97
@@ -4,18 +4,11 @@ import * as fs from 'fs';
4
4
  import * as os from 'os';
5
5
  import * as path from 'path';
6
6
  import {
7
- ADHDEV_OWNED_MARKERS,
8
7
  createDefaultWindowsAtomicHooks,
9
8
  findPortableNode22,
10
9
  performWindowsAtomicUpgrade,
11
10
  resolveWindowsInstallerLayout,
12
11
  } from './windows-atomic-upgrade.js';
13
- import {
14
- getProcessCommandLine,
15
- killProcess,
16
- stopOwnedProcessesForPrefixes,
17
- waitForPidExit,
18
- } from './process-lifecycle.js';
19
12
 
20
13
  const UPGRADE_HELPER_ENV = 'ADHDEV_DAEMON_UPGRADE_HELPER';
21
14
 
@@ -144,68 +137,19 @@ function resolveInstallPrefixFromPackageRoot(packageRoot: string, packageName: s
144
137
  return maybeLibDir;
145
138
  }
146
139
 
147
- // True when `prefix` is the bin dir of a portable Node 22 the installer manages
148
- // under ~/.adhdev/tools/node22/<node-vX>/. A `npm i -g adhdev` run while that
149
- // portable node is the active `node` installs adhdev into node's own default
150
- // global prefix (= that dir) — a "legacy node22-prefix" install that lives at
151
- // the FRONT of PATH (Enable-NodePath prepends node22) and shadows the canonical
152
- // dispatcher shims in ~/.adhdev/npm-global. Because self-upgrade reuses the
153
- // running prefix, that install then re-installs into the same node22 dir forever
154
- // and never converts to the dispatcher. Detecting it lets us force convergence.
155
- function isPortableNode22Prefix(prefix: string | null, homeDir: string): boolean {
156
- if (!prefix) return false;
157
- const portableRoot = path.join(homeDir, '.adhdev', 'tools', 'node22');
158
- const normalizedPrefix = path.resolve(prefix).replace(/[\\/]+$/, '').toLowerCase();
159
- const normalizedRoot = path.resolve(portableRoot).replace(/[\\/]+$/, '').toLowerCase();
160
- return normalizedPrefix === normalizedRoot || normalizedPrefix.startsWith(`${normalizedRoot}${path.sep.toLowerCase()}`);
161
- }
162
-
163
- // Redirect a legacy node22-prefix install to the canonical dispatcher install
164
- // root so resolveWindowsInstallerLayout accepts it and the atomic-upgrade
165
- // publishes the ~/.adhdev/npm-global pointer + shims. Prefer the version the
166
- // dispatcher pointer already names (so we sit on the real active dispatcher
167
- // prefix); otherwise synthesize a stable migration sentinel under npm-installs.
168
- // resolveWindowsInstallerLayout only requires a `npm-installs/version-*` path —
169
- // performWindowsAtomicUpgrade stages a fresh version- prefix of its own and uses
170
- // this only as the "old prefix" to stop/clean, so a non-existent path is a no-op.
171
- function canonicalDispatcherInstallPrefix(homeDir: string): string {
172
- const installRoot = path.join(homeDir, '.adhdev', 'npm-installs');
173
- const pointerPath = path.join(homeDir, '.adhdev', 'npm-global', '.adhdev-current');
174
- try {
175
- const activeVersion = fs.readFileSync(pointerPath, 'utf8').trim();
176
- if (activeVersion.startsWith('version-')) return path.join(installRoot, activeVersion);
177
- } catch {
178
- // No dispatcher pointer yet (first migration off the legacy layout).
179
- }
180
- return path.join(installRoot, 'version-legacy-migrate');
181
- }
182
-
183
140
  export function resolveCurrentGlobalInstallSurface(options: {
184
141
  packageName: string;
185
142
  currentCliPath?: string;
186
143
  nodeExecutable?: string;
187
144
  platform?: NodeJS.Platform;
188
- homeDir?: string;
189
145
  }): CurrentGlobalInstallSurface {
190
146
  const packageRoot = findCurrentPackageRoot(options.currentCliPath || process.argv[1], options.packageName);
191
147
  const npmInvocation = resolveSiblingNpmInvocation(options.nodeExecutable || process.execPath, options.platform);
192
- const platform = options.platform || process.platform;
193
- const homeDir = options.homeDir || os.homedir();
194
- let installPrefix = packageRoot ? resolveInstallPrefixFromPackageRoot(packageRoot, options.packageName) : null;
195
- // FIX C: on Windows, never let a self-upgrade perpetuate the legacy
196
- // node22-prefix install. If the running adhdev lives under ~/.adhdev/tools/
197
- // node22, force the install onto the canonical dispatcher prefix so the update
198
- // converges to the ~/.adhdev/npm-global pointer + shims. Scoped to win32 AND a
199
- // tools/node22 prefix so npm-linked dev / standalone / real dispatcher installs
200
- // are untouched.
201
- if (platform === 'win32' && isPortableNode22Prefix(installPrefix, homeDir)) {
202
- installPrefix = canonicalDispatcherInstallPrefix(homeDir);
203
- }
204
148
  return {
205
149
  npmExecutable: npmInvocation.executable,
206
150
  npmArgsPrefix: npmInvocation.argsPrefix,
207
151
  packageRoot,
208
- installPrefix,
152
+ installPrefix: packageRoot ? resolveInstallPrefixFromPackageRoot(packageRoot, options.packageName) : null,
209
153
  execOptions: npmInvocation.execOptions,
210
154
  };
211
155
  }
@@ -291,11 +235,77 @@ export function execNpmCommandSync(
291
235
  );
292
236
  }
293
237
 
238
+ function killPid(pid: number): boolean {
239
+ try {
240
+ if (process.platform === 'win32') {
241
+ execFileSync('taskkill', ['/PID', String(pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true });
242
+ } else {
243
+ process.kill(pid, 'SIGTERM');
244
+ }
245
+ return true;
246
+ } catch {
247
+ return false;
248
+ }
249
+ }
250
+
251
+ function getWindowsProcessCommandLine(pid: number): string | null {
252
+ const pidFilter = `ProcessId=${pid}`;
253
+ try {
254
+ const psOut = execFileSync('powershell.exe', [
255
+ '-NoProfile',
256
+ '-NonInteractive',
257
+ '-ExecutionPolicy', 'Bypass',
258
+ '-Command',
259
+ `(Get-CimInstance Win32_Process -Filter "${pidFilter}").CommandLine`,
260
+ ], { encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }).trim();
261
+ if (psOut) return psOut;
262
+ } catch {
263
+ // fall through to wmic fallback
264
+ }
265
+
266
+ try {
267
+ const wmicOut = execFileSync('wmic', [
268
+ 'process', 'where', pidFilter, 'get', 'CommandLine',
269
+ ], { encoding: 'utf8', timeout: 3000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }).trim();
270
+ if (wmicOut) return wmicOut;
271
+ } catch {
272
+ // noop
273
+ }
274
+ return null;
275
+ }
276
+
277
+ function getProcessCommandLine(pid: number): string | null {
278
+ if (!Number.isFinite(pid) || pid <= 0) return null;
279
+ if (process.platform === 'win32') return getWindowsProcessCommandLine(pid);
280
+ try {
281
+ const text = execFileSync('ps', ['-o', 'command=', '-p', String(pid)], {
282
+ encoding: 'utf8',
283
+ timeout: 3000,
284
+ stdio: ['ignore', 'pipe', 'ignore'],
285
+ }).trim();
286
+ return text || null;
287
+ } catch {
288
+ return null;
289
+ }
290
+ }
291
+
294
292
  function isManagedSessionHostPid(pid: number): boolean {
295
293
  const commandLine = getProcessCommandLine(pid);
296
294
  return !!commandLine && /session-host-daemon/i.test(commandLine);
297
295
  }
298
296
 
297
+ async function waitForPidExit(pid: number, timeoutMs: number): Promise<void> {
298
+ const start = Date.now();
299
+ while (Date.now() - start < timeoutMs) {
300
+ try {
301
+ process.kill(pid, 0);
302
+ await new Promise((resolve) => setTimeout(resolve, 250));
303
+ } catch {
304
+ return;
305
+ }
306
+ }
307
+ }
308
+
299
309
  export async function stopSessionHostProcesses(appName: string): Promise<void> {
300
310
  const pidFile = path.join(os.homedir(), '.adhdev', `${appName}-session-host.pid`);
301
311
  let killedPid: number | null = null;
@@ -303,7 +313,7 @@ export async function stopSessionHostProcesses(appName: string): Promise<void> {
303
313
  if (fs.existsSync(pidFile)) {
304
314
  const pid = Number.parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
305
315
  if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
306
- if (killProcess(pid)) killedPid = pid;
316
+ if (killPid(pid)) killedPid = pid;
307
317
  }
308
318
  }
309
319
  } catch {
@@ -420,7 +430,7 @@ export async function stopForeignNativeAddonHolders(
420
430
  appendUpgradeLog(
421
431
  `Foreign native-addon holder found: pid ${holder.pid}${holder.commandLine ? ` — ${holder.commandLine}` : ''}`,
422
432
  );
423
- const killed = killProcess(holder.pid);
433
+ const killed = killPid(holder.pid);
424
434
  if (killed) {
425
435
  await waitForPidExit(holder.pid, 15000);
426
436
  appendUpgradeLog(`Terminated foreign native-addon holder pid ${holder.pid}`);
@@ -590,55 +600,21 @@ async function runDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): Prom
590
600
  throw new Error(`portable Node.js 22 npm CLI is missing: ${npmCliPath}`);
591
601
  }
592
602
  appendUpgradeLog(`Installer-managed pointer layout detected; active prefix will remain untouched: ${windowsInstallerLayout.activePrefix}`);
593
-
594
- // Terminate any ADHDev-owned process still executing from the current active
595
- // prefix or the legacy stable shim tree before activation. The parent daemon
596
- // and this helper itself are excluded: the parent is already exiting, and the
597
- // helper must survive to complete the upgrade.
598
- const upgradePids = [process.pid, payload.parentPid].filter((n): n is number => Number.isFinite(n) && n > 0);
599
- const preStop = await stopOwnedProcessesForPrefixes({
600
- prefixes: [windowsInstallerLayout.activePrefix, windowsInstallerLayout.stablePrefix],
601
- excludePids: upgradePids,
602
- markers: Array.from(ADHDEV_OWNED_MARKERS),
603
- waitMs: 15_000,
604
- log: appendUpgradeLog,
605
- });
606
- if (preStop.survivors.length > 0) {
607
- throw new Error(
608
- `Cannot upgrade: owned processes still running under current prefix: ${preStop.survivors.map((s) => s.pid).join(', ')}`
609
- );
610
- }
611
-
612
- try {
613
- await performWindowsAtomicUpgrade({
614
- layout: windowsInstallerLayout,
603
+ await performWindowsAtomicUpgrade({
604
+ layout: windowsInstallerLayout,
605
+ packageName: payload.packageName,
606
+ targetVersion: payload.targetVersion,
607
+ portableNode,
608
+ hooks: createDefaultWindowsAtomicHooks({
615
609
  packageName: payload.packageName,
616
610
  targetVersion: payload.targetVersion,
617
- portableNode,
618
- excludePids: upgradePids,
619
- hooks: createDefaultWindowsAtomicHooks({
620
- packageName: payload.packageName,
621
- targetVersion: payload.targetVersion,
622
- npmCliPath,
623
- restartArgv,
624
- cwd: payload.cwd || process.cwd(),
625
- env: Object.fromEntries(Object.entries(process.env).filter(([key]) => key !== UPGRADE_HELPER_ENV)),
626
- log: appendUpgradeLog,
627
- }),
628
- });
629
- } catch (error: any) {
630
- // performWindowsAtomicUpgrade already rolled the pointer/shims back to the
631
- // prior version before rethrowing. Without a durable notice that rollback
632
- // was silent — the daemon simply kept running the old version (the rc.6
633
- // stuck-upgrade defect). Leave an actionable last-error file naming the
634
- // target that failed its health/version gate.
635
- emitUpgradeFailureNotice([
636
- `adhdev ${payload.packageName}@${payload.targetVersion} upgrade failed and was rolled back: ${error?.message || String(error)}`,
637
- `Previous version preserved (active prefix: ${windowsInstallerLayout.activePrefix}).`,
638
- 'See daemon-upgrade.log for the full install/health trace. The next daemon start will retry.',
639
- ]);
640
- throw error;
641
- }
611
+ npmCliPath,
612
+ restartArgv,
613
+ cwd: payload.cwd || process.cwd(),
614
+ env: Object.fromEntries(Object.entries(process.env).filter(([key]) => key !== UPGRADE_HELPER_ENV)),
615
+ log: appendUpgradeLog,
616
+ }),
617
+ });
642
618
  try { fs.unlinkSync(getUpgradeFailureNoticePath()); } catch { /* no previous failure notice */ }
643
619
  appendUpgradeLog('Installer-managed Windows atomic upgrade completed');
644
620
  return;