@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.
Files changed (217) hide show
  1. package/dist/index.d.ts +2662 -0
  2. package/dist/index.js +11341 -0
  3. package/dist/index.js.map +1 -0
  4. package/package.json +48 -0
  5. package/providers/_builtin/.github/workflows/generate-registry.yml +57 -0
  6. package/providers/_builtin/COMPATIBILITY.md +217 -0
  7. package/providers/_builtin/CONTRIBUTING.md +200 -0
  8. package/providers/_builtin/README.md +119 -0
  9. package/providers/_builtin/_helpers/index.js +188 -0
  10. package/providers/_builtin/acp/agentpool/provider.json +54 -0
  11. package/providers/_builtin/acp/amp/provider.json +52 -0
  12. package/providers/_builtin/acp/auggie/provider.json +57 -0
  13. package/providers/_builtin/acp/autodev/provider.json +54 -0
  14. package/providers/_builtin/acp/autohand/provider.json +52 -0
  15. package/providers/_builtin/acp/blackbox-ai/provider.json +54 -0
  16. package/providers/_builtin/acp/claude-agent/provider.json +57 -0
  17. package/providers/_builtin/acp/cline-acp/provider.json +54 -0
  18. package/providers/_builtin/acp/codebuddy/provider.json +54 -0
  19. package/providers/_builtin/acp/codex-cli/provider.json +57 -0
  20. package/providers/_builtin/acp/corust-agent/provider.json +52 -0
  21. package/providers/_builtin/acp/crow-cli/provider.json +54 -0
  22. package/providers/_builtin/acp/cursor-acp/provider.json +54 -0
  23. package/providers/_builtin/acp/deepagents/provider.json +52 -0
  24. package/providers/_builtin/acp/dimcode/provider.json +54 -0
  25. package/providers/_builtin/acp/docker-cagent/provider.json +57 -0
  26. package/providers/_builtin/acp/factory-droid/provider.json +60 -0
  27. package/providers/_builtin/acp/fast-agent/provider.json +52 -0
  28. package/providers/_builtin/acp/gemini-cli/provider.json +114 -0
  29. package/providers/_builtin/acp/github-copilot/provider.json +54 -0
  30. package/providers/_builtin/acp/goose/provider.json +57 -0
  31. package/providers/_builtin/acp/junie/provider.json +52 -0
  32. package/providers/_builtin/acp/kilo/provider.json +54 -0
  33. package/providers/_builtin/acp/kimi-cli/provider.json +57 -0
  34. package/providers/_builtin/acp/minion-code/provider.json +52 -0
  35. package/providers/_builtin/acp/mistral-vibe/provider.json +57 -0
  36. package/providers/_builtin/acp/nova/provider.json +54 -0
  37. package/providers/_builtin/acp/openclaw/provider.json +54 -0
  38. package/providers/_builtin/acp/opencode/provider.json +52 -0
  39. package/providers/_builtin/acp/openhands/provider.json +54 -0
  40. package/providers/_builtin/acp/pi-acp/provider.json +52 -0
  41. package/providers/_builtin/acp/qoder/provider.json +54 -0
  42. package/providers/_builtin/acp/qwen-code/provider.json +60 -0
  43. package/providers/_builtin/acp/stakpak/provider.json +54 -0
  44. package/providers/_builtin/acp/vtcode/provider.json +54 -0
  45. package/providers/_builtin/cli/claude-cli/provider.json +100 -0
  46. package/providers/_builtin/cli/codex-cli/provider.json +89 -0
  47. package/providers/_builtin/cli/gemini-cli/provider.json +93 -0
  48. package/providers/_builtin/docs/CDP_SELECTOR_GUIDE.md +370 -0
  49. package/providers/_builtin/docs/PROVIDER_GUIDE.md +916 -0
  50. package/providers/_builtin/extension/cline/provider.json +35 -0
  51. package/providers/_builtin/extension/cline/scripts/focus_editor.js +48 -0
  52. package/providers/_builtin/extension/cline/scripts/list_chats.js +100 -0
  53. package/providers/_builtin/extension/cline/scripts/list_models.js +43 -0
  54. package/providers/_builtin/extension/cline/scripts/list_modes.js +35 -0
  55. package/providers/_builtin/extension/cline/scripts/new_session.js +85 -0
  56. package/providers/_builtin/extension/cline/scripts/open_panel.js +25 -0
  57. package/providers/_builtin/extension/cline/scripts/read_chat.js +257 -0
  58. package/providers/_builtin/extension/cline/scripts/resolve_action.js +83 -0
  59. package/providers/_builtin/extension/cline/scripts/send_message.js +95 -0
  60. package/providers/_builtin/extension/cline/scripts/set_mode.js +36 -0
  61. package/providers/_builtin/extension/cline/scripts/set_model.js +36 -0
  62. package/providers/_builtin/extension/cline/scripts/switch_session.js +206 -0
  63. package/providers/_builtin/extension/cline/scripts.js +73 -0
  64. package/providers/_builtin/extension/roo-code/provider.json +35 -0
  65. package/providers/_builtin/extension/roo-code/scripts.js +659 -0
  66. package/providers/_builtin/ide/antigravity/provider.json +68 -0
  67. package/providers/_builtin/ide/antigravity/scripts/1.106/focus_editor.js +20 -0
  68. package/providers/_builtin/ide/antigravity/scripts/1.106/list_chats.js +137 -0
  69. package/providers/_builtin/ide/antigravity/scripts/1.106/list_models.js +38 -0
  70. package/providers/_builtin/ide/antigravity/scripts/1.106/list_modes.js +48 -0
  71. package/providers/_builtin/ide/antigravity/scripts/1.106/new_session.js +75 -0
  72. package/providers/_builtin/ide/antigravity/scripts/1.106/read_chat.js +262 -0
  73. package/providers/_builtin/ide/antigravity/scripts/1.106/resolve_action.js +68 -0
  74. package/providers/_builtin/ide/antigravity/scripts/1.106/scripts.js +57 -0
  75. package/providers/_builtin/ide/antigravity/scripts/1.106/send_message.js +56 -0
  76. package/providers/_builtin/ide/antigravity/scripts/1.106/set_mode.js +34 -0
  77. package/providers/_builtin/ide/antigravity/scripts/1.106/set_model.js +47 -0
  78. package/providers/_builtin/ide/antigravity/scripts/1.106/switch_session.js +114 -0
  79. package/providers/_builtin/ide/antigravity/scripts/1.107/focus_editor.js +20 -0
  80. package/providers/_builtin/ide/antigravity/scripts/1.107/list_chats.js +137 -0
  81. package/providers/_builtin/ide/antigravity/scripts/1.107/list_models.js +61 -0
  82. package/providers/_builtin/ide/antigravity/scripts/1.107/list_modes.js +72 -0
  83. package/providers/_builtin/ide/antigravity/scripts/1.107/new_session.js +75 -0
  84. package/providers/_builtin/ide/antigravity/scripts/1.107/read_chat.js +262 -0
  85. package/providers/_builtin/ide/antigravity/scripts/1.107/resolve_action.js +68 -0
  86. package/providers/_builtin/ide/antigravity/scripts/1.107/scripts.js +67 -0
  87. package/providers/_builtin/ide/antigravity/scripts/1.107/send_message.js +56 -0
  88. package/providers/_builtin/ide/antigravity/scripts/1.107/set_mode.js +67 -0
  89. package/providers/_builtin/ide/antigravity/scripts/1.107/set_model.js +72 -0
  90. package/providers/_builtin/ide/antigravity/scripts/1.107/switch_session.js +114 -0
  91. package/providers/_builtin/ide/cursor/provider.json +70 -0
  92. package/providers/_builtin/ide/cursor/scripts/0.49/dismiss_notification.js +30 -0
  93. package/providers/_builtin/ide/cursor/scripts/0.49/focus_editor.js +13 -0
  94. package/providers/_builtin/ide/cursor/scripts/0.49/list_models.js +78 -0
  95. package/providers/_builtin/ide/cursor/scripts/0.49/list_modes.js +40 -0
  96. package/providers/_builtin/ide/cursor/scripts/0.49/list_notifications.js +23 -0
  97. package/providers/_builtin/ide/cursor/scripts/0.49/list_sessions.js +42 -0
  98. package/providers/_builtin/ide/cursor/scripts/0.49/new_session.js +20 -0
  99. package/providers/_builtin/ide/cursor/scripts/0.49/open_panel.js +23 -0
  100. package/providers/_builtin/ide/cursor/scripts/0.49/read_chat.js +75 -0
  101. package/providers/_builtin/ide/cursor/scripts/0.49/resolve_action.js +19 -0
  102. package/providers/_builtin/ide/cursor/scripts/0.49/scripts.js +78 -0
  103. package/providers/_builtin/ide/cursor/scripts/0.49/send_message.js +23 -0
  104. package/providers/_builtin/ide/cursor/scripts/0.49/set_mode.js +38 -0
  105. package/providers/_builtin/ide/cursor/scripts/0.49/set_model.js +81 -0
  106. package/providers/_builtin/ide/cursor/scripts/0.49/switch_session.js +28 -0
  107. package/providers/_builtin/ide/kiro/provider.json +67 -0
  108. package/providers/_builtin/ide/kiro/scripts/focus_editor.js +20 -0
  109. package/providers/_builtin/ide/kiro/scripts/open_panel.js +47 -0
  110. package/providers/_builtin/ide/kiro/scripts/resolve_action.js +54 -0
  111. package/providers/_builtin/ide/kiro/scripts/send_message.js +29 -0
  112. package/providers/_builtin/ide/kiro/scripts/webview_list_models.js +39 -0
  113. package/providers/_builtin/ide/kiro/scripts/webview_list_modes.js +39 -0
  114. package/providers/_builtin/ide/kiro/scripts/webview_list_sessions.js +21 -0
  115. package/providers/_builtin/ide/kiro/scripts/webview_new_session.js +34 -0
  116. package/providers/_builtin/ide/kiro/scripts/webview_read_chat.js +68 -0
  117. package/providers/_builtin/ide/kiro/scripts/webview_send_message.js +72 -0
  118. package/providers/_builtin/ide/kiro/scripts/webview_set_mode.js +15 -0
  119. package/providers/_builtin/ide/kiro/scripts/webview_set_model.js +15 -0
  120. package/providers/_builtin/ide/kiro/scripts/webview_switch_session.js +26 -0
  121. package/providers/_builtin/ide/kiro/scripts.js +62 -0
  122. package/providers/_builtin/ide/pearai/provider.json +67 -0
  123. package/providers/_builtin/ide/pearai/scripts/focus_editor.js +20 -0
  124. package/providers/_builtin/ide/pearai/scripts/list_sessions.js +38 -0
  125. package/providers/_builtin/ide/pearai/scripts/new_session.js +55 -0
  126. package/providers/_builtin/ide/pearai/scripts/open_panel.js +46 -0
  127. package/providers/_builtin/ide/pearai/scripts/resolve_action.js +54 -0
  128. package/providers/_builtin/ide/pearai/scripts/send_message.js +29 -0
  129. package/providers/_builtin/ide/pearai/scripts/webview_list_models.js +43 -0
  130. package/providers/_builtin/ide/pearai/scripts/webview_list_modes.js +35 -0
  131. package/providers/_builtin/ide/pearai/scripts/webview_list_sessions.js +62 -0
  132. package/providers/_builtin/ide/pearai/scripts/webview_new_session.js +49 -0
  133. package/providers/_builtin/ide/pearai/scripts/webview_read_chat.js +92 -0
  134. package/providers/_builtin/ide/pearai/scripts/webview_resolve_action.js +59 -0
  135. package/providers/_builtin/ide/pearai/scripts/webview_send_message.js +72 -0
  136. package/providers/_builtin/ide/pearai/scripts/webview_set_mode.js +36 -0
  137. package/providers/_builtin/ide/pearai/scripts/webview_set_model.js +36 -0
  138. package/providers/_builtin/ide/pearai/scripts/webview_switch_session.js +34 -0
  139. package/providers/_builtin/ide/pearai/scripts.js +74 -0
  140. package/providers/_builtin/ide/trae/provider.json +66 -0
  141. package/providers/_builtin/ide/trae/scripts/focus_editor.js +20 -0
  142. package/providers/_builtin/ide/trae/scripts/list_chats.js +24 -0
  143. package/providers/_builtin/ide/trae/scripts/list_models.js +39 -0
  144. package/providers/_builtin/ide/trae/scripts/list_modes.js +39 -0
  145. package/providers/_builtin/ide/trae/scripts/new_session.js +30 -0
  146. package/providers/_builtin/ide/trae/scripts/open_panel.js +44 -0
  147. package/providers/_builtin/ide/trae/scripts/read_chat.js +113 -0
  148. package/providers/_builtin/ide/trae/scripts/resolve_action.js +54 -0
  149. package/providers/_builtin/ide/trae/scripts/send_message.js +69 -0
  150. package/providers/_builtin/ide/trae/scripts/set_mode.js +15 -0
  151. package/providers/_builtin/ide/trae/scripts/set_model.js +15 -0
  152. package/providers/_builtin/ide/trae/scripts/switch_session.js +23 -0
  153. package/providers/_builtin/ide/trae/scripts.js +57 -0
  154. package/providers/_builtin/ide/vscode/provider.json +64 -0
  155. package/providers/_builtin/ide/vscode-insiders/provider.json +62 -0
  156. package/providers/_builtin/ide/vscodium/provider.json +63 -0
  157. package/providers/_builtin/ide/windsurf/provider.json +53 -0
  158. package/providers/_builtin/ide/windsurf/scripts/focus_editor.js +30 -0
  159. package/providers/_builtin/ide/windsurf/scripts/list_chats.js +117 -0
  160. package/providers/_builtin/ide/windsurf/scripts/list_models.js +39 -0
  161. package/providers/_builtin/ide/windsurf/scripts/list_modes.js +39 -0
  162. package/providers/_builtin/ide/windsurf/scripts/new_session.js +69 -0
  163. package/providers/_builtin/ide/windsurf/scripts/open_panel.js +58 -0
  164. package/providers/_builtin/ide/windsurf/scripts/read_chat.js +297 -0
  165. package/providers/_builtin/ide/windsurf/scripts/resolve_action.js +68 -0
  166. package/providers/_builtin/ide/windsurf/scripts/send_message.js +87 -0
  167. package/providers/_builtin/ide/windsurf/scripts/set_mode.js +15 -0
  168. package/providers/_builtin/ide/windsurf/scripts/set_model.js +15 -0
  169. package/providers/_builtin/ide/windsurf/scripts/switch_session.js +58 -0
  170. package/providers/_builtin/ide/windsurf/scripts.js +57 -0
  171. package/providers/_builtin/registry.json +266 -0
  172. package/providers/_builtin/validate.js +156 -0
  173. package/src/agent-stream/index.ts +6 -0
  174. package/src/agent-stream/manager.ts +286 -0
  175. package/src/agent-stream/poller.ts +154 -0
  176. package/src/agent-stream/provider-adapter.ts +138 -0
  177. package/src/agent-stream/types.ts +61 -0
  178. package/src/boot/daemon-lifecycle.ts +252 -0
  179. package/src/cdp/devtools.ts +335 -0
  180. package/src/cdp/initializer.ts +191 -0
  181. package/src/cdp/manager.ts +897 -0
  182. package/src/cdp/scanner.ts +185 -0
  183. package/src/cdp/setup.ts +150 -0
  184. package/src/cli-adapter-types.ts +25 -0
  185. package/src/cli-adapters/provider-cli-adapter.ts +448 -0
  186. package/src/commands/cdp-commands.ts +208 -0
  187. package/src/commands/chat-commands.ts +675 -0
  188. package/src/commands/cli-manager.ts +353 -0
  189. package/src/commands/handler.ts +328 -0
  190. package/src/commands/router.ts +258 -0
  191. package/src/commands/stream-commands.ts +325 -0
  192. package/src/config/chat-history.ts +211 -0
  193. package/src/config/config.ts +219 -0
  194. package/src/daemon/dev-server.ts +2378 -0
  195. package/src/daemon/scaffold-template.ts +394 -0
  196. package/src/daemon-core.ts +50 -0
  197. package/src/detection/cli-detector.ts +89 -0
  198. package/src/detection/ide-detector.ts +157 -0
  199. package/src/index.ts +103 -0
  200. package/src/installer.ts +263 -0
  201. package/src/ipc-protocol.ts +133 -0
  202. package/src/launch.ts +433 -0
  203. package/src/logging/command-log.ts +180 -0
  204. package/src/logging/logger.ts +316 -0
  205. package/src/providers/acp-provider-instance.ts +1140 -0
  206. package/src/providers/cli-provider-instance.ts +207 -0
  207. package/src/providers/contracts.ts +524 -0
  208. package/src/providers/extension-provider-instance.ts +156 -0
  209. package/src/providers/ide-provider-instance.ts +377 -0
  210. package/src/providers/index.ts +18 -0
  211. package/src/providers/provider-instance-manager.ts +182 -0
  212. package/src/providers/provider-instance.ts +112 -0
  213. package/src/providers/provider-loader.ts +1031 -0
  214. package/src/providers/status-monitor.ts +125 -0
  215. package/src/providers/version-archive.ts +266 -0
  216. package/src/status/reporter.ts +294 -0
  217. package/src/types.ts +206 -0
@@ -0,0 +1,675 @@
1
+ /**
2
+ * Chat Commands — readChat, sendChat, listChats, newChat, switchChat,
3
+ * setMode, changeModel, setThoughtLevel, resolveAction, chatHistory
4
+ */
5
+
6
+ import type { CommandResult, CommandHelpers } from './handler.js';
7
+ import { readChatHistory } from '../config/chat-history.js';
8
+ import { LOG } from '../logging/logger.js';
9
+
10
+ export async function handleChatHistory(h: CommandHelpers, args: any): Promise<CommandResult> {
11
+ const { agentType, offset, limit, instanceId } = args;
12
+ try {
13
+ const provider = h.getProvider(agentType);
14
+ const agentStr = provider?.type || agentType || h.currentIdeType || '';
15
+ const result = readChatHistory(agentStr, offset || 0, limit || 30, instanceId);
16
+ return { success: true, ...result, agent: agentStr };
17
+ } catch (e: any) {
18
+ return { success: false, error: e.message };
19
+ }
20
+ }
21
+
22
+ export async function handleReadChat(h: CommandHelpers, args: any): Promise<CommandResult> {
23
+ const provider = h.getProvider();
24
+ const _log = (msg: string) => LOG.debug('Command', `[read_chat] ${msg}`);
25
+
26
+ // CLI / ACP category: read from adapter
27
+ if (provider?.category === 'cli' || provider?.category === 'acp') {
28
+ const adapter = h.getCliAdapter(provider.type);
29
+ if (adapter) {
30
+ _log(`${provider.category} adapter: ${(adapter as any).cliType}`);
31
+ const status = (adapter as any).getStatus?.();
32
+ if (status) {
33
+ return { success: true, messages: status.messages || [], status: status.status, activeModal: status.activeModal };
34
+ }
35
+ }
36
+ return { success: false, error: `${provider.category} adapter not found` };
37
+ }
38
+
39
+ // Extension category: evaluateInSession
40
+ if (provider?.category === 'extension') {
41
+ try {
42
+ const evalResult = await h.evaluateProviderScript('readChat', undefined, 50000);
43
+ if (evalResult?.result) {
44
+ let parsed = evalResult.result;
45
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
46
+ if (parsed && typeof parsed === 'object') {
47
+ _log(`Extension OK: ${parsed.messages?.length || 0} msgs`);
48
+ h.historyWriter.appendNewMessages(
49
+ provider.type || 'unknown_extension',
50
+ parsed.messages || [],
51
+ parsed.title,
52
+ args?.instanceId
53
+ );
54
+ return { success: true, ...parsed };
55
+ }
56
+ }
57
+ } catch (e: any) {
58
+ _log(`Extension error: ${e.message}`);
59
+ }
60
+ // Alternative: AgentStreamManager (script fail when)
61
+ if (h.agentStream) {
62
+ const cdp = h.getCdp();
63
+ if (cdp) {
64
+ const streams = await h.agentStream.collectAgentStreams(cdp);
65
+ const stream = streams.find((s: any) => s.agentType === provider.type);
66
+ if (stream) {
67
+ h.historyWriter.appendNewMessages(
68
+ stream.agentType,
69
+ stream.messages || [],
70
+ undefined,
71
+ args?.instanceId
72
+ );
73
+ return { success: true, messages: stream.messages || [], status: stream.status, agentType: stream.agentType };
74
+ }
75
+ }
76
+ }
77
+ return { success: true, messages: [], status: 'idle' };
78
+ }
79
+
80
+ // IDE category (default): cdp.evaluate
81
+ const cdp = h.getCdp();
82
+ if (!cdp?.isConnected) return { success: false, error: 'CDP not connected' };
83
+
84
+ // webview IDE (Kiro, PearAI) → evaluateInWebviewFrame directly use
85
+ const webviewScript = h.getProviderScript('webviewReadChat') || h.getProviderScript('webview_read_chat');
86
+ if (webviewScript) {
87
+ try {
88
+ const matchText = provider?.webviewMatchText;
89
+ const matchFn = matchText
90
+ ? (body: string) => body.includes(matchText)
91
+ : undefined;
92
+ const raw = await cdp.evaluateInWebviewFrame(webviewScript, matchFn);
93
+ if (raw) {
94
+ let parsed: any = raw;
95
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
96
+ if (parsed && typeof parsed === 'object') {
97
+ _log(`Webview OK: ${parsed.messages?.length || 0} msgs`);
98
+ h.historyWriter.appendNewMessages(
99
+ provider?.type || h.currentIdeType || 'unknown_webview',
100
+ parsed.messages || [],
101
+ parsed.title,
102
+ args?.instanceId
103
+ );
104
+ return { success: true, ...parsed };
105
+ }
106
+ }
107
+ } catch (e: any) {
108
+ _log(`Webview readChat error: ${e.message}`);
109
+ }
110
+ return { success: true, messages: [], status: 'idle' };
111
+ }
112
+
113
+ // Regular IDE (Cursor, Windsurf, Trae etc) → main DOM evaluate
114
+ const script = h.getProviderScript('readChat') || h.getProviderScript('read_chat');
115
+ if (script) {
116
+ try {
117
+ const result = await cdp.evaluate(script, 50000);
118
+ let parsed: any = result;
119
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
120
+ if (parsed && typeof parsed === 'object' && parsed.messages?.length > 0) {
121
+ _log(`OK: ${parsed.messages?.length} msgs`);
122
+ h.historyWriter.appendNewMessages(
123
+ provider?.type || h.currentIdeType || 'unknown_ide',
124
+ parsed.messages || [],
125
+ parsed.title,
126
+ args?.instanceId
127
+ );
128
+ return { success: true, ...parsed };
129
+ }
130
+ } catch (e: any) {
131
+ LOG.info('Command', `[read_chat] Script error: ${e.message}`);
132
+ }
133
+ }
134
+
135
+ return { success: true, messages: [], status: 'idle' };
136
+ }
137
+
138
+ export async function handleSendChat(h: CommandHelpers, args: any): Promise<CommandResult> {
139
+ const text = args?.text || args?.message;
140
+ if (!text) return { success: false, error: 'text required' };
141
+ const _log = (msg: string) => LOG.debug('Command', `[send_chat] ${msg}`);
142
+ const provider = h.getProvider();
143
+
144
+ // CLI / ACP category: transmit via adapter
145
+ if (provider?.category === 'cli' || provider?.category === 'acp') {
146
+ const adapter = h.getCliAdapter(provider.type);
147
+ if (adapter) {
148
+ _log(`${provider.category} adapter: ${(adapter as any).cliType}`);
149
+ try {
150
+ await adapter.sendMessage(text);
151
+ return { success: true, sent: true, method: `${provider.category}-adapter`, targetAgent: (adapter as any).cliType };
152
+ } catch (e: any) {
153
+ return { success: false, error: `${provider.category} send failed: ${e.message}` };
154
+ }
155
+ }
156
+ }
157
+
158
+ // Extension category: via AgentStreamManager
159
+ if (provider?.category === 'extension') {
160
+ _log(`Extension: ${provider.type}`);
161
+ // Method 1: provider sendMessage script via evaluateInSession
162
+ try {
163
+ const evalResult = await h.evaluateProviderScript('sendMessage', { MESSAGE: text }, 30000);
164
+ if (evalResult?.result) {
165
+ let parsed = evalResult.result;
166
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
167
+ if (parsed?.sent) {
168
+ _log(`Extension script sent OK`);
169
+ return { success: true, sent: true, method: 'extension-script' };
170
+ }
171
+ if (parsed?.needsTypeAndSend) {
172
+ _log(`Extension needsTypeAndSend → AgentStreamManager`);
173
+ }
174
+ }
175
+ } catch (e: any) {
176
+ _log(`Extension script error: ${e.message}`);
177
+ }
178
+ // Method 2: AgentStreamManager
179
+ if (h.agentStream && h.getCdp()) {
180
+ const ok = await h.agentStream.sendToAgent(h.getCdp()!, provider.type, text, h.currentIdeType);
181
+ if (ok) {
182
+ _log(`AgentStreamManager sent OK`);
183
+ return { success: true, sent: true, method: 'agent-stream' };
184
+ }
185
+ }
186
+ return { success: false, error: `Extension '${provider.type}' send failed` };
187
+ }
188
+
189
+ // IDE category (default): Provider → typeAndSend → script
190
+ const targetCdp = h.getCdp();
191
+ if (!targetCdp?.isConnected) {
192
+ _log(`No CDP for ${h.currentIdeType}`);
193
+ return { success: false, error: `CDP for ${h.currentIdeType || 'unknown'} not connected` };
194
+ }
195
+
196
+ _log(`Targeting IDE: ${h.currentIdeType}`);
197
+
198
+ // Method 0: webview-based IDE (try webviewSendMessage first)
199
+ if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
200
+ try {
201
+ const webviewScript = (provider.scripts as any).webviewSendMessage(text);
202
+ if (webviewScript && targetCdp.evaluateInWebviewFrame) {
203
+ const matchText = provider.webviewMatchText;
204
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
205
+ const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
206
+ let wvParsed: any = wvResult;
207
+ if (typeof wvResult === 'string') { try { wvParsed = JSON.parse(wvResult); } catch { } }
208
+ if (wvParsed?.sent) {
209
+ _log(`webviewSendMessage (priority) OK`);
210
+ return { success: true, sent: true, method: 'webview-script-priority' };
211
+ }
212
+ _log(`webviewSendMessage (priority) did not confirm sent, falling through`);
213
+ }
214
+ } catch (e: any) {
215
+ _log(`webviewSendMessage (priority) failed: ${e.message}, falling through`);
216
+ }
217
+ }
218
+
219
+ // Method 1: use provider.inputMethod if available (main frame input)
220
+ if (provider?.inputMethod === 'cdp-type-and-send' && provider.inputSelector) {
221
+ try {
222
+ const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
223
+ if (sent) {
224
+ _log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
225
+ return { success: true, sent: true, method: 'typeAndSend-provider' };
226
+ }
227
+ } catch (e: any) {
228
+ _log(`typeAndSend(provider) failed: ${e.message}`);
229
+ }
230
+ }
231
+
232
+ // Method 2: provider sendMessage script
233
+ const sendScript = h.getProviderScript('sendMessage', { MESSAGE: text });
234
+ if (sendScript) {
235
+ try {
236
+ const result = await targetCdp.evaluate(sendScript, 30000);
237
+ let parsed: any = result;
238
+ if (typeof result === 'string') { try { parsed = JSON.parse(result); } catch { } }
239
+ if (parsed?.sent) {
240
+ _log(`sendMessage script OK`);
241
+ return { success: true, sent: true, method: 'script' };
242
+ }
243
+ // needsTypeAndSend response: typeAndSend using script-specified selector
244
+ if (parsed?.needsTypeAndSend && parsed?.selector) {
245
+ try {
246
+ const sent = await targetCdp.typeAndSend(parsed.selector, text);
247
+ if (sent) {
248
+ _log(`typeAndSend(script.selector=${parsed.selector}) success`);
249
+ return { success: true, sent: true, method: 'typeAndSend-script' };
250
+ }
251
+ } catch (e: any) {
252
+ _log(`typeAndSend(script.selector) failed: ${e.message}`);
253
+ }
254
+ }
255
+ // webviewSendMessage: attempt direct transmission from inside webview iframe
256
+ if (parsed?.needsTypeAndSend && provider?.scripts?.webviewSendMessage) {
257
+ try {
258
+ const webviewScript = (provider.scripts as any).webviewSendMessage(text);
259
+ if (webviewScript && targetCdp.evaluateInWebviewFrame) {
260
+ const matchText = provider.webviewMatchText;
261
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
262
+ const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
263
+ let wvParsed: any = wvResult;
264
+ if (typeof wvResult === 'string') { try { wvParsed = JSON.parse(wvResult); } catch { } }
265
+ if (wvParsed?.sent) {
266
+ _log(`webviewSendMessage OK`);
267
+ return { success: true, sent: true, method: 'webview-script' };
268
+ }
269
+ }
270
+ } catch (e: any) {
271
+ _log(`webviewSendMessage failed: ${e.message}`);
272
+ }
273
+ }
274
+ // Coordinate-based fallback: input field inside webview iframe
275
+ if (parsed?.needsTypeAndSend && parsed?.clickCoords) {
276
+ try {
277
+ const { x, y } = parsed.clickCoords;
278
+ const sent = await targetCdp.typeAndSendAt(x, y, text);
279
+ if (sent) {
280
+ _log(`typeAndSendAt(${x},${y}) success`);
281
+ return { success: true, sent: true, method: 'typeAndSendAt-script' };
282
+ }
283
+ } catch (e: any) {
284
+ _log(`typeAndSendAt failed: ${e.message}`);
285
+ }
286
+ }
287
+ } catch (e: any) {
288
+ _log(`sendMessage script failed: ${e.message}`);
289
+ }
290
+ }
291
+
292
+ _log('All methods failed');
293
+ return { success: false, error: 'No provider method could send the message' };
294
+ }
295
+
296
+ export async function handleListChats(h: CommandHelpers, args: any): Promise<CommandResult> {
297
+ const provider = h.getProvider();
298
+
299
+ // Extension: via AgentStreamManager
300
+ if (provider?.category === 'extension' && h.agentStream && h.getCdp()) {
301
+ try {
302
+ const chats = await h.agentStream.listAgentChats(h.getCdp()!, provider.type);
303
+ LOG.info('Command', `[list_chats] Extension: ${chats.length} chats`);
304
+ return { success: true, chats };
305
+ } catch (e: any) {
306
+ LOG.info('Command', `[list_chats] Extension error: ${e.message}`);
307
+ }
308
+ }
309
+
310
+ // webview IDE
311
+ try {
312
+ const webviewScript = h.getProviderScript('webviewListSessions') || h.getProviderScript('webview_list_sessions');
313
+ if (webviewScript) {
314
+ const matchText = provider?.webviewMatchText;
315
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
316
+ const raw = await h.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
317
+ let parsed: any = raw;
318
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
319
+ if (parsed?.sessions) {
320
+ LOG.info('Command', `[list_chats] Webview OK: ${parsed.sessions.length} chats`);
321
+ return { success: true, chats: parsed.sessions };
322
+ }
323
+ }
324
+ } catch (e: any) {
325
+ LOG.info('Command', `[list_chats] Webview error: ${e.message}`);
326
+ }
327
+
328
+ // IDE/default: evaluateProviderScript
329
+ try {
330
+ const evalResult = await h.evaluateProviderScript('listSessions');
331
+ if (evalResult) {
332
+ let parsed = evalResult.result;
333
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
334
+ if (Array.isArray(parsed)) {
335
+ LOG.info('Command', `[list_chats] OK: ${parsed.length} chats`);
336
+ return { success: true, chats: parsed };
337
+ }
338
+ }
339
+ } catch (e: any) {
340
+ LOG.info('Command', `[list_chats] error: ${e.message}`);
341
+ }
342
+
343
+ return { success: false, error: 'listSessions script not available for this provider' };
344
+ }
345
+
346
+ export async function handleNewChat(h: CommandHelpers, args: any): Promise<CommandResult> {
347
+ const provider = h.getProvider();
348
+
349
+ if (provider?.category === 'extension' && h.agentStream && h.getCdp()) {
350
+ const ok = await h.agentStream.newAgentSession(h.getCdp()!, provider.type, h.currentIdeType);
351
+ return { success: ok };
352
+ }
353
+
354
+ // webview IDE
355
+ try {
356
+ const webviewScript = h.getProviderScript('webviewNewSession') || h.getProviderScript('webview_new_session');
357
+ if (webviewScript) {
358
+ const matchText = provider?.webviewMatchText;
359
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
360
+ const raw = await h.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
361
+ if (raw) return { success: true, result: raw };
362
+ }
363
+ } catch (e: any) {
364
+ return { success: false, error: `webviewNewSession failed: ${e.message}` };
365
+ }
366
+
367
+ try {
368
+ const evalResult = await h.evaluateProviderScript('newSession');
369
+ if (evalResult) return { success: true };
370
+ } catch (e: any) {
371
+ return { success: false, error: `newSession failed: ${e.message}` };
372
+ }
373
+
374
+ return { success: false, error: 'newSession script not available for this provider' };
375
+ }
376
+
377
+ export async function handleSwitchChat(h: CommandHelpers, args: any): Promise<CommandResult> {
378
+ const provider = h.getProvider();
379
+ const ideType = h.currentIdeType;
380
+ const sessionId = args?.sessionId || args?.id || args?.chatId;
381
+ if (!sessionId) return { success: false, error: 'sessionId required' };
382
+ LOG.info('Command', `[switch_chat] sessionId=${sessionId}, ideType=${ideType}`);
383
+
384
+ if (provider?.category === 'extension' && h.agentStream && h.getCdp()) {
385
+ const ok = await h.agentStream.switchAgentSession(h.getCdp()!, provider.type, sessionId);
386
+ return { success: ok, result: ok ? 'switched' : 'failed' };
387
+ }
388
+
389
+ const cdp = h.getCdp(ideType);
390
+ if (!cdp?.isConnected) return { success: false, error: 'CDP not connected' };
391
+
392
+ // webview IDE
393
+ try {
394
+ const webviewScript = h.getProviderScript('webviewSwitchSession', { SESSION_ID: JSON.stringify(sessionId) });
395
+ if (webviewScript) {
396
+ const matchText = provider?.webviewMatchText;
397
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
398
+ const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
399
+ if (raw) return { success: true, result: raw };
400
+ }
401
+ } catch (e: any) {
402
+ return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
403
+ }
404
+
405
+ const script = h.getProviderScript('switchSession', { SESSION_ID: JSON.stringify(sessionId) })
406
+ || h.getProviderScript('switch_session', { SESSION_ID: JSON.stringify(sessionId) });
407
+ if (!script) return { success: false, error: 'switch_session script not available' };
408
+
409
+ try {
410
+ const raw = await cdp.evaluate(script, 15000);
411
+ LOG.info('Command', `[switch_chat] result: ${raw}`);
412
+
413
+ let parsed: any = null;
414
+ try { parsed = typeof raw === 'string' ? JSON.parse(raw) : raw; } catch { }
415
+
416
+ if (parsed?.action === 'click' && parsed.clickX && parsed.clickY) {
417
+ const x = Math.round(parsed.clickX);
418
+ const y = Math.round(parsed.clickY);
419
+ LOG.info('Command', `[switch_chat] CDP click at (${x}, ${y}) for "${parsed.title}"`);
420
+ await cdp.send('Input.dispatchMouseEvent', {
421
+ type: 'mousePressed', x, y, button: 'left', clickCount: 1
422
+ });
423
+ await cdp.send('Input.dispatchMouseEvent', {
424
+ type: 'mouseReleased', x, y, button: 'left', clickCount: 1
425
+ });
426
+ await new Promise(r => setTimeout(r, 2000));
427
+
428
+ // Auto-handle workspace selection dialog
429
+ const wsResult = await cdp.evaluate(`
430
+ (() => {
431
+ const inp = Array.from(document.querySelectorAll('input[type="text"]'))
432
+ .find(i => i.offsetWidth > 0 && (i.placeholder || '').includes('Select where'));
433
+ if (!inp) return null;
434
+ const rows = inp.closest('[class*="quickInput"]')?.querySelectorAll('[class*="cursor-pointer"]');
435
+ if (rows && rows.length > 0) {
436
+ const r = rows[0].getBoundingClientRect();
437
+ return JSON.stringify({ x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) });
438
+ }
439
+ return null;
440
+ })()
441
+ `, 5000);
442
+ if (wsResult) {
443
+ try {
444
+ const ws = JSON.parse(wsResult as string);
445
+ await cdp.send('Input.dispatchMouseEvent', {
446
+ type: 'mousePressed', x: ws.x, y: ws.y, button: 'left', clickCount: 1
447
+ });
448
+ await cdp.send('Input.dispatchMouseEvent', {
449
+ type: 'mouseReleased', x: ws.x, y: ws.y, button: 'left', clickCount: 1
450
+ });
451
+ } catch { }
452
+ }
453
+ return { success: true, result: 'switched' };
454
+ }
455
+
456
+ if (parsed?.error) return { success: false, error: parsed.error };
457
+ return { success: true, result: raw };
458
+ } catch (e: any) {
459
+ LOG.error('Command', `[switch_chat] error: ${e.message}`);
460
+ return { success: false, error: e.message };
461
+ }
462
+ }
463
+
464
+ export async function handleSetMode(h: CommandHelpers, args: any): Promise<CommandResult> {
465
+ const provider = h.getProvider();
466
+ const mode = args?.mode || 'agent';
467
+
468
+ // ACP provider
469
+ if (provider?.category === 'acp') {
470
+ const adapter = h.getCliAdapter(provider.type);
471
+ if (adapter) {
472
+ const acpInstance = (adapter as any)._acpInstance;
473
+ if (acpInstance && typeof acpInstance.onEvent === 'function') {
474
+ acpInstance.onEvent('set_mode', { mode });
475
+ return { success: true, mode };
476
+ }
477
+ }
478
+ return { success: false, error: 'ACP adapter not found' };
479
+ }
480
+
481
+ // 1. webview setMode
482
+ const webviewScript = h.getProviderScript('webviewSetMode', { MODE: JSON.stringify(mode) });
483
+ if (webviewScript) {
484
+ const cdp = h.getCdp();
485
+ if (cdp?.isConnected) {
486
+ try {
487
+ const matchText = provider?.webviewMatchText;
488
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
489
+ const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
490
+ let result: any = raw;
491
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch { } }
492
+ if (result?.success) return { success: true, mode, method: 'webview-script' };
493
+ } catch (e: any) {
494
+ LOG.info('Command', `[set_mode] webview script error: ${e.message}`);
495
+ }
496
+ }
497
+ }
498
+
499
+ // 2. main frame setMode
500
+ const mainScript = h.getProviderScript('setMode', { MODE: JSON.stringify(mode) });
501
+ if (mainScript) {
502
+ try {
503
+ const evalResult = await h.evaluateProviderScript('setMode', { MODE: JSON.stringify(mode) }, 15000);
504
+ if (evalResult?.result) {
505
+ let parsed = evalResult.result;
506
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
507
+ if (parsed?.success) return { success: true, mode, method: 'script' };
508
+ }
509
+ } catch (e: any) {
510
+ LOG.info('Command', `[set_mode] script error: ${e.message}`);
511
+ }
512
+ }
513
+
514
+ return { success: false, error: `setMode '${mode}' not supported by this provider` };
515
+ }
516
+
517
+ export async function handleChangeModel(h: CommandHelpers, args: any): Promise<CommandResult> {
518
+ const provider = h.getProvider();
519
+ const model = args?.model;
520
+
521
+ LOG.info('Command', `[change_model] model=${model} provider=${provider?.type} category=${provider?.category} ideType=${h.currentIdeType} providerType=${h.currentProviderType}`);
522
+
523
+ // ACP provider
524
+ if (provider?.category === 'acp') {
525
+ const adapter = h.getCliAdapter(provider.type);
526
+ LOG.info('Command', `[change_model] ACP adapter found: ${!!adapter}, type=${(adapter as any)?.cliType}, hasAcpInstance=${!!(adapter as any)?._acpInstance}`);
527
+ if (adapter) {
528
+ const acpInstance = (adapter as any)._acpInstance;
529
+ if (acpInstance && typeof acpInstance.onEvent === 'function') {
530
+ acpInstance.onEvent('change_model', { model });
531
+ LOG.info('Command', `[change_model] Dispatched change_model event to ACP instance`);
532
+ return { success: true, model };
533
+ }
534
+ }
535
+ return { success: false, error: 'ACP adapter not found' };
536
+ }
537
+
538
+ // 1. webview setModel
539
+ const webviewScript = h.getProviderScript('webviewSetModel', { MODEL: JSON.stringify(model) });
540
+ if (webviewScript) {
541
+ const cdp = h.getCdp();
542
+ if (cdp?.isConnected) {
543
+ try {
544
+ const matchText = provider?.webviewMatchText;
545
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
546
+ const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
547
+ let result: any = raw;
548
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch { } }
549
+ if (result?.success) return { success: true, model, method: 'webview-script' };
550
+ } catch (e: any) {
551
+ LOG.info('Command', `[change_model] webview script error: ${e.message}`);
552
+ }
553
+ }
554
+ }
555
+
556
+ // 2. main frame setModel
557
+ const mainScript = h.getProviderScript('setModel', { MODEL: JSON.stringify(model) });
558
+ if (mainScript) {
559
+ try {
560
+ const evalResult = await h.evaluateProviderScript('setModel', { MODEL: JSON.stringify(model) }, 15000);
561
+ if (evalResult?.result) {
562
+ let parsed = evalResult.result;
563
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
564
+ if (parsed?.success) return { success: true, model, method: 'script' };
565
+ }
566
+ } catch (e: any) {
567
+ LOG.info('Command', `[change_model] script error: ${e.message}`);
568
+ }
569
+ }
570
+
571
+ return { success: false, error: 'changeModel not supported by this IDE provider' };
572
+ }
573
+
574
+ export async function handleSetThoughtLevel(h: CommandHelpers, args: any): Promise<CommandResult> {
575
+ const configId = args?.configId;
576
+ const value = args?.value;
577
+ if (!configId || !value) return { success: false, error: 'configId and value required' };
578
+
579
+ const provider = h.getProvider();
580
+ if (!provider || provider.category !== 'acp') {
581
+ return { success: false, error: 'set_thought_level only for ACP providers' };
582
+ }
583
+ const adapter = h.getCliAdapter(provider.type);
584
+ const acpInstance = adapter?._acpInstance;
585
+ if (!acpInstance) return { success: false, error: 'ACP instance not found' };
586
+
587
+ try {
588
+ await acpInstance.setConfigOption(configId, value);
589
+ LOG.info('Command', `[set_thought_level] ${configId}=${value} for ${provider.type}`);
590
+ return { success: true, configId, value };
591
+ } catch (e: any) {
592
+ return { success: false, error: e?.message };
593
+ }
594
+ }
595
+
596
+ export async function handleResolveAction(h: CommandHelpers, args: any): Promise<CommandResult> {
597
+ const provider = h.getProvider();
598
+ const action = args?.action || 'approve';
599
+ const button = args?.button || args?.buttonText
600
+ || (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : 'Accept');
601
+
602
+ LOG.info('Command', `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
603
+
604
+ // 1. Extension: via AgentStreamManager
605
+ if (provider?.category === 'extension' && h.agentStream && h.getCdp()) {
606
+ const ok = await h.agentStream.resolveAgentAction(
607
+ h.getCdp()!, provider.type, action, h.currentIdeType
608
+ );
609
+ return { success: ok };
610
+ }
611
+
612
+ // 2. Webview Provider script
613
+ if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
614
+ const script = h.getProviderScript('webviewResolveAction', { action, button, buttonText: button })
615
+ || h.getProviderScript('webview_resolve_action', { action, button, buttonText: button });
616
+ if (script) {
617
+ const cdp = h.getCdp();
618
+ if (cdp?.isConnected) {
619
+ try {
620
+ const matchText = provider?.webviewMatchText;
621
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
622
+ const raw = await cdp.evaluateInWebviewFrame?.(script, matchFn);
623
+ let result: any = raw;
624
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch { } }
625
+ LOG.info('Command', `[resolveAction] webview script result: ${JSON.stringify(result)}`);
626
+
627
+ if (result?.resolved) return { success: true, clicked: result.clicked };
628
+ if (result?.found && result.x != null && result.y != null) {
629
+ LOG.info('Command', `[resolveAction] Webview coordinate click not fully supported via CDP. Click directly in script.`);
630
+ }
631
+ if (result?.found || result?.resolved) return { success: true };
632
+ } catch (e: any) {
633
+ return { success: false, error: `webviewResolveAction failed: ${e.message}` };
634
+ }
635
+ }
636
+ }
637
+ }
638
+
639
+ // 3. Provider script (Main DOM) → returns coords → CDP mouse click
640
+ if (provider?.scripts?.resolveAction) {
641
+ const script = provider.scripts.resolveAction({ action, button, buttonText: button });
642
+ if (script) {
643
+ const cdp = h.getCdp();
644
+ if (!cdp?.isConnected) return { success: false, error: 'CDP not connected' };
645
+ try {
646
+ const raw = await cdp.evaluate(script, 30000);
647
+ let result: any = raw;
648
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch {} }
649
+ LOG.info('Command', `[resolveAction] script result: ${JSON.stringify(result)}`);
650
+
651
+ if (result?.resolved) {
652
+ LOG.info('Command', `[resolveAction] script-click resolved — "${result.clicked}"`);
653
+ return { success: true, clicked: result.clicked };
654
+ }
655
+ if (result?.found && result.x != null && result.y != null) {
656
+ const x = result.x;
657
+ const y = result.y;
658
+ await cdp.send('Input.dispatchMouseEvent', {
659
+ type: 'mousePressed', x, y, button: 'left', clickCount: 1
660
+ });
661
+ await cdp.send('Input.dispatchMouseEvent', {
662
+ type: 'mouseReleased', x, y, button: 'left', clickCount: 1
663
+ });
664
+ LOG.info('Command', `[resolveAction] CDP click at (${x}, ${y}) — "${result.text}"`);
665
+ return { success: true, clicked: result.text };
666
+ }
667
+ return { success: false, error: result?.found === false ? `Button not found: ${button}` : 'No coordinates' };
668
+ } catch (e: any) {
669
+ return { success: false, error: `resolveAction failed: ${e.message}` };
670
+ }
671
+ }
672
+ }
673
+
674
+ return { success: false, error: 'resolveAction script not available for this provider' };
675
+ }