@adhdev/daemon-core 0.5.3
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 +2662 -0
- package/dist/index.js +11341 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
- package/providers/_builtin/.github/workflows/generate-registry.yml +57 -0
- package/providers/_builtin/COMPATIBILITY.md +217 -0
- package/providers/_builtin/CONTRIBUTING.md +200 -0
- package/providers/_builtin/README.md +119 -0
- package/providers/_builtin/_helpers/index.js +188 -0
- package/providers/_builtin/acp/agentpool/provider.json +54 -0
- package/providers/_builtin/acp/amp/provider.json +52 -0
- package/providers/_builtin/acp/auggie/provider.json +57 -0
- package/providers/_builtin/acp/autodev/provider.json +54 -0
- package/providers/_builtin/acp/autohand/provider.json +52 -0
- package/providers/_builtin/acp/blackbox-ai/provider.json +54 -0
- package/providers/_builtin/acp/claude-agent/provider.json +57 -0
- package/providers/_builtin/acp/cline-acp/provider.json +54 -0
- package/providers/_builtin/acp/codebuddy/provider.json +54 -0
- package/providers/_builtin/acp/codex-cli/provider.json +57 -0
- package/providers/_builtin/acp/corust-agent/provider.json +52 -0
- package/providers/_builtin/acp/crow-cli/provider.json +54 -0
- package/providers/_builtin/acp/cursor-acp/provider.json +54 -0
- package/providers/_builtin/acp/deepagents/provider.json +52 -0
- package/providers/_builtin/acp/dimcode/provider.json +54 -0
- package/providers/_builtin/acp/docker-cagent/provider.json +57 -0
- package/providers/_builtin/acp/factory-droid/provider.json +60 -0
- package/providers/_builtin/acp/fast-agent/provider.json +52 -0
- package/providers/_builtin/acp/gemini-cli/provider.json +114 -0
- package/providers/_builtin/acp/github-copilot/provider.json +54 -0
- package/providers/_builtin/acp/goose/provider.json +57 -0
- package/providers/_builtin/acp/junie/provider.json +52 -0
- package/providers/_builtin/acp/kilo/provider.json +54 -0
- package/providers/_builtin/acp/kimi-cli/provider.json +57 -0
- package/providers/_builtin/acp/minion-code/provider.json +52 -0
- package/providers/_builtin/acp/mistral-vibe/provider.json +57 -0
- package/providers/_builtin/acp/nova/provider.json +54 -0
- package/providers/_builtin/acp/openclaw/provider.json +54 -0
- package/providers/_builtin/acp/opencode/provider.json +52 -0
- package/providers/_builtin/acp/openhands/provider.json +54 -0
- package/providers/_builtin/acp/pi-acp/provider.json +52 -0
- package/providers/_builtin/acp/qoder/provider.json +54 -0
- package/providers/_builtin/acp/qwen-code/provider.json +60 -0
- package/providers/_builtin/acp/stakpak/provider.json +54 -0
- package/providers/_builtin/acp/vtcode/provider.json +54 -0
- package/providers/_builtin/cli/claude-cli/provider.json +100 -0
- package/providers/_builtin/cli/codex-cli/provider.json +89 -0
- package/providers/_builtin/cli/gemini-cli/provider.json +93 -0
- package/providers/_builtin/docs/CDP_SELECTOR_GUIDE.md +370 -0
- package/providers/_builtin/docs/PROVIDER_GUIDE.md +916 -0
- package/providers/_builtin/extension/cline/provider.json +35 -0
- package/providers/_builtin/extension/cline/scripts/focus_editor.js +48 -0
- package/providers/_builtin/extension/cline/scripts/list_chats.js +100 -0
- package/providers/_builtin/extension/cline/scripts/list_models.js +43 -0
- package/providers/_builtin/extension/cline/scripts/list_modes.js +35 -0
- package/providers/_builtin/extension/cline/scripts/new_session.js +85 -0
- package/providers/_builtin/extension/cline/scripts/open_panel.js +25 -0
- package/providers/_builtin/extension/cline/scripts/read_chat.js +257 -0
- package/providers/_builtin/extension/cline/scripts/resolve_action.js +83 -0
- package/providers/_builtin/extension/cline/scripts/send_message.js +95 -0
- package/providers/_builtin/extension/cline/scripts/set_mode.js +36 -0
- package/providers/_builtin/extension/cline/scripts/set_model.js +36 -0
- package/providers/_builtin/extension/cline/scripts/switch_session.js +206 -0
- package/providers/_builtin/extension/cline/scripts.js +73 -0
- package/providers/_builtin/extension/roo-code/provider.json +35 -0
- package/providers/_builtin/extension/roo-code/scripts.js +659 -0
- package/providers/_builtin/ide/antigravity/provider.json +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/focus_editor.js +20 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_chats.js +137 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_models.js +38 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_modes.js +48 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/new_session.js +75 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/read_chat.js +262 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/resolve_action.js +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/scripts.js +57 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/send_message.js +56 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/set_mode.js +34 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/set_model.js +47 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/switch_session.js +114 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/focus_editor.js +20 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_chats.js +137 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_models.js +61 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_modes.js +72 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/new_session.js +75 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/read_chat.js +262 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/resolve_action.js +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/scripts.js +67 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/send_message.js +56 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/set_mode.js +67 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/set_model.js +72 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/switch_session.js +114 -0
- package/providers/_builtin/ide/cursor/provider.json +70 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/dismiss_notification.js +30 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/focus_editor.js +13 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_models.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_modes.js +40 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_notifications.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_sessions.js +42 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/new_session.js +20 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/open_panel.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/read_chat.js +75 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/resolve_action.js +19 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/scripts.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/send_message.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/set_mode.js +38 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/set_model.js +81 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/switch_session.js +28 -0
- package/providers/_builtin/ide/kiro/provider.json +67 -0
- package/providers/_builtin/ide/kiro/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/kiro/scripts/open_panel.js +47 -0
- package/providers/_builtin/ide/kiro/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/kiro/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_models.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_modes.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_sessions.js +21 -0
- package/providers/_builtin/ide/kiro/scripts/webview_new_session.js +34 -0
- package/providers/_builtin/ide/kiro/scripts/webview_read_chat.js +68 -0
- package/providers/_builtin/ide/kiro/scripts/webview_send_message.js +72 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_mode.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_model.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_switch_session.js +26 -0
- package/providers/_builtin/ide/kiro/scripts.js +62 -0
- package/providers/_builtin/ide/pearai/provider.json +67 -0
- package/providers/_builtin/ide/pearai/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/pearai/scripts/list_sessions.js +38 -0
- package/providers/_builtin/ide/pearai/scripts/new_session.js +55 -0
- package/providers/_builtin/ide/pearai/scripts/open_panel.js +46 -0
- package/providers/_builtin/ide/pearai/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/pearai/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_models.js +43 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_modes.js +35 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_sessions.js +62 -0
- package/providers/_builtin/ide/pearai/scripts/webview_new_session.js +49 -0
- package/providers/_builtin/ide/pearai/scripts/webview_read_chat.js +92 -0
- package/providers/_builtin/ide/pearai/scripts/webview_resolve_action.js +59 -0
- package/providers/_builtin/ide/pearai/scripts/webview_send_message.js +72 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_mode.js +36 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_model.js +36 -0
- package/providers/_builtin/ide/pearai/scripts/webview_switch_session.js +34 -0
- package/providers/_builtin/ide/pearai/scripts.js +74 -0
- package/providers/_builtin/ide/trae/provider.json +66 -0
- package/providers/_builtin/ide/trae/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/trae/scripts/list_chats.js +24 -0
- package/providers/_builtin/ide/trae/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/trae/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/trae/scripts/new_session.js +30 -0
- package/providers/_builtin/ide/trae/scripts/open_panel.js +44 -0
- package/providers/_builtin/ide/trae/scripts/read_chat.js +113 -0
- package/providers/_builtin/ide/trae/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/trae/scripts/send_message.js +69 -0
- package/providers/_builtin/ide/trae/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/trae/scripts/set_model.js +15 -0
- package/providers/_builtin/ide/trae/scripts/switch_session.js +23 -0
- package/providers/_builtin/ide/trae/scripts.js +57 -0
- package/providers/_builtin/ide/vscode/provider.json +64 -0
- package/providers/_builtin/ide/vscode-insiders/provider.json +62 -0
- package/providers/_builtin/ide/vscodium/provider.json +63 -0
- package/providers/_builtin/ide/windsurf/provider.json +53 -0
- package/providers/_builtin/ide/windsurf/scripts/focus_editor.js +30 -0
- package/providers/_builtin/ide/windsurf/scripts/list_chats.js +117 -0
- package/providers/_builtin/ide/windsurf/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/new_session.js +69 -0
- package/providers/_builtin/ide/windsurf/scripts/open_panel.js +58 -0
- package/providers/_builtin/ide/windsurf/scripts/read_chat.js +297 -0
- package/providers/_builtin/ide/windsurf/scripts/resolve_action.js +68 -0
- package/providers/_builtin/ide/windsurf/scripts/send_message.js +87 -0
- package/providers/_builtin/ide/windsurf/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/windsurf/scripts/set_model.js +15 -0
- package/providers/_builtin/ide/windsurf/scripts/switch_session.js +58 -0
- package/providers/_builtin/ide/windsurf/scripts.js +57 -0
- package/providers/_builtin/registry.json +266 -0
- package/providers/_builtin/validate.js +156 -0
- package/src/agent-stream/index.ts +6 -0
- package/src/agent-stream/manager.ts +286 -0
- package/src/agent-stream/poller.ts +154 -0
- package/src/agent-stream/provider-adapter.ts +138 -0
- package/src/agent-stream/types.ts +61 -0
- package/src/boot/daemon-lifecycle.ts +252 -0
- package/src/cdp/devtools.ts +335 -0
- package/src/cdp/initializer.ts +191 -0
- package/src/cdp/manager.ts +897 -0
- package/src/cdp/scanner.ts +185 -0
- package/src/cdp/setup.ts +150 -0
- package/src/cli-adapter-types.ts +25 -0
- package/src/cli-adapters/provider-cli-adapter.ts +448 -0
- package/src/commands/cdp-commands.ts +208 -0
- package/src/commands/chat-commands.ts +675 -0
- package/src/commands/cli-manager.ts +353 -0
- package/src/commands/handler.ts +328 -0
- package/src/commands/router.ts +258 -0
- package/src/commands/stream-commands.ts +325 -0
- package/src/config/chat-history.ts +211 -0
- package/src/config/config.ts +219 -0
- package/src/daemon/dev-server.ts +2378 -0
- package/src/daemon/scaffold-template.ts +394 -0
- package/src/daemon-core.ts +50 -0
- package/src/detection/cli-detector.ts +89 -0
- package/src/detection/ide-detector.ts +157 -0
- package/src/index.ts +103 -0
- package/src/installer.ts +263 -0
- package/src/ipc-protocol.ts +133 -0
- package/src/launch.ts +433 -0
- package/src/logging/command-log.ts +180 -0
- package/src/logging/logger.ts +316 -0
- package/src/providers/acp-provider-instance.ts +1140 -0
- package/src/providers/cli-provider-instance.ts +207 -0
- package/src/providers/contracts.ts +524 -0
- package/src/providers/extension-provider-instance.ts +156 -0
- package/src/providers/ide-provider-instance.ts +377 -0
- package/src/providers/index.ts +18 -0
- package/src/providers/provider-instance-manager.ts +182 -0
- package/src/providers/provider-instance.ts +112 -0
- package/src/providers/provider-loader.ts +1031 -0
- package/src/providers/status-monitor.ts +125 -0
- package/src/providers/version-archive.ts +266 -0
- package/src/status/reporter.ts +294 -0
- package/src/types.ts +206 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ADHDev Provider Validator
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node validate.js # validate all providers
|
|
7
|
+
* node validate.js ide/my-ide/provider.js # validate a single file
|
|
8
|
+
*/
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const REQUIRED_FIELDS = ['type', 'name', 'category'];
|
|
13
|
+
const VALID_CATEGORIES = ['ide', 'extension', 'cli', 'acp'];
|
|
14
|
+
const USED_PORTS = new Map();
|
|
15
|
+
const USED_TYPES = new Map();
|
|
16
|
+
|
|
17
|
+
let errors = 0;
|
|
18
|
+
let warnings = 0;
|
|
19
|
+
let validated = 0;
|
|
20
|
+
|
|
21
|
+
function validate(filePath) {
|
|
22
|
+
const rel = path.relative(process.cwd(), filePath);
|
|
23
|
+
|
|
24
|
+
// 1. Syntax check
|
|
25
|
+
try {
|
|
26
|
+
delete require.cache[require.resolve(filePath)];
|
|
27
|
+
} catch {}
|
|
28
|
+
|
|
29
|
+
let mod;
|
|
30
|
+
try {
|
|
31
|
+
mod = require(filePath);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error(`❌ ${rel}: syntax error — ${e.message}`);
|
|
34
|
+
errors++;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 2. Required fields
|
|
39
|
+
for (const field of REQUIRED_FIELDS) {
|
|
40
|
+
if (!mod[field]) {
|
|
41
|
+
console.error(`❌ ${rel}: missing required field '${field}'`);
|
|
42
|
+
errors++;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 3. Valid category
|
|
48
|
+
if (!VALID_CATEGORIES.includes(mod.category)) {
|
|
49
|
+
console.error(`❌ ${rel}: invalid category '${mod.category}' (must be: ${VALID_CATEGORIES.join(', ')})`);
|
|
50
|
+
errors++;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 4. Unique type
|
|
55
|
+
if (USED_TYPES.has(mod.type)) {
|
|
56
|
+
console.error(`❌ ${rel}: duplicate type '${mod.type}' (also in ${USED_TYPES.get(mod.type)})`);
|
|
57
|
+
errors++;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
USED_TYPES.set(mod.type, rel);
|
|
61
|
+
|
|
62
|
+
// 5. IDE-specific checks
|
|
63
|
+
if (mod.category === 'ide') {
|
|
64
|
+
if (!mod.cdpPorts || !Array.isArray(mod.cdpPorts) || mod.cdpPorts.length < 2) {
|
|
65
|
+
console.warn(`⚠ ${rel}: IDE missing cdpPorts [primary, fallback]`);
|
|
66
|
+
warnings++;
|
|
67
|
+
} else {
|
|
68
|
+
for (const port of mod.cdpPorts) {
|
|
69
|
+
if (USED_PORTS.has(port)) {
|
|
70
|
+
console.error(`❌ ${rel}: CDP port ${port} conflicts with ${USED_PORTS.get(port)}`);
|
|
71
|
+
errors++;
|
|
72
|
+
}
|
|
73
|
+
USED_PORTS.set(port, rel);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!mod.cli) {
|
|
78
|
+
console.warn(`⚠ ${rel}: IDE missing 'cli' field`);
|
|
79
|
+
warnings++;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!mod.paths) {
|
|
83
|
+
console.warn(`⚠ ${rel}: IDE missing 'paths' (install detection won't work)`);
|
|
84
|
+
warnings++;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 6. ACP-specific checks
|
|
89
|
+
if (mod.category === 'acp') {
|
|
90
|
+
if (!mod.spawn || !mod.spawn.command) {
|
|
91
|
+
console.warn(`⚠ ${rel}: ACP missing spawn.command`);
|
|
92
|
+
warnings++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 7. Scripts check
|
|
97
|
+
if (mod.category === 'ide' || mod.category === 'extension') {
|
|
98
|
+
const hasRead = mod.scripts?.readChat || mod.scripts?.webviewReadChat;
|
|
99
|
+
const hasSend = mod.scripts?.sendMessage || mod.scripts?.webviewSendMessage;
|
|
100
|
+
if (!hasRead) {
|
|
101
|
+
console.warn(`⚠ ${rel}: no readChat/webviewReadChat script`);
|
|
102
|
+
warnings++;
|
|
103
|
+
}
|
|
104
|
+
if (!hasSend) {
|
|
105
|
+
console.warn(`⚠ ${rel}: no sendMessage/webviewSendMessage script`);
|
|
106
|
+
warnings++;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 8. Webview IDE consistency
|
|
111
|
+
if (mod.category === 'ide' && mod.webviewMatchText) {
|
|
112
|
+
if (!mod.scripts?.webviewReadChat) {
|
|
113
|
+
console.warn(`⚠ ${rel}: has webviewMatchText but no webviewReadChat script`);
|
|
114
|
+
warnings++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
validated++;
|
|
119
|
+
console.log(`✅ ${rel}: ${mod.type} (${mod.category}) — ${mod.name}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function scanDir(dir) {
|
|
123
|
+
if (!fs.existsSync(dir)) return;
|
|
124
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
125
|
+
const full = path.join(dir, entry.name);
|
|
126
|
+
if (entry.isDirectory()) {
|
|
127
|
+
if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue;
|
|
128
|
+
scanDir(full);
|
|
129
|
+
} else if (entry.name === 'provider.js') {
|
|
130
|
+
validate(full);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ─── Main ───
|
|
136
|
+
const args = process.argv.slice(2);
|
|
137
|
+
|
|
138
|
+
if (args.length > 0) {
|
|
139
|
+
// Validate specific file(s)
|
|
140
|
+
for (const arg of args) {
|
|
141
|
+
const filePath = path.resolve(arg);
|
|
142
|
+
if (!fs.existsSync(filePath)) {
|
|
143
|
+
console.error(`❌ File not found: ${arg}`);
|
|
144
|
+
errors++;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
validate(filePath);
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
// Validate all
|
|
151
|
+
console.log('🔍 Validating all providers...\n');
|
|
152
|
+
scanDir(process.cwd());
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log(`\n━━━ Result: ${validated} passed, ${errors} errors, ${warnings} warnings ━━━`);
|
|
156
|
+
process.exit(errors > 0 ? 1 : 0);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { DaemonAgentStreamManager } from './manager.js';
|
|
2
|
+
export type { ManagedAgent } from './manager.js';
|
|
3
|
+
export { ProviderStreamAdapter } from './provider-adapter.js';
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
export { AgentStreamPoller } from './poller.js';
|
|
6
|
+
export type { AgentStreamPollerDeps } from './poller.js';
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DaemonAgentStreamManager — manage agent streams (ported for Daemon)
|
|
3
|
+
*
|
|
4
|
+
* Agent stream manager for extension data collection.
|
|
5
|
+
* All vscode dependencies removed — pure Node.js environment.
|
|
6
|
+
*
|
|
7
|
+
* Panel focus is delegated to Extension via IPC.
|
|
8
|
+
* CDP session management uses DaemonCdpManager directly.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { DaemonCdpManager, AgentWebviewTarget } from '../cdp/manager.js';
|
|
12
|
+
import { ProviderLoader } from '../providers/provider-loader.js';
|
|
13
|
+
import { ProviderStreamAdapter } from './provider-adapter.js';
|
|
14
|
+
import { LOG } from '../logging/logger.js';
|
|
15
|
+
import type {
|
|
16
|
+
IAgentStreamAdapter,
|
|
17
|
+
AgentStreamState,
|
|
18
|
+
AgentChatListItem,
|
|
19
|
+
AgentEvaluateFn,
|
|
20
|
+
} from './types.js';
|
|
21
|
+
|
|
22
|
+
export interface ManagedAgent {
|
|
23
|
+
adapter: IAgentStreamAdapter;
|
|
24
|
+
sessionId: string;
|
|
25
|
+
target: AgentWebviewTarget;
|
|
26
|
+
lastState: AgentStreamState | null;
|
|
27
|
+
lastError: string | null;
|
|
28
|
+
lastHiddenCheckTime: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class DaemonAgentStreamManager {
|
|
32
|
+
private allAdapters: IAgentStreamAdapter[] = [];
|
|
33
|
+
private managed = new Map<string, ManagedAgent>();
|
|
34
|
+
private enabled = true;
|
|
35
|
+
private logFn: (msg: string) => void;
|
|
36
|
+
private lastDiscoveryTime = 0;
|
|
37
|
+
private discoveryIntervalMs = 10_000;
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
private _activeAgentType: string | null = null;
|
|
41
|
+
|
|
42
|
+
constructor(logFn?: (msg: string) => void, providerLoader?: ProviderLoader) {
|
|
43
|
+
this.logFn = logFn || LOG.forComponent('AgentStream').asLogFn();
|
|
44
|
+
|
|
45
|
+
// Create adapter for all extension providers
|
|
46
|
+
// Per-IDE filtering is handled by each CDP manager via setExtensionProviders
|
|
47
|
+
if (providerLoader) {
|
|
48
|
+
const allExtProviders = providerLoader.getByCategory('extension');
|
|
49
|
+
for (const p of allExtProviders) {
|
|
50
|
+
const adapter = new ProviderStreamAdapter(p);
|
|
51
|
+
this.allAdapters.push(adapter);
|
|
52
|
+
this.logFn(`[AgentStream] Adapter created: ${p.type} (${p.name})`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
setEnabled(enabled: boolean) { this.enabled = enabled; }
|
|
58
|
+
get isEnabled() { return this.enabled; }
|
|
59
|
+
get activeAgentType(): string | null { return this._activeAgentType; }
|
|
60
|
+
|
|
61
|
+
/** Panel focus based on provider.js focusPanel or extensionId (currently no-op) */
|
|
62
|
+
async ensureAgentPanelOpen(agentType: string, targetIdeType?: string): Promise<void> {
|
|
63
|
+
// Extension was removed, so localServer-based panel focus no longer works
|
|
64
|
+
// Can be replaced with CDP-based focus (future implementation)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async switchActiveAgent(cdp: DaemonCdpManager, agentType: string | null): Promise<void> {
|
|
68
|
+
if (this._activeAgentType === agentType) return;
|
|
69
|
+
|
|
70
|
+
if (this._activeAgentType) {
|
|
71
|
+
const prev = this.managed.get(this._activeAgentType);
|
|
72
|
+
if (prev) {
|
|
73
|
+
try { await cdp.detachAgent(prev.sessionId); } catch { }
|
|
74
|
+
this.managed.delete(this._activeAgentType);
|
|
75
|
+
this.logFn(`[AgentStream] Deactivated: ${prev.adapter.agentName}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this._activeAgentType = agentType;
|
|
80
|
+
this.lastDiscoveryTime = 0;
|
|
81
|
+
this.logFn(`[AgentStream] Active agent: ${agentType || 'none'}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Agent webview discovery + session connection */
|
|
85
|
+
async syncAgentSessions(cdp: DaemonCdpManager): Promise<void> {
|
|
86
|
+
if (!this.enabled || !this._activeAgentType) return;
|
|
87
|
+
|
|
88
|
+
const now = Date.now();
|
|
89
|
+
if (this.managed.has(this._activeAgentType) && (now - this.lastDiscoveryTime) < this.discoveryIntervalMs) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.lastDiscoveryTime = now;
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const targets = await cdp.discoverAgentWebviews();
|
|
96
|
+
const activeTarget = targets.find(t => t.agentType === this._activeAgentType);
|
|
97
|
+
|
|
98
|
+
if (activeTarget && !this.managed.has(this._activeAgentType)) {
|
|
99
|
+
const adapter = this.allAdapters.find(a => a.agentType === this._activeAgentType);
|
|
100
|
+
if (adapter) {
|
|
101
|
+
const sessionId = await cdp.attachToAgent(activeTarget);
|
|
102
|
+
if (sessionId) {
|
|
103
|
+
this.managed.set(this._activeAgentType, {
|
|
104
|
+
adapter,
|
|
105
|
+
sessionId,
|
|
106
|
+
target: activeTarget,
|
|
107
|
+
lastState: null,
|
|
108
|
+
lastError: null,
|
|
109
|
+
lastHiddenCheckTime: 0,
|
|
110
|
+
});
|
|
111
|
+
this.logFn(`[AgentStream] Connected: ${adapter.agentName}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Cleanup inactive agents
|
|
117
|
+
for (const [type, agent] of this.managed) {
|
|
118
|
+
if (type !== this._activeAgentType) {
|
|
119
|
+
await cdp.detachAgent(agent.sessionId);
|
|
120
|
+
this.managed.delete(type);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.discoveryIntervalMs = this.managed.has(this._activeAgentType) ? 30_000 : 10_000;
|
|
125
|
+
} catch (e) {
|
|
126
|
+
this.logFn(`[AgentStream] sync error: ${(e as Error).message}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Collect active agent status */
|
|
131
|
+
async collectAgentStreams(cdp: DaemonCdpManager): Promise<AgentStreamState[]> {
|
|
132
|
+
if (!this.enabled) return [];
|
|
133
|
+
|
|
134
|
+
const results: AgentStreamState[] = [];
|
|
135
|
+
|
|
136
|
+
if (this._activeAgentType && this.managed.has(this._activeAgentType)) {
|
|
137
|
+
const agent = this.managed.get(this._activeAgentType)!;
|
|
138
|
+
const type = this._activeAgentType;
|
|
139
|
+
|
|
140
|
+
const isHidden = agent.lastState?.status === 'panel_hidden';
|
|
141
|
+
const hiddenCacheFresh = isHidden && (Date.now() - agent.lastHiddenCheckTime < 30000);
|
|
142
|
+
|
|
143
|
+
if (hiddenCacheFresh) {
|
|
144
|
+
results.push(agent.lastState!);
|
|
145
|
+
} else {
|
|
146
|
+
try {
|
|
147
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
148
|
+
cdp.evaluateInSession(agent.sessionId, expr, timeout);
|
|
149
|
+
const state = await agent.adapter.readChat(evaluate);
|
|
150
|
+
agent.lastState = state;
|
|
151
|
+
agent.lastError = null;
|
|
152
|
+
if (state.status === 'panel_hidden') {
|
|
153
|
+
agent.lastHiddenCheckTime = Date.now();
|
|
154
|
+
}
|
|
155
|
+
results.push(state);
|
|
156
|
+
} catch (e) {
|
|
157
|
+
const errorMsg = (e as Error)?.message || String(e);
|
|
158
|
+
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
159
|
+
agent.lastError = errorMsg;
|
|
160
|
+
results.push({
|
|
161
|
+
agentType: type,
|
|
162
|
+
agentName: agent.adapter.agentName,
|
|
163
|
+
extensionId: agent.adapter.extensionId,
|
|
164
|
+
status: 'disconnected',
|
|
165
|
+
messages: agent.lastState?.messages || [],
|
|
166
|
+
inputContent: '',
|
|
167
|
+
});
|
|
168
|
+
if (errorMsg.includes('timeout') || errorMsg.includes('not connected') || errorMsg.includes('Session')) {
|
|
169
|
+
try { await cdp.detachAgent(agent.sessionId); } catch { }
|
|
170
|
+
this.managed.delete(type);
|
|
171
|
+
this.lastDiscoveryTime = 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return results;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async sendToAgent(cdp: DaemonCdpManager, agentType: string, text: string, targetIdeType?: string): Promise<boolean> {
|
|
181
|
+
await this.ensureAgentPanelOpen(agentType, targetIdeType);
|
|
182
|
+
const agent = this.managed.get(agentType);
|
|
183
|
+
if (!agent) return false;
|
|
184
|
+
try {
|
|
185
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
186
|
+
cdp.evaluateInSession(agent.sessionId, expr, timeout);
|
|
187
|
+
await agent.adapter.sendMessage(evaluate, text);
|
|
188
|
+
return true;
|
|
189
|
+
} catch (e) {
|
|
190
|
+
this.logFn(`[AgentStream] sendToAgent(${agentType}) error: ${(e as Error).message}`);
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async resolveAgentAction(cdp: DaemonCdpManager, agentType: string, action: 'approve' | 'reject', targetIdeType?: string): Promise<boolean> {
|
|
196
|
+
await this.ensureAgentPanelOpen(agentType, targetIdeType);
|
|
197
|
+
const agent = this.managed.get(agentType);
|
|
198
|
+
if (!agent) return false;
|
|
199
|
+
try {
|
|
200
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
201
|
+
cdp.evaluateInSession(agent.sessionId, expr, timeout);
|
|
202
|
+
return await agent.adapter.resolveAction(evaluate, action);
|
|
203
|
+
} catch (e) {
|
|
204
|
+
this.logFn(`[AgentStream] resolveAction(${agentType}) error: ${(e as Error).message}`);
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async newAgentSession(cdp: DaemonCdpManager, agentType: string, targetIdeType?: string): Promise<boolean> {
|
|
210
|
+
await this.ensureAgentPanelOpen(agentType, targetIdeType);
|
|
211
|
+
const agent = this.managed.get(agentType);
|
|
212
|
+
if (!agent) return false;
|
|
213
|
+
try {
|
|
214
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
215
|
+
cdp.evaluateInSession(agent.sessionId, expr, timeout);
|
|
216
|
+
await agent.adapter.newSession(evaluate);
|
|
217
|
+
return true;
|
|
218
|
+
} catch (e) {
|
|
219
|
+
this.logFn(`[AgentStream] newSession(${agentType}) error: ${(e as Error).message}`);
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async listAgentChats(cdp: DaemonCdpManager, agentType: string): Promise<AgentChatListItem[]> {
|
|
225
|
+
let agent = this.managed.get(agentType);
|
|
226
|
+
// on-demand: try activate+sync if not in managed list
|
|
227
|
+
if (!agent) {
|
|
228
|
+
this.logFn(`[AgentStream] listChats: ${agentType} not managed, trying on-demand activation`);
|
|
229
|
+
await this.switchActiveAgent(cdp, agentType);
|
|
230
|
+
await this.syncAgentSessions(cdp);
|
|
231
|
+
agent = this.managed.get(agentType);
|
|
232
|
+
}
|
|
233
|
+
if (!agent || typeof agent.adapter.listChats !== 'function') return [];
|
|
234
|
+
try {
|
|
235
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
236
|
+
cdp.evaluateInSession(agent!.sessionId, expr, timeout);
|
|
237
|
+
return await agent.adapter.listChats(evaluate);
|
|
238
|
+
} catch (e) {
|
|
239
|
+
this.logFn(`[AgentStream] listChats(${agentType}) error: ${(e as Error).message}`);
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async switchAgentSession(cdp: DaemonCdpManager, agentType: string, sessionId: string): Promise<boolean> {
|
|
245
|
+
let agent = this.managed.get(agentType);
|
|
246
|
+
if (!agent) {
|
|
247
|
+
this.logFn(`[AgentStream] switchSession: ${agentType} not managed, trying on-demand activation`);
|
|
248
|
+
await this.switchActiveAgent(cdp, agentType);
|
|
249
|
+
await this.syncAgentSessions(cdp);
|
|
250
|
+
agent = this.managed.get(agentType);
|
|
251
|
+
}
|
|
252
|
+
if (!agent || typeof agent.adapter.switchSession !== 'function') return false;
|
|
253
|
+
try {
|
|
254
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
255
|
+
cdp.evaluateInSession(agent!.sessionId, expr, timeout);
|
|
256
|
+
return await agent.adapter.switchSession(evaluate, sessionId);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
this.logFn(`[AgentStream] switchSession(${agentType}) error: ${(e as Error).message}`);
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async focusAgentEditor(cdp: DaemonCdpManager, agentType: string): Promise<boolean> {
|
|
264
|
+
const agent = this.managed.get(agentType);
|
|
265
|
+
if (!agent || typeof agent.adapter.focusEditor !== 'function') return false;
|
|
266
|
+
try {
|
|
267
|
+
const evaluate: AgentEvaluateFn = (expr, timeout) =>
|
|
268
|
+
cdp.evaluateInSession(agent.sessionId, expr, timeout);
|
|
269
|
+
await agent.adapter.focusEditor(evaluate);
|
|
270
|
+
return true;
|
|
271
|
+
} catch (e) {
|
|
272
|
+
this.logFn(`[AgentStream] focusEditor(${agentType}) error: ${(e as Error).message}`);
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
getConnectedAgents(): string[] { return Array.from(this.managed.keys()); }
|
|
278
|
+
getManagedAgent(agentType: string): ManagedAgent | undefined { return this.managed.get(agentType); }
|
|
279
|
+
|
|
280
|
+
async dispose(cdp: DaemonCdpManager): Promise<void> {
|
|
281
|
+
for (const [, agent] of this.managed) {
|
|
282
|
+
try { await cdp.detachAgent(agent.sessionId); } catch { }
|
|
283
|
+
}
|
|
284
|
+
this.managed.clear();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentStreamPoller — Periodic agent stream polling + extension dynamic management
|
|
3
|
+
*
|
|
4
|
+
* Extracted from cloud daemon's startAgentStreamPolling() logic.
|
|
5
|
+
* Used by both daemon-cloud and daemon-standalone.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* 1. Refresh extension providers in CDP managers (config changes take effect immediately)
|
|
9
|
+
* 2. Dynamically add/remove IDE instance extensions based on enabled state
|
|
10
|
+
* 3. Sync agent sessions + collect agent streams
|
|
11
|
+
* 4. Auto-discover agents in connected IDEs
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { DaemonCdpManager } from '../cdp/manager.js';
|
|
15
|
+
import type { DaemonAgentStreamManager } from './manager.js';
|
|
16
|
+
import type { ProviderLoader } from '../providers/provider-loader.js';
|
|
17
|
+
import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
|
|
18
|
+
import { registerExtensionProviders } from '../cdp/setup.js';
|
|
19
|
+
import { LOG } from '../logging/logger.js';
|
|
20
|
+
import type { AgentStreamState } from './types.js';
|
|
21
|
+
|
|
22
|
+
// ─── Types ───
|
|
23
|
+
|
|
24
|
+
export interface AgentStreamPollerDeps {
|
|
25
|
+
agentStreamManager: DaemonAgentStreamManager;
|
|
26
|
+
providerLoader: ProviderLoader;
|
|
27
|
+
instanceManager: ProviderInstanceManager;
|
|
28
|
+
cdpManagers: Map<string, DaemonCdpManager>;
|
|
29
|
+
/** Callback when agent streams are updated */
|
|
30
|
+
onStreamsUpdated?: (ideType: string, streams: AgentStreamState[]) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class AgentStreamPoller {
|
|
34
|
+
private deps: AgentStreamPollerDeps;
|
|
35
|
+
private _activeIdeType: string | null = null;
|
|
36
|
+
private timer: NodeJS.Timeout | null = null;
|
|
37
|
+
|
|
38
|
+
constructor(deps: AgentStreamPollerDeps) {
|
|
39
|
+
this.deps = deps;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Currently active IDE type for agent streaming */
|
|
43
|
+
get activeIde(): string | null {
|
|
44
|
+
return this._activeIdeType;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Reset active IDE tracking (e.g., when IDE is stopped) */
|
|
48
|
+
resetActiveIde(ideType: string): void {
|
|
49
|
+
if (this._activeIdeType === ideType) {
|
|
50
|
+
this._activeIdeType = null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Start polling (idempotent — ignored if already started) */
|
|
55
|
+
start(intervalMs = 5000): void {
|
|
56
|
+
if (this.timer) return; // Already running
|
|
57
|
+
|
|
58
|
+
this.timer = setInterval(async () => {
|
|
59
|
+
await this.tick();
|
|
60
|
+
}, intervalMs);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Stop polling */
|
|
64
|
+
stop(): void {
|
|
65
|
+
if (this.timer) {
|
|
66
|
+
clearInterval(this.timer);
|
|
67
|
+
this.timer = null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Single poll tick — can also be called manually */
|
|
72
|
+
private async tick(): Promise<void> {
|
|
73
|
+
const {
|
|
74
|
+
agentStreamManager,
|
|
75
|
+
providerLoader,
|
|
76
|
+
instanceManager,
|
|
77
|
+
cdpManagers,
|
|
78
|
+
} = this.deps;
|
|
79
|
+
|
|
80
|
+
if (!agentStreamManager || cdpManagers.size === 0) return;
|
|
81
|
+
|
|
82
|
+
// ─── Phase 1: Refresh extension providers + IDE instance extensions ───
|
|
83
|
+
for (const [ideType, cdp] of cdpManagers) {
|
|
84
|
+
// 1a. Refresh CDP manager's extension providers from config
|
|
85
|
+
registerExtensionProviders(providerLoader, cdp, ideType);
|
|
86
|
+
|
|
87
|
+
// 1b. Dynamically add/remove IDE instance extensions
|
|
88
|
+
const ideInstance = instanceManager.getInstance(`ide:${ideType}`) as any;
|
|
89
|
+
if (ideInstance?.getExtensionTypes && ideInstance?.addExtension && ideInstance?.removeExtension) {
|
|
90
|
+
const currentExtTypes = new Set(ideInstance.getExtensionTypes() as string[]);
|
|
91
|
+
const enabledExtTypes = new Set(
|
|
92
|
+
providerLoader.getEnabledByCategory('extension', ideType).map((p: any) => p.type)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Remove disabled extensions
|
|
96
|
+
for (const extType of currentExtTypes) {
|
|
97
|
+
if (!enabledExtTypes.has(extType)) {
|
|
98
|
+
ideInstance.removeExtension(extType);
|
|
99
|
+
LOG.info('AgentStream', `Extension removed: ${extType} (disabled for ${ideType})`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Add newly enabled extensions
|
|
104
|
+
for (const extType of enabledExtTypes) {
|
|
105
|
+
if (!currentExtTypes.has(extType)) {
|
|
106
|
+
const extProvider = providerLoader.getMeta(extType);
|
|
107
|
+
if (extProvider) {
|
|
108
|
+
const extSettings = providerLoader.getSettings(extType);
|
|
109
|
+
ideInstance.addExtension(extProvider, extSettings);
|
|
110
|
+
LOG.info('AgentStream', `Extension added: ${extType} (enabled for ${ideType})`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ─── Phase 2: Agent session sync + collect ───
|
|
118
|
+
|
|
119
|
+
// If agent already connected to a specific IDE, only operate on that CDP
|
|
120
|
+
if (this._activeIdeType) {
|
|
121
|
+
const cdp = cdpManagers.get(this._activeIdeType);
|
|
122
|
+
if (cdp?.isConnected) {
|
|
123
|
+
try {
|
|
124
|
+
await agentStreamManager.syncAgentSessions(cdp);
|
|
125
|
+
const streams = await agentStreamManager.collectAgentStreams(cdp);
|
|
126
|
+
this.deps.onStreamsUpdated?.(this._activeIdeType, streams);
|
|
127
|
+
} catch { }
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
// CDP lost — reset
|
|
131
|
+
this._activeIdeType = null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ─── Phase 3: Auto-discover agents ───
|
|
135
|
+
if (!agentStreamManager.activeAgentType) {
|
|
136
|
+
for (const [ideType, cdp] of cdpManagers) {
|
|
137
|
+
if (!cdp.isConnected) continue;
|
|
138
|
+
try {
|
|
139
|
+
const discovered = await cdp.discoverAgentWebviews();
|
|
140
|
+
if (discovered.length > 0) {
|
|
141
|
+
this._activeIdeType = ideType;
|
|
142
|
+
await agentStreamManager.switchActiveAgent(cdp, discovered[0].agentType);
|
|
143
|
+
LOG.info('AgentStream', `Auto-activated: ${discovered[0].agentType} (${ideType})`);
|
|
144
|
+
// sync+collect immediately
|
|
145
|
+
await agentStreamManager.syncAgentSessions(cdp);
|
|
146
|
+
const streams = await agentStreamManager.collectAgentStreams(cdp);
|
|
147
|
+
this.deps.onStreamsUpdated?.(ideType, streams);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
} catch { }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|