@adhdev/daemon-core 0.6.58 → 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 (245) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +87 -89
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/src/detection/ide-detector.ts +1 -1
  6. package/src/providers/provider-loader.ts +3 -6
  7. package/providers/_builtin/.github/workflows/generate-registry.yml +0 -76
  8. package/providers/_builtin/COMPATIBILITY.md +0 -217
  9. package/providers/_builtin/CONTRIBUTING.md +0 -200
  10. package/providers/_builtin/README.md +0 -119
  11. package/providers/_builtin/_helpers/index.js +0 -188
  12. package/providers/_builtin/acp/agentpool/provider.json +0 -54
  13. package/providers/_builtin/acp/amp/provider.json +0 -52
  14. package/providers/_builtin/acp/auggie/provider.json +0 -57
  15. package/providers/_builtin/acp/autodev/provider.json +0 -54
  16. package/providers/_builtin/acp/autohand/provider.json +0 -52
  17. package/providers/_builtin/acp/blackbox-ai/provider.json +0 -54
  18. package/providers/_builtin/acp/claude-agent/provider.json +0 -57
  19. package/providers/_builtin/acp/cline-acp/provider.json +0 -54
  20. package/providers/_builtin/acp/codebuddy/provider.json +0 -54
  21. package/providers/_builtin/acp/codex-cli/provider.json +0 -57
  22. package/providers/_builtin/acp/corust-agent/provider.json +0 -52
  23. package/providers/_builtin/acp/crow-cli/provider.json +0 -54
  24. package/providers/_builtin/acp/cursor-acp/provider.json +0 -54
  25. package/providers/_builtin/acp/deepagents/provider.json +0 -52
  26. package/providers/_builtin/acp/dimcode/provider.json +0 -54
  27. package/providers/_builtin/acp/docker-cagent/provider.json +0 -57
  28. package/providers/_builtin/acp/factory-droid/provider.json +0 -60
  29. package/providers/_builtin/acp/fast-agent/provider.json +0 -52
  30. package/providers/_builtin/acp/gemini-cli/provider.json +0 -114
  31. package/providers/_builtin/acp/github-copilot/provider.json +0 -54
  32. package/providers/_builtin/acp/goose/provider.json +0 -57
  33. package/providers/_builtin/acp/junie/provider.json +0 -52
  34. package/providers/_builtin/acp/kilo/provider.json +0 -54
  35. package/providers/_builtin/acp/kimi-cli/provider.json +0 -57
  36. package/providers/_builtin/acp/minion-code/provider.json +0 -52
  37. package/providers/_builtin/acp/mistral-vibe/provider.json +0 -57
  38. package/providers/_builtin/acp/nova/provider.json +0 -54
  39. package/providers/_builtin/acp/openclaw/provider.json +0 -54
  40. package/providers/_builtin/acp/opencode/provider.json +0 -52
  41. package/providers/_builtin/acp/openhands/provider.json +0 -54
  42. package/providers/_builtin/acp/pi-acp/provider.json +0 -52
  43. package/providers/_builtin/acp/qoder/provider.json +0 -54
  44. package/providers/_builtin/acp/qwen-code/provider.json +0 -60
  45. package/providers/_builtin/acp/stakpak/provider.json +0 -54
  46. package/providers/_builtin/acp/vtcode/provider.json +0 -54
  47. package/providers/_builtin/cli/aider-cli/provider.json +0 -37
  48. package/providers/_builtin/cli/aider-cli/scripts/1.0/detect_status.js +0 -20
  49. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_approval.js +0 -10
  50. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_output.js +0 -97
  51. package/providers/_builtin/cli/aider-cli/scripts/1.0/scripts.js +0 -7
  52. package/providers/_builtin/cli/claude-cli/provider.json +0 -121
  53. package/providers/_builtin/cli/claude-cli/scripts/1.0/detect_status.js +0 -83
  54. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_approval.js +0 -97
  55. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_output.js +0 -417
  56. package/providers/_builtin/cli/claude-cli/scripts/1.0/scripts.js +0 -42
  57. package/providers/_builtin/cli/codex-cli/provider.json +0 -90
  58. package/providers/_builtin/cli/codex-cli/scripts/1.0/detect_status.js +0 -54
  59. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_approval.js +0 -91
  60. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_output.js +0 -522
  61. package/providers/_builtin/cli/codex-cli/scripts/1.0/scripts.js +0 -11
  62. package/providers/_builtin/cli/cursor-cli/provider.json +0 -37
  63. package/providers/_builtin/cli/cursor-cli/scripts/1.0/detect_status.js +0 -19
  64. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_approval.js +0 -10
  65. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_output.js +0 -48
  66. package/providers/_builtin/cli/cursor-cli/scripts/1.0/scripts.js +0 -7
  67. package/providers/_builtin/cli/gemini-cli/provider.json +0 -109
  68. package/providers/_builtin/cli/gemini-cli/scripts/1.0/detect_status.js +0 -26
  69. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_approval.js +0 -22
  70. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_output.js +0 -71
  71. package/providers/_builtin/cli/gemini-cli/scripts/1.0/scripts.js +0 -12
  72. package/providers/_builtin/cli/github-copilot-cli/provider.json +0 -37
  73. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/detect_status.js +0 -19
  74. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_approval.js +0 -9
  75. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_output.js +0 -48
  76. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/scripts.js +0 -7
  77. package/providers/_builtin/cli/goose-cli/provider.json +0 -37
  78. package/providers/_builtin/cli/goose-cli/scripts/1.0/detect_status.js +0 -20
  79. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_approval.js +0 -10
  80. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_output.js +0 -48
  81. package/providers/_builtin/cli/goose-cli/scripts/1.0/scripts.js +0 -7
  82. package/providers/_builtin/cli/opencode-cli/provider.json +0 -37
  83. package/providers/_builtin/cli/opencode-cli/scripts/1.0/detect_status.js +0 -15
  84. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_approval.js +0 -9
  85. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_output.js +0 -48
  86. package/providers/_builtin/cli/opencode-cli/scripts/1.0/scripts.js +0 -7
  87. package/providers/_builtin/docs/CDP_SELECTOR_GUIDE.md +0 -370
  88. package/providers/_builtin/docs/PROVIDER_GUIDE.md +0 -916
  89. package/providers/_builtin/extension/cline/provider.json +0 -37
  90. package/providers/_builtin/extension/cline/scripts/1.0/focus_editor.js +0 -48
  91. package/providers/_builtin/extension/cline/scripts/1.0/list_chats.js +0 -100
  92. package/providers/_builtin/extension/cline/scripts/1.0/list_models.js +0 -43
  93. package/providers/_builtin/extension/cline/scripts/1.0/list_modes.js +0 -35
  94. package/providers/_builtin/extension/cline/scripts/1.0/new_session.js +0 -85
  95. package/providers/_builtin/extension/cline/scripts/1.0/open_panel.js +0 -25
  96. package/providers/_builtin/extension/cline/scripts/1.0/read_chat.js +0 -270
  97. package/providers/_builtin/extension/cline/scripts/1.0/resolve_action.js +0 -83
  98. package/providers/_builtin/extension/cline/scripts/1.0/scripts.js +0 -82
  99. package/providers/_builtin/extension/cline/scripts/1.0/send_message.js +0 -95
  100. package/providers/_builtin/extension/cline/scripts/1.0/set_mode.js +0 -36
  101. package/providers/_builtin/extension/cline/scripts/1.0/set_model.js +0 -36
  102. package/providers/_builtin/extension/cline/scripts/1.0/switch_session.js +0 -206
  103. package/providers/_builtin/extension/codex/provider.json +0 -38
  104. package/providers/_builtin/extension/codex/scripts/1.0/click_conversation_webview.js +0 -24
  105. package/providers/_builtin/extension/codex/scripts/1.0/explore_chat_webview.js +0 -110
  106. package/providers/_builtin/extension/codex/scripts/1.0/explore_controls_webview.js +0 -75
  107. package/providers/_builtin/extension/codex/scripts/1.0/explore_dom.js +0 -58
  108. package/providers/_builtin/extension/codex/scripts/1.0/explore_dropdown_webview.js +0 -64
  109. package/providers/_builtin/extension/codex/scripts/1.0/inspect_code_webview.js +0 -55
  110. package/providers/_builtin/extension/codex/scripts/1.0/list_models.js +0 -63
  111. package/providers/_builtin/extension/codex/scripts/1.0/list_modes.js +0 -140
  112. package/providers/_builtin/extension/codex/scripts/1.0/message_structure_webview.js +0 -79
  113. package/providers/_builtin/extension/codex/scripts/1.0/new_session.js +0 -26
  114. package/providers/_builtin/extension/codex/scripts/1.0/read_chat.js +0 -516
  115. package/providers/_builtin/extension/codex/scripts/1.0/resolve_action.js +0 -82
  116. package/providers/_builtin/extension/codex/scripts/1.0/send_message.js +0 -42
  117. package/providers/_builtin/extension/codex/scripts/1.0/set_mode.js +0 -165
  118. package/providers/_builtin/extension/codex/scripts/1.0/set_model.js +0 -86
  119. package/providers/_builtin/extension/roo-code/provider.json +0 -37
  120. package/providers/_builtin/extension/roo-code/scripts/1.0/scripts.js +0 -82
  121. package/providers/_builtin/ide/antigravity/provider.json +0 -88
  122. package/providers/_builtin/ide/antigravity/scripts/1.0/focus_editor.js +0 -20
  123. package/providers/_builtin/ide/antigravity/scripts/1.0/list_chats.js +0 -137
  124. package/providers/_builtin/ide/antigravity/scripts/1.0/list_models.js +0 -61
  125. package/providers/_builtin/ide/antigravity/scripts/1.0/list_modes.js +0 -72
  126. package/providers/_builtin/ide/antigravity/scripts/1.0/new_session.js +0 -75
  127. package/providers/_builtin/ide/antigravity/scripts/1.0/read_chat.js +0 -352
  128. package/providers/_builtin/ide/antigravity/scripts/1.0/resolve_action.js +0 -63
  129. package/providers/_builtin/ide/antigravity/scripts/1.0/scripts.js +0 -67
  130. package/providers/_builtin/ide/antigravity/scripts/1.0/send_message.js +0 -56
  131. package/providers/_builtin/ide/antigravity/scripts/1.0/set_mode.js +0 -67
  132. package/providers/_builtin/ide/antigravity/scripts/1.0/set_model.js +0 -72
  133. package/providers/_builtin/ide/antigravity/scripts/1.0/switch_session.js +0 -114
  134. package/providers/_builtin/ide/cursor/provider.json +0 -70
  135. package/providers/_builtin/ide/cursor/scripts/1.0/dismiss_notification.js +0 -30
  136. package/providers/_builtin/ide/cursor/scripts/1.0/focus_editor.js +0 -13
  137. package/providers/_builtin/ide/cursor/scripts/1.0/list_models.js +0 -78
  138. package/providers/_builtin/ide/cursor/scripts/1.0/list_modes.js +0 -40
  139. package/providers/_builtin/ide/cursor/scripts/1.0/list_notifications.js +0 -23
  140. package/providers/_builtin/ide/cursor/scripts/1.0/list_sessions.js +0 -42
  141. package/providers/_builtin/ide/cursor/scripts/1.0/new_session.js +0 -20
  142. package/providers/_builtin/ide/cursor/scripts/1.0/open_panel.js +0 -23
  143. package/providers/_builtin/ide/cursor/scripts/1.0/read_chat.js +0 -318
  144. package/providers/_builtin/ide/cursor/scripts/1.0/resolve_action.js +0 -19
  145. package/providers/_builtin/ide/cursor/scripts/1.0/scripts.js +0 -78
  146. package/providers/_builtin/ide/cursor/scripts/1.0/send_message.js +0 -23
  147. package/providers/_builtin/ide/cursor/scripts/1.0/set_mode.js +0 -38
  148. package/providers/_builtin/ide/cursor/scripts/1.0/set_model.js +0 -81
  149. package/providers/_builtin/ide/cursor/scripts/1.0/switch_session.js +0 -28
  150. package/providers/_builtin/ide/kiro/provider.json +0 -68
  151. package/providers/_builtin/ide/kiro/scripts/1.0/focus_editor.js +0 -20
  152. package/providers/_builtin/ide/kiro/scripts/1.0/open_panel.js +0 -47
  153. package/providers/_builtin/ide/kiro/scripts/1.0/resolve_action.js +0 -54
  154. package/providers/_builtin/ide/kiro/scripts/1.0/send_message.js +0 -29
  155. package/providers/_builtin/ide/kiro/scripts/1.0/webview_dump_html.js +0 -1
  156. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_models.js +0 -42
  157. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_modes.js +0 -22
  158. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_sessions.js +0 -21
  159. package/providers/_builtin/ide/kiro/scripts/1.0/webview_new_session.js +0 -34
  160. package/providers/_builtin/ide/kiro/scripts/1.0/webview_read_chat.js +0 -161
  161. package/providers/_builtin/ide/kiro/scripts/1.0/webview_resolve_action.js +0 -62
  162. package/providers/_builtin/ide/kiro/scripts/1.0/webview_send_message.js +0 -94
  163. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_mode.js +0 -34
  164. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_model.js +0 -47
  165. package/providers/_builtin/ide/kiro/scripts/1.0/webview_switch_session.js +0 -26
  166. package/providers/_builtin/ide/pearai/.tmp/after_rich.json +0 -157
  167. package/providers/_builtin/ide/pearai/.tmp/after_rich_raw.json +0 -161
  168. package/providers/_builtin/ide/pearai/.tmp/after_switch.json +0 -592
  169. package/providers/_builtin/ide/pearai/.tmp/after_switch_raw.json +0 -596
  170. package/providers/_builtin/ide/pearai/.tmp/home_dump_raw.json +0 -176
  171. package/providers/_builtin/ide/pearai/.tmp/items_raw.json +0 -778
  172. package/providers/_builtin/ide/pearai/.tmp/webview_dump.json +0 -157
  173. package/providers/_builtin/ide/pearai/.tmp/webview_dump_raw.json +0 -161
  174. package/providers/_builtin/ide/pearai/provider.json +0 -71
  175. package/providers/_builtin/ide/pearai/scripts/1.0/focus_editor.js +0 -16
  176. package/providers/_builtin/ide/pearai/scripts/1.0/list_models.js +0 -45
  177. package/providers/_builtin/ide/pearai/scripts/1.0/list_modes.js +0 -44
  178. package/providers/_builtin/ide/pearai/scripts/1.0/list_sessions.js +0 -93
  179. package/providers/_builtin/ide/pearai/scripts/1.0/new_session.js +0 -38
  180. package/providers/_builtin/ide/pearai/scripts/1.0/open_panel.js +0 -23
  181. package/providers/_builtin/ide/pearai/scripts/1.0/read_chat.js +0 -169
  182. package/providers/_builtin/ide/pearai/scripts/1.0/resolve_action.js +0 -60
  183. package/providers/_builtin/ide/pearai/scripts/1.0/scripts.js +0 -111
  184. package/providers/_builtin/ide/pearai/scripts/1.0/send_message.js +0 -104
  185. package/providers/_builtin/ide/pearai/scripts/1.0/set_mode.js +0 -51
  186. package/providers/_builtin/ide/pearai/scripts/1.0/set_model.js +0 -54
  187. package/providers/_builtin/ide/pearai/scripts/1.0/switch_session.js +0 -81
  188. package/providers/_builtin/ide/trae/provider.json +0 -72
  189. package/providers/_builtin/ide/trae/scripts/1.0/focus_editor.js +0 -20
  190. package/providers/_builtin/ide/trae/scripts/1.0/list_chats.js +0 -24
  191. package/providers/_builtin/ide/trae/scripts/1.0/list_models.js +0 -39
  192. package/providers/_builtin/ide/trae/scripts/1.0/list_modes.js +0 -39
  193. package/providers/_builtin/ide/trae/scripts/1.0/new_session.js +0 -30
  194. package/providers/_builtin/ide/trae/scripts/1.0/open_panel.js +0 -44
  195. package/providers/_builtin/ide/trae/scripts/1.0/read_chat.js +0 -113
  196. package/providers/_builtin/ide/trae/scripts/1.0/resolve_action.js +0 -54
  197. package/providers/_builtin/ide/trae/scripts/1.0/scripts.js +0 -82
  198. package/providers/_builtin/ide/trae/scripts/1.0/send_message.js +0 -69
  199. package/providers/_builtin/ide/trae/scripts/1.0/set_mode.js +0 -15
  200. package/providers/_builtin/ide/trae/scripts/1.0/set_model.js +0 -15
  201. package/providers/_builtin/ide/trae/scripts/1.0/switch_session.js +0 -23
  202. package/providers/_builtin/ide/vscode/provider.json +0 -74
  203. package/providers/_builtin/ide/vscode/scripts/1.0/focus_editor.js +0 -1
  204. package/providers/_builtin/ide/vscode/scripts/1.0/list_models.js +0 -1
  205. package/providers/_builtin/ide/vscode/scripts/1.0/list_sessions.js +0 -1
  206. package/providers/_builtin/ide/vscode/scripts/1.0/new_session.js +0 -1
  207. package/providers/_builtin/ide/vscode/scripts/1.0/open_panel.js +0 -1
  208. package/providers/_builtin/ide/vscode/scripts/1.0/read_chat.js +0 -1
  209. package/providers/_builtin/ide/vscode/scripts/1.0/resolve_action.js +0 -1
  210. package/providers/_builtin/ide/vscode/scripts/1.0/scripts.js +0 -25
  211. package/providers/_builtin/ide/vscode/scripts/1.0/send_message.js +0 -1
  212. package/providers/_builtin/ide/vscode/scripts/1.0/set_model.js +0 -1
  213. package/providers/_builtin/ide/vscode/scripts/1.0/switch_session.js +0 -1
  214. package/providers/_builtin/ide/vscode-insiders/provider.json +0 -68
  215. package/providers/_builtin/ide/vscodium/provider.json +0 -69
  216. package/providers/_builtin/ide/windsurf/provider.json +0 -57
  217. package/providers/_builtin/ide/windsurf/scripts/1.0/focus_editor.js +0 -36
  218. package/providers/_builtin/ide/windsurf/scripts/1.0/list_chats.js +0 -23
  219. package/providers/_builtin/ide/windsurf/scripts/1.0/list_models.js +0 -56
  220. package/providers/_builtin/ide/windsurf/scripts/1.0/list_modes.js +0 -63
  221. package/providers/_builtin/ide/windsurf/scripts/1.0/list_sessions.js +0 -79
  222. package/providers/_builtin/ide/windsurf/scripts/1.0/new_session.js +0 -58
  223. package/providers/_builtin/ide/windsurf/scripts/1.0/open_panel.js +0 -67
  224. package/providers/_builtin/ide/windsurf/scripts/1.0/read_chat.js +0 -253
  225. package/providers/_builtin/ide/windsurf/scripts/1.0/resolve_action.js +0 -82
  226. package/providers/_builtin/ide/windsurf/scripts/1.0/scripts.js +0 -82
  227. package/providers/_builtin/ide/windsurf/scripts/1.0/send_message.js +0 -20
  228. package/providers/_builtin/ide/windsurf/scripts/1.0/set_mode.js +0 -43
  229. package/providers/_builtin/ide/windsurf/scripts/1.0/set_model.js +0 -49
  230. package/providers/_builtin/ide/windsurf/scripts/1.0/switch_session.js +0 -82
  231. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/focus_editor.js +0 -30
  232. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_chats.js +0 -117
  233. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_models.js +0 -39
  234. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_modes.js +0 -39
  235. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/new_session.js +0 -69
  236. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/open_panel.js +0 -58
  237. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/read_chat.js +0 -315
  238. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/resolve_action.js +0 -68
  239. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/scripts.js +0 -82
  240. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/send_message.js +0 -87
  241. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/set_mode.js +0 -15
  242. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/set_model.js +0 -15
  243. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/switch_session.js +0 -58
  244. package/providers/_builtin/registry.json +0 -376
  245. package/providers/_builtin/validate.js +0 -156
@@ -1,417 +0,0 @@
1
- /**
2
- * Claude Code — parse_output
3
- *
4
- * Reference implementation for CLI PTY parsing:
5
- * - prefer the visible screen snapshot (`screenText`)
6
- * - keep transcript state incrementally via `messages`
7
- * - fall back to noisy rolling buffers when older runtimes do not provide screenText
8
- */
9
-
10
- 'use strict';
11
-
12
- const detectStatus = require('./detect_status.js');
13
- const parseApproval = require('./parse_approval.js');
14
-
15
- function splitLines(text) {
16
- return String(text || '')
17
- .replace(/\u0007/g, '')
18
- .split(/\r\n|\n|\r/g)
19
- .map(line => line.replace(/\s+$/, ''));
20
- }
21
-
22
- function sanitizeLine(line) {
23
- return String(line || '')
24
- .replace(/\u0007/g, '')
25
- .replace(/^\d+;/, '')
26
- .replace(/\s+$/, '');
27
- }
28
-
29
- function normalizeText(text) {
30
- return String(text || '')
31
- .replace(/\s+/g, ' ')
32
- .trim();
33
- }
34
-
35
- function looksLikeSamePrompt(left, right) {
36
- const a = normalizeText(left);
37
- const b = normalizeText(right);
38
- if (!a || !b) return false;
39
- if (a === b) return true;
40
- const minLength = Math.min(a.length, b.length);
41
- if (minLength < 24) return false;
42
- return a.startsWith(b) || b.startsWith(a) || a.includes(b) || b.includes(a);
43
- }
44
-
45
- function isSpinnerOnlyText(text) {
46
- const lines = splitLines(text)
47
- .map(line => stripAssistantPrefix(sanitizeLine(line).trim()))
48
- .filter(Boolean);
49
- if (lines.length === 0) return true;
50
- return lines.every(line => isStatusLine(line) || /^(?:[A-Z][a-z]+ing\u2026?|[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+)$/.test(line));
51
- }
52
-
53
- function looksLikePromptEchoText(candidate, promptText, previousMessages) {
54
- const normalizedCandidate = normalizeText(candidate);
55
- if (!normalizedCandidate) return false;
56
- if (promptText && looksLikeSamePrompt(normalizedCandidate, promptText)) return true;
57
-
58
- const lastUser = [...(Array.isArray(previousMessages) ? previousMessages : [])]
59
- .reverse()
60
- .find(message => message?.role === 'user' && typeof message.content === 'string');
61
- return !!lastUser && looksLikeSamePrompt(normalizedCandidate, lastUser.content);
62
- }
63
-
64
- function parsePromptLine(line) {
65
- const trimmed = sanitizeLine(line).trim();
66
- const match = trimmed.match(/^[❯›>]\s*(.*)$/);
67
- if (!match) return null;
68
- const body = match[1].trim();
69
- if (/^\d+[.)]\s+/.test(body)) return null;
70
- return body;
71
- }
72
-
73
- function isBoxLine(trimmed) {
74
- return /^[─═╭╮╰╯│┌┐└┘├┤┬┴┼]+$/.test(trimmed);
75
- }
76
-
77
- function isFooterLine(trimmed) {
78
- return /^➜\s+\S+/.test(trimmed)
79
- || /^Update available!/i.test(trimmed)
80
- || /Claude Code v\d/i.test(trimmed)
81
- || /^(Sonnet|Opus|Haiku)\b/i.test(trimmed)
82
- || /^[◐◑◒◓◴◵◶◷◸◹◺◿].*\/effort/i.test(trimmed)
83
- || /^⏵⏵\s+accept edits on/i.test(trimmed)
84
- || /^ctrl\+g to edit in VS Code/i.test(trimmed)
85
- || /^✳\s*Claude Code/i.test(trimmed)
86
- || /^[▗▖▘▝\s]+~\//.test(trimmed);
87
- }
88
-
89
- function isStatusLine(trimmed) {
90
- if (!trimmed) return true;
91
- if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+$/.test(trimmed)) return true;
92
- if (/^[⠂⠐⠒⠓⠦⠴⠶⠷⠿]\s+/.test(trimmed)) return true;
93
- if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) return true;
94
- if (/(?:Finagling|Scurrying|Bloviating|Whatchamacallit(?:ing)?|Hatching|Tinkering|Thinking|Processing|Working|Analyzing|Planning|Drafting|Synthesizing|Inspecting|Reading|Searching)\u2026?$/i.test(trimmed)) return true;
95
- if (/Allow\s*once|Always\s*allow|\(y\/n\)|\[Y\/n\]/i.test(trimmed)) return true;
96
- return false;
97
- }
98
-
99
- function isNoiseLine(line) {
100
- const trimmed = sanitizeLine(line).trim();
101
- if (!trimmed) return true;
102
- if (/^…\s+\+\d+\s+lines\b/i.test(trimmed)) return true;
103
- if (isBoxLine(trimmed)) return true;
104
- if (isFooterLine(trimmed)) return true;
105
- if (isStatusLine(trimmed)) return true;
106
- if (/^Type your message/i.test(trimmed)) return true;
107
- if (/^for\s*shortcuts/i.test(trimmed)) return true;
108
- if (/^\? for help/i.test(trimmed)) return true;
109
- if (/^Press enter/i.test(trimmed)) return true;
110
- return false;
111
- }
112
-
113
- function stripAssistantPrefix(trimmed) {
114
- return trimmed
115
- .replace(/^[⏺•]\s+/, '')
116
- .replace(/^⎿\s+/, '')
117
- .replace(/^[✻✶✳✢✽]\s+/, '')
118
- .trim();
119
- }
120
-
121
- function collectMeaningfulLines(lines) {
122
- const out = [];
123
- let captureDetails = false;
124
- for (let index = 0; index < lines.length; index++) {
125
- const rawLine = lines[index];
126
- const promptText = parsePromptLine(rawLine);
127
- if (promptText !== null) continue;
128
-
129
- const sanitized = sanitizeLine(rawLine);
130
- const trimmed = sanitized.trim();
131
- if (isNoiseLine(trimmed)) continue;
132
- const nextTrimmed = sanitizeLine(lines[index + 1] || '').trim();
133
- if (/\u2026\)$/.test(trimmed) && /^⎿\s+/.test(nextTrimmed)) continue;
134
-
135
- const cleaned = stripAssistantPrefix(trimmed);
136
- if (!cleaned) continue;
137
- if (/^⏺\s+/.test(trimmed)) {
138
- captureDetails = /^(?:Bash|Read|Task)\(/.test(cleaned)
139
- || /^(?:Exact output|Output|Result):/i.test(cleaned);
140
- if (out[out.length - 1] !== cleaned) out.push(cleaned);
141
- continue;
142
- }
143
-
144
- if (/^⎿\s+/.test(trimmed)) {
145
- if (!captureDetails || /^…\s+\+\d+\s+lines\b/i.test(cleaned)) continue;
146
- if (out[out.length - 1] !== cleaned) out.push(cleaned);
147
- continue;
148
- }
149
-
150
- if (!captureDetails && /^\d+\s+/.test(trimmed)) continue;
151
- if (cleaned.length === 1 && /^[A-Za-z]$/.test(cleaned)) continue;
152
- if (out[out.length - 1] !== cleaned) out.push(cleaned);
153
- }
154
- return out;
155
- }
156
-
157
- function looksLikeStructuredDataLine(text) {
158
- const line = stripAssistantPrefix(sanitizeLine(text).trim());
159
- if (!line) return false;
160
- return /^[{\[]/.test(line)
161
- || /^[A-Z0-9_]+=/.test(line)
162
- || /^\/[A-Za-z0-9._/-]+$/.test(line)
163
- || /^\d+$/.test(line);
164
- }
165
-
166
- function extractDenseOutputBlock(text) {
167
- const lines = splitLines(text);
168
- const blocks = [];
169
- let current = [];
170
-
171
- for (const rawLine of lines) {
172
- const promptText = parsePromptLine(rawLine);
173
- const sanitized = sanitizeLine(rawLine).trim();
174
- if (promptText !== null || isNoiseLine(sanitized)) {
175
- if (current.length > 0) {
176
- blocks.push(current);
177
- current = [];
178
- }
179
- continue;
180
- }
181
-
182
- const cleaned = stripAssistantPrefix(sanitized);
183
- if (!cleaned) {
184
- if (current.length > 0) {
185
- blocks.push(current);
186
- current = [];
187
- }
188
- continue;
189
- }
190
- current.push(cleaned);
191
- }
192
-
193
- if (current.length > 0) blocks.push(current);
194
-
195
- const scored = blocks
196
- .map(block => ({
197
- block,
198
- structured: block.filter(looksLikeStructuredDataLine).length,
199
- }))
200
- .filter(entry => entry.block.length >= 5 && entry.structured >= Math.max(3, Math.floor(entry.block.length * 0.6)));
201
-
202
- const mergeBlocks = (existing, next) => {
203
- if (existing.length === 0) return [...next];
204
- const maxOverlap = Math.min(existing.length, next.length);
205
- for (let overlap = maxOverlap; overlap >= 1; overlap--) {
206
- let matches = true;
207
- for (let i = 0; i < overlap; i++) {
208
- if (existing[existing.length - overlap + i] !== next[i]) {
209
- matches = false;
210
- break;
211
- }
212
- }
213
- if (matches) {
214
- return existing.concat(next.slice(overlap));
215
- }
216
- }
217
- return existing.concat(next);
218
- };
219
-
220
- const merged = scored.reduce((acc, entry) => mergeBlocks(acc, entry.block), []);
221
- return merged.join('\n').trim();
222
- }
223
-
224
- function collectAssistantBlocks(lines) {
225
- const blocks = [];
226
- let current = null;
227
- for (const rawLine of lines) {
228
- const sanitized = sanitizeLine(rawLine);
229
- const trimmed = sanitized.trim();
230
- if (!trimmed || isNoiseLine(trimmed)) continue;
231
-
232
- if (/^⏺\s+/.test(trimmed)) {
233
- const title = stripAssistantPrefix(trimmed);
234
- if (!title) {
235
- current = null;
236
- continue;
237
- }
238
- current = {
239
- title,
240
- lines: [title],
241
- isTool: /^(?:Bash|Read|Write|Edit|MultiEdit|Task|Glob|Grep|LS|NotebookEdit)\(/.test(title),
242
- };
243
- blocks.push(current);
244
- continue;
245
- }
246
-
247
- if (!current) continue;
248
- const cleaned = stripAssistantPrefix(trimmed);
249
- if (!cleaned || /^…\s+\+\d+\s+lines\b/i.test(cleaned)) continue;
250
- current.lines.push(cleaned);
251
- }
252
- return blocks;
253
- }
254
-
255
- function extractVisibleTurn(text, previousMessages) {
256
- const lines = splitLines(text);
257
- const emptyPromptIndex = (() => {
258
- for (let i = lines.length - 1; i >= 0; i--) {
259
- if (parsePromptLine(lines[i]) === '') return i;
260
- }
261
- return -1;
262
- })();
263
-
264
- const userPrompt = (() => {
265
- const upperBound = emptyPromptIndex >= 0 ? emptyPromptIndex - 1 : lines.length - 1;
266
- for (let i = upperBound; i >= 0; i--) {
267
- const parsed = parsePromptLine(lines[i]);
268
- if (parsed) return { index: i, text: parsed };
269
- }
270
- return { index: -1, text: '' };
271
- })();
272
-
273
- const promptLines = [];
274
- let assistantStart = userPrompt.index >= 0 ? userPrompt.index + 1 : 0;
275
- if (userPrompt.index >= 0) {
276
- promptLines.push(userPrompt.text);
277
- for (let i = userPrompt.index + 1; i < lines.length; i++) {
278
- const trimmed = sanitizeLine(lines[i]).trim();
279
- if (!trimmed) {
280
- assistantStart = i + 1;
281
- break;
282
- }
283
- if (/^[⏺•]/.test(trimmed) || isBoxLine(trimmed) || isFooterLine(trimmed) || isStatusLine(trimmed) || /^([❯›>]\s*)?\d+[.)]\s+/.test(trimmed)) {
284
- assistantStart = i;
285
- break;
286
- }
287
- promptLines.push(trimmed);
288
- assistantStart = i + 1;
289
- }
290
- }
291
-
292
- const end = emptyPromptIndex >= 0 ? emptyPromptIndex : lines.length;
293
- const assistantWindow = lines.slice(assistantStart, end);
294
- const blocks = collectAssistantBlocks(assistantWindow);
295
- const lastNarrativeBlock = [...blocks].reverse().find(block => !block.isTool);
296
- let assistantLines = lastNarrativeBlock
297
- ? lastNarrativeBlock.lines
298
- : collectMeaningfulLines(assistantWindow);
299
-
300
- if (assistantLines.length === 0 && Array.isArray(previousMessages) && previousMessages.length > 0) {
301
- assistantLines = collectMeaningfulLines(lines);
302
- }
303
-
304
- return {
305
- promptText: promptLines.join(' ').trim(),
306
- assistantText: assistantLines.join('\n').trim(),
307
- };
308
- }
309
-
310
- function extractPartialAssistant(text) {
311
- const meaningful = collectMeaningfulLines(splitLines(text));
312
- return meaningful.join('\n').trim();
313
- }
314
-
315
- function buildMessages(previousMessages, promptText, assistantText, partialText) {
316
- const base = Array.isArray(previousMessages)
317
- ? previousMessages
318
- .filter(message => message && (message.role === 'user' || message.role === 'assistant'))
319
- .map(message => ({
320
- role: message.role,
321
- content: typeof message.content === 'string' ? message.content : String(message.content || ''),
322
- timestamp: message.timestamp,
323
- }))
324
- : [];
325
-
326
- if (!promptText && base.length === 0) {
327
- return base;
328
- }
329
-
330
- if (promptText) {
331
- const normalizedPrompt = normalizeText(promptText);
332
- const last = base[base.length - 1];
333
- const previousUser = last?.role === 'assistant' ? base[base.length - 2] : last;
334
- if (!previousUser || previousUser.role !== 'user' || !looksLikeSamePrompt(previousUser.content, normalizedPrompt)) {
335
- base.push({ role: 'user', content: promptText });
336
- }
337
- }
338
-
339
- const candidateAssistant = assistantText || partialText;
340
- if (!candidateAssistant) return base;
341
-
342
- const normalizedAssistant = normalizeText(candidateAssistant);
343
- if (!normalizedAssistant) return base;
344
- if (looksLikePromptEchoText(candidateAssistant, promptText, previousMessages)) return base;
345
- if (!assistantText && isSpinnerOnlyText(candidateAssistant)) return base;
346
-
347
- const last = base[base.length - 1];
348
- if (last && last.role === 'assistant') {
349
- if (normalizeText(last.content) !== normalizedAssistant) {
350
- last.content = candidateAssistant;
351
- }
352
- } else {
353
- base.push({ role: 'assistant', content: candidateAssistant });
354
- }
355
-
356
- return base;
357
- }
358
-
359
- function toMessageObjects(messages, status) {
360
- return messages.slice(-50).map((message, index, slice) => ({
361
- id: `msg_${index}`,
362
- role: message.role,
363
- content: typeof message.content === 'string' && message.content.length > 6000
364
- ? message.content.slice(0, 6000) + '\n[... truncated]'
365
- : message.content,
366
- index,
367
- kind: 'standard',
368
- ...(status === 'generating' && index === slice.length - 1 && message.role === 'assistant'
369
- ? { meta: { streaming: true } }
370
- : {}),
371
- }));
372
- }
373
-
374
- module.exports = function parseOutput(input) {
375
- const screenText = String(input?.screenText || '');
376
- const buffer = String(input?.buffer || '');
377
- const terminalHistory = String(input?.terminalHistory || '');
378
- const tail = String(input?.recentBuffer || (screenText || buffer).slice(-500));
379
- const previousMessages = Array.isArray(input?.messages) ? input.messages : [];
380
- const transcriptSource = screenText || buffer;
381
-
382
- const status = detectStatus({
383
- tail,
384
- screenText,
385
- rawBuffer: input?.rawBuffer || '',
386
- });
387
-
388
- const activeModal = status === 'waiting_approval'
389
- ? parseApproval({ buffer: screenText || buffer, rawBuffer: input?.rawBuffer || '', tail })
390
- : null;
391
-
392
- const { promptText, assistantText: visibleAssistantText } = status === 'waiting_approval'
393
- ? { promptText: '', assistantText: '' }
394
- : extractVisibleTurn(transcriptSource, previousMessages);
395
- const denseTerminalOutput = extractDenseOutputBlock(terminalHistory || buffer);
396
- const assistantText = denseTerminalOutput || visibleAssistantText;
397
- const rawPartialText = status === 'generating'
398
- ? extractPartialAssistant(input?.partialResponse || '')
399
- : '';
400
- const partialText = (!rawPartialText
401
- || isSpinnerOnlyText(rawPartialText)
402
- || looksLikePromptEchoText(rawPartialText, promptText, previousMessages))
403
- ? ''
404
- : rawPartialText;
405
- const messages = toMessageObjects(
406
- buildMessages(previousMessages, promptText, assistantText, partialText),
407
- status
408
- );
409
-
410
- return {
411
- id: 'cli_session',
412
- status,
413
- title: 'Claude Code',
414
- messages,
415
- activeModal,
416
- };
417
- };
@@ -1,42 +0,0 @@
1
- /**
2
- * Claude Code CLI Scripts — v1.0
3
- *
4
- * CLI scripts differ from IDE scripts:
5
- * - IDE scripts return JS code strings for CDP evaluate (browser context)
6
- * - CLI scripts are Node.js functions that receive PTY buffer and return structured data
7
- *
8
- * Each export receives an `input` object:
9
- * { buffer: string, rawBuffer: string, recentBuffer: string, messages: Array }
10
- * and returns a result conforming to the output contract.
11
- */
12
-
13
- 'use strict';
14
-
15
- const fs = require('fs');
16
- const path = require('path');
17
- const DIR = __dirname;
18
-
19
- function loadModule(name) {
20
- try { return require(path.join(DIR, name)); }
21
- catch { return null; }
22
- }
23
-
24
- // ─── Core ───
25
-
26
- /** Parse full PTY output → ReadChatResult */
27
- module.exports.parseOutput = (input) => {
28
- const mod = loadModule('parse_output.js');
29
- return mod ? mod(input) : null;
30
- };
31
-
32
- /** Lightweight status detection (100ms polling) → AgentStatus string */
33
- module.exports.detectStatus = (input) => {
34
- const mod = loadModule('detect_status.js');
35
- return mod ? mod(input) : null;
36
- };
37
-
38
- /** Parse approval modal from PTY output → ModalInfo | null */
39
- module.exports.parseApproval = (input) => {
40
- const mod = loadModule('parse_approval.js');
41
- return mod ? mod(input) : null;
42
- };
@@ -1,90 +0,0 @@
1
- {
2
- "type": "codex-cli",
3
- "name": "Codex CLI",
4
- "category": "cli",
5
- "aliases": [
6
- "codex"
7
- ],
8
- "icon": "🧠",
9
- "displayName": "Codex CLI",
10
- "settings": {
11
- "mode": {
12
- "type": "select",
13
- "default": "chat",
14
- "public": true,
15
- "label": "Display Mode",
16
- "description": "terminal: Native PTY view, chat: Parsed message view",
17
- "options": [
18
- "terminal",
19
- "chat"
20
- ]
21
- },
22
- "notifications": {
23
- "type": "boolean",
24
- "default": true,
25
- "public": true,
26
- "label": "Notifications",
27
- "description": "Display notifications on state changes"
28
- },
29
- "autoApprove": {
30
- "type": "boolean",
31
- "default": false,
32
- "public": true,
33
- "label": "Auto Approve",
34
- "description": "Automatically approve all tool calls without user confirmation"
35
- },
36
- "approvalAlert": {
37
- "type": "boolean",
38
- "default": true,
39
- "public": true,
40
- "label": "Approval Notifications",
41
- "description": "Show notification when approval is needed"
42
- },
43
- "longGeneratingAlert": {
44
- "type": "boolean",
45
- "default": true,
46
- "public": true,
47
- "label": "Long Generation Alert",
48
- "description": "Alert when generation takes too long"
49
- },
50
- "longGeneratingThresholdSec": {
51
- "type": "number",
52
- "default": 180,
53
- "public": true,
54
- "label": "Long Generation Threshold (sec)",
55
- "min": 30,
56
- "max": 600
57
- }
58
- },
59
- "binary": "codex",
60
- "sendDelayMs": 1200,
61
- "sendKey": "\r",
62
- "spawn": {
63
- "command": "codex",
64
- "args": [],
65
- "shell": false,
66
- "env": {}
67
- },
68
- "patterns": {
69
- "prompt": [
70
- { "source": "To get started, describe a task or try one of these commands", "flags": "i" },
71
- { "source": "^>\\s*$", "flags": "m" }
72
- ],
73
- "generating": [
74
- { "source": "Working \\(\\d+s", "flags": "i" }
75
- ],
76
- "approval": [
77
- { "source": "Always approve this session", "flags": "i" },
78
- { "source": "Approve and run now", "flags": "i" },
79
- { "source": "Allow command\\?", "flags": "i" }
80
- ],
81
- "ready": []
82
- },
83
- "compatibility": [
84
- {
85
- "ideVersion": ">=0.42.0",
86
- "scriptDir": "scripts/1.0"
87
- }
88
- ],
89
- "defaultScriptDir": "scripts/1.0"
90
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * Codex CLI — detect_status
3
- */
4
- 'use strict';
5
-
6
- function sourceText(input) {
7
- return `${String(input?.screenText || '')}\n${String(input?.tail || '')}`;
8
- }
9
-
10
- function hasWelcomeScreen(text) {
11
- return /OpenAI Codex/i.test(text)
12
- && /To get started, describe a task/i.test(text);
13
- }
14
-
15
- function hasStartupApproval(text) {
16
- return /You are running Codex in/i.test(text)
17
- && /Press Enter to continue/i.test(text)
18
- && /(?:^|\n)[▌> \t]*1\.\s+/m.test(text)
19
- && /(?:^|\n)[▌> \t]*2\.\s+/m.test(text);
20
- }
21
-
22
- function hasCommandApproval(text) {
23
- const hasAllowPrompt = /Allow Codex to (?:run|apply)/i.test(text)
24
- || /Allow command\?/i.test(text);
25
- const hasButtons = /Approve and run now/i.test(text)
26
- || /Always approve this session/i.test(text)
27
- || /(?:^|\n)[▌> \t]*1\.\s+.*(?:approve|allow|run)/im.test(text)
28
- || /(?:^|\n)[▌> \t]*2\.\s+.*(?:always|session)/im.test(text);
29
- const hasFooter = /Press Enter to confirm/i.test(text)
30
- || /Esc to cancel/i.test(text);
31
- return hasAllowPrompt
32
- || (hasButtons && hasFooter)
33
- || /Approve and run now/i.test(text)
34
- || /Always approve this session/i.test(text)
35
- || /(?:^|\n)[▌> \t]*1\.\s+.*(?:approve|allow|run)/im.test(text);
36
- }
37
-
38
- module.exports = function detectStatus(input) {
39
- const text = sourceText(input);
40
- if (!text.trim()) return 'idle';
41
-
42
- if (hasStartupApproval(text) || hasCommandApproval(text)) return 'waiting_approval';
43
-
44
- if (/Esc to interrupt/i.test(text)) return 'generating';
45
- if (/(?:Thinking|Planning|Searching|Reading|Working|Analyzing|Inspecting|Responding|Following instructions clearly)[^\n]*\(\d+s\b/i.test(text)) {
46
- return 'generating';
47
- }
48
- if (/[⠁-⣿]/.test(text) && /(?:Working|Thinking|Esc to interrupt)/i.test(text)) return 'generating';
49
-
50
- if (hasWelcomeScreen(text)) return 'idle';
51
- if (/⏎\s+send/i.test(text)) return 'idle';
52
-
53
- return 'idle';
54
- };
@@ -1,91 +0,0 @@
1
- /**
2
- * Codex CLI — parse_approval
3
- */
4
- 'use strict';
5
-
6
- function splitLines(text) {
7
- return String(text || '')
8
- .replace(/\u0007/g, '')
9
- .split(/\r\n|\n|\r/g)
10
- .map(line => line.replace(/\s+$/, ''));
11
- }
12
-
13
- function normalize(line) {
14
- return String(line || '')
15
- .replace(/\u0007/g, '')
16
- .replace(/^\d+;/, '')
17
- .replace(/\s+/g, ' ')
18
- .trim();
19
- }
20
-
21
- function isBoxLine(line) {
22
- return /^[─═╭╮╰╯│┌┐└┘├┤┬┴┼]+$/.test(line);
23
- }
24
-
25
- function isFooterLine(line) {
26
- return /⏎\s+send/i.test(line)
27
- || /⌃J\s+newline/i.test(line)
28
- || /⌃T\s+transcript/i.test(line)
29
- || /⌃C\s+quit/i.test(line)
30
- || /Press Enter to (?:continue|confirm)/i.test(line)
31
- || /Esc to cancel/i.test(line);
32
- }
33
-
34
- function stripLeadingMarkers(s) {
35
- return s.replace(/^(?:[▌>]\s*)+/, '').trim();
36
- }
37
-
38
- function normalizeButton(line) {
39
- return stripLeadingMarkers(normalize(line))
40
- .replace(/^\d+\.\s+/, '')
41
- .replace(/\s{2,}\([A-Za-z]\)\s.*$/, '')
42
- .trim();
43
- }
44
-
45
- function isButtonLine(line) {
46
- return /^\d+\.\s+/.test(stripLeadingMarkers(normalize(line)));
47
- }
48
-
49
- module.exports = function parseApproval(input) {
50
- const text = String(input?.buffer || input?.tail || '');
51
- const lines = splitLines(text);
52
- if (lines.length === 0) return null;
53
-
54
- const buttons = [];
55
- let currentButton = '';
56
- const recentLines = lines.slice(-60);
57
- for (const rawLine of recentLines) {
58
- const line = normalize(rawLine);
59
- if (!line) continue;
60
- if (isButtonLine(rawLine)) {
61
- if (currentButton && !buttons.includes(currentButton)) buttons.push(currentButton);
62
- currentButton = normalizeButton(rawLine);
63
- continue;
64
- }
65
- if (!currentButton) continue;
66
- if (isFooterLine(line) || isBoxLine(line)) continue;
67
- if (/^(?:model|directory):/i.test(line)) continue;
68
- const continuation = stripLeadingMarkers(line);
69
- if (!continuation) continue;
70
- currentButton = `${currentButton} ${continuation}`.replace(/\s+/g, ' ').trim();
71
- }
72
- if (currentButton && !buttons.includes(currentButton)) buttons.push(currentButton);
73
-
74
- const approvalText = lines
75
- .map(normalize)
76
- .filter(line => line && !isBoxLine(line) && !isButtonLine(line) && !isFooterLine(line))
77
- .filter(line => !/^OpenAI Codex\b/i.test(line))
78
- .filter(line => !/^model:/i.test(line))
79
- .filter(line => !/^directory:/i.test(line));
80
-
81
- const hasApproval = /You are running Codex in/i.test(text)
82
- || /Allow Codex to (?:run|apply)/i.test(text)
83
- || /Allow command\?/i.test(text)
84
- || buttons.length > 0;
85
- if (!hasApproval) return null;
86
-
87
- return {
88
- message: approvalText.slice(-3).join(' ').slice(0, 240) || 'Codex approval required',
89
- buttons: buttons.length > 0 ? buttons : ['Approve', 'Deny'],
90
- };
91
- };