@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.
- package/dist/agent-stream/manager.d.ts +1 -0
- package/dist/agent-stream/provider-adapter.d.ts +1 -0
- package/dist/agent-stream/types.d.ts +3 -0
- package/dist/boot/daemon-lifecycle.d.ts +2 -1
- package/dist/cdp/manager.d.ts +2 -0
- package/dist/cli-adapter-types.d.ts +34 -5
- package/dist/cli-adapters/provider-cli-adapter.d.ts +4 -158
- package/dist/cli-adapters/provider-cli-config.d.ts +30 -0
- package/dist/cli-adapters/provider-cli-parse.d.ts +42 -0
- package/dist/cli-adapters/provider-cli-runtime.d.ts +29 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +158 -0
- package/dist/commands/handler.d.ts +4 -3
- package/dist/config/config.d.ts +4 -3
- package/dist/index.js +866 -592
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +868 -595
- package/dist/index.mjs.map +1 -1
- package/dist/providers/contracts.d.ts +10 -1
- package/dist/providers/provider-loader.d.ts +3 -0
- package/dist/status/reporter.d.ts +2 -3
- package/dist/status/snapshot.d.ts +2 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +3 -1
- package/src/agent-stream/manager.ts +8 -2
- package/src/agent-stream/poller.ts +19 -5
- package/src/agent-stream/provider-adapter.ts +11 -7
- package/src/agent-stream/types.ts +3 -0
- package/src/boot/daemon-lifecycle.ts +7 -6
- package/src/cdp/initializer.ts +2 -2
- package/src/cdp/manager.ts +5 -0
- package/src/cdp/setup.ts +1 -1
- package/src/cli-adapter-types.ts +37 -5
- package/src/cli-adapters/provider-cli-adapter.ts +212 -795
- package/src/cli-adapters/provider-cli-config.ts +66 -0
- package/src/cli-adapters/provider-cli-parse.ts +202 -0
- package/src/cli-adapters/provider-cli-runtime.ts +142 -0
- package/src/cli-adapters/provider-cli-shared.ts +439 -0
- package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +1 -1
- package/src/commands/cdp-commands.ts +6 -1
- package/src/commands/chat-commands.ts +45 -29
- package/src/commands/cli-manager.ts +28 -9
- package/src/commands/handler.ts +14 -10
- package/src/commands/router.ts +23 -10
- package/src/commands/stream-commands.ts +11 -5
- package/src/config/config.ts +4 -10
- package/src/daemon/dev-auto-implement.ts +22 -18
- package/src/daemon/dev-cli-debug.ts +59 -16
- package/src/daemon/dev-server.ts +67 -43
- package/src/providers/acp-provider-instance.ts +1 -1
- package/src/providers/cli-provider-instance.ts +2 -2
- package/src/providers/contracts.ts +12 -1
- package/src/providers/extension-provider-instance.ts +1 -1
- package/src/providers/ide-provider-instance.ts +39 -18
- package/src/providers/provider-loader.ts +85 -54
- package/src/providers/version-archive.ts +23 -5
- package/src/status/reporter.ts +18 -14
- 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,
|
|
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
|
|
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
|
|
308
|
-
|
|
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
|
-
|
|
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 (
|
|
549
|
-
const compat =
|
|
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 &&
|
|
574
|
-
const loaded = this.loadScriptsFromDir(type,
|
|
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: ${
|
|
578
|
-
resolved._resolvedScriptDir =
|
|
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,
|
|
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 =
|
|
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 (
|
|
614
|
+
} else if (base.compatibility && base.defaultScriptDir) {
|
|
616
615
|
// No version detected but compatibility format → use defaultScriptDir
|
|
617
|
-
const loaded = this.loadScriptsFromDir(type,
|
|
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: ${
|
|
621
|
-
resolved._resolvedScriptDir =
|
|
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,
|
|
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):
|
|
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)
|
|
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]) =>
|
|
977
|
-
.map(([key, def]) => ({ key, ...
|
|
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' &&
|
|
997
|
+
? (key === 'autoApprove' && schemaDef.type === 'boolean'
|
|
999
998
|
? true
|
|
1000
|
-
:
|
|
999
|
+
: schemaDef.default)
|
|
1001
1000
|
: undefined;
|
|
1002
1001
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
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]
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
1269
|
-
const flags =
|
|
1270
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
1289
|
-
this.providers.set(
|
|
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 ? '🔄' : '✅'} ${
|
|
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
|
|
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
|
|
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
|
}
|
package/src/status/reporter.ts
CHANGED
|
@@ -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,
|
|
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)
|
|
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
|
|
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
|
|
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:
|
|
235
|
-
lastSeenAt:
|
|
236
|
-
inboxBucket:
|
|
237
|
-
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:
|
|
256
|
+
private sendP2PPayload(payload: { timestamp?: number; system?: unknown; machine?: MachineInfo; [key: string]: unknown }): boolean {
|
|
255
257
|
const { timestamp: _ts, system: _sys, ...hashTarget } = payload;
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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);
|
package/src/status/snapshot.ts
CHANGED
|
@@ -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,
|
|
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
|
|
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)
|
|
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
|
|
217
|
+
options.cdpManagers,
|
|
217
218
|
);
|
|
218
219
|
for (const session of sessions) {
|
|
219
220
|
const lastSeenAt = getSessionSeenAt(state, session.id);
|