@adhdev/daemon-core 0.6.53 → 0.6.56

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 +84 -34
  2. package/dist/index.js +631 -305
  3. package/dist/index.js.map +1 -1
  4. package/package.json +2 -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 +312 -258
  148. package/src/cli-adapters/terminal-screen.ts +95 -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 +306 -62
  152. package/src/providers/acp-provider-instance.ts +1 -1
  153. package/src/providers/cli-provider-instance.ts +23 -9
  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
@@ -0,0 +1,37 @@
1
+ {
2
+ "type": "opencode-cli",
3
+ "name": "OpenCode CLI",
4
+ "category": "cli",
5
+ "aliases": [
6
+ "opencode"
7
+ ],
8
+ "icon": "🤖",
9
+ "displayName": "OpenCode 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
+ },
23
+ "binary": "opencode",
24
+ "spawn": {
25
+ "command": "opencode",
26
+ "args": [],
27
+ "shell": true,
28
+ "env": {}
29
+ },
30
+ "compatibility": [
31
+ {
32
+ "ideVersion": ">=1.3.0",
33
+ "scriptDir": "scripts/1.0"
34
+ }
35
+ ],
36
+ "defaultScriptDir": "scripts/1.0"
37
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * OpenCode CLI — detect_status
3
+ * OpenCode uses a TUI that resembles a chat interface.
4
+ */
5
+ 'use strict';
6
+ module.exports = function detectStatus(input) {
7
+ const { tail } = input;
8
+ if (!tail) return 'idle';
9
+ if (/Allow|Deny|approve|reject/i.test(tail) && /\(y\/n\)|confirm/i.test(tail)) return 'waiting_approval';
10
+ if (/[\u2800-\u28ff]/.test(tail)) return 'generating';
11
+ if (/[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/.test(tail)) return 'generating';
12
+ if (/thinking|generating|processing|running/i.test(tail)) return 'generating';
13
+ if (/esc to (cancel|stop)/i.test(tail)) return 'generating';
14
+ return 'idle';
15
+ };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+ module.exports = function parseApproval(input) {
3
+ const { tail } = input;
4
+ if (!tail) return null;
5
+ const hasApproval = /Allow|approve/i.test(tail) && /Deny|reject/i.test(tail);
6
+ if (!hasApproval && !/\(y\/n\)/i.test(tail)) return null;
7
+ const lines = tail.split('\n').map(l => l.trim()).filter(l => l && !/^[─═╭╮╰╯│]+$/.test(l));
8
+ return { message: lines.slice(-5).join(' ').slice(0, 200) || 'Approval required', buttons: ['Allow', 'Deny'] };
9
+ };
@@ -0,0 +1,48 @@
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
+ const userMatch = trimmed.match(/^[❯›>$]\s+(.+)$/);
13
+ if (userMatch && userMatch[1].length > 1) {
14
+ started = true;
15
+ if (currentRole && currentContent.length > 0) {
16
+ const text = currentContent.join('\n').trim();
17
+ if (text.length > 1) { messages.push({ id: `msg_${msgIndex}`, role: currentRole, content: text.slice(0, 6000), index: msgIndex, kind: 'standard' }); msgIndex++; }
18
+ }
19
+ currentRole = 'user'; currentContent = [userMatch[1]]; continue;
20
+ }
21
+ if (!started) continue;
22
+ if (currentRole === 'user' && trimmed && !userMatch) {
23
+ const text = currentContent.join('\n').trim();
24
+ if (text.length > 1) { messages.push({ id: `msg_${msgIndex}`, role: 'user', content: text, index: msgIndex, kind: 'standard' }); msgIndex++; }
25
+ currentRole = 'assistant'; currentContent = [];
26
+ }
27
+ if (!trimmed || /^[─═╭╮╰╯│]+$/.test(trimmed) || /^[\u2800-\u28ff]+$/.test(trimmed)) continue;
28
+ if (currentRole) currentContent.push(trimmed);
29
+ }
30
+ if (currentRole && currentContent.length > 0) {
31
+ const text = currentContent.join('\n').trim();
32
+ if (text.length > 1) messages.push({ id: `msg_${msgIndex}`, role: currentRole, content: text.slice(0, 6000), index: msgIndex, kind: 'standard' });
33
+ }
34
+ return messages.length > 50 ? messages.slice(-50) : messages;
35
+ }
36
+
37
+ module.exports = function parseOutput(input) {
38
+ const { buffer, recentBuffer, partialResponse, screenText } = input;
39
+ const transcript = screenText || buffer;
40
+ const tail = recentBuffer || (transcript || '').slice(-500);
41
+ const status = detectStatus({ tail });
42
+ const activeModal = status === 'waiting_approval' ? parseApproval({ buffer: transcript, tail }) : null;
43
+ const messages = splitTurns(transcript);
44
+ if (status === 'generating' && partialResponse && partialResponse.trim().length > 2) {
45
+ messages.push({ id: 'msg_partial', role: 'assistant', content: partialResponse.trim().slice(0, 6000), index: messages.length, kind: 'standard', meta: { streaming: true } });
46
+ }
47
+ return { id: 'cli_session', status, title: 'OpenCode CLI', messages, activeModal };
48
+ };
@@ -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; };
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Cline v1 — focus_editor
3
3
  *
4
- * Cline webview iframe 내부의 입력 필드에 포커스.
5
- * send_message 전에 호출하거나, 대시보드 "Focus" 버튼에 사용.
4
+ * Cline webview iframe focus on input field inside.
5
+ * send_message Call before send_message or use for dashboard Focus button.
6
6
  *
7
- * 최종 확인: 2026-03-07
7
+ * final Check: 2026-03-07
8
8
  */
9
9
  (() => {
10
10
  try {
@@ -12,7 +12,7 @@
12
12
  const doc = inner?.contentDocument || inner?.contentWindow?.document;
13
13
  if (!doc) return 'no doc';
14
14
 
15
- // data-testid 우선 → fallback
15
+ // data-testid first → fallback
16
16
  let target = doc.querySelector('[data-testid="chat-input"]');
17
17
  if (!target) {
18
18
  const textareas = doc.querySelectorAll('textarea');
@@ -36,7 +36,7 @@
36
36
  if (!target) return 'no input';
37
37
 
38
38
  target.focus();
39
- // 커서를 끝으로 이동
39
+ // Move cursor to end
40
40
  if (target.tagName === 'TEXTAREA' || target.tagName === 'INPUT') {
41
41
  const len = (target.value || '').length;
42
42
  target.setSelectionRange(len, len);
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Cline v1 — list_chats (Fiber + DOM 이중 접근)
2
+ * Cline v1 — list_chats (Fiber + DOM dual access)
3
3
  *
4
- * 1차: React Fiber에서 taskHistory 배열 추출
5
- * __reactFiber, __reactProps, __reactContainer 모두 탐색
6
- * 2차: Virtuoso DOM 파싱
4
+ * 1st: extract taskHistory array from React Fiber
5
+ * Search all of __reactFiber, __reactProps, __reactContainer
6
+ * 2nd: Virtuoso DOM parsing
7
7
  *
8
- * 반환: JSON 문자열 — [{id, title, status, time, cost, tokensIn, tokensOut, modelId}]
8
+ * Return: JSON string — [{id, title, status, time, cost, tokensIn, tokensOut, modelId}]
9
9
  *
10
- * 최종 확인: 2026-03-07
10
+ * final Check: 2026-03-07
11
11
  */
12
12
  (() => {
13
13
  try {
@@ -15,7 +15,7 @@
15
15
  const doc = inner?.contentDocument || inner?.contentWindow?.document;
16
16
  if (!doc) return JSON.stringify({ error: 'no_doc', panel: 'hidden' });
17
17
 
18
- // Fiber 찾기 helper — __reactFiber, __reactProps, __reactContainer 모두 검색
18
+ // Fiber key search helper — search all __reactFiber, __reactProps, __reactContainer
19
19
  const findFiberKey = (el) => Object.keys(el).find(k =>
20
20
  k.startsWith('__reactFiber') || k.startsWith('__reactProps') || k.startsWith('__reactContainer'));
21
21
 
@@ -23,14 +23,14 @@
23
23
  const fk = findFiberKey(el);
24
24
  if (!fk) return null;
25
25
  let fiber = el[fk];
26
- // __reactContainer 경우 내부 fiber tree root로 접근
26
+ // If __reactContainer, access inner fiber tree root
27
27
  if (fk.startsWith('__reactContainer') && fiber?._internalRoot?.current) {
28
28
  fiber = fiber._internalRoot.current;
29
29
  }
30
30
  return fiber;
31
31
  };
32
32
 
33
- // ─── 1차: Fiber props에서 taskHistory 찾기 ───
33
+ // ─── 1st: search taskHistory from Fiber props ───
34
34
  const allEls = doc.querySelectorAll('*');
35
35
  let taskHistory = null;
36
36
 
@@ -44,7 +44,7 @@
44
44
  taskHistory = props.taskHistory;
45
45
  break;
46
46
  }
47
- // memoizedState 체인에서도 탐색
47
+ // Also search in memoizedState chain
48
48
  if (fiber.memoizedState) {
49
49
  let st = fiber.memoizedState;
50
50
  while (st) {
@@ -82,7 +82,7 @@
82
82
  return JSON.stringify(results);
83
83
  }
84
84
 
85
- // ─── 2차: Virtuoso DOM 파싱 ───
85
+ // ─── 2nd: Virtuoso DOM parsing ───
86
86
  const items = doc.querySelectorAll('[data-item-index]');
87
87
  if (items.length > 0) {
88
88
  const results = Array.from(items).slice(0, 50).map(el => ({
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Cline — list_models
3
- * 드롭다운에서 사용 가능한 모델 목록 + 현재 선택된 모델 반환
3
+ * Available from dropdown Model list + current Select return model
4
4
  * → { models: string[], current: string }
5
5
  */
6
6
  (async () => {
@@ -9,7 +9,7 @@
9
9
  const doc = inner?.contentDocument || inner?.contentWindow?.document;
10
10
  if (!doc) return JSON.stringify({ models: [], current: '', error: 'no doc' });
11
11
 
12
- // 현재 모델: mode-switch 또는 model selector에서 읽기
12
+ // Current model: read from mode-switch or model selector
13
13
  let current = '';
14
14
  const modeSwitch = doc.querySelector('[data-testid="mode-switch"]');
15
15
  if (modeSwitch) current = (modeSwitch.textContent || '').trim();
@@ -18,15 +18,15 @@
18
18
  if (modelSel) current = (modelSel.textContent || '').trim();
19
19
  }
20
20
 
21
- // 드롭다운 트리거 찾기
21
+ // Dropdown trigger search
22
22
  const trigger = doc.querySelector('[data-testid="model-selector"], [data-testid*="model-dropdown"], [data-testid="dropdown-trigger"]');
23
23
  if (!trigger) return JSON.stringify({ models: [], current, error: 'no model trigger' });
24
24
 
25
- // 드롭다운 열기
25
+ // Open dropdown
26
26
  trigger.click();
27
27
  await new Promise(r => setTimeout(r, 300));
28
28
 
29
- // 옵션 수집
29
+ // collect options
30
30
  const options = doc.querySelectorAll('[data-testid*="dropdown-option"], [role="option"], [class*="dropdown"] [class*="item"], [class*="listbox"] [class*="option"]');
31
31
  const models = [];
32
32
  for (const opt of options) {
@@ -34,7 +34,7 @@
34
34
  if (text && text.length > 1 && text.length < 100) models.push(text);
35
35
  }
36
36
 
37
- // 닫기
37
+ // close
38
38
  doc.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
39
39
  if (trigger.click) trigger.click(); // fallback close
40
40
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Cline — list_modes
3
- * 모드 selector에서 사용 가능한 모드 목록 + 현재 모드 반환
3
+ * Available Mode list from mode selector + Return current mode
4
4
  * → { modes: string[], current: string }
5
5
  */
6
6
  (async () => {
@@ -9,16 +9,16 @@
9
9
  const doc = inner?.contentDocument || inner?.contentWindow?.document;
10
10
  if (!doc) return JSON.stringify({ modes: [], current: '', error: 'no doc' });
11
11
 
12
- // 현재 모드
12
+ // Current mode
13
13
  const trigger = doc.querySelector('[data-testid="mode-selector-trigger"], [data-testid="mode-switch"]');
14
14
  if (!trigger) return JSON.stringify({ modes: [], current: '', error: 'no mode trigger' });
15
15
  const current = (trigger.textContent || '').trim();
16
16
 
17
- // 드롭다운 열기
17
+ // Open dropdown
18
18
  trigger.click();
19
19
  await new Promise(r => setTimeout(r, 300));
20
20
 
21
- // 옵션 수집
21
+ // collect options
22
22
  const options = doc.querySelectorAll('[data-testid*="mode-option"], [role="option"], [class*="dropdown"] [class*="item"], [class*="listbox"] [class*="option"]');
23
23
  const modes = [];
24
24
  for (const opt of options) {
@@ -26,7 +26,7 @@
26
26
  if (text && text.length > 1 && text.length < 50) modes.push(text);
27
27
  }
28
28
 
29
- // 닫기
29
+ // close
30
30
  doc.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
31
31
  if (trigger.click) trigger.click(); // fallback close
32
32
 
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Cline v1 — new_session
3
3
  *
4
- * 구조:
5
- * 1. "New Task" 버튼 또는 "+" 버튼 클릭
6
- * 2. data-testid 우선 → aria-label → 텍스트 매칭
4
+ * structure:
5
+ * 1. Click "New Task" button or "+" button
6
+ * 2. data-testid first → aria-label → text matching
7
7
  *
8
- * 최종 확인: 2026-03-07
8
+ * final Check: 2026-03-07
9
9
  */
10
10
  (() => {
11
11
  try {
@@ -16,7 +16,7 @@
16
16
  const buttons = Array.from(doc.querySelectorAll('button'))
17
17
  .filter(b => b.offsetWidth > 0 && b.offsetHeight > 0);
18
18
 
19
- // ─── 1단계: data-testid 기반 ───
19
+ // ─── 1step: data-testid based ───
20
20
  for (const btn of buttons) {
21
21
  const testId = (btn.getAttribute('data-testid') || '').toLowerCase();
22
22
  if (testId.includes('new-task') || testId.includes('new-chat') || testId.includes('new_task')) {
@@ -25,7 +25,7 @@
25
25
  }
26
26
  }
27
27
 
28
- // ─── 2단계: aria-label 기반 ───
28
+ // ─── 2step: Based on aria-label ───
29
29
  for (const btn of buttons) {
30
30
  const ariaLabel = (btn.getAttribute('aria-label') || '').toLowerCase();
31
31
  if (ariaLabel.includes('new task') || ariaLabel.includes('new chat')
@@ -35,7 +35,7 @@
35
35
  }
36
36
  }
37
37
 
38
- // ─── 3단계: 텍스트 매칭 ───
38
+ // ─── 3step: text matching ───
39
39
  for (const btn of buttons) {
40
40
  const text = (btn.textContent || '').trim();
41
41
  if (text === '+' || text.includes('New Task') || text.includes('New Chat')) {
@@ -44,16 +44,16 @@
44
44
  }
45
45
  }
46
46
 
47
- // ─── 4단계: SVG plus 아이콘 버튼 ───
47
+ // ─── Step 4: SVG plus icon button ───
48
48
  for (const btn of buttons) {
49
49
  const svg = btn.querySelector('svg');
50
50
  if (!svg) continue;
51
51
  const path = svg.querySelector('path');
52
52
  if (path) {
53
53
  const d = path.getAttribute('d') || '';
54
- // SVG plus icon 일반적인 path pattern
54
+ // Common SVG plus icon path pattern
55
55
  if (d.includes('M12') && (d.includes('H5') || d.includes('h') || d.includes('v'))) {
56
- // 다른 버튼 텍스트가 없는 아이콘 전용 버튼
56
+ // Icon-only button with no other button text
57
57
  const text = (btn.textContent || '').trim();
58
58
  if (text.length < 3) {
59
59
  btn.click();
@@ -63,13 +63,13 @@
63
63
  }
64
64
  }
65
65
 
66
- // ─── 5단계: 웰컴 화면 감지 (이미 세션) ───
66
+ // ─── Step 5: Welcome screen detect (already New session) ───
67
67
  const bodyText = (doc.body.textContent || '').toLowerCase();
68
68
  if (bodyText.includes('what can i do for you') || bodyText.includes('start a new task') || bodyText.includes('type your task')) {
69
69
  return 'clicked (already new)';
70
70
  }
71
71
 
72
- // ─── 6단계: History 감지Done 클릭으로 웰컴 복귀 ───
72
+ // ─── Step 6: History view detectreturn to welcome by clicking Done ───
73
73
  if (bodyText.includes('history') && bodyText.includes('done')) {
74
74
  for (const btn of buttons) {
75
75
  const text = (btn.textContent || '').trim();
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * Cline v1 — open_panel
3
3
  *
4
- * 패널 상태 확인 열기 시도.
4
+ * Check panel status and attempt to open.
5
5
  *
6
- * iframe 컨텍스트에서는 VS Code API 접근이 제한적이므로,
7
- * 패널이 숨겨져 있을 때는 'panel_hidden' 상태를 반환.
8
- * → daemon AgentStreamManager 또는
9
- * agent_stream_focus 메시지를 통해 열어야 함.
6
+ * VS Code API access is limited from iframe context,
7
+ * When panel is hidden 'panel_hidden' Return status.
8
+ * → daemon AgentStreamManager or
9
+ * agent_stream_focus must be opened via message.
10
10
  *
11
- * 반환: 'visible' | 'panel_hidden'
12
- * 최종 확인: 2026-03-07
11
+ * Return: 'visible' | 'panel_hidden'
12
+ * final Check: 2026-03-07
13
13
  */
14
14
  (() => {
15
15
  try {
@@ -1,18 +1,18 @@
1
1
  /**
2
- * Cline v1 — read_chat (v2 — Fiber 기반 역할 판별)
2
+ * Cline v1 — read_chat (v2 — Fiber based Determine role)
3
3
  *
4
- * 구조 (Cline 3.x — saoudrizwan.claude-dev):
4
+ * structure (Cline 3.x — saoudrizwan.claude-dev):
5
5
  * 1. outer webview iframe → inner contentDocument
6
- * 2. data-testid="virtuoso-item-list" (React Virtuoso) — 활성 메시지 블록
7
- * 3. React Fiber → data 배열에서 메시지 타입 직접 추출
6
+ * 2. data-testid="virtuoso-item-list" (React Virtuoso) — active message blocks
7
+ * 3. React Fiber → extract message type directly from data array
8
8
  * - type: "say", say: "user_feedback" → user
9
9
  * - type: "say", say: "text" → assistant
10
10
  * - type: "say", say: "checkpoint_created" → system (skip)
11
- * - type: "ask", ask: "followup" → assistant (질문)
12
- * - type: "ask", ask: "tool" → assistant (tool 승인 대기)
13
- * 4. DOM textContent에서 콘텐츠 추출 + 정제
11
+ * - type: "ask", ask: "followup" → assistant (question)
12
+ * - type: "ask", ask: "tool" → assistant (tool approval wait)
13
+ * 4. Extract content from DOM textContent + sanitize
14
14
  *
15
- * 최종 확인: 2026-03-07
15
+ * final Check: 2026-03-07
16
16
  */
17
17
  (() => {
18
18
  try {
@@ -26,7 +26,7 @@
26
26
 
27
27
  const isVisible = root.offsetHeight > 0;
28
28
 
29
- // ─── 1. Fiber에서 data 배열 추출 ───
29
+ // ─── 1. Extract data array from Fiber ───
30
30
  const virtuosoList = doc.querySelector('[data-testid="virtuoso-item-list"]');
31
31
  let fiberData = null;
32
32
 
@@ -48,11 +48,11 @@
48
48
  }
49
49
  }
50
50
 
51
- // ─── 2. 메시지 파싱 ───
51
+ // ─── 2. Message parsing ───
52
52
  const messages = [];
53
53
 
54
54
  if (fiberData) {
55
- // ★ Fiber 기반: 가장 정확한 역할 판별
55
+ // ★ Fiber based: most accurate Determine role
56
56
  for (let i = 0; i < fiberData.length; i++) {
57
57
  const item = fiberData[i];
58
58
  if (!item || typeof item !== 'object') continue;
@@ -62,20 +62,20 @@
62
62
  const askSub = item.ask; // "followup", "tool", "command", etc.
63
63
  const text = item.text || '';
64
64
 
65
- // 시스템 이벤트 스킵
65
+ // Skip system events
66
66
  if (saySub === 'checkpoint_created') continue;
67
67
  if (saySub === 'api_req_started' || saySub === 'api_req_finished') continue;
68
68
  if (saySub === 'shell_integration_warning') continue;
69
69
 
70
- // 역할 판별
70
+ // Determine role
71
71
  let role = 'assistant';
72
72
  if (saySub === 'user_feedback') role = 'user';
73
73
  if (saySub === 'user_feedback_diff') role = 'user';
74
74
 
75
- // 콘텐츠 추출
75
+ // Extract content
76
76
  let content = '';
77
77
  if (text) {
78
- // ask.followup text JSON일 있음
78
+ // ask.followup text may be JSON
79
79
  if (askSub === 'followup' && text.startsWith('{')) {
80
80
  try {
81
81
  const parsed = JSON.parse(text);
@@ -86,15 +86,15 @@
86
86
  }
87
87
  }
88
88
 
89
- // DOM 텍스트 fallback (Fiber text 비어있을 )
89
+ // DOM text fallback (when Fiber text is empty)
90
90
  if (!content && virtuosoList && virtuosoList.children[i]) {
91
91
  content = (virtuosoList.children[i].textContent || '').trim();
92
92
  }
93
93
 
94
- // 너무 짧거나 콘텐츠 스킵
94
+ // Skip too short or empty content
95
95
  if (!content || content.length < 2) continue;
96
96
 
97
- // 노이즈 정리
97
+ // Clean noise
98
98
  content = content
99
99
  .replace(/CheckpointCompareRestore(Save)?/gi, '')
100
100
  .replace(/^\s*API Request.*$/gm, '')
@@ -104,7 +104,7 @@
104
104
 
105
105
  if (content.length < 2) continue;
106
106
 
107
- // 코드 블록 보존 (DOM에서 구조 추출)
107
+ // Preserve code blocks (extract structure from DOM)
108
108
  if (virtuosoList.children[i]) {
109
109
  const domItem = virtuosoList.children[i];
110
110
  const preBlocks = domItem.querySelectorAll('pre');
@@ -147,20 +147,20 @@
147
147
  }
148
148
  }
149
149
 
150
- // 길이 제한
150
+ // Length limit
151
151
  if (content.length > 2000) content = content.substring(0, 2000) + '…';
152
152
 
153
153
  messages.push({
154
154
  role,
155
155
  content,
156
156
  timestamp: item.ts || (Date.now() - (fiberData.length - i) * 1000),
157
- // 디버그: 메시지 서브타입
157
+ // Debug: Message subtype
158
158
  _type: msgType,
159
159
  _sub: saySub || askSub,
160
160
  });
161
161
  }
162
162
  } else if (virtuosoList && virtuosoList.children.length > 0) {
163
- // Fallback: DOM 기반 파싱 (Fiber 접근 실패 )
163
+ // Fallback: DOM based parsing (Fiber on access failure)
164
164
  for (let i = 0; i < virtuosoList.children.length; i++) {
165
165
  const item = virtuosoList.children[i];
166
166
  const rawText = (item.textContent || '').trim();
@@ -180,14 +180,14 @@
180
180
  }
181
181
  }
182
182
 
183
- // ─── 3. 입력 필드 ───
183
+ // ─── 3. Input field ───
184
184
  let inputContent = '';
185
185
  const chatInput = doc.querySelector('[data-testid="chat-input"]');
186
186
  if (chatInput) {
187
187
  inputContent = chatInput.value || chatInput.textContent || '';
188
188
  }
189
189
 
190
- // ─── 4. 상태 판별 ───
190
+ // ─── 4. Status determination ───
191
191
  let status = 'idle';
192
192
  const buttons = Array.from(doc.querySelectorAll('button'))
193
193
  .filter(b => b.offsetWidth > 0);
@@ -195,7 +195,7 @@
195
195
 
196
196
  if (buttonTexts.includes('cancel')) status = 'generating';
197
197
 
198
- // Fiber data에서 마지막 type=ask인지 확인
198
+ // Fiber datafrom last type=ask Check
199
199
  if (fiberData && fiberData.length > 0) {
200
200
  const last = fiberData[fiberData.length - 1];
201
201
  if (last.type === 'ask') {
@@ -204,13 +204,13 @@
204
204
  }
205
205
  }
206
206
 
207
- // 버튼 기반 보완
207
+ // button based complement
208
208
  const approvalPatterns = /^(proceed|approve|allow|accept|save|run command|yes|confirm)/i;
209
209
  if (buttonTexts.some(b => approvalPatterns.test(b))) status = 'waiting_approval';
210
210
 
211
211
  if (!isVisible && messages.length === 0) status = 'panel_hidden';
212
212
 
213
- // ─── 5. 모델/모드 ───
213
+ // ─── 5. model/mode ───
214
214
  let model = '';
215
215
  const modeSwitch = doc.querySelector('[data-testid="mode-switch"]');
216
216
  if (modeSwitch) model = (modeSwitch.textContent || '').trim();
@@ -220,7 +220,7 @@
220
220
  }
221
221
  const mode = modeSwitch ? (modeSwitch.textContent || '').trim() : '';
222
222
 
223
- // ─── 6. 승인 모달 ───
223
+ // ─── 6. Approval modal ───
224
224
  let activeModal = null;
225
225
  if (status === 'waiting_approval') {
226
226
  const approvalBtns = buttons
@@ -246,7 +246,7 @@
246
246
  }
247
247
  }
248
248
 
249
- // ─── 7. 토큰/비용 ───
249
+ // ─── 7. Token/Cost ───
250
250
  let tokenInfo = '';
251
251
  const costEl = doc.querySelector('[data-testid*="cost"], [data-testid*="token"]');
252
252
  if (costEl) tokenInfo = (costEl.textContent || '').trim();