@adhdev/daemon-core 0.6.52 → 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 +77 -35
  2. package/dist/index.js +717 -275
  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 +6 -6
  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
@@ -1,29 +1,104 @@
1
1
  /**
2
- * PearAI — send_message
3
- *
4
- * PearAI의 채팅 입력은 webview iframe 안에 있어 메인 DOM에서 직접 접근 불가.
5
- * auxbar 하단의 입력 필드 좌표를 계산하여 clickCoords로 반환.
6
- * 데몬이 CDP Input API로 해당 좌표에 클릭+타이핑+Enter를 수행.
7
- *
8
- * 파라미터: ${ MESSAGE }
2
+ * PearAI — webview_send_message
9
3
  */
10
- (() => {
4
+ (async () => {
11
5
  try {
12
- const auxbar = document.getElementById('workbench.parts.auxiliarybar');
13
- if (!auxbar || auxbar.offsetWidth === 0) {
14
- return JSON.stringify({ sent: false, error: 'auxbar not found' });
6
+ const message = ${ MESSAGE };
7
+ const editor = document.querySelector('textarea[placeholder*="Type your task" i]')
8
+ || document.querySelector('textarea')
9
+ || document.querySelector('[contenteditable="true"]');
10
+
11
+ if (!editor) {
12
+ return JSON.stringify({ sent: false, error: 'input not found' });
13
+ }
14
+
15
+ editor.scrollIntoView({ block: 'center' });
16
+ editor.focus();
17
+ await new Promise((resolve) => setTimeout(resolve, 100));
18
+
19
+ const isTextarea = editor.tagName === 'TEXTAREA';
20
+ if (isTextarea) {
21
+ const previousValue = editor.value;
22
+ const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')?.set;
23
+ if (nativeSetter) nativeSetter.call(editor, message);
24
+ else editor.value = message;
25
+ if (editor._valueTracker) {
26
+ editor._valueTracker.setValue(previousValue);
27
+ }
28
+ editor.dispatchEvent(new Event('input', {
29
+ bubbles: true,
30
+ cancelable: true,
31
+ composed: true,
32
+ }));
33
+ editor.dispatchEvent(new Event('change', { bubbles: true }));
34
+
35
+ if ((editor.value || '') !== message) {
36
+ editor.value = '';
37
+ editor.setSelectionRange?.(0, 0);
38
+ editor.setRangeText?.(message, 0, editor.value.length, 'end');
39
+ editor.dispatchEvent(new Event('input', { bubbles: true, cancelable: true, composed: true }));
40
+ editor.dispatchEvent(new Event('change', { bubbles: true }));
41
+ }
42
+
43
+ if ((editor.value || '') !== message) {
44
+ editor.focus();
45
+ editor.select?.();
46
+ document.execCommand?.('insertText', false, message);
47
+ editor.dispatchEvent(new Event('input', { bubbles: true, cancelable: true, composed: true }));
48
+ editor.dispatchEvent(new Event('change', { bubbles: true }));
49
+ }
50
+ } else {
51
+ const selection = window.getSelection();
52
+ const range = document.createRange();
53
+ range.selectNodeContents(editor);
54
+ selection.removeAllRanges();
55
+ selection.addRange(range);
56
+ document.execCommand('delete', false, null);
57
+ document.execCommand('insertText', false, message);
58
+ editor.dispatchEvent(new InputEvent('input', {
59
+ bubbles: true,
60
+ cancelable: true,
61
+ composed: true,
62
+ data: message,
63
+ inputType: 'insertText',
64
+ }));
15
65
  }
16
66
 
17
- const rect = auxbar.getBoundingClientRect();
18
- const x = Math.round(rect.x + rect.width / 2);
19
- const y = Math.round(rect.y + rect.height - 80);
20
-
21
- return JSON.stringify({
22
- sent: false,
23
- needsTypeAndSend: true,
24
- clickCoords: { x, y },
25
- });
26
- } catch (e) {
27
- return JSON.stringify({ sent: false, error: e.message });
67
+ await new Promise((resolve) => setTimeout(resolve, 350));
68
+
69
+ const sendButton = Array.from(document.querySelectorAll('button'))
70
+ .find((button) => /send/i.test((button.textContent || '').trim()) && !button.disabled);
71
+
72
+ if (sendButton) {
73
+ sendButton.scrollIntoView({ block: 'center' });
74
+ sendButton.focus?.();
75
+ for (const type of ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click']) {
76
+ sendButton.dispatchEvent(new PointerEvent(type, {
77
+ bubbles: true,
78
+ cancelable: true,
79
+ view: window,
80
+ pointerId: 1,
81
+ pointerType: 'mouse',
82
+ }));
83
+ }
84
+ }
85
+
86
+ const enterOptions = {
87
+ key: 'Enter',
88
+ code: 'Enter',
89
+ keyCode: 13,
90
+ which: 13,
91
+ bubbles: true,
92
+ cancelable: true,
93
+ composed: true,
94
+ };
95
+
96
+ editor.dispatchEvent(new KeyboardEvent('keydown', enterOptions));
97
+ editor.dispatchEvent(new KeyboardEvent('keypress', enterOptions));
98
+ editor.dispatchEvent(new KeyboardEvent('keyup', enterOptions));
99
+
100
+ return JSON.stringify({ sent: true });
101
+ } catch (error) {
102
+ return JSON.stringify({ sent: false, error: String(error && error.message || error) });
28
103
  }
29
104
  })()
@@ -0,0 +1,51 @@
1
+ /**
2
+ * PearAI — webview_set_mode
3
+ * ${ MODE }
4
+ */
5
+ (async () => {
6
+ try {
7
+ const target = String(${ MODE }).trim().toLowerCase();
8
+ const knownModes = ['💻 code', '🏗️ architect', '❓ ask', '🪲 debug', 'code', 'architect', 'ask', 'debug'];
9
+ const trigger = Array.from(document.querySelectorAll('button[data-testid="dropdown-trigger"], button[title], button'))
10
+ .find((button) => /select mode for interaction/i.test(button.getAttribute('title') || ''));
11
+
12
+ if (!trigger) {
13
+ return JSON.stringify({ success: false, error: 'mode trigger not found' });
14
+ }
15
+
16
+ trigger.click();
17
+ await new Promise((resolve) => setTimeout(resolve, 250));
18
+
19
+ const options = Array.from(document.querySelectorAll('[role="option"], [cmdk-item], [data-radix-collection-item], button, div, span'))
20
+ .filter((node) => {
21
+ const rect = node.getBoundingClientRect();
22
+ const text = (node.textContent || '').trim();
23
+ return node !== trigger
24
+ && !trigger.contains(node)
25
+ && rect.width > 0
26
+ && rect.height > 0
27
+ && text
28
+ && text.length < 40;
29
+ });
30
+
31
+ const match = options.find((node) => {
32
+ const text = (node.textContent || '').trim().toLowerCase();
33
+ return knownModes.includes(text) && (text === target || text.includes(target));
34
+ });
35
+
36
+ if (!match) {
37
+ const current = (trigger.textContent || '').trim();
38
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
39
+ if (current.toLowerCase() === target || current.toLowerCase().includes(target)) {
40
+ return JSON.stringify({ success: true, mode: current });
41
+ }
42
+ return JSON.stringify({ success: false, error: 'mode not found: ' + target });
43
+ }
44
+
45
+ match.click();
46
+ await new Promise((resolve) => setTimeout(resolve, 200));
47
+ return JSON.stringify({ success: true, mode: (match.textContent || '').trim() });
48
+ } catch (error) {
49
+ return JSON.stringify({ success: false, error: String(error && error.message || error) });
50
+ }
51
+ })()
@@ -0,0 +1,54 @@
1
+ /**
2
+ * PearAI — webview_set_model
3
+ * ${ MODEL }
4
+ */
5
+ (async () => {
6
+ try {
7
+ const target = String(${ MODEL }).trim().toLowerCase();
8
+ const knownModelPattern = /default|gpt|claude|gemini|sonnet|haiku|o1|o3|4\.1|3\.7/i;
9
+ const trigger = Array.from(document.querySelectorAll('button[data-testid="dropdown-trigger"], button[title], button'))
10
+ .find((button) => /select api configuration/i.test(button.getAttribute('title') || ''));
11
+
12
+ if (!trigger) {
13
+ return JSON.stringify({ success: false, error: 'model trigger not found' });
14
+ }
15
+
16
+ trigger.click();
17
+ await new Promise((resolve) => setTimeout(resolve, 250));
18
+
19
+ const options = Array.from(document.querySelectorAll('[role="option"], [cmdk-item], [data-radix-collection-item], button, div, span'))
20
+ .filter((node) => {
21
+ const rect = node.getBoundingClientRect();
22
+ const text = (node.textContent || '').trim();
23
+ return node !== trigger
24
+ && !trigger.contains(node)
25
+ && rect.width > 0
26
+ && rect.height > 0
27
+ && text
28
+ && text.length < 80
29
+ && !node.querySelector('textarea')
30
+ && node.querySelectorAll('button').length === 0
31
+ && node.children.length <= 2;
32
+ });
33
+
34
+ const match = options.find((node) => {
35
+ const text = (node.textContent || '').trim().toLowerCase();
36
+ return knownModelPattern.test(text) && (text === target || text.includes(target));
37
+ });
38
+
39
+ if (!match) {
40
+ const current = (trigger.textContent || '').trim();
41
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
42
+ if (current.toLowerCase() === target || current.toLowerCase().includes(target)) {
43
+ return JSON.stringify({ success: true, model: current });
44
+ }
45
+ return JSON.stringify({ success: false, error: 'model not found: ' + target });
46
+ }
47
+
48
+ match.click();
49
+ await new Promise((resolve) => setTimeout(resolve, 200));
50
+ return JSON.stringify({ success: true, model: (match.textContent || '').trim() });
51
+ } catch (error) {
52
+ return JSON.stringify({ success: false, error: String(error && error.message || error) });
53
+ }
54
+ })()
@@ -0,0 +1,81 @@
1
+ /**
2
+ * PearAI — webview_switch_session
3
+ * ${ INDEX }
4
+ * ${ TITLE }
5
+ */
6
+ (() => {
7
+ try {
8
+ const targetIndex = Number(${ INDEX });
9
+ const targetTitle = String(${ TITLE }).trim().toLowerCase();
10
+
11
+ const clickElement = (element) => {
12
+ if (!element) return false;
13
+ const rect = element.getBoundingClientRect();
14
+ const x = rect.left + rect.width / 2;
15
+ const y = rect.top + rect.height / 2;
16
+ element.scrollIntoView({ block: 'center' });
17
+ element.focus?.();
18
+ element.click?.();
19
+ for (const type of ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click']) {
20
+ element.dispatchEvent(new PointerEvent(type, {
21
+ bubbles: true,
22
+ cancelable: true,
23
+ view: window,
24
+ clientX: x,
25
+ clientY: y,
26
+ pointerId: 1,
27
+ pointerType: 'mouse',
28
+ }));
29
+ }
30
+ return true;
31
+ };
32
+
33
+ const taskItems = Array.from(document.querySelectorAll('[data-testid^="task-item-"]'));
34
+ if (taskItems.length) {
35
+ let match = null;
36
+ if (targetTitle) {
37
+ match = taskItems.find((item) => (item.textContent || '').trim().toLowerCase().includes(targetTitle));
38
+ }
39
+ if (!match && Number.isInteger(targetIndex) && targetIndex >= 0 && targetIndex < taskItems.length) {
40
+ match = taskItems[targetIndex];
41
+ }
42
+ if (match && clickElement(match)) {
43
+ return JSON.stringify({ switched: true, title: (match.textContent || '').trim().slice(0, 120) });
44
+ }
45
+ }
46
+
47
+ const cards = Array.from(document.querySelectorAll('div')).filter((card) => {
48
+ const className = String(card.className || '');
49
+ const text = (card.textContent || '').trim();
50
+ return className.includes('bg-vscode-editor-background')
51
+ && className.includes('cursor-pointer')
52
+ && className.includes('overflow-hidden')
53
+ && !!card.querySelector('[data-testid="copy-prompt-button"]')
54
+ && /↑\s*\d|↓\s*\d/i.test(text)
55
+ && /MARCH|APRIL|MAY|JUNE|JULY|AUGUST|SEPTEMBER|OCTOBER|NOVEMBER|DECEMBER|JANUARY|FEBRUARY/i.test(text);
56
+ });
57
+
58
+ let match = null;
59
+ if (targetTitle) {
60
+ match = cards.find((card) => {
61
+ const promptText = (card.querySelector('.text-vscode-foreground')?.textContent || '').trim().toLowerCase();
62
+ return promptText.includes(targetTitle);
63
+ });
64
+ }
65
+ if (!match && Number.isInteger(targetIndex) && targetIndex >= 0 && targetIndex < cards.length) {
66
+ match = cards[targetIndex];
67
+ }
68
+ if (!match && cards.length === 1) {
69
+ match = cards[0];
70
+ }
71
+
72
+ const clickTarget = match ? (match.querySelector('.text-vscode-foreground') || match) : null;
73
+ if (clickTarget && clickElement(clickTarget)) {
74
+ return JSON.stringify({ switched: true, title: (match.textContent || '').trim().slice(0, 120) });
75
+ }
76
+
77
+ return JSON.stringify({ switched: false, error: 'session not found' });
78
+ } catch (error) {
79
+ return JSON.stringify({ switched: false, error: String(error && error.message || error) });
80
+ }
81
+ })()
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Cursor v1 — focus_editor
3
3
  *
4
- * CURSOR.md 4-5: 셀렉터 우선순위
4
+ * CURSOR.md 4-5: Selector priority
5
5
  * [contenteditable="true"][role="textbox"]
6
6
  * → .chat-input textarea
7
7
  * → .composer-input
8
8
  * → textarea
9
9
  *
10
- * 최종 확인: 2026-03-06
10
+ * final Check: 2026-03-06
11
11
  */
12
12
  (() => {
13
13
  const editor = document.querySelector('[contenteditable="true"][role="textbox"]')
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Trae — list_chats
3
3
  *
4
- * Trae 메인 DOM에서 / 세션 목록 가져오기.
4
+ * Trae from main DOM / Session list get.
5
5
  */
6
6
  (() => {
7
7
  try {
@@ -16,7 +16,7 @@
16
16
  return { id: String(i), title, active };
17
17
  });
18
18
 
19
- // 목록이 보이지 않으면 사이드바의 히스토리 버튼 확인
19
+ // list history button Check
20
20
  return JSON.stringify({ sessions });
21
21
  } catch (e) {
22
22
  return JSON.stringify({ error: e.message, sessions: [] });
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Trae — new_session
3
3
  *
4
- * "New Task" 생성 (⌃⌘N 단축키 또는 버튼 클릭).
5
- * Trae 메인 DOM에서 접근 가능.
4
+ * "New Task" create (⌃⌘N shortcut or button click).
5
+ * Trae from main DOM accessible.
6
6
  */
7
7
  (() => {
8
8
  try {
9
- // 버튼 찾기
9
+ // button search
10
10
  const buttons = document.querySelectorAll('button, [role="button"], .action-item a');
11
11
  for (const btn of buttons) {
12
12
  const text = (btn.textContent || '').trim();
@@ -17,7 +17,7 @@
17
17
  }
18
18
  }
19
19
 
20
- // 단축키 폴백: ⌃⌘N
20
+ // shortcut fallback: ⌃⌘N
21
21
  document.dispatchEvent(new KeyboardEvent('keydown', {
22
22
  key: 'n', code: 'KeyN', keyCode: 78,
23
23
  metaKey: true, ctrlKey: true,
@@ -1,20 +1,20 @@
1
1
  /**
2
2
  * Trae — open_panel
3
3
  *
4
- * Trae AI 채팅 패널 열기.
5
- * "TRAE" 버튼 또는 ⌘L 단축키로 열기.
4
+ * Trae AI chat panel open.
5
+ * "TRAE" button or ⌘L via shortcut open.
6
6
  *
7
- * 반환: 'visible' | 'opened' | 'error: ...'
7
+ * Return: 'visible' | 'opened' | 'error: ...'
8
8
  */
9
9
  (() => {
10
10
  try {
11
- // 1. 이미 열려 있는지 확인
11
+ // 1. if already open Check
12
12
  const sidebar = document.getElementById('workbench.parts.auxiliarybar');
13
13
  if (sidebar && sidebar.offsetWidth > 0 && sidebar.offsetHeight > 0) {
14
14
  return 'visible';
15
15
  }
16
16
 
17
- // 2. "TRAE" 버튼 클릭 시도
17
+ // 2. "TRAE" button click
18
18
  const toggleBtns = Array.from(document.querySelectorAll('li.action-item a, button, [role="button"]'));
19
19
  for (const btn of toggleBtns) {
20
20
  const label = (btn.getAttribute('aria-label') || '');
@@ -25,7 +25,7 @@
25
25
  }
26
26
  }
27
27
 
28
- // 3. Cmd+L 단축키 폴백 (Trae 기본 단축키)
28
+ // 3. Cmd+L shortcut fallback (Trae default shortcut)
29
29
  document.dispatchEvent(new KeyboardEvent('keydown', {
30
30
  key: 'l', code: 'KeyL', keyCode: 76,
31
31
  metaKey: true, ctrlKey: false,
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Trae — read_chat
3
3
  *
4
- * Trae 메인 DOM에서 직접 채팅 내용에 접근 가능.
5
- * 채팅 턴은 .chat-turn 요소로 구분.
6
- * 유저: .user-chat-bubble-request__content-wrapper
7
- * 어시스턴트: .assistant-chat-turn-content .chat-markdown
4
+ * Trae from main DOM chat content accessible.
5
+ * chat is .chat-turn element .
6
+ * : .user-chat-bubble-request__content-wrapper
7
+ * : .assistant-chat-turn-content .chat-markdown
8
8
  *
9
- * 반환: ReadChatResult { id, status, messages, title?, inputContent?, activeModal? }
9
+ * Return: ReadChatResult { id, status, messages, title?, inputContent?, activeModal? }
10
10
  */
11
11
  (() => {
12
12
  try {
@@ -15,7 +15,7 @@
15
15
  return JSON.stringify({ id: '', status: 'idle', messages: [] });
16
16
  }
17
17
 
18
- // ─── 1. 메시지 수집 ───
18
+ // ─── 1. Collect messages ───
19
19
  const messages = [];
20
20
  const turns = auxbar.querySelectorAll('.chat-turn');
21
21
 
@@ -50,22 +50,22 @@
50
50
  }
51
51
  });
52
52
 
53
- // ─── 2. 상태 감지 ───
53
+ // ─── 2. status detection ───
54
54
  let status = 'idle';
55
55
 
56
- // Stop 버튼 존재 → generating
56
+ // Stop button exists → generating
57
57
  const stopBtn = auxbar.querySelector('button[class*="stop"], [aria-label*="stop" i], [aria-label*="Stop"]');
58
58
  if (stopBtn && stopBtn.offsetWidth > 0) {
59
59
  status = 'generating';
60
60
  }
61
61
 
62
- // progress bar 활성 → generating
62
+ // progress bar → generating
63
63
  const progress = auxbar.querySelector('.monaco-progress-container:not(.done)');
64
64
  if (progress && progress.offsetWidth > 0) {
65
65
  status = 'generating';
66
66
  }
67
67
 
68
- // latest-assistant-bar 가장 정확한 상태 표시 (최종 판정)
68
+ // latest-assistant-bar most accurate (final determination)
69
69
  const latestBar = auxbar.querySelector('.latest-assistant-bar');
70
70
  if (latestBar) {
71
71
  const barText = latestBar.textContent.toLowerCase();
@@ -76,7 +76,7 @@
76
76
  }
77
77
  }
78
78
 
79
- // ─── 3. 승인 대기 모달 ───
79
+ // ─── 3. approval wait modal ───
80
80
  let activeModal = null;
81
81
  const dialogs = auxbar.querySelectorAll('[role="dialog"], .monaco-dialog-box, [class*="approval"], [class*="confirm"]');
82
82
  if (dialogs.length > 0) {
@@ -91,11 +91,11 @@
91
91
  }
92
92
  }
93
93
 
94
- // ─── 4. 입력 필드 내용 ───
94
+ // ─── 4. Input field content ───
95
95
  const input = auxbar.querySelector('.chat-input-v2-input-box-editable, [contenteditable="true"]');
96
96
  const inputContent = input ? input.textContent.trim() : '';
97
97
 
98
- // ─── 5. 세션 ID / 타이틀 ───
98
+ // ─── 5. Session ID / Title ───
99
99
  const sessionTab = auxbar.querySelector('[class*="session-tab"], [class*="chat-title"]');
100
100
  const title = sessionTab ? sessionTab.textContent.trim() : '';
101
101
 
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Trae — resolve_action
3
3
  *
4
- * 승인/거부 버튼 찾기 + 좌표 반환.
5
- * Trae의 approval 다이얼로그는 메인 DOM에 표시됨.
4
+ * Find approve/reject buttons + coordinates Return.
5
+ * Traeapproval dialog is displayed in main DOM.
6
6
  *
7
- * 파라미터: ${ BUTTON_TEXT }
7
+ * Parameter: ${ BUTTON_TEXT }
8
8
  */
9
9
  (() => {
10
10
  const want = ${ BUTTON_TEXT };
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * Trae — send_message
3
3
  *
4
- * Trae .chat-input-v2-input-box-editable (contenteditable / Lexical) 사용.
5
- * Lexical 내부 state 올바르게 업데이트하기 위해 Selection API + execCommand 사용.
4
+ * Trae .chat-input-v2-input-box-editable (contenteditable / Lexical) use.
5
+ * Lexical inside state to correctly update Selection API + execCommand use.
6
6
  *
7
- * 파라미터: ${ MESSAGE }
7
+ * Parameter: ${ MESSAGE }
8
8
  */
9
9
  (async () => {
10
10
  try {
11
11
  const msg = ${ MESSAGE };
12
12
 
13
- // ─── 1. 입력 필드 찾기 ───
13
+ // ─── 1. Find input field ───
14
14
  const editor =
15
15
  document.querySelector('.chat-input-v2-input-box-editable') ||
16
16
  document.querySelector('[contenteditable="true"][role="textbox"]') ||
@@ -18,11 +18,11 @@
18
18
 
19
19
  if (!editor) return JSON.stringify({ sent: false, error: 'no input found' });
20
20
 
21
- // ─── 2. 포커스 + 전체 선택 + 삭제 + 삽입 ───
21
+ // ─── 2. focus + all Select + delete + insert ───
22
22
  editor.focus();
23
23
  await new Promise(r => setTimeout(r, 100));
24
24
 
25
- // Selection API 전체 선택
25
+ // Selection API all Select
26
26
  const sel = window.getSelection();
27
27
  const range = document.createRange();
28
28
  range.selectNodeContents(editor);
@@ -30,23 +30,23 @@
30
30
  sel.addRange(range);
31
31
  await new Promise(r => setTimeout(r, 50));
32
32
 
33
- // 삭제 삽입 (Lexical state 동기화)
33
+ // Delete and insert (sync Lexical state)
34
34
  document.execCommand('delete', false, null);
35
35
  await new Promise(r => setTimeout(r, 50));
36
36
  document.execCommand('insertText', false, msg);
37
37
 
38
- // Input 이벤트
38
+ // Input event
39
39
  editor.dispatchEvent(new Event('input', { bubbles: true }));
40
40
  await new Promise(r => setTimeout(r, 500));
41
41
 
42
- // ─── 3. send 버튼 클릭 ───
42
+ // ─── 3. send button click ───
43
43
  const sendBtn = document.querySelector('.chat-input-v2-send-button');
44
44
  if (sendBtn && !sendBtn.disabled) {
45
45
  sendBtn.click();
46
46
  return JSON.stringify({ sent: true, method: 'button' });
47
47
  }
48
48
 
49
- // 버튼이 아직 disabled이면 Enter 키 시도
49
+ // button If still disabled, try Enter key
50
50
  const enterOpts = {
51
51
  key: 'Enter', code: 'Enter',
52
52
  keyCode: 13, which: 13,
@@ -57,7 +57,7 @@
57
57
  editor.dispatchEvent(new KeyboardEvent('keypress', enterOpts));
58
58
  editor.dispatchEvent(new KeyboardEvent('keyup', enterOpts));
59
59
 
60
- // 여전히 되면 needsTypeAndSend 폴백
60
+ // If still fails needsTypeAndSend fallback
61
61
  return JSON.stringify({
62
62
  sent: false,
63
63
  needsTypeAndSend: true,
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Trae — switch_session
3
3
  *
4
- * Trae 세션 전환.
5
- * 파라미터: ${ SESSION_ID }
4
+ * Trae Switch session tab.
5
+ * Parameter: ${ SESSION_ID }
6
6
  */
7
7
  (() => {
8
8
  try {
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * Windsurf v1 — focus_editor
3
3
  *
4
- * Cascade(채팅) 입력창에 포커스를 맞춥니다.
5
- * Windsurf VS Code 포크로, 채팅 UI "Cascade"라고 부릅니다.
4
+ * Cascade(chat) focus on input field.
5
+ * Windsurf VS Code fork, chat UI "Cascade"is called.
6
6
  *
7
- * DOM 구조:
7
+ * DOM structure:
8
8
  * #windsurf.cascadePanel → .chat-client-root
9
- * 입력: [contenteditable="true"][role="textbox"]
10
- * 또는 textarea (미로그인)
9
+ * input: [contenteditable="true"][role="textbox"]
10
+ * or textarea ()
11
11
  *
12
- * 최종 확인: Windsurf (2026-03-06)
12
+ * final Check: Windsurf (2026-03-06)
13
13
  */
14
14
  (() => {
15
15
  try {
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Windsurf v1 — list_chats
3
3
  *
4
- * Cascade 목록을 가져옵니다.
5
- * 패널이 닫혀 있으면 먼저 열고 탭이 렌더링될 때까지 대기합니다.
6
- * cascade-tab-{uuid} 요소들의 React Fiber에서 제목을 추출합니다.
4
+ * Cascade get tab list.
5
+ * If panel is closed open first and wait until tab is rendered.
6
+ * cascade-tab-{uuid} element React Fiberfrom title extract.
7
7
  *
8
- * 최종 확인: Windsurf 1.108.x (2026-03-10)
8
+ * final Check: Windsurf 1.108.x (2026-03-10)
9
9
  */
10
10
  (async () => {
11
11
  try {