@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,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DaemonCommandRouter — Unified command routing for daemon-level commands
|
|
3
|
+
*
|
|
4
|
+
* Extracted from cloud daemon's executeDaemonCommand() logic.
|
|
5
|
+
* Used by both daemon-cloud and daemon-standalone.
|
|
6
|
+
*
|
|
7
|
+
* Routing flow:
|
|
8
|
+
* 1. Daemon-level commands (launch_ide, stop_ide, restart_ide, etc.) → handled here
|
|
9
|
+
* 2. CLI/ACP commands → delegated to cliManager
|
|
10
|
+
* 3. Everything else → delegated to commandHandler.handle()
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { DaemonCdpManager } from '../cdp/manager.js';
|
|
14
|
+
import { registerExtensionProviders } from '../cdp/setup.js';
|
|
15
|
+
import { DaemonCommandHandler } from './handler.js';
|
|
16
|
+
import { DaemonCliManager } from './cli-manager.js';
|
|
17
|
+
import type { ProviderLoader } from '../providers/provider-loader.js';
|
|
18
|
+
import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
|
|
19
|
+
import { launchWithCdp } from '../launch.js';
|
|
20
|
+
import { detectIDEs } from '../detection/ide-detector.js';
|
|
21
|
+
import { LOG } from '../logging/logger.js';
|
|
22
|
+
import { logCommand } from '../logging/command-log.js';
|
|
23
|
+
import { getRecentLogs, LOG_PATH } from '../logging/logger.js';
|
|
24
|
+
import * as fs from 'fs';
|
|
25
|
+
|
|
26
|
+
// ─── Types ───
|
|
27
|
+
|
|
28
|
+
export interface CommandRouterDeps {
|
|
29
|
+
commandHandler: DaemonCommandHandler;
|
|
30
|
+
cliManager: DaemonCliManager;
|
|
31
|
+
cdpManagers: Map<string, DaemonCdpManager>;
|
|
32
|
+
providerLoader: ProviderLoader;
|
|
33
|
+
instanceManager: ProviderInstanceManager;
|
|
34
|
+
/** Reference to detected IDEs array (mutable — router updates it) */
|
|
35
|
+
detectedIdes: { value: any[] };
|
|
36
|
+
/** UUID instanceId → CDP manager key mapping */
|
|
37
|
+
instanceIdMap: Map<string, string>;
|
|
38
|
+
/** Callback for CDP manager creation after launch_ide (cloud: setupCdpManager, standalone: no-op) */
|
|
39
|
+
onCdpManagerCreated?: (ideType: string, manager: DaemonCdpManager) => void;
|
|
40
|
+
/** Callback after IDE connected (e.g., startAgentStreamPolling) */
|
|
41
|
+
onIdeConnected?: () => void;
|
|
42
|
+
/** Callback after status change (stop_ide, restart) */
|
|
43
|
+
onStatusChange?: () => void;
|
|
44
|
+
/** Callback after chat-related commands (cloud: throttled report) */
|
|
45
|
+
onPostChatCommand?: () => void;
|
|
46
|
+
/** Get a connected CDP manager (for agent stream reset check) */
|
|
47
|
+
getCdpLogFn?: (ideType: string) => (msg: string) => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface CommandRouterResult {
|
|
51
|
+
success: boolean;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Commands that trigger post-chat status updates
|
|
56
|
+
const CHAT_COMMANDS = [
|
|
57
|
+
'send_chat', 'new_chat', 'switch_chat', 'set_mode',
|
|
58
|
+
'change_model', 'agent_stream_send',
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
export class DaemonCommandRouter {
|
|
62
|
+
private deps: CommandRouterDeps;
|
|
63
|
+
|
|
64
|
+
constructor(deps: CommandRouterDeps) {
|
|
65
|
+
this.deps = deps;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Unified command routing.
|
|
70
|
+
* Returns result for all commands:
|
|
71
|
+
* 1. Daemon-level commands (launch_ide, stop_ide, etc.)
|
|
72
|
+
* 2. CLI commands (launch_cli, stop_cli, agent_command)
|
|
73
|
+
* 3. DaemonCommandHandler delegation (CDP/agent-stream/file commands)
|
|
74
|
+
*
|
|
75
|
+
* @param cmd Command name
|
|
76
|
+
* @param args Command arguments
|
|
77
|
+
* @param source Log source ('ws' | 'p2p' | 'standalone' | etc.)
|
|
78
|
+
*/
|
|
79
|
+
async execute(cmd: string, args: any, source: string = 'unknown'): Promise<CommandRouterResult> {
|
|
80
|
+
const cmdStart = Date.now();
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// 1. Try daemon-level command
|
|
84
|
+
const daemonResult = await this.executeDaemonCommand(cmd, args);
|
|
85
|
+
if (daemonResult) {
|
|
86
|
+
logCommand({ ts: new Date().toISOString(), cmd, source: source as any, args, success: daemonResult.success, durationMs: Date.now() - cmdStart });
|
|
87
|
+
return daemonResult;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 2. Delegate to DaemonCommandHandler
|
|
91
|
+
const handlerResult = await this.deps.commandHandler.handle(cmd, args);
|
|
92
|
+
logCommand({ ts: new Date().toISOString(), cmd, source: source as any, args, success: handlerResult.success, durationMs: Date.now() - cmdStart });
|
|
93
|
+
|
|
94
|
+
// 3. Post-chat command callback
|
|
95
|
+
if (CHAT_COMMANDS.includes(cmd) && this.deps.onPostChatCommand) {
|
|
96
|
+
this.deps.onPostChatCommand();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return handlerResult;
|
|
100
|
+
} catch (e: any) {
|
|
101
|
+
logCommand({ ts: new Date().toISOString(), cmd, source: source as any, args, success: false, error: e.message, durationMs: Date.now() - cmdStart });
|
|
102
|
+
throw e;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ─── Daemon-level command core ───────────────────
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Daemon-level command execution (IDE start/stop/restart, CLI, detect, logs).
|
|
110
|
+
* Returns null if not handled at this level → caller delegates to CommandHandler.
|
|
111
|
+
*/
|
|
112
|
+
private async executeDaemonCommand(cmd: string, args: any): Promise<CommandRouterResult | null> {
|
|
113
|
+
switch (cmd) {
|
|
114
|
+
// ─── CLI / ACP commands ───
|
|
115
|
+
case 'launch_cli':
|
|
116
|
+
case 'stop_cli':
|
|
117
|
+
case 'agent_command': {
|
|
118
|
+
return this.deps.cliManager.handleCliCommand(cmd, args);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ─── Logs ───
|
|
122
|
+
case 'get_logs': {
|
|
123
|
+
const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
|
|
124
|
+
const minLevel = args?.minLevel || 'info';
|
|
125
|
+
const sinceTs = args?.since || 0;
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
// Priority 1: ring buffer (fast and structured)
|
|
129
|
+
let logs = getRecentLogs(count, minLevel);
|
|
130
|
+
if (sinceTs > 0) {
|
|
131
|
+
logs = logs.filter((l: any) => l.ts > sinceTs);
|
|
132
|
+
}
|
|
133
|
+
if (logs.length > 0) {
|
|
134
|
+
return { success: true, logs, totalBuffered: logs.length };
|
|
135
|
+
}
|
|
136
|
+
// Priority 2: file fallback
|
|
137
|
+
if (fs.existsSync(LOG_PATH)) {
|
|
138
|
+
const content = fs.readFileSync(LOG_PATH, 'utf-8');
|
|
139
|
+
const allLines = content.split('\n');
|
|
140
|
+
const recent = allLines.slice(-count).join('\n');
|
|
141
|
+
return { success: true, logs: recent, totalLines: allLines.length };
|
|
142
|
+
}
|
|
143
|
+
return { success: true, logs: [], totalBuffered: 0 };
|
|
144
|
+
} catch (e: any) {
|
|
145
|
+
return { success: false, error: e.message };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ─── restart_session: IDE / CLI / ACP unified ───
|
|
150
|
+
case 'restart_session': {
|
|
151
|
+
const targetType = args?.cliType || args?.agentType || args?.ideType;
|
|
152
|
+
if (!targetType) throw new Error('cliType or ideType required');
|
|
153
|
+
|
|
154
|
+
// Check if IDE (in cdpManagers or provider category is ide)
|
|
155
|
+
const isIde = this.deps.cdpManagers.has(targetType) ||
|
|
156
|
+
this.deps.providerLoader.getMeta(targetType)?.category === 'ide';
|
|
157
|
+
|
|
158
|
+
if (isIde) {
|
|
159
|
+
// IDE restart: stop → launch
|
|
160
|
+
await this.stopIde(targetType);
|
|
161
|
+
const launchResult = await this.executeDaemonCommand('launch_ide', { ideType: targetType, enableCdp: true });
|
|
162
|
+
return { success: true, restarted: true, ideType: targetType, launch: launchResult };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// CLI/ACP restart: delegate to CliManager
|
|
166
|
+
return this.deps.cliManager.handleCliCommand(cmd, args);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ─── IDE stop ───
|
|
170
|
+
case 'stop_ide': {
|
|
171
|
+
const ideType = args?.ideType;
|
|
172
|
+
if (!ideType) throw new Error('ideType required');
|
|
173
|
+
await this.stopIde(ideType);
|
|
174
|
+
return { success: true, ideType, stopped: true };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ─── IDE restart ───
|
|
178
|
+
case 'restart_ide': {
|
|
179
|
+
const ideType = args?.ideType;
|
|
180
|
+
if (!ideType) throw new Error('ideType required');
|
|
181
|
+
await this.stopIde(ideType);
|
|
182
|
+
const launchResult = await this.executeDaemonCommand('launch_ide', { ideType, enableCdp: true });
|
|
183
|
+
return { success: true, ideType, restarted: true, launch: launchResult };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ─── IDE launch + CDP connect ───
|
|
187
|
+
case 'launch_ide': {
|
|
188
|
+
const launchArgs = { ...args, ideId: args?.ideId || args?.ideType };
|
|
189
|
+
const ideKey = launchArgs.ideId;
|
|
190
|
+
LOG.info('LaunchIDE', `target=${ideKey || 'auto'}`);
|
|
191
|
+
const result = await launchWithCdp(launchArgs);
|
|
192
|
+
|
|
193
|
+
if (result.success && result.port && result.ideId && !this.deps.cdpManagers.has(result.ideId)) {
|
|
194
|
+
const logFn = this.deps.getCdpLogFn
|
|
195
|
+
? this.deps.getCdpLogFn(result.ideId)
|
|
196
|
+
: LOG.forComponent(`CDP:${result.ideId}`).asLogFn();
|
|
197
|
+
const provider = this.deps.providerLoader.getMeta(result.ideId);
|
|
198
|
+
const manager = new DaemonCdpManager(result.port, logFn, undefined, (provider as any)?.targetFilter);
|
|
199
|
+
const connected = await manager.connect();
|
|
200
|
+
if (connected) {
|
|
201
|
+
// Register active extension providers for this IDE in CDP manager
|
|
202
|
+
registerExtensionProviders(this.deps.providerLoader, manager, result.ideId);
|
|
203
|
+
this.deps.cdpManagers.set(result.ideId, manager);
|
|
204
|
+
LOG.info('CDP', `Connected: ${result.ideId} (port ${result.port})`);
|
|
205
|
+
LOG.info('CDP', `${this.deps.cdpManagers.size} IDE(s) connected`);
|
|
206
|
+
|
|
207
|
+
// Notify consumer (cloud: setupCdpManager, standalone: setupIdeInstance)
|
|
208
|
+
this.deps.onCdpManagerCreated?.(result.ideId, manager);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
this.deps.onIdeConnected?.();
|
|
212
|
+
return { success: result.success, ...result as any };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ─── IDE detection ───
|
|
216
|
+
case 'detect_ides': {
|
|
217
|
+
this.deps.detectedIdes.value = await detectIDEs();
|
|
218
|
+
return { success: true, ides: this.deps.detectedIdes.value };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return null; // Not handled at this level → delegate to CommandHandler
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* IDE stop: CDP disconnect + remove from InstanceManager + clean instanceIdMap
|
|
227
|
+
*/
|
|
228
|
+
private async stopIde(ideType: string): Promise<void> {
|
|
229
|
+
// 1. Release CDP manager
|
|
230
|
+
const cdp = this.deps.cdpManagers.get(ideType);
|
|
231
|
+
if (cdp) {
|
|
232
|
+
try { cdp.disconnect(); } catch { /* noop */ }
|
|
233
|
+
this.deps.cdpManagers.delete(ideType);
|
|
234
|
+
LOG.info('StopIDE', `CDP disconnected: ${ideType}`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// 2. Remove IDE instance from InstanceManager
|
|
238
|
+
const instanceKey = `ide:${ideType}`;
|
|
239
|
+
const ideInstance = this.deps.instanceManager.getInstance(instanceKey) as any;
|
|
240
|
+
if (ideInstance) {
|
|
241
|
+
// Remove IDE and child Extension UUIDs from instanceIdMap
|
|
242
|
+
if (ideInstance.getInstanceId) {
|
|
243
|
+
this.deps.instanceIdMap.delete(ideInstance.getInstanceId());
|
|
244
|
+
}
|
|
245
|
+
if (ideInstance.getExtensionInstances) {
|
|
246
|
+
for (const ext of ideInstance.getExtensionInstances()) {
|
|
247
|
+
if (ext.getInstanceId) this.deps.instanceIdMap.delete(ext.getInstanceId());
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
this.deps.instanceManager.removeInstance(instanceKey);
|
|
251
|
+
LOG.info('StopIDE', `Instance removed: ${instanceKey}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 3. Notify consumer for status update
|
|
255
|
+
this.deps.onStatusChange?.();
|
|
256
|
+
LOG.info('StopIDE', `IDE stopped: ${ideType}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream Commands — Agent Stream, PTY I/O, Provider Settings,
|
|
3
|
+
* IDE Extension Settings, Extension Script Execution
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CommandResult, CommandHelpers } from './handler.js';
|
|
7
|
+
import type { ProviderLoader } from '../providers/provider-loader.js';
|
|
8
|
+
import { loadConfig } from '../config/config.js';
|
|
9
|
+
import { LOG } from '../logging/logger.js';
|
|
10
|
+
|
|
11
|
+
// ─── Agent Stream commands ───────────────────────
|
|
12
|
+
|
|
13
|
+
export async function handleAgentStreamSwitch(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
14
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
15
|
+
const agentType = args?.agentType || args?.agent || null;
|
|
16
|
+
await h.agentStream.switchActiveAgent(h.getCdp()!, agentType);
|
|
17
|
+
return { success: true, activeAgent: agentType };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function handleAgentStreamRead(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
21
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
22
|
+
const streams = await h.agentStream.collectAgentStreams(h.getCdp()!);
|
|
23
|
+
return { success: true, streams };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function handleAgentStreamSend(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
27
|
+
const agentType = args?.agentType || args?.agent;
|
|
28
|
+
const text = args?.text || args?.message;
|
|
29
|
+
if (!text) return { success: false, error: 'text required' };
|
|
30
|
+
|
|
31
|
+
// CLI adapter routing
|
|
32
|
+
if (agentType && h.ctx.adapters) {
|
|
33
|
+
for (const [key, adapter] of h.ctx.adapters.entries()) {
|
|
34
|
+
if (adapter.cliType === agentType || key.includes(agentType)) {
|
|
35
|
+
LOG.info('Command', `[agent_stream_send] Routing to CLI adapter: ${adapter.cliType}`);
|
|
36
|
+
try {
|
|
37
|
+
await adapter.sendMessage(text);
|
|
38
|
+
return { success: true, sent: true, targetAgent: adapter.cliType };
|
|
39
|
+
} catch (e: any) {
|
|
40
|
+
LOG.info('Command', `[agent_stream_send] CLI adapter failed: ${e.message}`);
|
|
41
|
+
return { success: false, error: `CLI send failed: ${e.message}` };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// CDP-based IDE agent routing
|
|
48
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
49
|
+
const resolvedAgent = agentType || h.agentStream.activeAgentType;
|
|
50
|
+
if (!resolvedAgent) return { success: false, error: 'agentType required' };
|
|
51
|
+
const ok = await h.agentStream.sendToAgent(h.getCdp()!, resolvedAgent, text, h.currentIdeType);
|
|
52
|
+
return { success: ok };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function handleAgentStreamResolve(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
56
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
57
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
58
|
+
const action = args?.action as 'approve' | 'reject' || 'approve';
|
|
59
|
+
if (!agentType) return { success: false, error: 'agentType required' };
|
|
60
|
+
const ok = await h.agentStream.resolveAgentAction(h.getCdp()!, agentType, action, h.currentIdeType);
|
|
61
|
+
return { success: ok };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function handleAgentStreamNew(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
65
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
66
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
67
|
+
if (!agentType) return { success: false, error: 'agentType required' };
|
|
68
|
+
const ok = await h.agentStream.newAgentSession(h.getCdp()!, agentType, h.currentIdeType);
|
|
69
|
+
return { success: ok };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function handleAgentStreamListChats(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
73
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
74
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
75
|
+
if (!agentType) return { success: false, error: 'agentType required' };
|
|
76
|
+
const chats = await h.agentStream.listAgentChats(h.getCdp()!, agentType);
|
|
77
|
+
return { success: true, chats };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function handleAgentStreamSwitchSession(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
81
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
82
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
83
|
+
const sessionId = args?.sessionId || args?.id;
|
|
84
|
+
if (!agentType || !sessionId) return { success: false, error: 'agentType and sessionId required' };
|
|
85
|
+
const ok = await h.agentStream.switchAgentSession(h.getCdp()!, agentType, sessionId);
|
|
86
|
+
return { success: ok };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function handleAgentStreamFocus(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
90
|
+
if (!h.agentStream || !h.getCdp()) return { success: false, error: 'AgentStream or CDP not available' };
|
|
91
|
+
const agentType = args?.agentType || args?.agent || h.agentStream.activeAgentType;
|
|
92
|
+
if (!agentType) return { success: false, error: 'agentType required' };
|
|
93
|
+
await h.agentStream.ensureAgentPanelOpen(agentType, h.currentIdeType);
|
|
94
|
+
const ok = await h.agentStream.focusAgentEditor(h.getCdp()!, agentType);
|
|
95
|
+
return { success: ok };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ─── PTY Raw I/O ──────────────────────────────────
|
|
99
|
+
|
|
100
|
+
export function handlePtyInput(h: CommandHelpers, args: any): CommandResult {
|
|
101
|
+
const { cliType, data } = args || {};
|
|
102
|
+
if (!data) return { success: false, error: 'data required' };
|
|
103
|
+
|
|
104
|
+
if (h.ctx.adapters) {
|
|
105
|
+
const targetCli = cliType || '';
|
|
106
|
+
if (!targetCli && h.ctx.adapters.size > 0) {
|
|
107
|
+
const first = h.ctx.adapters.values().next().value;
|
|
108
|
+
if (first && typeof first.writeRaw === 'function') {
|
|
109
|
+
first.writeRaw(data);
|
|
110
|
+
return { success: true };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
114
|
+
if (directAdapter && typeof directAdapter.writeRaw === 'function') {
|
|
115
|
+
directAdapter.writeRaw(data);
|
|
116
|
+
return { success: true };
|
|
117
|
+
}
|
|
118
|
+
for (const [, adapter] of h.ctx.adapters) {
|
|
119
|
+
if (adapter.cliType === targetCli && typeof adapter.writeRaw === 'function') {
|
|
120
|
+
adapter.writeRaw(data);
|
|
121
|
+
return { success: true };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const [key, adapter] of h.ctx.adapters) {
|
|
125
|
+
if ((key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.writeRaw === 'function') {
|
|
126
|
+
adapter.writeRaw(data);
|
|
127
|
+
return { success: true };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { success: false, error: `CLI adapter not found: ${cliType}` };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function handlePtyResize(h: CommandHelpers, args: any): CommandResult {
|
|
135
|
+
const { cliType, cols, rows, force } = args || {};
|
|
136
|
+
if (!cols || !rows) return { success: false, error: 'cols and rows required' };
|
|
137
|
+
|
|
138
|
+
if (h.ctx.adapters) {
|
|
139
|
+
const targetCli = cliType || '';
|
|
140
|
+
if (!targetCli && h.ctx.adapters.size > 0) {
|
|
141
|
+
const first = h.ctx.adapters.values().next().value;
|
|
142
|
+
if (first && typeof first.resize === 'function') {
|
|
143
|
+
if (force) { first.resize(cols - 1, rows); setTimeout(() => first.resize(cols, rows), 50); }
|
|
144
|
+
else { first.resize(cols, rows); }
|
|
145
|
+
return { success: true };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const directAdapter = h.ctx.adapters.get(targetCli);
|
|
149
|
+
if (directAdapter && typeof directAdapter.resize === 'function') {
|
|
150
|
+
if (force) {
|
|
151
|
+
directAdapter.resize(cols - 1, rows);
|
|
152
|
+
setTimeout(() => directAdapter.resize(cols, rows), 50);
|
|
153
|
+
} else {
|
|
154
|
+
directAdapter.resize(cols, rows);
|
|
155
|
+
}
|
|
156
|
+
return { success: true };
|
|
157
|
+
}
|
|
158
|
+
for (const [key, adapter] of h.ctx.adapters) {
|
|
159
|
+
if ((adapter.cliType === targetCli || key.startsWith(targetCli) || targetCli.startsWith(adapter.cliType)) && typeof adapter.resize === 'function') {
|
|
160
|
+
if (force) {
|
|
161
|
+
adapter.resize(cols - 1, rows);
|
|
162
|
+
setTimeout(() => adapter.resize(cols, rows), 50);
|
|
163
|
+
} else {
|
|
164
|
+
adapter.resize(cols, rows);
|
|
165
|
+
}
|
|
166
|
+
return { success: true };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { success: false, error: `CLI adapter not found: ${cliType}` };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ─── Provider Settings ────────────────────────
|
|
174
|
+
|
|
175
|
+
export function handleGetProviderSettings(h: CommandHelpers, args: any): CommandResult {
|
|
176
|
+
const loader = h.ctx.providerLoader as ProviderLoader | undefined;
|
|
177
|
+
const { providerType } = args || {};
|
|
178
|
+
if (providerType) {
|
|
179
|
+
const schema = loader?.getPublicSettings(providerType) || [];
|
|
180
|
+
const values = loader?.getSettings(providerType) || {};
|
|
181
|
+
return { success: true, providerType, schema, values };
|
|
182
|
+
}
|
|
183
|
+
const allSettings = loader?.getAllPublicSettings() || {};
|
|
184
|
+
const allValues: Record<string, any> = {};
|
|
185
|
+
for (const type of Object.keys(allSettings)) {
|
|
186
|
+
allValues[type] = loader?.getSettings(type) || {};
|
|
187
|
+
}
|
|
188
|
+
return { success: true, settings: allSettings, values: allValues };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function handleSetProviderSetting(h: CommandHelpers, args: any): CommandResult {
|
|
192
|
+
const loader = h.ctx.providerLoader as ProviderLoader | undefined;
|
|
193
|
+
const { providerType, key, value } = args || {};
|
|
194
|
+
if (!providerType || !key || value === undefined) {
|
|
195
|
+
return { success: false, error: 'providerType, key, and value are required' };
|
|
196
|
+
}
|
|
197
|
+
const result = loader?.setSetting(providerType, key, value);
|
|
198
|
+
if (result) {
|
|
199
|
+
if (h.ctx.instanceManager) {
|
|
200
|
+
const allSettings = loader?.getSettings(providerType) || {};
|
|
201
|
+
const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
|
|
202
|
+
LOG.info('Command', `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} → ${updated} instance(s) updated`);
|
|
203
|
+
}
|
|
204
|
+
return { success: true, providerType, key, value };
|
|
205
|
+
}
|
|
206
|
+
return { success: false, error: `Failed to set ${providerType}.${key} — invalid key, value, or not a public setting` };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ─── Extension Script Execution (Model/Mode) ─────
|
|
210
|
+
|
|
211
|
+
export async function handleExtensionScript(h: CommandHelpers, args: any, scriptName: string): Promise<CommandResult> {
|
|
212
|
+
const { agentType, ideType } = args || {};
|
|
213
|
+
LOG.info('Command', `[ExtScript] ${scriptName} agentType=${agentType} ideType=${ideType} _currentIdeType=${h.currentIdeType}`);
|
|
214
|
+
if (!agentType) return { success: false, error: 'agentType is required' };
|
|
215
|
+
|
|
216
|
+
const loader = h.ctx.providerLoader;
|
|
217
|
+
if (!loader) return { success: false, error: 'ProviderLoader not initialized' };
|
|
218
|
+
const provider = loader.resolve(agentType);
|
|
219
|
+
if (!provider) return { success: false, error: `Provider not found: ${agentType}` };
|
|
220
|
+
|
|
221
|
+
const webviewScriptName = `webview${scriptName.charAt(0).toUpperCase() + scriptName.slice(1)}`;
|
|
222
|
+
const hasWebviewScript = provider.category === 'ide' &&
|
|
223
|
+
!!provider.scripts?.[webviewScriptName];
|
|
224
|
+
|
|
225
|
+
const actualScriptName = hasWebviewScript ? webviewScriptName : scriptName;
|
|
226
|
+
|
|
227
|
+
if (!provider.scripts?.[actualScriptName as keyof typeof provider.scripts]) {
|
|
228
|
+
return { success: false, error: `Script '${actualScriptName}' not available for ${agentType}` };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const scriptFn = provider.scripts[actualScriptName as keyof typeof provider.scripts] as Function;
|
|
232
|
+
const scriptCode = scriptFn(args);
|
|
233
|
+
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
234
|
+
|
|
235
|
+
const cdpKey = provider.category === 'ide' ? (h.currentIdeType || agentType) : (h.currentIdeType || ideType);
|
|
236
|
+
LOG.info('Command', `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
237
|
+
const cdp = h.getCdp(cdpKey);
|
|
238
|
+
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || 'any'}` };
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
let result: unknown;
|
|
242
|
+
|
|
243
|
+
if (provider.category === 'extension') {
|
|
244
|
+
const sessions = cdp.getAgentSessions();
|
|
245
|
+
let targetSessionId: string | null = null;
|
|
246
|
+
for (const [sessionId, target] of sessions) {
|
|
247
|
+
if (target.agentType === agentType) {
|
|
248
|
+
targetSessionId = sessionId;
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (!targetSessionId) {
|
|
253
|
+
return { success: false, error: `No active session found for ${agentType}` };
|
|
254
|
+
}
|
|
255
|
+
result = await cdp.evaluateInSession(targetSessionId, scriptCode);
|
|
256
|
+
} else if (hasWebviewScript && cdp.evaluateInWebviewFrame) {
|
|
257
|
+
const matchText = provider.webviewMatchText;
|
|
258
|
+
const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
|
|
259
|
+
result = await cdp.evaluateInWebviewFrame(scriptCode, matchFn);
|
|
260
|
+
} else {
|
|
261
|
+
result = await cdp.evaluate(scriptCode, 30000);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (typeof result === 'string') {
|
|
265
|
+
try {
|
|
266
|
+
const parsed = JSON.parse(result);
|
|
267
|
+
return { success: true, ...parsed };
|
|
268
|
+
} catch {
|
|
269
|
+
return { success: true, result };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return { success: true, result };
|
|
273
|
+
} catch (e: any) {
|
|
274
|
+
return { success: false, error: `Script execution failed: ${e.message}` };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ─── IDE Extension Settings (per-IDE on/off) ─────
|
|
279
|
+
|
|
280
|
+
export function handleGetIdeExtensions(h: CommandHelpers, args: any): CommandResult {
|
|
281
|
+
const { ideType } = args || {};
|
|
282
|
+
const loader = h.ctx.providerLoader as ProviderLoader | undefined;
|
|
283
|
+
if (!loader) return { success: false, error: 'ProviderLoader not initialized' };
|
|
284
|
+
|
|
285
|
+
const allExtProviders = loader.getByCategory?.('extension') || [];
|
|
286
|
+
const config = loadConfig();
|
|
287
|
+
|
|
288
|
+
if (ideType) {
|
|
289
|
+
const extensions = allExtProviders.map(p => ({
|
|
290
|
+
type: p.type,
|
|
291
|
+
name: p.name,
|
|
292
|
+
extensionId: p.extensionId,
|
|
293
|
+
enabled: config.ideSettings?.[ideType]?.extensions?.[p.type]?.enabled === true,
|
|
294
|
+
}));
|
|
295
|
+
return { success: true, ideType, extensions };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const connectedIdes = [...(h.ctx.cdpManagers?.keys?.() || [])];
|
|
299
|
+
const result: Record<string, any[]> = {};
|
|
300
|
+
for (const ide of connectedIdes) {
|
|
301
|
+
result[ide] = allExtProviders.map(p => ({
|
|
302
|
+
type: p.type,
|
|
303
|
+
name: p.name,
|
|
304
|
+
extensionId: p.extensionId,
|
|
305
|
+
enabled: config.ideSettings?.[ide]?.extensions?.[p.type]?.enabled === true,
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
return { success: true, ides: result };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export function handleSetIdeExtension(h: CommandHelpers, args: any): CommandResult {
|
|
312
|
+
const { ideType, extensionType, enabled } = args || {};
|
|
313
|
+
if (!ideType || !extensionType || enabled === undefined) {
|
|
314
|
+
return { success: false, error: 'ideType, extensionType, and enabled are required' };
|
|
315
|
+
}
|
|
316
|
+
const loader = h.ctx.providerLoader as ProviderLoader | undefined;
|
|
317
|
+
if (!loader?.setIdeExtensionEnabled) {
|
|
318
|
+
return { success: false, error: 'ProviderLoader not initialized' };
|
|
319
|
+
}
|
|
320
|
+
const ok = loader.setIdeExtensionEnabled(ideType, extensionType, !!enabled);
|
|
321
|
+
if (ok) {
|
|
322
|
+
return { success: true, ideType, extensionType, enabled: !!enabled };
|
|
323
|
+
}
|
|
324
|
+
return { success: false, error: 'Failed to save setting' };
|
|
325
|
+
}
|