@adhdev/daemon-core 0.6.57 → 0.6.59

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 (241) hide show
  1. package/dist/index.d.ts +18 -1
  2. package/dist/index.js +339 -167
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/src/cli-adapters/provider-cli-adapter.ts +223 -48
  6. package/src/commands/chat-commands.ts +7 -1
  7. package/src/config/chat-history.ts +53 -1
  8. package/src/daemon/dev-server.ts +7 -9
  9. package/src/detection/ide-detector.ts +1 -1
  10. package/src/providers/cli-provider-instance.ts +10 -23
  11. package/src/providers/provider-instance.ts +1 -0
  12. package/src/providers/provider-loader.ts +3 -6
  13. package/src/providers/version-archive.ts +4 -1
  14. package/providers/_builtin/.github/workflows/generate-registry.yml +0 -76
  15. package/providers/_builtin/COMPATIBILITY.md +0 -217
  16. package/providers/_builtin/CONTRIBUTING.md +0 -200
  17. package/providers/_builtin/README.md +0 -119
  18. package/providers/_builtin/_helpers/index.js +0 -188
  19. package/providers/_builtin/acp/agentpool/provider.json +0 -54
  20. package/providers/_builtin/acp/amp/provider.json +0 -52
  21. package/providers/_builtin/acp/auggie/provider.json +0 -57
  22. package/providers/_builtin/acp/autodev/provider.json +0 -54
  23. package/providers/_builtin/acp/autohand/provider.json +0 -52
  24. package/providers/_builtin/acp/blackbox-ai/provider.json +0 -54
  25. package/providers/_builtin/acp/claude-agent/provider.json +0 -57
  26. package/providers/_builtin/acp/cline-acp/provider.json +0 -54
  27. package/providers/_builtin/acp/codebuddy/provider.json +0 -54
  28. package/providers/_builtin/acp/codex-cli/provider.json +0 -57
  29. package/providers/_builtin/acp/corust-agent/provider.json +0 -52
  30. package/providers/_builtin/acp/crow-cli/provider.json +0 -54
  31. package/providers/_builtin/acp/cursor-acp/provider.json +0 -54
  32. package/providers/_builtin/acp/deepagents/provider.json +0 -52
  33. package/providers/_builtin/acp/dimcode/provider.json +0 -54
  34. package/providers/_builtin/acp/docker-cagent/provider.json +0 -57
  35. package/providers/_builtin/acp/factory-droid/provider.json +0 -60
  36. package/providers/_builtin/acp/fast-agent/provider.json +0 -52
  37. package/providers/_builtin/acp/gemini-cli/provider.json +0 -114
  38. package/providers/_builtin/acp/github-copilot/provider.json +0 -54
  39. package/providers/_builtin/acp/goose/provider.json +0 -57
  40. package/providers/_builtin/acp/junie/provider.json +0 -52
  41. package/providers/_builtin/acp/kilo/provider.json +0 -54
  42. package/providers/_builtin/acp/kimi-cli/provider.json +0 -57
  43. package/providers/_builtin/acp/minion-code/provider.json +0 -52
  44. package/providers/_builtin/acp/mistral-vibe/provider.json +0 -57
  45. package/providers/_builtin/acp/nova/provider.json +0 -54
  46. package/providers/_builtin/acp/openclaw/provider.json +0 -54
  47. package/providers/_builtin/acp/opencode/provider.json +0 -52
  48. package/providers/_builtin/acp/openhands/provider.json +0 -54
  49. package/providers/_builtin/acp/pi-acp/provider.json +0 -52
  50. package/providers/_builtin/acp/qoder/provider.json +0 -54
  51. package/providers/_builtin/acp/qwen-code/provider.json +0 -60
  52. package/providers/_builtin/acp/stakpak/provider.json +0 -54
  53. package/providers/_builtin/acp/vtcode/provider.json +0 -54
  54. package/providers/_builtin/cli/aider-cli/provider.json +0 -37
  55. package/providers/_builtin/cli/aider-cli/scripts/1.0/detect_status.js +0 -20
  56. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_approval.js +0 -10
  57. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_output.js +0 -49
  58. package/providers/_builtin/cli/aider-cli/scripts/1.0/scripts.js +0 -7
  59. package/providers/_builtin/cli/claude-cli/provider.json +0 -109
  60. package/providers/_builtin/cli/claude-cli/scripts/1.0/detect_status.js +0 -31
  61. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_approval.js +0 -38
  62. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_output.js +0 -164
  63. package/providers/_builtin/cli/claude-cli/scripts/1.0/scripts.js +0 -42
  64. package/providers/_builtin/cli/codex-cli/provider.json +0 -88
  65. package/providers/_builtin/cli/codex-cli/scripts/1.0/detect_status.js +0 -20
  66. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_approval.js +0 -15
  67. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_output.js +0 -68
  68. package/providers/_builtin/cli/codex-cli/scripts/1.0/scripts.js +0 -11
  69. package/providers/_builtin/cli/cursor-cli/provider.json +0 -37
  70. package/providers/_builtin/cli/cursor-cli/scripts/1.0/detect_status.js +0 -19
  71. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_approval.js +0 -10
  72. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_output.js +0 -48
  73. package/providers/_builtin/cli/cursor-cli/scripts/1.0/scripts.js +0 -7
  74. package/providers/_builtin/cli/gemini-cli/provider.json +0 -109
  75. package/providers/_builtin/cli/gemini-cli/scripts/1.0/detect_status.js +0 -26
  76. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_approval.js +0 -22
  77. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_output.js +0 -71
  78. package/providers/_builtin/cli/gemini-cli/scripts/1.0/scripts.js +0 -12
  79. package/providers/_builtin/cli/github-copilot-cli/provider.json +0 -37
  80. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/detect_status.js +0 -19
  81. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_approval.js +0 -9
  82. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_output.js +0 -48
  83. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/scripts.js +0 -7
  84. package/providers/_builtin/cli/goose-cli/provider.json +0 -37
  85. package/providers/_builtin/cli/goose-cli/scripts/1.0/detect_status.js +0 -20
  86. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_approval.js +0 -10
  87. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_output.js +0 -48
  88. package/providers/_builtin/cli/goose-cli/scripts/1.0/scripts.js +0 -7
  89. package/providers/_builtin/cli/opencode-cli/provider.json +0 -37
  90. package/providers/_builtin/cli/opencode-cli/scripts/1.0/detect_status.js +0 -15
  91. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_approval.js +0 -9
  92. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_output.js +0 -48
  93. package/providers/_builtin/cli/opencode-cli/scripts/1.0/scripts.js +0 -7
  94. package/providers/_builtin/docs/CDP_SELECTOR_GUIDE.md +0 -370
  95. package/providers/_builtin/docs/PROVIDER_GUIDE.md +0 -916
  96. package/providers/_builtin/extension/cline/provider.json +0 -37
  97. package/providers/_builtin/extension/cline/scripts/1.0/focus_editor.js +0 -48
  98. package/providers/_builtin/extension/cline/scripts/1.0/list_chats.js +0 -100
  99. package/providers/_builtin/extension/cline/scripts/1.0/list_models.js +0 -43
  100. package/providers/_builtin/extension/cline/scripts/1.0/list_modes.js +0 -35
  101. package/providers/_builtin/extension/cline/scripts/1.0/new_session.js +0 -85
  102. package/providers/_builtin/extension/cline/scripts/1.0/open_panel.js +0 -25
  103. package/providers/_builtin/extension/cline/scripts/1.0/read_chat.js +0 -270
  104. package/providers/_builtin/extension/cline/scripts/1.0/resolve_action.js +0 -83
  105. package/providers/_builtin/extension/cline/scripts/1.0/scripts.js +0 -82
  106. package/providers/_builtin/extension/cline/scripts/1.0/send_message.js +0 -95
  107. package/providers/_builtin/extension/cline/scripts/1.0/set_mode.js +0 -36
  108. package/providers/_builtin/extension/cline/scripts/1.0/set_model.js +0 -36
  109. package/providers/_builtin/extension/cline/scripts/1.0/switch_session.js +0 -206
  110. package/providers/_builtin/extension/codex/provider.json +0 -38
  111. package/providers/_builtin/extension/codex/scripts/1.0/click_conversation_webview.js +0 -24
  112. package/providers/_builtin/extension/codex/scripts/1.0/explore_chat_webview.js +0 -110
  113. package/providers/_builtin/extension/codex/scripts/1.0/explore_controls_webview.js +0 -75
  114. package/providers/_builtin/extension/codex/scripts/1.0/explore_dom.js +0 -58
  115. package/providers/_builtin/extension/codex/scripts/1.0/explore_dropdown_webview.js +0 -64
  116. package/providers/_builtin/extension/codex/scripts/1.0/inspect_code_webview.js +0 -55
  117. package/providers/_builtin/extension/codex/scripts/1.0/list_models.js +0 -63
  118. package/providers/_builtin/extension/codex/scripts/1.0/list_modes.js +0 -140
  119. package/providers/_builtin/extension/codex/scripts/1.0/message_structure_webview.js +0 -79
  120. package/providers/_builtin/extension/codex/scripts/1.0/new_session.js +0 -26
  121. package/providers/_builtin/extension/codex/scripts/1.0/read_chat.js +0 -516
  122. package/providers/_builtin/extension/codex/scripts/1.0/resolve_action.js +0 -82
  123. package/providers/_builtin/extension/codex/scripts/1.0/send_message.js +0 -42
  124. package/providers/_builtin/extension/codex/scripts/1.0/set_mode.js +0 -165
  125. package/providers/_builtin/extension/codex/scripts/1.0/set_model.js +0 -86
  126. package/providers/_builtin/extension/roo-code/provider.json +0 -37
  127. package/providers/_builtin/extension/roo-code/scripts/1.0/scripts.js +0 -82
  128. package/providers/_builtin/ide/antigravity/provider.json +0 -88
  129. package/providers/_builtin/ide/antigravity/scripts/1.0/focus_editor.js +0 -20
  130. package/providers/_builtin/ide/antigravity/scripts/1.0/list_chats.js +0 -137
  131. package/providers/_builtin/ide/antigravity/scripts/1.0/list_models.js +0 -61
  132. package/providers/_builtin/ide/antigravity/scripts/1.0/list_modes.js +0 -72
  133. package/providers/_builtin/ide/antigravity/scripts/1.0/new_session.js +0 -75
  134. package/providers/_builtin/ide/antigravity/scripts/1.0/read_chat.js +0 -352
  135. package/providers/_builtin/ide/antigravity/scripts/1.0/resolve_action.js +0 -63
  136. package/providers/_builtin/ide/antigravity/scripts/1.0/scripts.js +0 -67
  137. package/providers/_builtin/ide/antigravity/scripts/1.0/send_message.js +0 -56
  138. package/providers/_builtin/ide/antigravity/scripts/1.0/set_mode.js +0 -67
  139. package/providers/_builtin/ide/antigravity/scripts/1.0/set_model.js +0 -72
  140. package/providers/_builtin/ide/antigravity/scripts/1.0/switch_session.js +0 -114
  141. package/providers/_builtin/ide/cursor/provider.json +0 -70
  142. package/providers/_builtin/ide/cursor/scripts/1.0/dismiss_notification.js +0 -30
  143. package/providers/_builtin/ide/cursor/scripts/1.0/focus_editor.js +0 -13
  144. package/providers/_builtin/ide/cursor/scripts/1.0/list_models.js +0 -78
  145. package/providers/_builtin/ide/cursor/scripts/1.0/list_modes.js +0 -40
  146. package/providers/_builtin/ide/cursor/scripts/1.0/list_notifications.js +0 -23
  147. package/providers/_builtin/ide/cursor/scripts/1.0/list_sessions.js +0 -42
  148. package/providers/_builtin/ide/cursor/scripts/1.0/new_session.js +0 -20
  149. package/providers/_builtin/ide/cursor/scripts/1.0/open_panel.js +0 -23
  150. package/providers/_builtin/ide/cursor/scripts/1.0/read_chat.js +0 -318
  151. package/providers/_builtin/ide/cursor/scripts/1.0/resolve_action.js +0 -19
  152. package/providers/_builtin/ide/cursor/scripts/1.0/scripts.js +0 -78
  153. package/providers/_builtin/ide/cursor/scripts/1.0/send_message.js +0 -23
  154. package/providers/_builtin/ide/cursor/scripts/1.0/set_mode.js +0 -38
  155. package/providers/_builtin/ide/cursor/scripts/1.0/set_model.js +0 -81
  156. package/providers/_builtin/ide/cursor/scripts/1.0/switch_session.js +0 -28
  157. package/providers/_builtin/ide/kiro/provider.json +0 -68
  158. package/providers/_builtin/ide/kiro/scripts/1.0/focus_editor.js +0 -20
  159. package/providers/_builtin/ide/kiro/scripts/1.0/open_panel.js +0 -47
  160. package/providers/_builtin/ide/kiro/scripts/1.0/resolve_action.js +0 -54
  161. package/providers/_builtin/ide/kiro/scripts/1.0/send_message.js +0 -29
  162. package/providers/_builtin/ide/kiro/scripts/1.0/webview_dump_html.js +0 -1
  163. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_models.js +0 -42
  164. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_modes.js +0 -22
  165. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_sessions.js +0 -21
  166. package/providers/_builtin/ide/kiro/scripts/1.0/webview_new_session.js +0 -34
  167. package/providers/_builtin/ide/kiro/scripts/1.0/webview_read_chat.js +0 -161
  168. package/providers/_builtin/ide/kiro/scripts/1.0/webview_resolve_action.js +0 -62
  169. package/providers/_builtin/ide/kiro/scripts/1.0/webview_send_message.js +0 -94
  170. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_mode.js +0 -34
  171. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_model.js +0 -47
  172. package/providers/_builtin/ide/kiro/scripts/1.0/webview_switch_session.js +0 -26
  173. package/providers/_builtin/ide/pearai/.tmp/after_rich.json +0 -157
  174. package/providers/_builtin/ide/pearai/.tmp/after_rich_raw.json +0 -161
  175. package/providers/_builtin/ide/pearai/.tmp/after_switch.json +0 -592
  176. package/providers/_builtin/ide/pearai/.tmp/after_switch_raw.json +0 -596
  177. package/providers/_builtin/ide/pearai/.tmp/home_dump_raw.json +0 -176
  178. package/providers/_builtin/ide/pearai/.tmp/items_raw.json +0 -778
  179. package/providers/_builtin/ide/pearai/.tmp/webview_dump.json +0 -157
  180. package/providers/_builtin/ide/pearai/.tmp/webview_dump_raw.json +0 -161
  181. package/providers/_builtin/ide/pearai/provider.json +0 -71
  182. package/providers/_builtin/ide/pearai/scripts/1.0/focus_editor.js +0 -16
  183. package/providers/_builtin/ide/pearai/scripts/1.0/list_models.js +0 -45
  184. package/providers/_builtin/ide/pearai/scripts/1.0/list_modes.js +0 -44
  185. package/providers/_builtin/ide/pearai/scripts/1.0/list_sessions.js +0 -93
  186. package/providers/_builtin/ide/pearai/scripts/1.0/new_session.js +0 -38
  187. package/providers/_builtin/ide/pearai/scripts/1.0/open_panel.js +0 -23
  188. package/providers/_builtin/ide/pearai/scripts/1.0/read_chat.js +0 -169
  189. package/providers/_builtin/ide/pearai/scripts/1.0/resolve_action.js +0 -60
  190. package/providers/_builtin/ide/pearai/scripts/1.0/scripts.js +0 -111
  191. package/providers/_builtin/ide/pearai/scripts/1.0/send_message.js +0 -104
  192. package/providers/_builtin/ide/pearai/scripts/1.0/set_mode.js +0 -51
  193. package/providers/_builtin/ide/pearai/scripts/1.0/set_model.js +0 -54
  194. package/providers/_builtin/ide/pearai/scripts/1.0/switch_session.js +0 -81
  195. package/providers/_builtin/ide/trae/provider.json +0 -72
  196. package/providers/_builtin/ide/trae/scripts/1.0/focus_editor.js +0 -20
  197. package/providers/_builtin/ide/trae/scripts/1.0/list_chats.js +0 -24
  198. package/providers/_builtin/ide/trae/scripts/1.0/list_models.js +0 -39
  199. package/providers/_builtin/ide/trae/scripts/1.0/list_modes.js +0 -39
  200. package/providers/_builtin/ide/trae/scripts/1.0/new_session.js +0 -30
  201. package/providers/_builtin/ide/trae/scripts/1.0/open_panel.js +0 -44
  202. package/providers/_builtin/ide/trae/scripts/1.0/read_chat.js +0 -113
  203. package/providers/_builtin/ide/trae/scripts/1.0/resolve_action.js +0 -54
  204. package/providers/_builtin/ide/trae/scripts/1.0/scripts.js +0 -82
  205. package/providers/_builtin/ide/trae/scripts/1.0/send_message.js +0 -69
  206. package/providers/_builtin/ide/trae/scripts/1.0/set_mode.js +0 -15
  207. package/providers/_builtin/ide/trae/scripts/1.0/set_model.js +0 -15
  208. package/providers/_builtin/ide/trae/scripts/1.0/switch_session.js +0 -23
  209. package/providers/_builtin/ide/vscode/provider.json +0 -70
  210. package/providers/_builtin/ide/vscode-insiders/provider.json +0 -68
  211. package/providers/_builtin/ide/vscodium/provider.json +0 -69
  212. package/providers/_builtin/ide/windsurf/provider.json +0 -57
  213. package/providers/_builtin/ide/windsurf/scripts/1.0/focus_editor.js +0 -36
  214. package/providers/_builtin/ide/windsurf/scripts/1.0/list_chats.js +0 -23
  215. package/providers/_builtin/ide/windsurf/scripts/1.0/list_models.js +0 -56
  216. package/providers/_builtin/ide/windsurf/scripts/1.0/list_modes.js +0 -63
  217. package/providers/_builtin/ide/windsurf/scripts/1.0/list_sessions.js +0 -79
  218. package/providers/_builtin/ide/windsurf/scripts/1.0/new_session.js +0 -58
  219. package/providers/_builtin/ide/windsurf/scripts/1.0/open_panel.js +0 -67
  220. package/providers/_builtin/ide/windsurf/scripts/1.0/read_chat.js +0 -253
  221. package/providers/_builtin/ide/windsurf/scripts/1.0/resolve_action.js +0 -82
  222. package/providers/_builtin/ide/windsurf/scripts/1.0/scripts.js +0 -82
  223. package/providers/_builtin/ide/windsurf/scripts/1.0/send_message.js +0 -20
  224. package/providers/_builtin/ide/windsurf/scripts/1.0/set_mode.js +0 -43
  225. package/providers/_builtin/ide/windsurf/scripts/1.0/set_model.js +0 -49
  226. package/providers/_builtin/ide/windsurf/scripts/1.0/switch_session.js +0 -82
  227. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/focus_editor.js +0 -30
  228. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_chats.js +0 -117
  229. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_models.js +0 -39
  230. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_modes.js +0 -39
  231. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/new_session.js +0 -69
  232. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/open_panel.js +0 -58
  233. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/read_chat.js +0 -315
  234. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/resolve_action.js +0 -68
  235. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/scripts.js +0 -82
  236. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/send_message.js +0 -87
  237. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/set_mode.js +0 -15
  238. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/set_model.js +0 -15
  239. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/switch_session.js +0 -58
  240. package/providers/_builtin/registry.json +0 -376
  241. package/providers/_builtin/validate.js +0 -156
@@ -1,315 +0,0 @@
1
- /**
2
- * Windsurf v1 — read_chat (v1 — Cascade DOM + Fiber)
3
- *
4
- * Windsurf VS Code fork, chat UI is "Cascade"is called.
5
- *
6
- * DOM structure:
7
- * #windsurf.cascadePanel → .chat-client-root
8
- * scroll: .cascade-scrollbar
9
- * list: .cascade-scrollbar .pb-20 > .flex.flex-col > .flex.flex-col.gap-2\.5
10
- * use : hasProse=false, hasWhitespace=true
11
- * AI : [class*="prose"] (prose-sm)
12
- * UI: .mark-js-ignore (ignore)
13
- * input: [data-lexical-editor="true"]
14
- *
15
- * Fiber props:
16
- * cascadeId: session ID
17
- * isRunning: create status
18
- * hasPendingTerminalCommand: approval wait
19
- * copyableText: AI response source
20
- *
21
- * final Check: Windsurf (2026-03-06)
22
- */
23
- (() => {
24
- try {
25
- // ─── 1. Container ───
26
- const cascade = document.querySelector('#windsurf\\.cascadePanel')
27
- || document.querySelector('.chat-client-root');
28
- if (!cascade) {
29
- return { id: 'no_cascade', status: 'idle', title: 'No Cascade', messages: [], inputContent: '', activeModal: null };
30
- }
31
-
32
- // ─── 2. Extract cascadeId, isRunning from Fiber (search from turn elements) ───
33
- let cascadeId = 'cascade';
34
- let isRunning = false;
35
- let hasPendingCmd = false;
36
- try {
37
- // Search Fiber from turn elements (cascadeId found at depth 6 from cascadePanel root)
38
- const scrollArea = cascade.querySelector('.cascade-scrollbar');
39
- const gapEls = scrollArea ? scrollArea.querySelectorAll('[class*="gap-2"]') : [];
40
- let firstTurn = null;
41
- for (const el of gapEls) {
42
- if (el.children.length >= 1 && el.closest('.cascade-scrollbar')) {
43
- firstTurn = el.children[0]; break;
44
- }
45
- }
46
- const fiberTarget = firstTurn || cascade;
47
- const fk = Object.keys(fiberTarget).find(k => k.startsWith('__reactFiber'));
48
- if (fk) {
49
- let fiber = fiberTarget[fk];
50
- for (let d = 0; d < 50 && fiber; d++) {
51
- const p = fiber.memoizedProps || fiber.pendingProps || {};
52
- if (p.cascadeId && typeof p.cascadeId === 'string') cascadeId = p.cascadeId;
53
- if (p.isRunning === true) isRunning = true;
54
- if (p.hasPendingTerminalCommand === true) hasPendingCmd = true;
55
- fiber = fiber.return;
56
- }
57
- }
58
- } catch (_) { }
59
-
60
- // ─── 3. status detection ───
61
- let status = 'idle';
62
- if (isRunning) status = 'generating';
63
-
64
- // Signal A: Stop button
65
- if (status === 'idle') {
66
- const allBtns = Array.from(document.querySelectorAll('button'));
67
- const stopBtn = allBtns.find(b => {
68
- if (b.offsetWidth === 0) return false;
69
- const label = (b.getAttribute('aria-label') || '').toLowerCase();
70
- const text = (b.textContent || '').trim().toLowerCase();
71
- return label.includes('stop') || label === 'cancel generation'
72
- || text === 'stop' || text === 'stop generating';
73
- });
74
- if (stopBtn) status = 'generating';
75
- }
76
-
77
- // Signal B: input field placeholder
78
- if (status === 'idle') {
79
- const editor = cascade.querySelector('[data-lexical-editor="true"]');
80
- if (editor) {
81
- const ph = (editor.getAttribute('placeholder') || '').toLowerCase();
82
- if (ph.includes('wait') || ph.includes('generating')) status = 'generating';
83
- }
84
- }
85
-
86
- const titleParts = document.title.split(' \u2014 ');
87
- const title = (titleParts.length >= 2 ? titleParts[titleParts.length - 1] : titleParts[0] || '').trim() || 'Cascade';
88
-
89
- // ─── 4. HTML → Markdown converter ───
90
- const BLOCK_TAGS = new Set(['DIV', 'P', 'BR', 'LI', 'TR', 'SECTION', 'ARTICLE', 'HEADER', 'FOOTER']);
91
- function extractCodeText(node) {
92
- if (node.nodeType === 3) return node.textContent || '';
93
- if (node.nodeType !== 1) return '';
94
- if (node.tagName === 'BR') return '\n';
95
- const parts = [];
96
- for (const child of node.childNodes) {
97
- const isBlock = child.nodeType === 1 && BLOCK_TAGS.has(child.tagName);
98
- const text = extractCodeText(child);
99
- if (text) {
100
- if (isBlock && parts.length > 0) parts.push('\n');
101
- parts.push(text);
102
- if (isBlock) parts.push('\n');
103
- }
104
- }
105
- return parts.join('').replace(/\n{2,}/g, '\n');
106
- }
107
- function htmlToMd(node) {
108
- if (node.nodeType === 3) return node.textContent || '';
109
- if (node.nodeType !== 1) return '';
110
- const tag = node.tagName;
111
- if (tag === 'STYLE' || tag === 'SCRIPT' || tag === 'SVG') return '';
112
- if (tag === 'TABLE') {
113
- const rows = Array.from(node.querySelectorAll('tr'));
114
- if (rows.length === 0) return '';
115
- const table = rows.map(tr =>
116
- Array.from(tr.querySelectorAll('th, td')).map(cell => (cell.textContent || '').trim().replace(/\|/g, '\\|'))
117
- );
118
- const colCount = Math.max(...table.map(r => r.length));
119
- const header = table[0] || [];
120
- const sep = Array(colCount).fill('---');
121
- const body = table.slice(1);
122
- let md = '| ' + header.join(' | ') + ' |\n';
123
- md += '| ' + sep.join(' | ') + ' |\n';
124
- for (const row of body) {
125
- while (row.length < colCount) row.push('');
126
- md += '| ' + row.join(' | ') + ' |\n';
127
- }
128
- return '\n' + md + '\n';
129
- }
130
- if (tag === 'UL') return '\n' + Array.from(node.children).map(li => '- ' + childrenToMd(li).trim()).join('\n') + '\n';
131
- if (tag === 'OL') return '\n' + Array.from(node.children).map((li, i) => (i + 1) + '. ' + childrenToMd(li).trim()).join('\n') + '\n';
132
- if (tag === 'LI') return childrenToMd(node);
133
- if (tag === 'H1') return '\n# ' + childrenToMd(node).trim() + '\n';
134
- if (tag === 'H2') return '\n## ' + childrenToMd(node).trim() + '\n';
135
- if (tag === 'H3') return '\n### ' + childrenToMd(node).trim() + '\n';
136
- if (tag === 'H4') return '\n#### ' + childrenToMd(node).trim() + '\n';
137
- if (tag === 'STRONG' || tag === 'B') return '**' + childrenToMd(node).trim() + '**';
138
- if (tag === 'EM' || tag === 'I') return '*' + childrenToMd(node).trim() + '*';
139
- if (tag === 'PRE') {
140
- const codeEl = node.querySelector('code');
141
- const lang = codeEl ? (codeEl.className.match(/language-(\w+)/)?.[1] || '') : '';
142
- const code = extractCodeText(codeEl || node);
143
- return '\n```' + lang + '\n' + code.trim() + '\n```\n';
144
- }
145
- if (tag === 'CODE') {
146
- if (node.parentElement && node.parentElement.tagName === 'PRE') return node.textContent || '';
147
- return '`' + (node.textContent || '').trim() + '`';
148
- }
149
- if (tag === 'BLOCKQUOTE') return '\n> ' + childrenToMd(node).trim().replace(/\n/g, '\n> ') + '\n';
150
- if (tag === 'A') return '[' + childrenToMd(node).trim() + '](' + (node.getAttribute('href') || '') + ')';
151
- if (tag === 'BR') return '\n';
152
- if (tag === 'P') return '\n' + childrenToMd(node).trim() + '\n';
153
- return childrenToMd(node);
154
- }
155
- function childrenToMd(node) {
156
- return Array.from(node.childNodes).map(htmlToMd).join('');
157
- }
158
-
159
- function getCleanMd(el) {
160
- const clone = el.cloneNode(true);
161
- clone.querySelectorAll('button, [role="button"], style, script, svg, .codicon, [class*="feedback"]').forEach(n => n.remove());
162
- clone.querySelectorAll('*').forEach(child => {
163
- if (!child.parentNode) return;
164
- const t = (child.textContent || '').trim();
165
- if (t.length > 60) return;
166
- const low = t.toLowerCase();
167
- if (/^(analyzed\s+\d|edited\s+\d|ran\s+\S|terminal\s|reading|searching)/i.test(low)) child.remove();
168
- });
169
- let md = htmlToMd(clone);
170
- md = md.replace(/\n{3,}/g, '\n\n').trim();
171
- return md;
172
- }
173
-
174
- // ─── 5. Collect messages ───
175
- const collected = [];
176
- const seenHashes = new Set();
177
-
178
- const scrollArea = cascade.querySelector('.cascade-scrollbar');
179
- if (!scrollArea) {
180
- return { id: cascadeId, status, title, messages: [], inputContent: '', activeModal: null };
181
- }
182
-
183
- // list Container search: .gap-2.5 with 2+ children
184
- let msgContainer = null;
185
- const gapEls = scrollArea.querySelectorAll('[class*="gap-2"]');
186
- for (const el of gapEls) {
187
- if (el.children.length >= 2 && el.closest('.cascade-scrollbar')) {
188
- msgContainer = el; break;
189
- }
190
- }
191
-
192
- if (msgContainer) {
193
- const turns = Array.from(msgContainer.children);
194
- for (const turn of turns) {
195
- // .mark-js-ignore = feedback UI → skip
196
- if ((turn.className || '').includes('mark-js-ignore')) continue;
197
- if (turn.offsetHeight < 10) continue;
198
-
199
- // Determine role: .prose = AI, otherwise user
200
- const proseEl = turn.querySelector('[class*="prose"]');
201
- const role = proseEl ? 'assistant' : 'user';
202
-
203
- let text = '';
204
- if (role === 'assistant') {
205
- // AI: Fiber copyableText use ( !)
206
- try {
207
- const fk = Object.keys(turn).find(k => k.startsWith('__reactFiber'));
208
- if (fk) {
209
- let fiber = turn[fk];
210
- for (let d = 0; d < 20 && fiber; d++) {
211
- const p = fiber.memoizedProps || {};
212
- if (p.copyableText && typeof p.copyableText === 'string' && p.copyableText.length > 5) {
213
- text = p.copyableText;
214
- break;
215
- }
216
- fiber = fiber.return;
217
- }
218
- }
219
- } catch (_) { }
220
-
221
- // In Fiber HTML→Markdown
222
- if (!text) {
223
- const mdRoot = proseEl || turn;
224
- text = getCleanMd(mdRoot);
225
- }
226
- } else {
227
- // User: whitespace-pre-wrap elementfrom text extract
228
- const whitespace = turn.querySelector('[class*="whitespace"]');
229
- text = (whitespace || turn).innerText?.trim() || '';
230
- }
231
-
232
- if (!text || text.length < 1) continue;
233
-
234
- const hash = role + ':' + text.slice(0, 200);
235
- if (seenHashes.has(hash)) continue;
236
- seenHashes.add(hash);
237
- collected.push({ role, text, el: turn });
238
- }
239
- }
240
-
241
- // DOM Order sorting
242
- collected.sort((a, b) => {
243
- const pos = a.el.compareDocumentPosition(b.el);
244
- if (pos & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
245
- if (pos & Node.DOCUMENT_POSITION_PRECEDING) return 1;
246
- return 0;
247
- });
248
-
249
- // latest 30only
250
- const trimmed = collected.length > 30 ? collected.slice(-30) : collected;
251
-
252
- const final = trimmed.map((m, i) => ({
253
- id: 'msg_' + i,
254
- role: m.role,
255
- content: m.text.length > 6000 ? m.text.slice(0, 6000) + '\n[... truncated]' : m.text,
256
- index: i,
257
- kind: 'standard'
258
- }));
259
-
260
- // ─── 6. input field ───
261
- const editor = cascade.querySelector('[data-lexical-editor="true"]')
262
- || cascade.querySelector('[contenteditable="true"][role="textbox"]')
263
- || cascade.querySelector('textarea:not(.xterm-helper-textarea)');
264
- const inputContent = editor ? (editor.innerText || editor.value || '').trim() : '';
265
-
266
- // ─── 7. modal/approval detect ───
267
- let activeModal = null;
268
- try {
269
- // Fiber: hasPendingTerminalCommand
270
- if (hasPendingCmd) {
271
- const allBtns = Array.from(document.querySelectorAll('button')).filter(b => b.offsetWidth > 0);
272
- const approvalBtns = allBtns.filter(b => {
273
- const t = (b.textContent || '').trim().toLowerCase();
274
- return /^(run|reject|skip|approve|allow|deny|cancel|accept)\b/i.test(t);
275
- });
276
- const btnTexts = [...new Set(approvalBtns.map(b => (b.textContent || '').trim()).filter(t => t.length < 40))];
277
- activeModal = { message: 'Terminal command pending', buttons: btnTexts.length > 0 ? btnTexts : ['Run', 'Reject'] };
278
- }
279
-
280
- // Dialog fallback
281
- if (!activeModal) {
282
- const dialog = document.querySelector('.monaco-dialog-box, [role="dialog"]');
283
- if (dialog && dialog.offsetWidth > 80) {
284
- const msg = (dialog.querySelector('.dialog-message') || dialog).innerText?.trim() || '';
285
- const buttons = Array.from(dialog.querySelectorAll('.monaco-button, button'))
286
- .map(b => (b.innerText || '').trim()).filter(t => t.length > 0 && t.length < 30);
287
- if (msg || buttons.length > 0) {
288
- activeModal = { message: msg.slice(0, 300), buttons };
289
- }
290
- }
291
- }
292
-
293
- // Inline approval buttons
294
- if (!activeModal) {
295
- const allBtns = Array.from(document.querySelectorAll('button')).filter(b => b.offsetWidth > 0);
296
- const approvalBtns = allBtns.filter(b => {
297
- const t = (b.textContent || '').trim().toLowerCase();
298
- if (t.length > 40) return false;
299
- return /^(run|reject|skip|approve|allow|deny)\b/i.test(t)
300
- || t === 'always allow' || t === 'always deny';
301
- });
302
- if (approvalBtns.length >= 2) {
303
- const btnTexts = [...new Set(approvalBtns.map(b => (b.textContent || '').trim()))];
304
- activeModal = { message: '', buttons: btnTexts };
305
- }
306
- }
307
-
308
- if (activeModal) status = 'waiting_approval';
309
- } catch (_) { activeModal = null; }
310
-
311
- return { id: cascadeId, status, title, messages: final, inputContent, activeModal };
312
- } catch (e) {
313
- return { id: 'error', status: 'error', error: e.message, messages: [] };
314
- }
315
- })()
@@ -1,68 +0,0 @@
1
- /**
2
- * Windsurf v1 — resolve_action
3
- *
4
- * approval Click dialogue/inline button.
5
- *
6
- * Parameter: ${ BUTTON_TEXT } — click button text (lowercase)
7
- *
8
- * final Check: Windsurf (2026-03-06)
9
- */
10
- (() => {
11
- try {
12
- const want = ${ BUTTON_TEXT };
13
- const normalize = (s) => (s || '').replace(/[\s\u200b\u00a0]+/g, ' ').trim().toLowerCase();
14
- const matches = (text) => {
15
- const t = normalize(text);
16
- if (!t) return false;
17
- if (t === want) return true;
18
- if (t.indexOf(want) === 0) return true;
19
- if (want === 'run' && (/^run\s*/.test(t) || t === 'enter' || t === '⏎')) return true;
20
- if (want === 'approve' && (t.includes('approve') || t === 'always allow' || t === 'allow')) return true;
21
- if (want === 'reject' && (t.includes('reject') || t === 'deny' || t === 'always deny')) return true;
22
- return false;
23
- };
24
- const click = (el) => {
25
- el.focus?.();
26
- const rect = el.getBoundingClientRect();
27
- const x = rect.left + rect.width / 2;
28
- const y = rect.top + rect.height / 2;
29
- for (const type of ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click']) {
30
- el.dispatchEvent(new PointerEvent(type, {
31
- bubbles: true, cancelable: true, view: window,
32
- clientX: x, clientY: y, pointerId: 1, pointerType: 'mouse'
33
- }));
34
- }
35
- return true;
36
- };
37
-
38
- // 1. Dialog inside
39
- const dialog = document.querySelector('.monaco-dialog-box, [role="dialog"]');
40
- if (dialog && dialog.offsetWidth > 80) {
41
- const btns = dialog.querySelectorAll('.monaco-button, button');
42
- for (const b of btns) {
43
- if (matches(b.textContent)) return click(b);
44
- }
45
- }
46
-
47
- // 2. all visible button
48
- const sel = 'button, [role="button"], .monaco-button';
49
- const allBtns = Array.from(document.querySelectorAll(sel))
50
- .filter(b => b.offsetWidth > 0 && b.offsetHeight > 0);
51
- for (const b of allBtns) {
52
- if (matches(b.textContent)) return click(b);
53
- }
54
-
55
- // 3. Enter key fallback (run)
56
- if (want === 'run') {
57
- document.activeElement?.dispatchEvent(new KeyboardEvent('keydown', {
58
- key: 'Enter', code: 'Enter', keyCode: 13,
59
- bubbles: true, cancelable: true
60
- }));
61
- return true;
62
- }
63
-
64
- return false;
65
- } catch (e) {
66
- return false;
67
- }
68
- })()
@@ -1,82 +0,0 @@
1
- /**
2
- * CDP Scripts — Router
3
- *
4
- * Version routing is handled by ProviderLoader:
5
- * Pattern:
6
- * - Scripts WITHOUT params: loaded as-is (self-invoking IIFE)
7
- * - Scripts WITH params: loaded as function expression, invoked with params JSON
8
- * e.g. `(${script})(${JSON.stringify(params)})`
9
- */
10
-
11
- 'use strict';
12
-
13
- const fs = require('fs');
14
- const path = require('path');
15
-
16
- function load(name) {
17
- try { return fs.readFileSync(path.join(__dirname, name), 'utf-8'); }
18
- catch { return null; }
19
- }
20
-
21
- function withParams(name, params) {
22
- let script = load(name);
23
- if (!script) return null;
24
-
25
- // For legacy scripts checking MESSAGE, interpolate them manually
26
- if (script.includes('${ MESSAGE }')) {
27
- const msg = params?.MESSAGE || params?.text || '';
28
- return script.replace(/\$\{ MESSAGE \}/g, JSON.stringify(msg));
29
- }
30
- if (script.includes('${ BUTTON_TEXT }')) {
31
- const btn = params?.BUTTON_TEXT || params?.buttonText || '';
32
- return script.replace(/\$\{ BUTTON_TEXT \}/g, JSON.stringify(btn));
33
- }
34
-
35
- return `(${script})(${JSON.stringify(params)})`;
36
- }
37
-
38
- // ─── Core (no params — IIFE) ───
39
-
40
- module.exports.readChat = () => load('read_chat.js') || load('webview_read_chat.js');
41
- module.exports.sendMessage = (params) => {
42
- let s = load('send_message.js');
43
- if (!s) s = load('webview_send_message.js');
44
- if (!s) return null;
45
- // Legacy template substitution fallback
46
- if (s.includes('${ MESSAGE }')) {
47
- const msg = params?.MESSAGE || params?.text || params || '';
48
- return s.replace(/\$\{ MESSAGE \}/g, JSON.stringify(msg));
49
- }
50
- return withParams('send_message.js', params) || withParams('webview_send_message.js', params);
51
- };
52
- module.exports.listSessions = () => load('list_sessions.js');
53
- module.exports.newSession = () => load('new_session.js');
54
- module.exports.focusEditor = () => load('focus_editor.js');
55
- module.exports.openPanel = () => load('open_panel.js');
56
- module.exports.listModels = () => load('list_models.js');
57
- module.exports.listModes = () => load('list_modes.js');
58
-
59
- // ─── With params (function expression) ───
60
-
61
- module.exports.switchSession = (params) => {
62
- const index = typeof params === 'number' ? params : params?.index ?? 0;
63
- const title = typeof params === 'string' ? params : params?.title || null;
64
- return withParams('switch_session.js', { index, title });
65
- };
66
-
67
- module.exports.resolveAction = (params) => {
68
- const action = typeof params === 'string' ? params : params?.action || 'approve';
69
- const buttonText = params?.button || params?.buttonText
70
- || (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : action);
71
- return withParams('resolve_action.js', { buttonText, BUTTON_TEXT: buttonText });
72
- };
73
-
74
- module.exports.setModel = (params) => {
75
- const model = typeof params === 'string' ? params : params?.model;
76
- return withParams('set_model.js', { model });
77
- };
78
-
79
- module.exports.setMode = (params) => {
80
- const mode = typeof params === 'string' ? params : params?.mode;
81
- return withParams('set_mode.js', { mode });
82
- };
@@ -1,87 +0,0 @@
1
- /**
2
- * Windsurf v1 — send_message
3
- *
4
- * Windsurf Lexical editor ([data-lexical-editor="true"])uses.
5
- * contenteditable divsince it is execCommand('insertText') or InputEventallows input via.
6
- *
7
- * ⚠️ Lexicalis input event detect:
8
- * - execCommand('insertText') is most stable
9
- * - nativeSetter approach does not work
10
- * - Uses InputEvent('insertText') as fallback
11
- *
12
- * Enter key needs KeyboardEvent full sequence (keydown + keypress + keyup).
13
- *
14
- * Parameter: ${ MESSAGE }
15
- * final Check: Windsurf 1.108.x (2026-03-10)
16
- */
17
- (async () => {
18
- try {
19
- const msg = ${ MESSAGE };
20
-
21
- // ─── 1. Find Lexical editor (fallback chain) ───
22
- const editor =
23
- document.querySelector('[data-lexical-editor="true"]') ||
24
- document.querySelector('[contenteditable="true"][role="textbox"]') ||
25
- document.querySelector('.cascade-input [contenteditable="true"]') ||
26
- document.querySelector('.chat-input textarea') ||
27
- document.querySelector('textarea:not(.xterm-helper-textarea)');
28
-
29
- if (!editor) return 'error: no input found';
30
-
31
- const isTextarea = editor.tagName === 'TEXTAREA';
32
-
33
- if (isTextarea) {
34
- // ─── textarea fallback (not logged in, etc.) ───
35
- editor.focus();
36
- const proto = HTMLTextAreaElement.prototype;
37
- const nativeSetter = Object.getOwnPropertyDescriptor(proto, 'value')?.set;
38
- if (nativeSetter) nativeSetter.call(editor, msg);
39
- else editor.value = msg;
40
-
41
- editor.dispatchEvent(new Event('input', { bubbles: true }));
42
- editor.dispatchEvent(new Event('change', { bubbles: true }));
43
-
44
- await new Promise(r => setTimeout(r, 300));
45
-
46
- const enterOpts = {
47
- key: 'Enter', code: 'Enter',
48
- keyCode: 13, which: 13,
49
- bubbles: true, cancelable: true, composed: true,
50
- };
51
- editor.dispatchEvent(new KeyboardEvent('keydown', enterOpts));
52
- editor.dispatchEvent(new KeyboardEvent('keypress', enterOpts));
53
- editor.dispatchEvent(new KeyboardEvent('keyup', enterOpts));
54
-
55
- return 'sent';
56
- }
57
-
58
- // ─── 2. contenteditable (Lexical) editor ───
59
- editor.focus();
60
-
61
- // Select existing content and delete
62
- document.execCommand('selectAll', false, null);
63
- document.execCommand('delete', false, null);
64
-
65
- // text insertion (Lexicalis execCommand('insertText')recognizes)
66
- document.execCommand('insertText', false, msg);
67
-
68
- // React/Lexicalnotify changes to
69
- editor.dispatchEvent(new Event('input', { bubbles: true }));
70
-
71
- await new Promise(r => setTimeout(r, 300));
72
-
73
- // ─── 3. Enter key sending (full sequence) ───
74
- const enterOpts = {
75
- key: 'Enter', code: 'Enter',
76
- keyCode: 13, which: 13,
77
- bubbles: true, cancelable: true, composed: true,
78
- };
79
- editor.dispatchEvent(new KeyboardEvent('keydown', enterOpts));
80
- editor.dispatchEvent(new KeyboardEvent('keypress', enterOpts));
81
- editor.dispatchEvent(new KeyboardEvent('keyup', enterOpts));
82
-
83
- return 'sent';
84
- } catch (e) {
85
- return 'error: ' + e.message;
86
- }
87
- })()
@@ -1,15 +0,0 @@
1
- /**
2
- * Generic fallback — set_model
3
- * ${ MODEL }
4
- */
5
- (() => {
6
- try {
7
- const want = ${ MODEL } || '';
8
- const norm = (t) => t.toLowerCase().trim();
9
-
10
- // Very basic click attempt
11
- return JSON.stringify({ success: false, error: 'Model selection requires UI interaction not supported by generic script' });
12
- } catch (e) {
13
- return JSON.stringify({ success: false, error: e.message });
14
- }
15
- })()
@@ -1,15 +0,0 @@
1
- /**
2
- * Generic fallback — set_model
3
- * ${ MODEL }
4
- */
5
- (() => {
6
- try {
7
- const want = ${ MODEL } || '';
8
- const norm = (t) => t.toLowerCase().trim();
9
-
10
- // Very basic click attempt
11
- return JSON.stringify({ success: false, error: 'Model selection requires UI interaction not supported by generic script' });
12
- } catch (e) {
13
- return JSON.stringify({ success: false, error: e.message });
14
- }
15
- })()
@@ -1,58 +0,0 @@
1
- /**
2
- * Windsurf v1 — switch_session
3
- *
4
- * Cascade session(conversation) .
5
- * cascade-tab-{id} actual clickable child DIV inside
6
- * React onClick calls directly.
7
- *
8
- * Parameter: ${ SESSION_ID } — session ID (cascade-tab UUID)
9
- *
10
- * final Check: Windsurf 1.108.x (2026-03-10)
11
- */
12
- (() => {
13
- try {
14
- const id = ${ SESSION_ID };
15
-
16
- // Helper: find React onClick on an element or its children
17
- function clickReact(el) {
18
- // Check element itself and children for React onClick
19
- const targets = [el, ...el.querySelectorAll('*')];
20
- for (const t of targets) {
21
- const rp = Object.keys(t).find(k => k.startsWith('__reactProps'));
22
- if (rp && typeof t[rp].onClick === 'function') {
23
- t[rp].onClick({
24
- preventDefault: () => { },
25
- stopPropagation: () => { },
26
- nativeEvent: { stopImmediatePropagation: () => { } },
27
- target: t, currentTarget: t, button: 0, type: 'click'
28
- });
29
- return true;
30
- }
31
- }
32
- return false;
33
- }
34
-
35
- // 1. cascade-tab-{id} element search
36
- const tab = document.getElementById('cascade-tab-' + id);
37
- if (tab) {
38
- if (clickReact(tab)) return 'switched';
39
- // Fallback: DOM click
40
- tab.click();
41
- return 'switched-dom';
42
- }
43
-
44
- // 2. title matching
45
- const tabs = document.querySelectorAll('[id^="cascade-tab-"]');
46
- for (const t of tabs) {
47
- if (t.textContent?.trim() === id) {
48
- if (clickReact(t)) return 'switched-by-title';
49
- t.click();
50
- return 'switched-by-title-dom';
51
- }
52
- }
53
-
54
- return 'not_found';
55
- } catch (e) {
56
- return 'error: ' + e.message;
57
- }
58
- })()