@adhdev/daemon-core 0.9.82-rc.513 → 0.9.82-rc.514

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.513",
3
+ "version": "0.9.82-rc.514",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -47,8 +47,8 @@
47
47
  "author": "vilmire",
48
48
  "license": "AGPL-3.0-or-later",
49
49
  "dependencies": {
50
- "@adhdev/mesh-shared": "0.9.82-rc.513",
51
- "@adhdev/session-host-core": "0.9.82-rc.513",
50
+ "@adhdev/mesh-shared": "0.9.82-rc.514",
51
+ "@adhdev/session-host-core": "0.9.82-rc.514",
52
52
  "@agentclientprotocol/sdk": "^0.16.1",
53
53
  "ajv": "^8.20.0",
54
54
  "ajv-formats": "^3.0.1",
@@ -25,7 +25,7 @@ import { VersionArchive, detectAllVersions } from '../providers/version-archive.
25
25
  import { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
26
26
  import { DevServer } from '../daemon/dev-server.js';
27
27
  import { detectIDEs, type IDEInfo } from '../detection/ide-detector.js';
28
- import { detectCLI, detectCLIs, getCachedProviderVersions } from '../detection/cli-detector.js';
28
+ import { detectCLI, detectCLIs, getCachedProviderVersions, setDefaultProviderLoader } from '../detection/cli-detector.js';
29
29
  import { getDaemonBuildInfo } from '../build-info.js';
30
30
  import { SessionRegistry } from '../sessions/registry.js';
31
31
  import { LOG, installGlobalInterceptor } from '../logging/logger.js';
@@ -192,6 +192,12 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
192
192
  // commands (and the REST endpoint at /api/v1/providers/updates).
193
193
  providerLoader.loadAll();
194
194
  providerLoader.registerToDetector();
195
+ // Register this loader as the default for loader-less provider-version reads.
196
+ // The coordinator's own self/worktree node self-heal (mesh-node-identity.ts) reads
197
+ // getCachedProviderVersions() with no loader in scope; without this the detection
198
+ // list is empty and the self node's provider-version chips never populate, even
199
+ // though remote nodes (which self-report via the git_status envelope) do.
200
+ setDefaultProviderLoader(providerLoader);
195
201
 
196
202
  // 2.5 Provider version detection & archive
197
203
  // Run after startup work continues. The detector still performs expensive
@@ -555,6 +555,18 @@ export const meshStatusHandlers: Record<string, HighFamilyHandler> = {
555
555
  }
556
556
  applyInlineMeshBranchConvergence(mesh, node, status);
557
557
  finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode, directTruthUnavailable: directTruthUnavailableNodeIds.has(nodeId) });
558
+ // T7: providerVersions/daemonBuildVersion are stamped onto the initial
559
+ // status snapshot above from node.reported* — but recordInlineMeshDirectGitTruth
560
+ // (which self-heals those node fields from the local version cache for the
561
+ // coordinator's own self/worktree nodes) runs AFTER that snapshot. Re-sync from
562
+ // the now-stamped node here so the self node surfaces its chips in the same call
563
+ // rather than lagging a poll cycle. Additive; skipped when the node never reported.
564
+ if (node.reportedProviderVersions && typeof node.reportedProviderVersions === 'object') {
565
+ status.providerVersions = node.reportedProviderVersions;
566
+ }
567
+ if (typeof node.reportedDaemonBuildVersion === 'string' && node.reportedDaemonBuildVersion) {
568
+ status.daemonBuildVersion = node.reportedDaemonBuildVersion;
569
+ }
558
570
  return status;
559
571
  };
560
572
  const meshNodeEntries = [...(mesh.nodes || []).entries()];
@@ -235,11 +235,31 @@ let cachedProviderVersions: Record<string, string> = {};
235
235
  let cachedProviderVersionsAt = 0;
236
236
  let providerVersionsRefreshInFlight: Promise<void> | null = null;
237
237
 
238
+ // The daemon's active ProviderLoader, registered once at boot. detectCLIs only
239
+ // builds its detection list from a loader (no loader ⇒ empty list ⇒ empty version
240
+ // map), and getCachedProviderVersions is reachable on paths that have no loader in
241
+ // scope — most importantly the coordinator's own self/worktree node self-heal in
242
+ // mesh-node-identity.ts, which is a pure module with no daemon handle. Registering
243
+ // the loader here lets those loader-less reads still detect providers instead of
244
+ // silently returning {}. An explicit loader argument always wins over this default.
245
+ let defaultProviderLoader: ProviderLoader | undefined;
246
+
247
+ /**
248
+ * Register this daemon's ProviderLoader as the fallback used by loader-less
249
+ * provider-version reads (getCachedProviderVersions() with no argument). Called
250
+ * once at boot. Without it the coordinator's self node never resolves a CLI list,
251
+ * so its provider-version chips stay empty even though remote nodes populate.
252
+ */
253
+ export function setDefaultProviderLoader(providerLoader: ProviderLoader): void {
254
+ defaultProviderLoader = providerLoader;
255
+ }
256
+
238
257
  function refreshProviderVersionsSnapshot(providerLoader?: ProviderLoader): Promise<void> {
239
258
  if (providerVersionsRefreshInFlight) return providerVersionsRefreshInFlight;
259
+ const loader = providerLoader ?? defaultProviderLoader;
240
260
  providerVersionsRefreshInFlight = (async () => {
241
261
  try {
242
- const detected = await detectCLIs(providerLoader, { includeVersion: true });
262
+ const detected = await detectCLIs(loader, { includeVersion: true });
243
263
  cachedProviderVersions = buildProviderVersions(detected);
244
264
  cachedProviderVersionsAt = Date.now();
245
265
  } catch {