@adhdev/daemon-core 0.8.30 → 0.8.32

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 (57) hide show
  1. package/dist/agent-stream/manager.d.ts +1 -0
  2. package/dist/agent-stream/provider-adapter.d.ts +1 -0
  3. package/dist/agent-stream/types.d.ts +3 -0
  4. package/dist/boot/daemon-lifecycle.d.ts +2 -1
  5. package/dist/cdp/manager.d.ts +2 -0
  6. package/dist/cli-adapter-types.d.ts +34 -5
  7. package/dist/cli-adapters/provider-cli-adapter.d.ts +4 -158
  8. package/dist/cli-adapters/provider-cli-config.d.ts +30 -0
  9. package/dist/cli-adapters/provider-cli-parse.d.ts +42 -0
  10. package/dist/cli-adapters/provider-cli-runtime.d.ts +29 -0
  11. package/dist/cli-adapters/provider-cli-shared.d.ts +158 -0
  12. package/dist/commands/handler.d.ts +4 -3
  13. package/dist/config/config.d.ts +4 -3
  14. package/dist/index.js +866 -592
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +868 -595
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/providers/contracts.d.ts +10 -1
  19. package/dist/providers/provider-loader.d.ts +3 -0
  20. package/dist/status/reporter.d.ts +2 -3
  21. package/dist/status/snapshot.d.ts +2 -1
  22. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  23. package/package.json +3 -1
  24. package/src/agent-stream/manager.ts +8 -2
  25. package/src/agent-stream/poller.ts +19 -5
  26. package/src/agent-stream/provider-adapter.ts +11 -7
  27. package/src/agent-stream/types.ts +3 -0
  28. package/src/boot/daemon-lifecycle.ts +7 -6
  29. package/src/cdp/initializer.ts +2 -2
  30. package/src/cdp/manager.ts +5 -0
  31. package/src/cdp/setup.ts +1 -1
  32. package/src/cli-adapter-types.ts +37 -5
  33. package/src/cli-adapters/provider-cli-adapter.ts +212 -795
  34. package/src/cli-adapters/provider-cli-config.ts +66 -0
  35. package/src/cli-adapters/provider-cli-parse.ts +202 -0
  36. package/src/cli-adapters/provider-cli-runtime.ts +142 -0
  37. package/src/cli-adapters/provider-cli-shared.ts +439 -0
  38. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +1 -1
  39. package/src/commands/cdp-commands.ts +6 -1
  40. package/src/commands/chat-commands.ts +45 -29
  41. package/src/commands/cli-manager.ts +28 -9
  42. package/src/commands/handler.ts +14 -10
  43. package/src/commands/router.ts +23 -10
  44. package/src/commands/stream-commands.ts +11 -5
  45. package/src/config/config.ts +4 -10
  46. package/src/daemon/dev-auto-implement.ts +22 -18
  47. package/src/daemon/dev-cli-debug.ts +59 -16
  48. package/src/daemon/dev-server.ts +67 -43
  49. package/src/providers/acp-provider-instance.ts +1 -1
  50. package/src/providers/cli-provider-instance.ts +2 -2
  51. package/src/providers/contracts.ts +12 -1
  52. package/src/providers/extension-provider-instance.ts +1 -1
  53. package/src/providers/ide-provider-instance.ts +39 -18
  54. package/src/providers/provider-loader.ts +85 -54
  55. package/src/providers/version-archive.ts +23 -5
  56. package/src/status/reporter.ts +18 -14
  57. package/src/status/snapshot.ts +5 -4
@@ -21,6 +21,7 @@ import { registerIDEDefinition } from '../detection/ide-detector.js';
21
21
  import { LOG } from '../logging/logger.js';
22
22
  import { VersionArchive } from './version-archive.js';
23
23
  import type {
24
+ ProviderCompatibilityEntry,
24
25
  ProviderModule,
25
26
  ProviderCategory,
26
27
  ProviderScripts,
@@ -43,7 +44,7 @@ export class ProviderLoader {
43
44
  private watchers: any[] = [];
44
45
  private logFn: (msg: string) => void;
45
46
  private versionArchive: VersionArchive | null = null;
46
- private scriptsCache = new Map<string, Record<string, any>>();
47
+ private scriptsCache = new Map<string, Partial<ProviderScripts>>();
47
48
 
48
49
  /** Inject VersionArchive so resolve() can auto-detect installed versions */
49
50
  setVersionArchive(archive: VersionArchive): void {
@@ -240,10 +241,7 @@ export class ProviderLoader {
240
241
  const result: { id: string; displayName: string; icon: string; command: string; category: string; versionCommand?: string }[] = [];
241
242
  for (const p of this.providers.values()) {
242
243
  if ((p.category === 'cli' || p.category === 'acp') && p.spawn?.command) {
243
- const verCmdConfig = (p as any).versionCommand;
244
- const versionCommand = typeof verCmdConfig === 'object' && verCmdConfig !== null
245
- ? verCmdConfig[process.platform]
246
- : verCmdConfig;
244
+ const versionCommand = this.getPlatformVersionCommand(p.versionCommand);
247
245
  const command = this.getSpawnCommand(p.type, p.spawn.command);
248
246
  result.push({
249
247
  id: p.type,
@@ -304,8 +302,8 @@ export class ProviderLoader {
304
302
  * that runtime attach/remove uses.
305
303
  */
306
304
  getIdeExtensionEnabledState(ideType: string, extensionType: string): boolean {
307
- const { loadConfig } = require('../config/config.js');
308
- const config = loadConfig();
305
+ const config = this.readConfig();
306
+ if (!config) return false;
309
307
  const baseIdeType = ideType.split('_')[0];
310
308
  const val = config.ideSettings?.[baseIdeType]?.extensions?.[extensionType]?.enabled;
311
309
  return val === true;
@@ -315,15 +313,16 @@ export class ProviderLoader {
315
313
  * Save IDE extension enabled setting
316
314
  */
317
315
  setIdeExtensionEnabled(ideType: string, extensionType: string, enabled: boolean): boolean {
316
+ const config = this.readConfig();
317
+ if (!config) return false;
318
+
318
319
  try {
319
- const { loadConfig, saveConfig } = require('../config/config.js');
320
- const config = loadConfig();
321
320
  const baseIdeType = ideType.split('_')[0];
322
321
  if (!config.ideSettings) config.ideSettings = {};
323
322
  if (!config.ideSettings[baseIdeType]) config.ideSettings[baseIdeType] = {};
324
323
  if (!config.ideSettings[baseIdeType].extensions) config.ideSettings[baseIdeType].extensions = {};
325
324
  config.ideSettings[baseIdeType].extensions[extensionType] = { enabled };
326
- saveConfig(config);
325
+ this.writeConfig(config);
327
326
  this.log(`IDE extension setting: ${ideType}.${extensionType}.enabled = ${enabled}`);
328
327
  return true;
329
328
  } catch (e) {
@@ -545,8 +544,8 @@ export class ProviderLoader {
545
544
  resolved._resolvedVersion = currentVersion;
546
545
 
547
546
  // --- New format: compatibility array ---
548
- if (Array.isArray((base as any).compatibility)) {
549
- const compat = (base as any).compatibility as { ideVersion: string; scriptDir: string }[];
547
+ if (base.compatibility) {
548
+ const compat = base.compatibility;
550
549
  let matched = false;
551
550
 
552
551
  for (const entry of compat) {
@@ -570,15 +569,15 @@ export class ProviderLoader {
570
569
  }
571
570
 
572
571
  // No compatibility match → defaultScriptDir
573
- if (!matched && (base as any).defaultScriptDir) {
574
- const loaded = this.loadScriptsFromDir(type, (base as any).defaultScriptDir);
572
+ if (!matched && base.defaultScriptDir) {
573
+ const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
575
574
  if (loaded) {
576
575
  resolved.scripts = loaded;
577
- this.log(` [compatibility] ${type} v${currentVersion} → default: ${(base as any).defaultScriptDir}`);
578
- resolved._resolvedScriptDir = (base as any).defaultScriptDir;
576
+ this.log(` [compatibility] ${type} v${currentVersion} → default: ${base.defaultScriptDir}`);
577
+ resolved._resolvedScriptDir = base.defaultScriptDir;
579
578
  resolved._resolvedScriptsSource = 'defaultScriptDir:version_miss';
580
579
  if (providerDir) {
581
- const fullDir = path.join(providerDir, (base as any).defaultScriptDir);
580
+ const fullDir = path.join(providerDir, base.defaultScriptDir);
582
581
  resolved._resolvedScriptsPath = fs.existsSync(path.join(fullDir, 'scripts.js'))
583
582
  ? path.join(fullDir, 'scripts.js')
584
583
  : fullDir;
@@ -592,7 +591,7 @@ export class ProviderLoader {
592
591
  for (const [range, override] of Object.entries(base.versions)) {
593
592
  if (!this.matchesVersion(currentVersion, range)) continue;
594
593
 
595
- const dirOverride = (override as any).__dir as string | undefined;
594
+ const dirOverride = override.__dir;
596
595
  if (dirOverride) {
597
596
  const loaded = this.loadScriptsFromDir(type, dirOverride);
598
597
  if (loaded) {
@@ -612,16 +611,16 @@ export class ProviderLoader {
612
611
  }
613
612
  }
614
613
  }
615
- } else if (Array.isArray((base as any).compatibility) && (base as any).defaultScriptDir) {
614
+ } else if (base.compatibility && base.defaultScriptDir) {
616
615
  // No version detected but compatibility format → use defaultScriptDir
617
- const loaded = this.loadScriptsFromDir(type, (base as any).defaultScriptDir);
616
+ const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
618
617
  if (loaded) {
619
618
  resolved.scripts = loaded;
620
- this.log(` [compatibility] ${type} no version detected → default: ${(base as any).defaultScriptDir}`);
621
- resolved._resolvedScriptDir = (base as any).defaultScriptDir;
619
+ this.log(` [compatibility] ${type} no version detected → default: ${base.defaultScriptDir}`);
620
+ resolved._resolvedScriptDir = base.defaultScriptDir;
622
621
  resolved._resolvedScriptsSource = 'defaultScriptDir:no_version';
623
622
  if (providerDir) {
624
- const fullDir = path.join(providerDir, (base as any).defaultScriptDir);
623
+ const fullDir = path.join(providerDir, base.defaultScriptDir);
625
624
  resolved._resolvedScriptsPath = fs.existsSync(path.join(fullDir, 'scripts.js'))
626
625
  ? path.join(fullDir, 'scripts.js')
627
626
  : fullDir;
@@ -647,7 +646,7 @@ export class ProviderLoader {
647
646
  * Load scripts from a scriptDir within a provider directory.
648
647
  * Tries scripts.js first, then individual .js files.
649
648
  */
650
- private loadScriptsFromDir(type: string, scriptDir: string): Record<string, any> | null {
649
+ private loadScriptsFromDir(type: string, scriptDir: string): Partial<ProviderScripts> | null {
651
650
  const providerDir = this.findProviderDirInternal(type);
652
651
  if (!providerDir) {
653
652
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
@@ -679,7 +678,7 @@ export class ProviderLoader {
679
678
  }
680
679
 
681
680
  // Fallback: build from individual .js files
682
- const result = this.buildScriptWrappersFromDir(dir) as Record<string, any>;
681
+ const result = this.buildScriptWrappersFromDir(dir);
683
682
  this.scriptsCache.set(dir, result);
684
683
  return result;
685
684
  }
@@ -973,8 +972,8 @@ export class ProviderLoader {
973
972
  getPublicSettings(type: string): ProviderSettingSchema[] {
974
973
  const settings = this.getSettingsSchema(type);
975
974
  return Object.entries(settings)
976
- .filter(([, def]) => (def as any).public === true)
977
- .map(([key, def]) => ({ key, ...(def as any) }));
975
+ .filter(([, def]) => def.public === true)
976
+ .map(([key, def]) => ({ key, ...def }));
978
977
  }
979
978
 
980
979
  /**
@@ -995,20 +994,14 @@ export class ProviderLoader {
995
994
  getSettingValue(type: string, key: string): any {
996
995
  const schemaDef = this.getSettingsSchema(type)[key];
997
996
  const defaultVal = schemaDef
998
- ? (key === 'autoApprove' && (schemaDef as any).type === 'boolean'
997
+ ? (key === 'autoApprove' && schemaDef.type === 'boolean'
999
998
  ? true
1000
- : (schemaDef as any).default)
999
+ : schemaDef.default)
1001
1000
  : undefined;
1002
1001
 
1003
- // Load user-saved value
1004
- try {
1005
- const { loadConfig } = require('../config/config.js');
1006
- const config = loadConfig();
1007
- const userVal = config.providerSettings?.[type]?.[key];
1008
- return userVal !== undefined ? userVal : defaultVal;
1009
- } catch {
1010
- return defaultVal;
1011
- }
1002
+ const config = this.readConfig();
1003
+ const userVal = config?.providerSettings?.[type]?.[key];
1004
+ return userVal !== undefined ? userVal : defaultVal;
1012
1005
  }
1013
1006
 
1014
1007
  /**
@@ -1027,7 +1020,7 @@ export class ProviderLoader {
1027
1020
  * Save provider setting value (writes to config.json)
1028
1021
  */
1029
1022
  setSetting(type: string, key: string, value: any): boolean {
1030
- const schemaDef = this.getSettingsSchema(type)[key] as any;
1023
+ const schemaDef = this.getSettingsSchema(type)[key];
1031
1024
  if (!schemaDef) return false;
1032
1025
 
1033
1026
  // Non-public settings cannot be modified externally
@@ -1043,13 +1036,14 @@ export class ProviderLoader {
1043
1036
  }
1044
1037
  if (schemaDef.type === 'select' && schemaDef.options && !schemaDef.options.includes(value)) return false;
1045
1038
 
1039
+ const config = this.readConfig();
1040
+ if (!config) return false;
1041
+
1046
1042
  try {
1047
- const { loadConfig, saveConfig } = require('../config/config.js');
1048
- const config = loadConfig();
1049
1043
  if (!config.providerSettings) config.providerSettings = {};
1050
1044
  if (!config.providerSettings[type]) config.providerSettings[type] = {};
1051
1045
  config.providerSettings[type][key] = value;
1052
- saveConfig(config);
1046
+ this.writeConfig(config);
1053
1047
  this.log(`Setting updated: ${type}.${key} = ${JSON.stringify(value)}`);
1054
1048
  return true;
1055
1049
  } catch (e) {
@@ -1065,6 +1059,37 @@ export class ProviderLoader {
1065
1059
  return trimmed ? trimmed : null;
1066
1060
  }
1067
1061
 
1062
+ protected readConfig(): any | null {
1063
+ try {
1064
+ const { loadConfig } = require('../config/config.js');
1065
+ return loadConfig();
1066
+ } catch {
1067
+ return null;
1068
+ }
1069
+ }
1070
+
1071
+ protected writeConfig(config: any): void {
1072
+ const { saveConfig } = require('../config/config.js');
1073
+ saveConfig(config);
1074
+ }
1075
+
1076
+ private getPlatformVersionCommand(versionCommand?: ProviderModule['versionCommand']): string | undefined {
1077
+ if (!versionCommand) return undefined;
1078
+ if (typeof versionCommand === 'string') {
1079
+ const trimmed = versionCommand.trim();
1080
+ return trimmed || undefined;
1081
+ }
1082
+ const platformValue = versionCommand[process.platform];
1083
+ if (typeof platformValue === 'string' && platformValue.trim()) {
1084
+ return platformValue.trim();
1085
+ }
1086
+ const defaultValue = versionCommand.default;
1087
+ if (typeof defaultValue === 'string' && defaultValue.trim()) {
1088
+ return defaultValue.trim();
1089
+ }
1090
+ return undefined;
1091
+ }
1092
+
1068
1093
  private getSettingsSchema(type: string): Record<string, ProviderSettingDef> {
1069
1094
  const provider = this.providers.get(type);
1070
1095
  if (!provider) return {};
@@ -1192,7 +1217,7 @@ export class ProviderLoader {
1192
1217
  if (!file.endsWith('.js')) continue;
1193
1218
  const scriptName = toCamel(file.replace('.js', ''));
1194
1219
  const filePath = path.join(dir, file);
1195
- (result as any)[scriptName] = (...args: any[]): string => {
1220
+ result[scriptName] = (...args: any[]): string => {
1196
1221
  try {
1197
1222
  let content = fs.readFileSync(filePath, 'utf-8');
1198
1223
  if (args[0] && typeof args[0] === 'object') {
@@ -1259,40 +1284,46 @@ export class ProviderLoader {
1259
1284
  const jsonPath = path.join(d, 'provider.json');
1260
1285
  try {
1261
1286
  const raw = fs.readFileSync(jsonPath, 'utf-8');
1262
- const mod = JSON.parse(raw) as ProviderModule;
1287
+ const mod = JSON.parse(raw) as Omit<ProviderModule, 'extensionIdPattern'> & {
1288
+ extensionIdPattern?: RegExp | string;
1289
+ };
1263
1290
 
1264
1291
  if (!mod.type || !mod.name || !mod.category) {
1265
1292
  this.log(`⚠ Invalid provider at ${jsonPath}: missing type/name/category`);
1266
1293
  } else {
1267
1294
  // Restore RegExp fields from JSON (extensionIdPattern)
1268
- if ((mod as any).extensionIdPattern && typeof (mod as any).extensionIdPattern === 'string') {
1269
- const flags = (mod as any).extensionIdPattern_flags || '';
1270
- (mod as any).extensionIdPattern = new RegExp((mod as any).extensionIdPattern, flags);
1271
- delete (mod as any).extensionIdPattern_flags;
1295
+ if (typeof mod.extensionIdPattern === 'string') {
1296
+ const flags = mod.extensionIdPattern_flags || '';
1297
+ mod.extensionIdPattern = new RegExp(mod.extensionIdPattern, flags);
1272
1298
  }
1299
+ const { extensionIdPattern_flags, extensionIdPattern, ...providerFields } = mod;
1300
+ const normalizedProvider: ProviderModule = {
1301
+ ...providerFields,
1302
+ ...(extensionIdPattern instanceof RegExp ? { extensionIdPattern } : {}),
1303
+ };
1273
1304
 
1274
1305
  // Load scripts.js if exists (IDE/Extension)
1275
1306
  // Skip for compatibility-format providers — scripts loaded lazily in resolve()
1276
- const hasCompatibility = Array.isArray((mod as any).compatibility);
1307
+ const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
1277
1308
  const scriptsPath = path.join(d, 'scripts.js');
1278
1309
  if (!hasCompatibility && fs.existsSync(scriptsPath)) {
1279
1310
  try {
1280
1311
  delete require.cache[require.resolve(scriptsPath)];
1281
- const scripts = require(scriptsPath);
1282
- mod.scripts = scripts;
1312
+ const scripts = require(scriptsPath) as Partial<ProviderScripts>;
1313
+ normalizedProvider.scripts = scripts;
1283
1314
  } catch (e) {
1284
1315
  this.log(`⚠ Failed to load scripts: ${scriptsPath}: ${(e as Error).message}`);
1285
1316
  }
1286
1317
  }
1287
1318
 
1288
- const existed = this.providers.has(mod.type);
1289
- this.providers.set(mod.type, mod);
1319
+ const existed = this.providers.has(normalizedProvider.type);
1320
+ this.providers.set(normalizedProvider.type, normalizedProvider);
1290
1321
  count++;
1291
1322
  // Identify source tier for debugging
1292
1323
  const source = d.startsWith(this.userDir) && !d.includes('.upstream')
1293
1324
  ? 'user' : 'upstream';
1294
1325
  const overrideWarning = existed && source === 'user' ? ' ⚠ OVERRIDES upstream' : '';
1295
- this.log(` ${existed ? '🔄' : '✅'} ${mod.type} (${mod.category}) — ${mod.name} [${source}]${overrideWarning}`);
1326
+ this.log(` ${existed ? '🔄' : '✅'} ${normalizedProvider.type} (${normalizedProvider.category}) — ${normalizedProvider.name} [${source}]${overrideWarning}`);
1296
1327
  }
1297
1328
  } catch (e) {
1298
1329
  this.log(`⚠ Failed to load ${jsonPath}: ${(e as Error).message}`);
@@ -15,6 +15,7 @@ import * as os from 'os';
15
15
  import { execSync } from 'child_process';
16
16
  import { platform } from 'os';
17
17
  import type { ProviderLoader } from './provider-loader.js';
18
+ import type { ProviderModule } from './contracts.js';
18
19
 
19
20
  // ─── Types ──────────────────────────────────────
20
21
 
@@ -141,6 +142,26 @@ function parseVersion(raw: string): string {
141
142
  return match ? match[1] : raw.split('\n')[0].substring(0, 100);
142
143
  }
143
144
 
145
+ function getPlatformVersionCommand(
146
+ versionCommand: ProviderModule['versionCommand'],
147
+ currentOs: string,
148
+ ): string | undefined {
149
+ if (!versionCommand) return undefined;
150
+ if (typeof versionCommand === 'string') {
151
+ const trimmed = versionCommand.trim();
152
+ return trimmed || undefined;
153
+ }
154
+ const platformValue = versionCommand[currentOs];
155
+ if (typeof platformValue === 'string' && platformValue.trim()) {
156
+ return platformValue.trim();
157
+ }
158
+ const defaultValue = versionCommand.default;
159
+ if (typeof defaultValue === 'string' && defaultValue.trim()) {
160
+ return defaultValue.trim();
161
+ }
162
+ return undefined;
163
+ }
164
+
144
165
  function getVersion(binary: string, versionCommand?: string): string | null {
145
166
  // Custom version command from provider.json
146
167
  if (versionCommand) {
@@ -200,10 +221,7 @@ export async function detectAllVersions(
200
221
  detectedAt: new Date().toISOString(),
201
222
  };
202
223
 
203
- const verCmdConfig = (provider as any).versionCommand;
204
- const versionCommand = typeof verCmdConfig === 'object' && verCmdConfig !== null
205
- ? verCmdConfig[currentOs]
206
- : verCmdConfig;
224
+ const versionCommand = getPlatformVersionCommand(provider.versionCommand, currentOs);
207
225
 
208
226
  if (provider.category === 'ide') {
209
227
  // IDE: check app path + CLI
@@ -256,7 +274,7 @@ export async function detectAllVersions(
256
274
 
257
275
  // Check testedVersions — warn if installed version is not documented
258
276
  if (info.version && info.installed) {
259
- const testedVersions: string[] = (provider as any).testedVersions || [];
277
+ const testedVersions = provider.testedVersions || [];
260
278
  if (testedVersions.length > 0 && !testedVersions.includes(info.version)) {
261
279
  info.warning = `Version ${info.version} is not in testedVersions [${testedVersions.join(', ')}]. Scripts may not work correctly.`;
262
280
  }
@@ -6,6 +6,8 @@
6
6
  */
7
7
 
8
8
  import { LOG } from '../logging/logger.js';
9
+ import type { DaemonCdpManager } from '../cdp/manager.js';
10
+ import type { MachineInfo } from '../shared-types.js';
9
11
  import { buildSessionEntries } from './builders.js';
10
12
  import { buildStatusSnapshot } from './snapshot.js';
11
13
  import type {
@@ -19,7 +21,7 @@ import type {
19
21
 
20
22
  export interface StatusReporterDeps {
21
23
  serverConn: { isConnected(): boolean; sendMessage(type: string, data: any): void; getUserPlan(): string } | null;
22
- cdpManagers: Map<string, { isConnected: boolean }>;
24
+ cdpManagers: Map<string, DaemonCdpManager>;
23
25
  p2p: { isConnected: boolean; isAvailable: boolean; connectionState: string; connectedPeerCount: number; screenshotActive: boolean; sendStatus(data: any): void } | null;
24
26
  providerLoader: { resolve(type: string): any; getAll(): any[] };
25
27
  detectedIdes: any[];
@@ -65,7 +67,7 @@ export class DaemonStatusReporter {
65
67
  if (this.deps.p2p?.isConnected) {
66
68
  this.sendUnifiedStatusReport({ p2pOnly: true }).catch(e => LOG.warn('Status', `P2P status send failed: ${e?.message}`));
67
69
  }
68
- }, 5_000) as any;
70
+ }, 5_000);
69
71
  }
70
72
 
71
73
  stopReporting(): void {
@@ -174,14 +176,14 @@ export class DaemonStatusReporter {
174
176
  // IDE/CLI/ACP states → managed entries (shared builder)
175
177
  const sessions = buildSessionEntries(
176
178
  allStates,
177
- this.deps.cdpManagers as Map<string, any>,
179
+ this.deps.cdpManagers,
178
180
  );
179
181
 
180
182
  // ═══ Assemble payload (P2P — required data only) ═══
181
183
  const payload: Record<string, any> = {
182
184
  ...buildStatusSnapshot({
183
185
  allStates,
184
- cdpManagers: this.deps.cdpManagers as Map<string, unknown>,
186
+ cdpManagers: this.deps.cdpManagers,
185
187
  providerLoader: this.deps.providerLoader,
186
188
  detectedIdes: this.deps.detectedIdes || [],
187
189
  instanceId: this.deps.instanceId,
@@ -231,10 +233,10 @@ export class DaemonStatusReporter {
231
233
  currentPlan: session.currentPlan,
232
234
  currentAutoApprove: session.currentAutoApprove,
233
235
  lastUpdated: session.lastUpdated,
234
- unread: (session as any).unread,
235
- lastSeenAt: (session as any).lastSeenAt,
236
- inboxBucket: (session as any).inboxBucket,
237
- surfaceHidden: (session as any).surfaceHidden,
236
+ unread: session.unread,
237
+ lastSeenAt: session.lastSeenAt,
238
+ inboxBucket: session.inboxBucket,
239
+ surfaceHidden: session.surfaceHidden,
238
240
  controlValues: session.controlValues,
239
241
  providerControls: session.providerControls,
240
242
  acpConfigOptions: session.acpConfigOptions,
@@ -251,13 +253,15 @@ export class DaemonStatusReporter {
251
253
 
252
254
  // ─── P2P ─────────────────────────────────────────
253
255
 
254
- private sendP2PPayload(payload: Record<string, any>): boolean {
256
+ private sendP2PPayload(payload: { timestamp?: number; system?: unknown; machine?: MachineInfo; [key: string]: unknown }): boolean {
255
257
  const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
256
- if (hashTarget.machine) {
257
- const { freeMem: _f, availableMem: _a, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine as any;
258
- hashTarget.machine = stableMachine;
259
- }
260
- const h = this.simpleHash(JSON.stringify(hashTarget));
258
+ const hashPayload = hashTarget.machine
259
+ ? (() => {
260
+ const { freeMem: _f, availableMem: _a, loadavg: _l, uptime: _u, ...stableMachine } = hashTarget.machine;
261
+ return { ...hashTarget, machine: stableMachine };
262
+ })()
263
+ : hashTarget;
264
+ const h = this.simpleHash(JSON.stringify(hashPayload));
261
265
  if (h !== this.lastP2PStatusHash) {
262
266
  this.lastP2PStatusHash = h;
263
267
  this.deps.p2p?.sendStatus(payload);
@@ -14,6 +14,7 @@ import { getWorkspaceState } from '../config/workspaces.js';
14
14
  import { getHostMemorySnapshot } from '../system/host-memory.js';
15
15
  import { getTerminalBackendRuntimeStatus } from '../cli-adapters/terminal-screen.js';
16
16
  import { LOG } from '../logging/logger.js';
17
+ import type { DaemonCdpManager } from '../cdp/manager.js';
17
18
  import { buildSessionEntries, isCdpConnected } from './builders.js';
18
19
  import type { ProviderState } from '../providers/provider-instance.js';
19
20
  import type {
@@ -27,7 +28,7 @@ import type {
27
28
 
28
29
  export interface StatusSnapshotOptions {
29
30
  allStates: ProviderState[];
30
- cdpManagers: Map<string, unknown>;
31
+ cdpManagers: Map<string, DaemonCdpManager>;
31
32
  providerLoader: {
32
33
  getAll(): Array<{
33
34
  type: string;
@@ -75,7 +76,7 @@ function buildDetectedIdeInfos(
75
76
  id: ide.id,
76
77
  type: ide.id,
77
78
  name: ide.displayName || ide.name || ide.id,
78
- running: isCdpConnected(cdpManagers as Map<string, any>, ide.id),
79
+ running: isCdpConnected(cdpManagers, ide.id),
79
80
  ...(ide.path ? { path: ide.path } : {}),
80
81
  }));
81
82
  }
@@ -132,7 +133,7 @@ export function getSessionCompletionMarker(session: {
132
133
  }> | null
133
134
  } | null
134
135
  }) {
135
- const lastMessage = session.activeChat?.messages?.at?.(-1) as any;
136
+ const lastMessage = session.activeChat?.messages?.at?.(-1);
136
137
  if (!lastMessage) return '';
137
138
  const role = typeof lastMessage.role === 'string' ? lastMessage.role : '';
138
139
  if (role === 'user' || role === 'human' || role === 'system') return '';
@@ -213,7 +214,7 @@ export function buildStatusSnapshot(options: StatusSnapshotOptions): StatusSnaps
213
214
  const recentActivity = getRecentActivity(state, 20);
214
215
  const sessions = buildSessionEntries(
215
216
  options.allStates,
216
- options.cdpManagers as Map<string, any>,
217
+ options.cdpManagers,
217
218
  );
218
219
  for (const session of sessions) {
219
220
  const lastSeenAt = getSessionSeenAt(state, session.id);