@adhdev/daemon-core 0.6.53 → 0.6.55

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 (164) hide show
  1. package/dist/index.d.ts +76 -34
  2. package/dist/index.js +714 -271
  3. package/dist/index.js.map +1 -1
  4. package/package.json +1 -1
  5. package/providers/_builtin/_helpers/index.js +26 -26
  6. package/providers/_builtin/cli/aider-cli/provider.json +37 -0
  7. package/providers/_builtin/cli/aider-cli/scripts/1.0/detect_status.js +20 -0
  8. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_approval.js +10 -0
  9. package/providers/_builtin/cli/aider-cli/scripts/1.0/parse_output.js +49 -0
  10. package/providers/_builtin/cli/aider-cli/scripts/1.0/scripts.js +7 -0
  11. package/providers/_builtin/cli/claude-cli/provider.json +9 -2
  12. package/providers/_builtin/cli/claude-cli/scripts/1.0/detect_status.js +31 -0
  13. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_approval.js +38 -0
  14. package/providers/_builtin/cli/claude-cli/scripts/1.0/parse_output.js +164 -0
  15. package/providers/_builtin/cli/claude-cli/scripts/1.0/scripts.js +42 -0
  16. package/providers/_builtin/cli/codex-cli/provider.json +9 -2
  17. package/providers/_builtin/cli/codex-cli/scripts/1.0/detect_status.js +20 -0
  18. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_approval.js +15 -0
  19. package/providers/_builtin/cli/codex-cli/scripts/1.0/parse_output.js +68 -0
  20. package/providers/_builtin/cli/codex-cli/scripts/1.0/scripts.js +11 -0
  21. package/providers/_builtin/cli/cursor-cli/provider.json +37 -0
  22. package/providers/_builtin/cli/cursor-cli/scripts/1.0/detect_status.js +19 -0
  23. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_approval.js +10 -0
  24. package/providers/_builtin/cli/cursor-cli/scripts/1.0/parse_output.js +48 -0
  25. package/providers/_builtin/cli/cursor-cli/scripts/1.0/scripts.js +7 -0
  26. package/providers/_builtin/cli/gemini-cli/provider.json +9 -2
  27. package/providers/_builtin/cli/gemini-cli/scripts/1.0/detect_status.js +26 -0
  28. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_approval.js +22 -0
  29. package/providers/_builtin/cli/gemini-cli/scripts/1.0/parse_output.js +71 -0
  30. package/providers/_builtin/cli/gemini-cli/scripts/1.0/scripts.js +12 -0
  31. package/providers/_builtin/cli/github-copilot-cli/provider.json +37 -0
  32. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/detect_status.js +19 -0
  33. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_approval.js +9 -0
  34. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/parse_output.js +48 -0
  35. package/providers/_builtin/cli/github-copilot-cli/scripts/1.0/scripts.js +7 -0
  36. package/providers/_builtin/cli/goose-cli/provider.json +37 -0
  37. package/providers/_builtin/cli/goose-cli/scripts/1.0/detect_status.js +20 -0
  38. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_approval.js +10 -0
  39. package/providers/_builtin/cli/goose-cli/scripts/1.0/parse_output.js +48 -0
  40. package/providers/_builtin/cli/goose-cli/scripts/1.0/scripts.js +7 -0
  41. package/providers/_builtin/cli/opencode-cli/provider.json +37 -0
  42. package/providers/_builtin/cli/opencode-cli/scripts/1.0/detect_status.js +15 -0
  43. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_approval.js +9 -0
  44. package/providers/_builtin/cli/opencode-cli/scripts/1.0/parse_output.js +48 -0
  45. package/providers/_builtin/cli/opencode-cli/scripts/1.0/scripts.js +7 -0
  46. package/providers/_builtin/extension/cline/scripts/1.0/focus_editor.js +5 -5
  47. package/providers/_builtin/extension/cline/scripts/1.0/list_chats.js +11 -11
  48. package/providers/_builtin/extension/cline/scripts/1.0/list_models.js +6 -6
  49. package/providers/_builtin/extension/cline/scripts/1.0/list_modes.js +5 -5
  50. package/providers/_builtin/extension/cline/scripts/1.0/new_session.js +12 -12
  51. package/providers/_builtin/extension/cline/scripts/1.0/open_panel.js +7 -7
  52. package/providers/_builtin/extension/cline/scripts/1.0/read_chat.js +29 -29
  53. package/providers/_builtin/extension/cline/scripts/1.0/resolve_action.js +19 -19
  54. package/providers/_builtin/extension/cline/scripts/1.0/send_message.js +15 -15
  55. package/providers/_builtin/extension/cline/scripts/1.0/set_mode.js +4 -4
  56. package/providers/_builtin/extension/cline/scripts/1.0/set_model.js +4 -4
  57. package/providers/_builtin/extension/cline/scripts/1.0/switch_session.js +21 -21
  58. package/providers/_builtin/extension/codex/scripts/1.0/explore_controls_webview.js +2 -2
  59. package/providers/_builtin/extension/codex/scripts/1.0/list_models.js +1 -1
  60. package/providers/_builtin/extension/codex/scripts/1.0/list_modes.js +1 -1
  61. package/providers/_builtin/extension/codex/scripts/1.0/new_session.js +2 -2
  62. package/providers/_builtin/extension/codex/scripts/1.0/read_chat.js +6 -6
  63. package/providers/_builtin/extension/codex/scripts/1.0/resolve_action.js +3 -3
  64. package/providers/_builtin/extension/codex/scripts/1.0/set_model.js +1 -1
  65. package/providers/_builtin/ide/antigravity/scripts/1.0/focus_editor.js +2 -2
  66. package/providers/_builtin/ide/antigravity/scripts/1.0/list_chats.js +19 -19
  67. package/providers/_builtin/ide/antigravity/scripts/1.0/list_models.js +1 -1
  68. package/providers/_builtin/ide/antigravity/scripts/1.0/list_modes.js +1 -1
  69. package/providers/_builtin/ide/antigravity/scripts/1.0/new_session.js +17 -17
  70. package/providers/_builtin/ide/antigravity/scripts/1.0/read_chat.js +41 -41
  71. package/providers/_builtin/ide/antigravity/scripts/1.0/resolve_action.js +6 -6
  72. package/providers/_builtin/ide/antigravity/scripts/1.0/send_message.js +13 -13
  73. package/providers/_builtin/ide/antigravity/scripts/1.0/set_model.js +1 -1
  74. package/providers/_builtin/ide/antigravity/scripts/1.0/switch_session.js +13 -13
  75. package/providers/_builtin/ide/cursor/scripts/1.0/dismiss_notification.js +3 -3
  76. package/providers/_builtin/ide/cursor/scripts/1.0/focus_editor.js +1 -1
  77. package/providers/_builtin/ide/cursor/scripts/1.0/list_models.js +12 -12
  78. package/providers/_builtin/ide/cursor/scripts/1.0/list_modes.js +5 -5
  79. package/providers/_builtin/ide/cursor/scripts/1.0/list_notifications.js +2 -2
  80. package/providers/_builtin/ide/cursor/scripts/1.0/list_sessions.js +5 -5
  81. package/providers/_builtin/ide/cursor/scripts/1.0/new_session.js +1 -1
  82. package/providers/_builtin/ide/cursor/scripts/1.0/open_panel.js +3 -3
  83. package/providers/_builtin/ide/cursor/scripts/1.0/read_chat.js +9 -9
  84. package/providers/_builtin/ide/cursor/scripts/1.0/resolve_action.js +4 -4
  85. package/providers/_builtin/ide/cursor/scripts/1.0/send_message.js +5 -5
  86. package/providers/_builtin/ide/cursor/scripts/1.0/set_mode.js +4 -4
  87. package/providers/_builtin/ide/cursor/scripts/1.0/set_model.js +12 -12
  88. package/providers/_builtin/ide/cursor/scripts/1.0/switch_session.js +2 -2
  89. package/providers/_builtin/ide/kiro/scripts/1.0/focus_editor.js +2 -2
  90. package/providers/_builtin/ide/kiro/scripts/1.0/open_panel.js +7 -7
  91. package/providers/_builtin/ide/kiro/scripts/1.0/resolve_action.js +3 -3
  92. package/providers/_builtin/ide/kiro/scripts/1.0/send_message.js +4 -4
  93. package/providers/_builtin/ide/kiro/scripts/1.0/webview_list_sessions.js +2 -2
  94. package/providers/_builtin/ide/kiro/scripts/1.0/webview_new_session.js +5 -5
  95. package/providers/_builtin/ide/kiro/scripts/1.0/webview_read_chat.js +13 -13
  96. package/providers/_builtin/ide/kiro/scripts/1.0/webview_resolve_action.js +1 -1
  97. package/providers/_builtin/ide/kiro/scripts/1.0/webview_send_message.js +8 -8
  98. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_mode.js +1 -1
  99. package/providers/_builtin/ide/kiro/scripts/1.0/webview_set_model.js +1 -1
  100. package/providers/_builtin/ide/kiro/scripts/1.0/webview_switch_session.js +3 -3
  101. package/providers/_builtin/ide/pearai/.tmp/after_rich.json +157 -0
  102. package/providers/_builtin/ide/pearai/.tmp/after_rich_raw.json +161 -0
  103. package/providers/_builtin/ide/pearai/.tmp/after_switch.json +592 -0
  104. package/providers/_builtin/ide/pearai/.tmp/after_switch_raw.json +596 -0
  105. package/providers/_builtin/ide/pearai/.tmp/home_dump_raw.json +176 -0
  106. package/providers/_builtin/ide/pearai/.tmp/items_raw.json +778 -0
  107. package/providers/_builtin/ide/pearai/.tmp/webview_dump.json +157 -0
  108. package/providers/_builtin/ide/pearai/.tmp/webview_dump_raw.json +161 -0
  109. package/providers/_builtin/ide/pearai/provider.json +1 -3
  110. package/providers/_builtin/ide/pearai/scripts/1.0/focus_editor.js +12 -16
  111. package/providers/_builtin/ide/pearai/scripts/1.0/list_models.js +45 -0
  112. package/providers/_builtin/ide/pearai/scripts/1.0/list_modes.js +44 -0
  113. package/providers/_builtin/ide/pearai/scripts/1.0/list_sessions.js +82 -27
  114. package/providers/_builtin/ide/pearai/scripts/1.0/new_session.js +26 -43
  115. package/providers/_builtin/ide/pearai/scripts/1.0/open_panel.js +10 -33
  116. package/providers/_builtin/ide/pearai/scripts/1.0/read_chat.js +169 -0
  117. package/providers/_builtin/ide/pearai/scripts/1.0/resolve_action.js +47 -41
  118. package/providers/_builtin/ide/pearai/scripts/1.0/scripts.js +36 -7
  119. package/providers/_builtin/ide/pearai/scripts/1.0/send_message.js +97 -22
  120. package/providers/_builtin/ide/pearai/scripts/1.0/set_mode.js +51 -0
  121. package/providers/_builtin/ide/pearai/scripts/1.0/set_model.js +54 -0
  122. package/providers/_builtin/ide/pearai/scripts/1.0/switch_session.js +81 -0
  123. package/providers/_builtin/ide/trae/scripts/1.0/focus_editor.js +2 -2
  124. package/providers/_builtin/ide/trae/scripts/1.0/list_chats.js +2 -2
  125. package/providers/_builtin/ide/trae/scripts/1.0/new_session.js +4 -4
  126. package/providers/_builtin/ide/trae/scripts/1.0/open_panel.js +6 -6
  127. package/providers/_builtin/ide/trae/scripts/1.0/read_chat.js +13 -13
  128. package/providers/_builtin/ide/trae/scripts/1.0/resolve_action.js +3 -3
  129. package/providers/_builtin/ide/trae/scripts/1.0/send_message.js +11 -11
  130. package/providers/_builtin/ide/trae/scripts/1.0/switch_session.js +2 -2
  131. package/providers/_builtin/ide/windsurf/scripts/1.0/focus_editor.js +6 -6
  132. package/providers/_builtin/ide/windsurf/scripts/1.0/list_chats.js +4 -4
  133. package/providers/_builtin/ide/windsurf/scripts/1.0/list_sessions.js +6 -6
  134. package/providers/_builtin/ide/windsurf/scripts/1.0/new_session.js +9 -9
  135. package/providers/_builtin/ide/windsurf/scripts/1.0/open_panel.js +6 -6
  136. package/providers/_builtin/ide/windsurf/scripts/1.0/resolve_action.js +8 -8
  137. package/providers/_builtin/ide/windsurf/scripts/1.0/switch_session.js +8 -8
  138. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/focus_editor.js +6 -6
  139. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/list_chats.js +12 -12
  140. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/new_session.js +15 -15
  141. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/open_panel.js +10 -10
  142. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/read_chat.js +33 -33
  143. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/resolve_action.js +6 -6
  144. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/send_message.js +16 -16
  145. package/providers/_builtin/ide/windsurf/scripts/1.0.bak/switch_session.js +7 -7
  146. package/providers/_builtin/registry.json +76 -3
  147. package/src/cli-adapters/provider-cli-adapter.ts +267 -251
  148. package/src/cli-adapters/terminal-screen.ts +268 -0
  149. package/src/commands/chat-commands.ts +41 -15
  150. package/src/commands/cli-manager.ts +4 -2
  151. package/src/daemon/dev-server.ts +245 -35
  152. package/src/providers/acp-provider-instance.ts +1 -1
  153. package/src/providers/cli-provider-instance.ts +21 -8
  154. package/src/providers/provider-loader.ts +3 -2
  155. package/providers/_builtin/ide/pearai/scripts/1.0/webview_list_models.js +0 -43
  156. package/providers/_builtin/ide/pearai/scripts/1.0/webview_list_modes.js +0 -35
  157. package/providers/_builtin/ide/pearai/scripts/1.0/webview_list_sessions.js +0 -62
  158. package/providers/_builtin/ide/pearai/scripts/1.0/webview_new_session.js +0 -49
  159. package/providers/_builtin/ide/pearai/scripts/1.0/webview_read_chat.js +0 -92
  160. package/providers/_builtin/ide/pearai/scripts/1.0/webview_resolve_action.js +0 -59
  161. package/providers/_builtin/ide/pearai/scripts/1.0/webview_send_message.js +0 -72
  162. package/providers/_builtin/ide/pearai/scripts/1.0/webview_set_mode.js +0 -36
  163. package/providers/_builtin/ide/pearai/scripts/1.0/webview_set_model.js +0 -36
  164. package/providers/_builtin/ide/pearai/scripts/1.0/webview_switch_session.js +0 -34
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.6.53",
3
+ "version": "0.6.55",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Provider Helpers — 공유 유틸리티
2
+ * Provider Helpers — Shared utilities
3
3
  *
4
- * provider.js에서 require해 사용할 있는 공통 함수들.
5
- * 사용은 선택사항 provider.js 독립적이어도 됨.
4
+ * Common functions available via require in each provider.js.
5
+ * Usage is optional each provider.js can be self-contained.
6
6
  *
7
- * 사용법 (provider.js 내부):
7
+ * Usage (inside provider.js):
8
8
  * const { getWebviewDoc, htmlToMd, waitFor } = require('../../_helpers/index.js');
9
9
  */
10
10
 
11
11
  /**
12
- * Extension webview iframe의 contentDocument 접근
13
- * @param {string} [selector='iframe'] - iframe 셀렉터
14
- * @returns {string} CDP evaluate JS 코드 (document 변수를 설정)
12
+ * Access contentDocument of extension webview iframe
13
+ * @param {string} [selector='iframe'] - iframe selector
14
+ * @returns {string} JS code for CDP evaluate (sets document variable)
15
15
  */
16
16
  function getWebviewDoc(selector = 'iframe') {
17
17
  return `
@@ -21,11 +21,11 @@ function getWebviewDoc(selector = 'iframe') {
21
21
  }
22
22
 
23
23
  /**
24
- * React Fiber 데이터 추출 헬퍼 코드
25
- * 특정 엔트리 포인트에서 시작해 memoizedState를 순회
26
- * @param {string[]} entrySelectors - 엔트리 포인트 CSS 셀렉터
27
- * @param {number} [maxDepth=200] - Fiber 트리 최대 순회 깊이
28
- * @returns {string} CDP evaluate JS 코드 (변수 _fiberData 설정)
24
+ * React Fiber data extraction helper code
25
+ * Traverse memoizedState starting from specific entry points
26
+ * @param {string[]} entrySelectors - Entry point CSS selectors
27
+ * @param {number} [maxDepth=200] - Max Fiber tree traversal depth
28
+ * @returns {string} JS code for CDP evaluate (sets _fiberData variable)
29
29
  */
30
30
  function getFiber(entrySelectors, maxDepth = 200) {
31
31
  const sels = JSON.stringify(entrySelectors);
@@ -61,10 +61,10 @@ function getFiber(entrySelectors, maxDepth = 200) {
61
61
  }
62
62
 
63
63
  /**
64
- * 텍스트 입력 + Enter 전송 코드 생성
65
- * @param {string} varName - 텍스트가 저장된 변수명
66
- * @param {string} selectorExpr - 에디터 요소 참조 JS 표현식
67
- * @returns {string} CDP evaluate용 JS 코드
64
+ * Generate text input + Enter submission code
65
+ * @param {string} varName - Variable name containing the text
66
+ * @param {string} selectorExpr - JS expression referencing the editor element
67
+ * @returns {string} JS code for CDP evaluate
68
68
  */
69
69
  function typeAndSubmit(varName, selectorExpr) {
70
70
  return `
@@ -85,10 +85,10 @@ function typeAndSubmit(varName, selectorExpr) {
85
85
  }
86
86
 
87
87
  /**
88
- * 요소 대기 코드 생성
89
- * @param {string} selector - CSS 셀렉터
90
- * @param {number} [timeout=5000] - 최대 대기 시간 (ms)
91
- * @returns {string} CDP evaluate JS 코드 (표현식요소 또는 null)
88
+ * Generate element wait code
89
+ * @param {string} selector - CSS selector
90
+ * @param {number} [timeout=5000] - Max wait time (ms)
91
+ * @returns {string} JS code for CDP evaluate (expressionelement or null)
92
92
  */
93
93
  function waitFor(selector, timeout = 5000) {
94
94
  return `
@@ -106,9 +106,9 @@ function waitFor(selector, timeout = 5000) {
106
106
  }
107
107
 
108
108
  /**
109
- * HTML → Markdown 변환 함수 (CDP 코드 문자열)
110
- * 대시보드가 ReactMarkdown+remarkGfm 사용하므로 HTML GFM으로 변환 필요
111
- * @returns {string} htmlToMd, childrenToMd 함수 선언 코드
109
+ * HTML → Markdown conversion function (CDP code string)
110
+ * Dashboard uses ReactMarkdown+remarkGfm, so HTML must be converted to GFM
111
+ * @returns {string} htmlToMd, childrenToMd function declaration code
112
112
  */
113
113
  function htmlToMdCode() {
114
114
  return `
@@ -166,9 +166,9 @@ function htmlToMdCode() {
166
166
  }
167
167
 
168
168
  /**
169
- * 노이즈 텍스트 필터링 (상태 메시지, MCP )
170
- * @param {string} text - 원본 텍스트
171
- * @returns {boolean} true 노이즈
169
+ * Noise text filtering (status messages, MCP, etc.)
170
+ * @param {string} text - Original text
171
+ * @returns {boolean} true if noise
172
172
  */
173
173
  function isNoiseText(text) {
174
174
  const low = (text || '').trim().toLowerCase();
@@ -0,0 +1,37 @@
1
+ {
2
+ "type": "aider-cli",
3
+ "name": "Aider",
4
+ "category": "cli",
5
+ "aliases": [
6
+ "aider"
7
+ ],
8
+ "icon": "🤖",
9
+ "displayName": "Aider",
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
+ },
23
+ "binary": "aider",
24
+ "spawn": {
25
+ "command": "aider",
26
+ "args": [],
27
+ "shell": true,
28
+ "env": {}
29
+ },
30
+ "compatibility": [
31
+ {
32
+ "ideVersion": ">=0.86.0",
33
+ "scriptDir": "scripts/1.0"
34
+ }
35
+ ],
36
+ "defaultScriptDir": "scripts/1.0"
37
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Aider — detect_status
3
+ * Aider uses a simpler TUI with '>' prompts and tool output markers.
4
+ */
5
+ 'use strict';
6
+ module.exports = function detectStatus(input) {
7
+ const { tail } = input;
8
+ if (!tail) return 'idle';
9
+ // Aider approval: "Allow creation of new file" / "Run shell command?"
10
+ if (/Allow\s*creation/i.test(tail) && /\(y\/n\)/i.test(tail)) return 'waiting_approval';
11
+ if (/Run\s*shell\s*command/i.test(tail)) return 'waiting_approval';
12
+ if (/Apply\s*(edit|change)/i.test(tail) && /\(y\/n\)/i.test(tail)) return 'waiting_approval';
13
+ // generating
14
+ if (/[\u2800-\u28ff]/.test(tail)) return 'generating';
15
+ if (/[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/.test(tail)) return 'generating';
16
+ if (/Thinking|Sending|Streaming/i.test(tail)) return 'generating';
17
+ // Aider shows "Tokens:" after completion — if we see that, it's idle
18
+ if (/Tokens:/i.test(tail)) return 'idle';
19
+ return 'idle';
20
+ };
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+ module.exports = function parseApproval(input) {
3
+ const { tail } = input;
4
+ if (!tail) return null;
5
+ const hasApproval = /Allow\s*creation/i.test(tail) || /Run\s*shell\s*command/i.test(tail) ||
6
+ /Apply\s*(edit|change)/i.test(tail) || /\(y\/n\)/i.test(tail);
7
+ if (!hasApproval) return null;
8
+ const lines = tail.split('\n').map(l => l.trim()).filter(l => l && l.length > 2);
9
+ return { message: lines.slice(-5).join(' ').slice(0, 200) || 'Approval required', buttons: ['Yes (y)', 'No (n)'] };
10
+ };
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+ const detectStatus = require('./detect_status.js');
3
+ const parseApproval = require('./parse_approval.js');
4
+
5
+ function splitTurns(buffer) {
6
+ const messages = [];
7
+ if (!buffer || buffer.length < 5) return messages;
8
+ const lines = buffer.split('\n');
9
+ let currentRole = null, currentContent = [], msgIndex = 0, started = false;
10
+ for (const line of lines) {
11
+ const trimmed = line.trim();
12
+ // Aider prompt is just '>' at start of line
13
+ const userMatch = trimmed.match(/^[❯›>]\s+(.+)$/);
14
+ if (userMatch && userMatch[1].length > 1) {
15
+ started = true;
16
+ if (currentRole && currentContent.length > 0) {
17
+ const text = currentContent.join('\n').trim();
18
+ if (text.length > 1) { messages.push({ id: `msg_${msgIndex}`, role: currentRole, content: text.slice(0, 6000), index: msgIndex, kind: 'standard' }); msgIndex++; }
19
+ }
20
+ currentRole = 'user'; currentContent = [userMatch[1]]; continue;
21
+ }
22
+ if (!started) continue;
23
+ if (currentRole === 'user' && trimmed && !userMatch) {
24
+ const text = currentContent.join('\n').trim();
25
+ if (text.length > 1) { messages.push({ id: `msg_${msgIndex}`, role: 'user', content: text, index: msgIndex, kind: 'standard' }); msgIndex++; }
26
+ currentRole = 'assistant'; currentContent = [];
27
+ }
28
+ if (!trimmed || /^[\u2800-\u28ff]+$/.test(trimmed)) continue;
29
+ if (currentRole) currentContent.push(trimmed);
30
+ }
31
+ if (currentRole && currentContent.length > 0) {
32
+ const text = currentContent.join('\n').trim();
33
+ if (text.length > 1) messages.push({ id: `msg_${msgIndex}`, role: currentRole, content: text.slice(0, 6000), index: msgIndex, kind: 'standard' });
34
+ }
35
+ return messages.length > 50 ? messages.slice(-50) : messages;
36
+ }
37
+
38
+ module.exports = function parseOutput(input) {
39
+ const { buffer, recentBuffer, partialResponse, screenText } = input;
40
+ const transcript = screenText || buffer;
41
+ const tail = recentBuffer || (transcript || '').slice(-500);
42
+ const status = detectStatus({ tail });
43
+ const activeModal = status === 'waiting_approval' ? parseApproval({ buffer: transcript, tail }) : null;
44
+ const messages = splitTurns(transcript);
45
+ if (status === 'generating' && partialResponse && partialResponse.trim().length > 2) {
46
+ messages.push({ id: 'msg_partial', role: 'assistant', content: partialResponse.trim().slice(0, 6000), index: messages.length, kind: 'standard', meta: { streaming: true } });
47
+ }
48
+ return { id: 'cli_session', status, title: 'Aider', messages, activeModal };
49
+ };
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+ const path = require('path');
3
+ const DIR = __dirname;
4
+ function loadModule(name) { try { return require(path.join(DIR, name)); } catch { return null; } }
5
+ module.exports.parseOutput = (input) => { const m = loadModule('parse_output.js'); return m ? m(input) : null; };
6
+ module.exports.detectStatus = (input) => { const m = loadModule('detect_status.js'); return m ? m(input) : null; };
7
+ module.exports.parseApproval = (input) => { const m = loadModule('parse_approval.js'); return m ? m(input) : null; };
@@ -11,7 +11,7 @@
11
11
  "settings": {
12
12
  "mode": {
13
13
  "type": "select",
14
- "default": "terminal",
14
+ "default": "chat",
15
15
  "public": true,
16
16
  "label": "Display Mode",
17
17
  "description": "terminal: Native PTY view, chat: Parsed message view",
@@ -98,5 +98,12 @@
98
98
  "0": "1",
99
99
  "1": "2",
100
100
  "2": "3"
101
- }
101
+ },
102
+ "compatibility": [
103
+ {
104
+ "ideVersion": ">=2.1.0",
105
+ "scriptDir": "scripts/1.0"
106
+ }
107
+ ],
108
+ "defaultScriptDir": "scripts/1.0"
102
109
  }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Claude Code — detect_status
3
+ *
4
+ * Lightweight status detection for high-frequency polling.
5
+ * Input: { tail: string } — last ~500 chars of ANSI-stripped PTY output
6
+ * Output: 'idle' | 'generating' | 'waiting_approval'
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ module.exports = function detectStatus(input) {
12
+ const { tail } = input;
13
+ if (!tail) return 'idle';
14
+
15
+ // ─── waiting_approval (highest priority) ───
16
+ // Claude Code approval menu items
17
+ if (/Allow\s*once/i.test(tail) || /Always\s*allow/i.test(tail)) return 'waiting_approval';
18
+ if (/\(y\/n\)/i.test(tail) || /\[Y\/n\]/i.test(tail)) return 'waiting_approval';
19
+
20
+ // ─── generating ───
21
+ // Braille spinner characters (universal TUI spinner)
22
+ if (/[\u2800-\u28ff]/.test(tail)) return 'generating';
23
+ // Status line indicators
24
+ if (/esc to (cancel|interrupt|stop)/i.test(tail)) return 'generating';
25
+ if (/generating\.\.\./i.test(tail)) return 'generating';
26
+ if (/Claude is (?:thinking|processing|working)/i.test(tail)) return 'generating';
27
+ if (/Flummoxing/i.test(tail)) return 'generating';
28
+
29
+ // ─── idle ───
30
+ return 'idle';
31
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Claude Code — parse_approval
3
+ *
4
+ * Extract approval modal info from PTY output.
5
+ * Input: { buffer: string, tail: string }
6
+ * Output: { message: string, buttons: string[] } | null
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ module.exports = function parseApproval(input) {
12
+ const { buffer, tail } = input;
13
+ const check = tail || (buffer || '').slice(-800);
14
+ if (!check) return null;
15
+
16
+ // Claude Code approval patterns
17
+ const hasApproval =
18
+ /Allow\s*once/i.test(check) ||
19
+ /Always\s*allow/i.test(check) ||
20
+ /\(y\/n\)/i.test(check) ||
21
+ /\[Y\/n\]/i.test(check);
22
+
23
+ if (!hasApproval) return null;
24
+
25
+ // Extract context message (last few meaningful lines before the approval)
26
+ const lines = check.split('\n')
27
+ .map(l => l.trim())
28
+ .filter(l => l && !/^[─═╭╮╰╯│]+$/.test(l));
29
+
30
+ const message = lines.slice(-5).join(' ').slice(0, 200) || 'Approval required';
31
+
32
+ // Claude Code-specific button labels
33
+ // These map to approvalKeys in provider.json: { "0": "1", "1": "2", "2": "3" }
34
+ return {
35
+ message,
36
+ buttons: ['Yes (y)', 'Always allow (a)', 'Deny (Esc)'],
37
+ };
38
+ };
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Claude Code — parse_output
3
+ *
4
+ * Full PTY buffer → ReadChatResult conversion.
5
+ * Called less frequently than detectStatus (on demand, not polling).
6
+ *
7
+ * Input: {
8
+ * buffer: string, // Full ANSI-stripped accumulated PTY output
9
+ * rawBuffer: string, // Raw PTY output (with ANSI)
10
+ * recentBuffer: string, // Recent 1000 chars (ANSI-stripped)
11
+ * messages: Array, // Previously parsed messages (for delta)
12
+ * partialResponse: string, // Current partial response being generated
13
+ * }
14
+ *
15
+ * Output: ReadChatResult {
16
+ * messages: [{ id, role, content, index, kind?, meta? }],
17
+ * status: AgentStatus,
18
+ * activeModal?: ModalInfo | null,
19
+ * title?: string,
20
+ * }
21
+ */
22
+
23
+ 'use strict';
24
+
25
+ const detectStatus = require('./detect_status.js');
26
+ const parseApproval = require('./parse_approval.js');
27
+
28
+ function normalizeText(text) {
29
+ return String(text || '')
30
+ .replace(/\s+/g, ' ')
31
+ .trim();
32
+ }
33
+
34
+ function sanitizeLine(line) {
35
+ return String(line || '').replace(/\s+$/, '');
36
+ }
37
+
38
+ function isNoiseLine(line) {
39
+ const trimmed = line.trim();
40
+ if (!trimmed) return true;
41
+ if (/^[─═╭╮╰╯│┌┐└┘├┤┬┴┼]+$/.test(trimmed)) return true;
42
+ if (/^Type your message/i.test(trimmed)) return true;
43
+ if (/^for\s*shortcuts/i.test(trimmed)) return true;
44
+ if (/^\? for help/i.test(trimmed)) return true;
45
+ if (/^Press enter/i.test(trimmed)) return true;
46
+ if (/^[\u2800-\u28ff]+$/.test(trimmed)) return true;
47
+ if (/^esc to (cancel|interrupt|stop)/i.test(trimmed)) return true;
48
+ if (/^Allow\s*once/i.test(trimmed)) return true;
49
+ if (/^Always\s*allow/i.test(trimmed)) return true;
50
+ if (/^\[(Y\/n|y\/n)\]$/i.test(trimmed)) return true;
51
+ return false;
52
+ }
53
+
54
+ function extractPromptLine(lines) {
55
+ for (let i = lines.length - 1; i >= 0; i--) {
56
+ const trimmed = lines[i].trim();
57
+ const match = trimmed.match(/^[❯›>]\s+(.+)$/);
58
+ if (match && match[1].trim().length > 0) {
59
+ return { index: i, text: match[1].trim() };
60
+ }
61
+ }
62
+ return { index: -1, text: '' };
63
+ }
64
+
65
+ function extractVisibleAssistant(screenText) {
66
+ if (!screenText) return { promptText: '', assistantText: '' };
67
+ const lines = screenText.split('\n').map(sanitizeLine);
68
+ const prompt = extractPromptLine(lines);
69
+ const afterPrompt = prompt.index >= 0 ? lines.slice(prompt.index + 1) : lines;
70
+ const contentLines = afterPrompt.filter(line => !isNoiseLine(line));
71
+ return {
72
+ promptText: prompt.text,
73
+ assistantText: contentLines.join('\n').trim(),
74
+ };
75
+ }
76
+
77
+ function toMessageObjects(messages, status) {
78
+ const max = 50;
79
+ const slice = messages.slice(-max);
80
+ return slice.map((message, index) => ({
81
+ id: `msg_${index}`,
82
+ role: message.role,
83
+ content: typeof message.content === 'string' && message.content.length > 6000
84
+ ? message.content.slice(0, 6000) + '\n[... truncated]'
85
+ : message.content,
86
+ index,
87
+ kind: 'standard',
88
+ ...(status === 'generating' && index === slice.length - 1 && message.role === 'assistant'
89
+ ? { meta: { streaming: true } }
90
+ : {}),
91
+ }));
92
+ }
93
+
94
+ function buildMessages(previousMessages, promptText, assistantText, status, partialResponse) {
95
+ const base = Array.isArray(previousMessages)
96
+ ? previousMessages.map(m => ({
97
+ role: m.role,
98
+ content: typeof m.content === 'string' ? m.content : String(m.content || ''),
99
+ timestamp: m.timestamp,
100
+ }))
101
+ : [];
102
+
103
+ const last = base[base.length - 1];
104
+ if (promptText) {
105
+ const normalizedPrompt = normalizeText(promptText);
106
+ if (!last || last.role !== 'user' || normalizeText(last.content) !== normalizedPrompt) {
107
+ base.push({ role: 'user', content: promptText });
108
+ }
109
+ }
110
+
111
+ const candidateAssistant = normalizeText(partialResponse || '') || assistantText;
112
+ if (candidateAssistant) {
113
+ const normalizedAssistant = normalizeText(candidateAssistant);
114
+ const lastMsg = base[base.length - 1];
115
+ if (lastMsg && lastMsg.role === 'assistant') {
116
+ const existing = normalizeText(lastMsg.content);
117
+ if (normalizedAssistant !== existing) {
118
+ lastMsg.content = candidateAssistant;
119
+ }
120
+ } else {
121
+ base.push({ role: 'assistant', content: candidateAssistant });
122
+ }
123
+ }
124
+
125
+ if (status !== 'generating') {
126
+ const lastMsg = base[base.length - 1];
127
+ if (lastMsg?.role === 'assistant') {
128
+ const visible = normalizeText(assistantText);
129
+ if (visible && visible !== normalizeText(lastMsg.content)) {
130
+ lastMsg.content = assistantText;
131
+ }
132
+ }
133
+ }
134
+
135
+ return base;
136
+ }
137
+
138
+ module.exports = function parseOutput(input) {
139
+ const { buffer, recentBuffer, partialResponse, screenText, messages: previousMessages } = input;
140
+ const transcript = screenText || buffer || '';
141
+
142
+ // Status
143
+ const tail = (recentBuffer || (transcript || '').slice(-500));
144
+ const status = detectStatus({ tail });
145
+
146
+ // Modal
147
+ const activeModal = status === 'waiting_approval'
148
+ ? parseApproval({ buffer: transcript, tail })
149
+ : null;
150
+
151
+ const { promptText, assistantText } = extractVisibleAssistant(transcript);
152
+ const messages = toMessageObjects(
153
+ buildMessages(previousMessages, promptText, assistantText, status, partialResponse),
154
+ status
155
+ );
156
+
157
+ return {
158
+ id: 'cli_session',
159
+ status,
160
+ title: 'Claude Code',
161
+ messages,
162
+ activeModal,
163
+ };
164
+ };
@@ -0,0 +1,42 @@
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
+ };
@@ -10,7 +10,7 @@
10
10
  "settings": {
11
11
  "mode": {
12
12
  "type": "select",
13
- "default": "terminal",
13
+ "default": "chat",
14
14
  "public": true,
15
15
  "label": "Display Mode",
16
16
  "description": "terminal: Native PTY view, chat: Parsed message view",
@@ -77,5 +77,12 @@
77
77
  { "source": "Allow command\\?", "flags": "i" }
78
78
  ],
79
79
  "ready": []
80
- }
80
+ },
81
+ "compatibility": [
82
+ {
83
+ "ideVersion": ">=0.42.0",
84
+ "scriptDir": "scripts/1.0"
85
+ }
86
+ ],
87
+ "defaultScriptDir": "scripts/1.0"
81
88
  }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Codex CLI — detect_status
3
+ * OpenAI Codex CLI uses a different TUI pattern.
4
+ */
5
+ 'use strict';
6
+ module.exports = function detectStatus(input) {
7
+ const { tail } = input;
8
+ if (!tail) return 'idle';
9
+
10
+ // waiting_approval
11
+ if (/approve|deny|allow|reject/i.test(tail) && /\[.*\]/i.test(tail)) return 'waiting_approval';
12
+ if (/Run command/i.test(tail) && /\(y\/n\)/i.test(tail)) return 'waiting_approval';
13
+
14
+ // generating
15
+ if (/[\u2800-\u28ff]/.test(tail)) return 'generating';
16
+ if (/[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/.test(tail)) return 'generating';
17
+ if (/thinking|processing|running/i.test(tail)) return 'generating';
18
+
19
+ return 'idle';
20
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Codex CLI — parse_approval
3
+ */
4
+ 'use strict';
5
+ module.exports = function parseApproval(input) {
6
+ const { tail } = input;
7
+ if (!tail) return null;
8
+ const hasApproval = /approve|allow/i.test(tail) && /deny|reject/i.test(tail);
9
+ if (!hasApproval && !/\(y\/n\)/i.test(tail)) return null;
10
+ const lines = tail.split('\n').map(l => l.trim()).filter(l => l && !/^[─═╭╮╰╯│]+$/.test(l));
11
+ return {
12
+ message: lines.slice(-5).join(' ').slice(0, 200) || 'Approval required',
13
+ buttons: ['Approve', 'Deny'],
14
+ };
15
+ };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Codex CLI — parse_output
3
+ */
4
+ 'use strict';
5
+ const detectStatus = require('./detect_status.js');
6
+ const parseApproval = require('./parse_approval.js');
7
+
8
+ function splitTurns(buffer) {
9
+ const messages = [];
10
+ if (!buffer || buffer.length < 5) return messages;
11
+ const lines = buffer.split('\n');
12
+ let currentRole = null;
13
+ let currentContent = [];
14
+ let msgIndex = 0;
15
+ let started = false;
16
+
17
+ for (const line of lines) {
18
+ const trimmed = line.trim();
19
+ const userMatch = trimmed.match(/^[❯›>$]\s+(.+)$/);
20
+ if (userMatch && userMatch[1].length > 1) {
21
+ started = true;
22
+ if (currentRole && currentContent.length > 0) {
23
+ const text = currentContent.join('\n').trim();
24
+ if (text.length > 1) {
25
+ messages.push({ id: `msg_${msgIndex}`, role: currentRole, content: text.slice(0, 6000), index: msgIndex, kind: 'standard' });
26
+ msgIndex++;
27
+ }
28
+ }
29
+ currentRole = 'user';
30
+ currentContent = [userMatch[1]];
31
+ continue;
32
+ }
33
+ if (!started) continue;
34
+ if (currentRole === 'user' && trimmed && !userMatch) {
35
+ const text = currentContent.join('\n').trim();
36
+ if (text.length > 1) {
37
+ messages.push({ id: `msg_${msgIndex}`, role: 'user', content: text, index: msgIndex, kind: 'standard' });
38
+ msgIndex++;
39
+ }
40
+ currentRole = 'assistant';
41
+ currentContent = [];
42
+ }
43
+ if (!trimmed) continue;
44
+ if (/^[─═╭╮╰╯│]+$/.test(trimmed)) continue;
45
+ if (/^[\u2800-\u28ff]+$/.test(trimmed)) continue;
46
+ if (currentRole) currentContent.push(trimmed);
47
+ }
48
+ if (currentRole && currentContent.length > 0) {
49
+ const text = currentContent.join('\n').trim();
50
+ if (text.length > 1) {
51
+ messages.push({ id: `msg_${msgIndex}`, role: currentRole, content: text.slice(0, 6000), index: msgIndex, kind: 'standard' });
52
+ }
53
+ }
54
+ return messages.length > 50 ? messages.slice(-50) : messages;
55
+ }
56
+
57
+ module.exports = function parseOutput(input) {
58
+ const { buffer, recentBuffer, partialResponse, screenText } = input;
59
+ const transcript = screenText || buffer;
60
+ const tail = recentBuffer || (transcript || '').slice(-500);
61
+ const status = detectStatus({ tail });
62
+ const activeModal = status === 'waiting_approval' ? parseApproval({ buffer: transcript, tail }) : null;
63
+ const messages = splitTurns(transcript);
64
+ if (status === 'generating' && partialResponse && partialResponse.trim().length > 2) {
65
+ messages.push({ id: 'msg_partial', role: 'assistant', content: partialResponse.trim().slice(0, 6000), index: messages.length, kind: 'standard', meta: { streaming: true } });
66
+ }
67
+ return { id: 'cli_session', status, title: 'Codex CLI', messages, activeModal };
68
+ };