@adhdev/daemon-core 0.6.67 → 0.6.68
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/index.d.ts +22 -28
- package/dist/index.js +69 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/agent-stream/poller.ts +1 -2
- package/src/boot/daemon-lifecycle.ts +2 -3
- package/src/cdp/initializer.ts +18 -12
- package/src/cdp/manager.ts +3 -0
- package/src/cdp/scanner.ts +2 -2
- package/src/cdp/setup.ts +3 -6
- package/src/commands/router.ts +5 -6
- package/src/config/config.ts +3 -0
- package/src/daemon/dev-server.ts +47 -0
- package/src/daemon-core.ts +1 -1
- package/src/index.ts +0 -1
- package/src/providers/provider-loader.ts +14 -9
- package/src/shared-types.ts +5 -6
- package/src/status/builders.ts +2 -3
- package/src/types.ts +1 -1
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AgentStreamPoller — Periodic agent stream polling + extension dynamic management
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Used by both daemon-cloud and daemon-standalone.
|
|
4
|
+
* Handles periodic agent stream polling and extension dynamic management.
|
|
6
5
|
*
|
|
7
6
|
* Responsibilities:
|
|
8
7
|
* 1. Refresh extension providers in CDP managers (config changes take effect immediately)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Daemon Lifecycle — Shared init + shutdown
|
|
2
|
+
* Daemon Lifecycle — Shared init + shutdown logic
|
|
3
3
|
*
|
|
4
4
|
* initDaemonComponents(): Creates all core daemon components in correct order.
|
|
5
5
|
* shutdownDaemonComponents(): Graceful shutdown of all components.
|
|
@@ -77,7 +77,6 @@ export interface DaemonComponents {
|
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* Initialize all daemon core components.
|
|
80
|
-
* Shared by both cloud and standalone daemons.
|
|
81
80
|
*
|
|
82
81
|
* Order:
|
|
83
82
|
* 1. Global log interceptor
|
|
@@ -99,6 +98,7 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
|
|
|
99
98
|
const providerLoader = new ProviderLoader({
|
|
100
99
|
logFn: config.providerLogFn,
|
|
101
100
|
disableUpstream,
|
|
101
|
+
userDir: appConfig.providerDir,
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
// If no upstream providers exist, fetch them first (blocking — critical for new users)
|
|
@@ -244,7 +244,6 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
|
|
|
244
244
|
|
|
245
245
|
/**
|
|
246
246
|
* Graceful shutdown of all daemon components.
|
|
247
|
-
* Shared by both cloud and standalone daemons.
|
|
248
247
|
*
|
|
249
248
|
* Order:
|
|
250
249
|
* 1. Stop timers (poller, cdpInitializer)
|
package/src/cdp/initializer.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DaemonCdpInitializer — Unified CDP initialization + periodic scanning
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Unified CDP initialization + periodic scanning.
|
|
5
5
|
*
|
|
6
6
|
* Features:
|
|
7
7
|
* 1. Initial connection: connectAll() — multi-window aware
|
|
@@ -90,6 +90,8 @@ export class DaemonCdpInitializer {
|
|
|
90
90
|
const targets = await DaemonCdpManager.listAllTargets(port);
|
|
91
91
|
|
|
92
92
|
if (targets.length === 0) {
|
|
93
|
+
// Prevent duplicate fallback connection
|
|
94
|
+
if (cdpManagers.has(ide)) return;
|
|
93
95
|
// Fallback: direct single connection (probeCdpPort first)
|
|
94
96
|
if (!await probeCdpPort(port)) return;
|
|
95
97
|
const provider = providerLoader.getMeta(ide);
|
|
@@ -112,13 +114,23 @@ export class DaemonCdpInitializer {
|
|
|
112
114
|
// 2. Multi-window: create separate CdpManager per page
|
|
113
115
|
for (let i = 0; i < targets.length; i++) {
|
|
114
116
|
const target = targets[i];
|
|
115
|
-
|
|
117
|
+
|
|
118
|
+
// Check if ANY existing manager for this IDE is already tracking this target.id
|
|
119
|
+
let alreadyTracked = false;
|
|
120
|
+
for (const [key, m] of cdpManagers.entries()) {
|
|
121
|
+
if ((key === ide || key.startsWith(`${ide}_`)) && m.targetId === target.id) {
|
|
122
|
+
alreadyTracked = true;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (alreadyTracked) continue;
|
|
127
|
+
|
|
128
|
+
// Stable key using target.id instead of fluctuating window title
|
|
116
129
|
let managerKey: string;
|
|
117
|
-
if (targets.length === 1) {
|
|
130
|
+
if (targets.length === 1 && !cdpManagers.has(ide)) {
|
|
118
131
|
managerKey = ide;
|
|
119
132
|
} else {
|
|
120
|
-
|
|
121
|
-
managerKey = `${ide}_${workspaceName}`;
|
|
133
|
+
managerKey = `${ide}_${target.id}`;
|
|
122
134
|
}
|
|
123
135
|
|
|
124
136
|
if (cdpManagers.has(managerKey)) continue;
|
|
@@ -156,13 +168,7 @@ export class DaemonCdpInitializer {
|
|
|
156
168
|
|
|
157
169
|
for (const [ide, ports] of Object.entries(portMap)) {
|
|
158
170
|
const primaryPort = ports[0];
|
|
159
|
-
|
|
160
|
-
// Skip if already connected
|
|
161
|
-
const alreadyConnected = [...cdpManagers.entries()].some(([key, m]) =>
|
|
162
|
-
m.isConnected && (key === ide || key.startsWith(ide + '_'))
|
|
163
|
-
);
|
|
164
|
-
if (alreadyConnected) continue;
|
|
165
|
-
|
|
171
|
+
// Always try to connect to find new windows
|
|
166
172
|
await this.connectIdePort(primaryPort, ide);
|
|
167
173
|
}
|
|
168
174
|
}, intervalMs);
|
package/src/cdp/manager.ts
CHANGED
|
@@ -107,6 +107,9 @@ export class DaemonCdpManager {
|
|
|
107
107
|
/** Connected page title (includes workspace name) */
|
|
108
108
|
get pageTitle(): string { return this._pageTitle; }
|
|
109
109
|
|
|
110
|
+
/** Connected target ID */
|
|
111
|
+
get targetId(): string | null { return this._targetId; }
|
|
112
|
+
|
|
110
113
|
/**
|
|
111
114
|
* Query all workbench pages on port (static)
|
|
112
115
|
* Returns multiple entries if multiple IDE windows are open on same port
|
package/src/cdp/scanner.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DaemonCdpScanner — Periodic CDP port scanning & auto-connect
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Periodic CDP port scanning and auto-connect for IDE discovery.
|
|
5
5
|
* Provides a unified approach to:
|
|
6
6
|
* 1. Initial CDP port discovery
|
|
7
7
|
* 2. Periodic scanning for newly launched IDEs
|
|
@@ -142,7 +142,7 @@ export class DaemonCdpScanner {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
* Multi-window connection
|
|
145
|
+
* Multi-window connection.
|
|
146
146
|
* Multiple CDP managers per IDE — one per workbench page.
|
|
147
147
|
*/
|
|
148
148
|
private async connectMultiWindow(port: number, ide: string): Promise<void> {
|
package/src/cdp/setup.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DaemonCdpSetup — Shared CDP initialization helpers
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Used by both daemon-cloud and daemon-standalone to ensure
|
|
8
|
-
* consistent CDP → ProviderInstance registration.
|
|
4
|
+
* Common CDP setup logic for consistent
|
|
5
|
+
* CDP → ProviderInstance registration.
|
|
9
6
|
*/
|
|
10
7
|
|
|
11
8
|
import { DaemonCdpManager } from './manager.js';
|
|
@@ -20,7 +17,7 @@ export interface CdpSetupContext {
|
|
|
20
17
|
cdpManagers: Map<string, DaemonCdpManager>;
|
|
21
18
|
/** UUID instanceId → CDP manager key mapping */
|
|
22
19
|
instanceIdMap: Map<string, string>;
|
|
23
|
-
/** Server connection (optional
|
|
20
|
+
/** Server connection (optional) */
|
|
24
21
|
serverConn?: any;
|
|
25
22
|
}
|
|
26
23
|
|
package/src/commands/router.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DaemonCommandRouter — Unified command routing for daemon-level commands
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Used by both daemon-cloud and daemon-standalone.
|
|
4
|
+
* Unified command routing for daemon-level commands.
|
|
6
5
|
*
|
|
7
6
|
* Routing flow:
|
|
8
7
|
* 1. Daemon-level commands (launch_ide, stop_ide, restart_ide, etc.) → handled here
|
|
@@ -39,13 +38,13 @@ export interface CommandRouterDeps {
|
|
|
39
38
|
detectedIdes: { value: any[] };
|
|
40
39
|
/** UUID instanceId → CDP manager key mapping */
|
|
41
40
|
instanceIdMap: Map<string, string>;
|
|
42
|
-
/** Callback for CDP manager creation after launch_ide
|
|
41
|
+
/** Callback for CDP manager creation after launch_ide */
|
|
43
42
|
onCdpManagerCreated?: (ideType: string, manager: DaemonCdpManager) => void;
|
|
44
43
|
/** Callback after IDE connected (e.g., startAgentStreamPolling) */
|
|
45
44
|
onIdeConnected?: () => void;
|
|
46
45
|
/** Callback after status change (stop_ide, restart) */
|
|
47
46
|
onStatusChange?: () => void;
|
|
48
|
-
/** Callback after chat-related commands
|
|
47
|
+
/** Callback after chat-related commands */
|
|
49
48
|
onPostChatCommand?: () => void;
|
|
50
49
|
/** Get a connected CDP manager (for agent stream reset check) */
|
|
51
50
|
getCdpLogFn?: (ideType: string) => (msg: string) => void;
|
|
@@ -234,7 +233,7 @@ export class DaemonCommandRouter {
|
|
|
234
233
|
LOG.info('CDP', `Connected: ${result.ideId} (port ${result.port})`);
|
|
235
234
|
LOG.info('CDP', `${this.deps.cdpManagers.size} IDE(s) connected`);
|
|
236
235
|
|
|
237
|
-
// Notify consumer (
|
|
236
|
+
// Notify consumer (e.g. setupIdeInstance)
|
|
238
237
|
this.deps.onCdpManagerCreated?.(result.ideId, manager);
|
|
239
238
|
}
|
|
240
239
|
}
|
|
@@ -271,7 +270,7 @@ export class DaemonCommandRouter {
|
|
|
271
270
|
try {
|
|
272
271
|
const { execSync } = await import('child_process');
|
|
273
272
|
|
|
274
|
-
// Detect package
|
|
273
|
+
// Detect package name for upgrade
|
|
275
274
|
const isStandalone = this.deps.packageName === '@adhdev/daemon-standalone'
|
|
276
275
|
|| process.argv[1]?.includes('daemon-standalone');
|
|
277
276
|
const pkgName = isStandalone ? '@adhdev/daemon-standalone' : 'adhdev';
|
package/src/config/config.ts
CHANGED
|
@@ -84,6 +84,9 @@ export interface ADHDevConfig {
|
|
|
84
84
|
// Disable upstream provider auto-download (use builtin only)
|
|
85
85
|
// Controllable from CLI (--no-upstream) and dashboard (machine page)
|
|
86
86
|
disableUpstream?: boolean;
|
|
87
|
+
|
|
88
|
+
// Optional custom provider directory for local development
|
|
89
|
+
providerDir?: string;
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
export interface CliHistoryEntry {
|
package/src/daemon/dev-server.ts
CHANGED
|
@@ -2405,6 +2405,34 @@ export class DevServer {
|
|
|
2405
2405
|
}
|
|
2406
2406
|
}
|
|
2407
2407
|
|
|
2408
|
+
// ── Markdown Guides (Provider Fix) ──
|
|
2409
|
+
const docsDir = path.join(providerDir, '../../docs');
|
|
2410
|
+
const loadGuide = (name: string) => {
|
|
2411
|
+
try {
|
|
2412
|
+
const p = path.join(docsDir, name);
|
|
2413
|
+
if (fs.existsSync(p)) return fs.readFileSync(p, 'utf-8');
|
|
2414
|
+
} catch { /* ignore */ }
|
|
2415
|
+
return null;
|
|
2416
|
+
};
|
|
2417
|
+
|
|
2418
|
+
const providerGuide = loadGuide('PROVIDER_GUIDE.md');
|
|
2419
|
+
if (providerGuide) {
|
|
2420
|
+
lines.push('## Documentation: PROVIDER_GUIDE.md');
|
|
2421
|
+
lines.push('```markdown');
|
|
2422
|
+
lines.push(providerGuide);
|
|
2423
|
+
lines.push('```');
|
|
2424
|
+
lines.push('');
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
const cdpGuide = loadGuide('CDP_SELECTOR_GUIDE.md');
|
|
2428
|
+
if (cdpGuide) {
|
|
2429
|
+
lines.push('## Documentation: CDP_SELECTOR_GUIDE.md');
|
|
2430
|
+
lines.push('```markdown');
|
|
2431
|
+
lines.push(cdpGuide);
|
|
2432
|
+
lines.push('```');
|
|
2433
|
+
lines.push('');
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2408
2436
|
// ── Task ──
|
|
2409
2437
|
lines.push('## Task');
|
|
2410
2438
|
lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(', ')}**`);
|
|
@@ -2629,6 +2657,25 @@ export class DevServer {
|
|
|
2629
2657
|
}
|
|
2630
2658
|
}
|
|
2631
2659
|
|
|
2660
|
+
// ── Markdown Guides (Provider Fix) ──
|
|
2661
|
+
const docsDir = path.join(providerDir, '../../docs');
|
|
2662
|
+
const loadGuide = (name: string) => {
|
|
2663
|
+
try {
|
|
2664
|
+
const p = path.join(docsDir, name);
|
|
2665
|
+
if (fs.existsSync(p)) return fs.readFileSync(p, 'utf-8');
|
|
2666
|
+
} catch { /* ignore */ }
|
|
2667
|
+
return null;
|
|
2668
|
+
};
|
|
2669
|
+
|
|
2670
|
+
const providerGuide = loadGuide('PROVIDER_GUIDE.md');
|
|
2671
|
+
if (providerGuide) {
|
|
2672
|
+
lines.push('## Documentation: PROVIDER_GUIDE.md');
|
|
2673
|
+
lines.push('```markdown');
|
|
2674
|
+
lines.push(providerGuide);
|
|
2675
|
+
lines.push('```');
|
|
2676
|
+
lines.push('');
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2632
2679
|
lines.push('## Runtime Contract');
|
|
2633
2680
|
lines.push('The daemon runtime is already implemented in `packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts`.');
|
|
2634
2681
|
lines.push('Your scripts receive PTY-derived input and must return plain JS objects.');
|
package/src/daemon-core.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DaemonCore — Core daemon orchestrator interface
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Provides the core daemon orchestrator interface consumed by daemon-standalone.
|
|
5
5
|
* Actual implementation extracted from launcher and placed in this package.
|
|
6
6
|
*/
|
|
7
7
|
|
package/src/index.ts
CHANGED
|
@@ -59,11 +59,14 @@ export class ProviderLoader {
|
|
|
59
59
|
} else {
|
|
60
60
|
this.builtinDirs = [];
|
|
61
61
|
}
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
//
|
|
66
|
-
this.
|
|
62
|
+
// Default directory for auto-downloads
|
|
63
|
+
const defaultProvidersDir = path.join(os.homedir(), '.adhdev', 'providers');
|
|
64
|
+
|
|
65
|
+
// User custom directory: ~/.adhdev/providers/ or custom via config
|
|
66
|
+
this.userDir = options?.userDir || defaultProvidersDir;
|
|
67
|
+
|
|
68
|
+
// Upstream auto-download directory is always in the default location to avoid polluting custom dirs
|
|
69
|
+
this.upstreamDir = path.join(defaultProvidersDir, '.upstream');
|
|
67
70
|
this.disableUpstream = options?.disableUpstream ?? false;
|
|
68
71
|
this.logFn = options?.logFn || LOG.forComponent('Provider').asLogFn();
|
|
69
72
|
}
|
|
@@ -301,7 +304,8 @@ export class ProviderLoader {
|
|
|
301
304
|
try {
|
|
302
305
|
const { loadConfig } = require('../config/config.js');
|
|
303
306
|
const config = loadConfig();
|
|
304
|
-
const
|
|
307
|
+
const baseIdeType = ideType.split('_')[0];
|
|
308
|
+
const val = config.ideSettings?.[baseIdeType]?.extensions?.[type]?.enabled;
|
|
305
309
|
return val === true; // undefined → false (default inactive)
|
|
306
310
|
} catch {
|
|
307
311
|
return false;
|
|
@@ -315,10 +319,11 @@ export class ProviderLoader {
|
|
|
315
319
|
try {
|
|
316
320
|
const { loadConfig, saveConfig } = require('../config/config.js');
|
|
317
321
|
const config = loadConfig();
|
|
322
|
+
const baseIdeType = ideType.split('_')[0];
|
|
318
323
|
if (!config.ideSettings) config.ideSettings = {};
|
|
319
|
-
if (!config.ideSettings[
|
|
320
|
-
if (!config.ideSettings[
|
|
321
|
-
config.ideSettings[
|
|
324
|
+
if (!config.ideSettings[baseIdeType]) config.ideSettings[baseIdeType] = {};
|
|
325
|
+
if (!config.ideSettings[baseIdeType].extensions) config.ideSettings[baseIdeType].extensions = {};
|
|
326
|
+
config.ideSettings[baseIdeType].extensions[extensionType] = { enabled };
|
|
322
327
|
saveConfig(config);
|
|
323
328
|
this.log(`IDE extension setting: ${ideType}.${extensionType}.enabled = ${enabled}`);
|
|
324
329
|
return true;
|
package/src/shared-types.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ADHDev Shared Types — Cross-package type definitions
|
|
3
3
|
*
|
|
4
|
-
* Types used across daemon-core, web-core,
|
|
4
|
+
* Types used across daemon-core, web-core, and downstream consumers.
|
|
5
5
|
* Import via: import type { ... } from '@adhdev/daemon-core/types'
|
|
6
6
|
*
|
|
7
7
|
* IMPORTANT: This file must remain runtime-free (types only).
|
|
8
|
-
* Cloudflare Workers (server) can import type-only modules safely.
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
10
|
import type {
|
|
@@ -50,9 +49,9 @@ export type { WorkspaceEntry } from './config/workspaces.js';
|
|
|
50
49
|
|
|
51
50
|
// ─── Managed Entry Types (reporter → server/web) ────────────────────
|
|
52
51
|
// These define the shape of data sent by DaemonStatusReporter
|
|
53
|
-
// and consumed by web-core
|
|
52
|
+
// and consumed by web-core and downstream consumers.
|
|
54
53
|
|
|
55
|
-
/** IDE entry as reported by daemon to
|
|
54
|
+
/** IDE entry as reported by daemon to dashboard */
|
|
56
55
|
export interface ManagedIdeEntry {
|
|
57
56
|
ideType: string;
|
|
58
57
|
ideVersion: string;
|
|
@@ -69,7 +68,7 @@ export interface ManagedIdeEntry {
|
|
|
69
68
|
currentAutoApprove?: string;
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
/** CLI entry as reported by daemon to
|
|
71
|
+
/** CLI entry as reported by daemon to dashboard */
|
|
73
72
|
export interface ManagedCliEntry {
|
|
74
73
|
id: string;
|
|
75
74
|
instanceId: string;
|
|
@@ -81,7 +80,7 @@ export interface ManagedCliEntry {
|
|
|
81
80
|
activeChat: _ActiveChatData | null;
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
/** ACP entry as reported by daemon to
|
|
83
|
+
/** ACP entry as reported by daemon to dashboard */
|
|
85
84
|
export interface ManagedAcpEntry {
|
|
86
85
|
id: string;
|
|
87
86
|
acpType: string;
|
package/src/status/builders.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
* Status Builders — shared conversion functions for ProviderState → ManagedEntry
|
|
3
3
|
*
|
|
4
4
|
* Used by:
|
|
5
|
-
* - daemon-cloud (DaemonStatusReporter)
|
|
6
5
|
* - daemon-standalone (StandaloneServer.getStatus)
|
|
6
|
+
* - DaemonStatusReporter
|
|
7
7
|
*
|
|
8
|
-
* Consolidates
|
|
9
|
-
* previously copy-pasted between cloud and standalone codebases.
|
|
8
|
+
* Consolidates ProviderState→ManagedEntry mapping logic.
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
import type { DaemonCdpManager } from '../cdp/manager.js';
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ADHDev Daemon Core — Shared Types
|
|
3
3
|
*
|
|
4
|
-
* Shared types referenced by daemon-core, daemon-standalone,
|
|
4
|
+
* Shared types referenced by daemon-core, daemon-standalone, and web-core.
|
|
5
5
|
* When modifying this file, also update interface contracts in AGENT_PROTOCOL.md.
|
|
6
6
|
*/
|
|
7
7
|
import type { StatusReportPayload } from './shared-types.js';
|