@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
@@ -1866,6 +1866,51 @@ export class DevServer {
1866
1866
 
1867
1867
  // ─── Phase 2: Auto-Implement Backend ───
1868
1868
 
1869
+ private getDefaultAutoImplReference(category: string, type: string): string {
1870
+ if (category === 'cli') {
1871
+ return type === 'codex-cli' ? 'claude-cli' : 'codex-cli';
1872
+ }
1873
+ return 'antigravity';
1874
+ }
1875
+
1876
+ private resolveAutoImplReference(category: string, requestedReference: string | undefined, targetType: string): string | null {
1877
+ const desired = requestedReference || this.getDefaultAutoImplReference(category, targetType);
1878
+ const ref = this.providerLoader.resolve(desired) || this.providerLoader.getMeta(desired);
1879
+ if (ref?.category === category) return desired;
1880
+
1881
+ const all = this.providerLoader.getAll();
1882
+ const fallback = all.find((p: any) => p.category === category && p.type !== targetType);
1883
+ return fallback?.type || null;
1884
+ }
1885
+
1886
+ private loadAutoImplReferenceScripts(category: string, referenceType: string | null): Record<string, string> {
1887
+ if (!referenceType) return {};
1888
+
1889
+ const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
1890
+ const refDir = path.join(builtinDir, category, referenceType);
1891
+ if (!fs.existsSync(refDir)) return {};
1892
+
1893
+ const referenceScripts: Record<string, string> = {};
1894
+ const scriptsDir = path.join(refDir, 'scripts');
1895
+ if (!fs.existsSync(scriptsDir)) return referenceScripts;
1896
+
1897
+ const versions = fs.readdirSync(scriptsDir).filter((d: string) => {
1898
+ try { return fs.statSync(path.join(scriptsDir, d)).isDirectory(); } catch { return false; }
1899
+ }).sort().reverse();
1900
+ if (versions.length === 0) return referenceScripts;
1901
+
1902
+ const latestDir = path.join(scriptsDir, versions[0]);
1903
+ for (const file of fs.readdirSync(latestDir)) {
1904
+ if (!file.endsWith('.js')) continue;
1905
+ try {
1906
+ referenceScripts[file] = fs.readFileSync(path.join(latestDir, file), 'utf-8');
1907
+ } catch {
1908
+ // ignore broken reference files
1909
+ }
1910
+ }
1911
+ return referenceScripts;
1912
+ }
1913
+
1869
1914
  private async handleAutoImplement(type: string, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
1870
1915
  const body = await this.readBody(req);
1871
1916
  const { agent = 'claude-cli', functions, reference = 'antigravity', model, comment } = body;
@@ -1888,37 +1933,33 @@ export class DevServer {
1888
1933
  try {
1889
1934
  // 1. Collect DOM context
1890
1935
  // 1. Skip heavy DOM pre-parsing (Agent will use cURL to explore via CDP!)
1891
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'analyzing', message: '에이전트 초기화 (DOM 탐색 권한 부여)...' } });
1936
+ const resolvedReference = this.resolveAutoImplReference(provider.category, reference, type);
1937
+ this.sendAutoImplSSE({
1938
+ event: 'progress',
1939
+ data: {
1940
+ function: '_init',
1941
+ status: 'analyzing',
1942
+ message: provider.category === 'cli'
1943
+ ? 'Initializing agent (granting CLI PTY debug access)...'
1944
+ : 'Initializing agent (granting DOM access)...'
1945
+ }
1946
+ });
1892
1947
  const domContext = null;
1893
1948
 
1894
1949
  // 2. Load reference scripts
1895
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'loading_reference', message: `레퍼런스 스크립트 로드 중 (${reference})...` } });
1896
-
1897
- let referenceScripts: Record<string, string> = {};
1898
- const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
1899
- const refDir = path.join(builtinDir, 'ide', reference);
1900
- if (fs.existsSync(refDir)) {
1901
- // Find latest versioned scripts dir
1902
- const scriptsDir = path.join(refDir, 'scripts');
1903
- if (fs.existsSync(scriptsDir)) {
1904
- const versions = fs.readdirSync(scriptsDir).filter((d: string) => {
1905
- try { return fs.statSync(path.join(scriptsDir, d)).isDirectory(); } catch { return false; }
1906
- }).sort().reverse();
1907
- if (versions.length > 0) {
1908
- const latestDir = path.join(scriptsDir, versions[0]);
1909
- for (const file of fs.readdirSync(latestDir)) {
1910
- if (file.endsWith('.js')) {
1911
- try {
1912
- referenceScripts[file] = fs.readFileSync(path.join(latestDir, file), 'utf-8');
1913
- } catch { /* skip */ }
1914
- }
1915
- }
1916
- }
1950
+ this.sendAutoImplSSE({
1951
+ event: 'progress',
1952
+ data: {
1953
+ function: '_init',
1954
+ status: 'loading_reference',
1955
+ message: `Loading reference script (${resolvedReference || 'none'})...`
1917
1956
  }
1918
- }
1957
+ });
1958
+
1959
+ const referenceScripts = this.loadAutoImplReferenceScripts(provider.category, resolvedReference);
1919
1960
 
1920
1961
  // 3. Build the prompt
1921
- const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment);
1962
+ const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference);
1922
1963
 
1923
1964
  // 4. Write prompt to temp file (avoids shell escaping issues with special chars)
1924
1965
  const tmpDir = path.join(os.tmpdir(), 'adhdev-autoimpl');
@@ -1940,7 +1981,7 @@ export class DevServer {
1940
1981
 
1941
1982
  // ─── ACP Agent: use ACP SDK (JSON-RPC protocol) ───
1942
1983
  if (agentCategory === 'acp') {
1943
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `ACP 에이전트 실행 중: ${spawn.command} ${(spawn.args || []).join(' ')}` } });
1984
+ this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `Spawning ACP agent: ${spawn.command} ${(spawn.args || []).join(' ')}` } });
1944
1985
  this.autoImplStatus = { running: true, type, progress: [] };
1945
1986
 
1946
1987
  // Dynamic import ACP SDK
@@ -2022,7 +2063,7 @@ export class DevServer {
2022
2063
  this.autoImplProcess = null;
2023
2064
  this.autoImplStatus.running = false;
2024
2065
  const success = code === 0;
2025
- this.sendAutoImplSSE({ event: 'complete', data: { success, exitCode: code, functions, message: success ? '✅ ACP Auto-implement 완료' : `❌ ACP 에이전트 종료 (code: ${code})` } });
2066
+ this.sendAutoImplSSE({ event: 'complete', data: { success, exitCode: code, functions, message: success ? '✅ ACP Auto-implement complete' : `❌ ACP agent exited (code: ${code})` } });
2026
2067
  try { this.providerLoader.reload(); } catch { /* ignore */ }
2027
2068
  try { fs.unlinkSync(promptFile); } catch { /* ignore */ }
2028
2069
  this.log(`Auto-implement (ACP) ${success ? 'completed' : 'failed'}: ${type} (exit: ${code})`);
@@ -2034,18 +2075,18 @@ export class DevServer {
2034
2075
  this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'initializing', message: 'ACP initialize...' } });
2035
2076
  await connection.initialize({ protocolVersion: PROTOCOL_VERSION, clientCapabilities: {} });
2036
2077
 
2037
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'session', message: 'ACP session 생성 중...' } });
2078
+ this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'session', message: 'Creating ACP session...' } });
2038
2079
  const session = await connection.newSession({ cwd: providerDir, mcpServers: [] });
2039
2080
  const sessionId = session?.sessionId;
2040
2081
  if (!sessionId) throw new Error('No sessionId returned from session/new');
2041
2082
 
2042
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'prompting', message: `프롬프트 전송 (${prompt.length} chars)...` } });
2083
+ this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'prompting', message: `Sending prompt (${prompt.length} chars)...` } });
2043
2084
  await connection.prompt({
2044
2085
  sessionId,
2045
2086
  prompt: [{ type: 'text', text: prompt }],
2046
2087
  });
2047
2088
 
2048
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_done', status: 'complete', message: '✅ ACP 프롬프트 처리 완료' } });
2089
+ this.sendAutoImplSSE({ event: 'progress', data: { function: '_done', status: 'complete', message: '✅ ACP prompt processing complete' } });
2049
2090
  } catch (e: any) {
2050
2091
  this.sendAutoImplSSE({ event: 'output', data: { chunk: `[ACP Error] ${e.message}\n`, stream: 'stderr' } });
2051
2092
  this.log(`Auto-implement ACP error: ${e.message}`);
@@ -2105,7 +2146,7 @@ export class DevServer {
2105
2146
  shellCmd = `cat '${promptFile}' | ${command} ${escapedArgs}`;
2106
2147
  }
2107
2148
 
2108
- this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `에이전트 실행 중: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
2149
+ this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'spawning', message: `Spawning agent: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
2109
2150
 
2110
2151
  this.autoImplStatus = { running: true, type, progress: [] };
2111
2152
  const spawnedAt = Date.now();
@@ -2218,7 +2259,7 @@ export class DevServer {
2218
2259
  const success = code === 0;
2219
2260
  this.sendAutoImplSSE({
2220
2261
  event: 'complete',
2221
- data: { success, exitCode: code, functions, message: success ? '✅ Auto-implement 완료' : `❌ 에이전트 종료 (code: ${code})` },
2262
+ data: { success, exitCode: code, functions, message: success ? '✅ Auto-implement complete' : `❌ Agent exited (code: ${code})` },
2222
2263
  });
2223
2264
  try { this.providerLoader.reload(); } catch { /* ignore */ }
2224
2265
  try { fs.unlinkSync(promptFile); } catch { /* ignore */ }
@@ -2247,7 +2288,7 @@ export class DevServer {
2247
2288
  success,
2248
2289
  exitCode: code,
2249
2290
  functions,
2250
- message: success ? '✅ Auto-implement 완료' : `❌ 에이전트 종료 (code: ${code})`,
2291
+ message: success ? '✅ Auto-implement complete' : `❌ Agent exited (code: ${code})`,
2251
2292
  },
2252
2293
  });
2253
2294
  try { this.providerLoader.reload(); } catch { /* ignore */ }
@@ -2278,7 +2319,12 @@ export class DevServer {
2278
2319
  domContext: any,
2279
2320
  referenceScripts: Record<string, string>,
2280
2321
  userComment?: string,
2322
+ referenceType?: string | null,
2281
2323
  ): string {
2324
+ if (provider.category === 'cli') {
2325
+ return this.buildCliAutoImplPrompt(type, provider, providerDir, functions, referenceScripts, userComment, referenceType);
2326
+ }
2327
+
2282
2328
  const lines: string[] = [];
2283
2329
 
2284
2330
  // ── System instructions ──
@@ -2341,7 +2387,7 @@ export class DevServer {
2341
2387
  };
2342
2388
 
2343
2389
  if (Object.keys(referenceScripts).length > 0) {
2344
- lines.push('## Reference Implementation (from Antigravity provider)');
2390
+ lines.push(`## Reference Implementation (from ${referenceType || 'antigravity'} provider)`);
2345
2391
  lines.push('These are WORKING scripts from another IDE. Adapt the PATTERNS (not selectors) for the target IDE.');
2346
2392
  lines.push('');
2347
2393
  for (const fn of functions) {
@@ -2507,6 +2553,170 @@ export class DevServer {
2507
2553
  return lines.join('\n');
2508
2554
  }
2509
2555
 
2556
+ private buildCliAutoImplPrompt(
2557
+ type: string,
2558
+ provider: any,
2559
+ providerDir: string,
2560
+ functions: string[],
2561
+ referenceScripts: Record<string, string>,
2562
+ userComment?: string,
2563
+ referenceType?: string | null,
2564
+ ): string {
2565
+ const lines: string[] = [];
2566
+
2567
+ lines.push('You are implementing PTY parsing scripts for a CLI provider.');
2568
+ lines.push('Be concise. Do NOT explain your reasoning. Edit files directly and verify with the local DevServer.');
2569
+ lines.push('');
2570
+
2571
+ lines.push(`# Target: ${provider.name || type} (${type})`);
2572
+ lines.push(`Provider directory: \`${providerDir}\``);
2573
+ lines.push('Provider category: `cli`');
2574
+ lines.push('');
2575
+
2576
+ lines.push('## Current Target Files');
2577
+ lines.push('These are the files you need to edit. Replace TODO or heuristic-only logic with working PTY-aware implementations.');
2578
+ lines.push('');
2579
+
2580
+ const scriptsDir = path.join(providerDir, 'scripts');
2581
+ if (fs.existsSync(scriptsDir)) {
2582
+ const versions = fs.readdirSync(scriptsDir).filter((d: string) => {
2583
+ try { return fs.statSync(path.join(scriptsDir, d)).isDirectory(); } catch { return false; }
2584
+ }).sort().reverse();
2585
+ if (versions.length > 0) {
2586
+ const vDir = path.join(scriptsDir, versions[0]);
2587
+ lines.push(`Scripts version directory: \`${vDir}\``);
2588
+ lines.push('');
2589
+ for (const file of fs.readdirSync(vDir)) {
2590
+ if (!file.endsWith('.js')) continue;
2591
+ try {
2592
+ const content = fs.readFileSync(path.join(vDir, file), 'utf-8');
2593
+ lines.push(`### \`${file}\``);
2594
+ lines.push('```javascript');
2595
+ lines.push(content);
2596
+ lines.push('```');
2597
+ lines.push('');
2598
+ } catch {
2599
+ // ignore
2600
+ }
2601
+ }
2602
+ }
2603
+ }
2604
+
2605
+ const funcToFile: Record<string, string> = {
2606
+ parseOutput: 'parse_output.js',
2607
+ detectStatus: 'detect_status.js',
2608
+ parseApproval: 'parse_approval.js',
2609
+ };
2610
+
2611
+ if (Object.keys(referenceScripts).length > 0) {
2612
+ lines.push(`## Reference Implementation (from ${referenceType || 'another CLI'} provider)`);
2613
+ lines.push('These are working CLI PTY parser scripts. Reuse the parsing shape and runtime contract, but adapt to the target CLI screen.');
2614
+ lines.push('');
2615
+ for (const fn of functions) {
2616
+ const fileName = funcToFile[fn];
2617
+ if (fileName && referenceScripts[fileName]) {
2618
+ lines.push(`### ${fn} → \`${fileName}\``);
2619
+ lines.push('```javascript');
2620
+ lines.push(referenceScripts[fileName]);
2621
+ lines.push('```');
2622
+ lines.push('');
2623
+ }
2624
+ }
2625
+ if (referenceScripts['scripts.js']) {
2626
+ lines.push('### Router → `scripts.js`');
2627
+ lines.push('```javascript');
2628
+ lines.push(referenceScripts['scripts.js']);
2629
+ lines.push('```');
2630
+ lines.push('');
2631
+ }
2632
+ }
2633
+
2634
+ lines.push('## Runtime Contract');
2635
+ lines.push('The daemon runtime is already implemented in `packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts`.');
2636
+ lines.push('Your scripts receive PTY-derived input and must return plain JS objects.');
2637
+ lines.push('');
2638
+ lines.push('| Function | Input | Return |');
2639
+ lines.push('|---|---|---|');
2640
+ lines.push('| `parseOutput` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |');
2641
+ lines.push('| `detectStatus` | `{ tail }` | `idle`, `generating`, `waiting_approval`, or `error` |');
2642
+ lines.push('| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |');
2643
+ lines.push('');
2644
+
2645
+ lines.push('## Rules');
2646
+ lines.push('1. These scripts run in Node.js CommonJS, not in the browser. Do NOT use DOM APIs.');
2647
+ lines.push('2. Prefer `screenText` for current visible UI state. That is the PTY equivalent of parsing the current IDE DOM.');
2648
+ lines.push('3. Use `messages` as prior transcript state so redraws do not duplicate old turns on every parse.');
2649
+ lines.push('4. Use `partialResponse` for the actively streaming assistant text when status is `generating`.');
2650
+ lines.push('5. `detectStatus` must stay lightweight and tail-based. Do not scan the entire history there.');
2651
+ lines.push('6. `parseApproval` should understand the live approval area and return clean button labels.');
2652
+ lines.push('7. Use `rawBuffer` only when ANSI/control-sequence artifacts matter. Do not depend on raw escape noise unless necessary.');
2653
+ lines.push('8. Keep exports compatible with the existing `scripts.js` router (`module.exports = function ...`).');
2654
+ lines.push('9. Do not rewrite unrelated provider config. Only touch the scripts needed for this task unless a tiny supporting change is required.');
2655
+ lines.push('');
2656
+
2657
+ lines.push('## Task');
2658
+ lines.push(`Edit files in \`${providerDir}\` to implement: **${functions.join(', ')}**`);
2659
+ lines.push('');
2660
+
2661
+ lines.push('## Verification API');
2662
+ lines.push('Use the DevServer CLI debug endpoints, not DOM/CDP routes.');
2663
+ lines.push('');
2664
+ lines.push('### 1. Launch the target CLI');
2665
+ lines.push('```bash');
2666
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/launch \\`);
2667
+ lines.push(' -H "Content-Type: application/json" \\');
2668
+ lines.push(` -d '{"type":"${type}","workingDir":"${providerDir.replace(/\\/g, '\\\\')}"}'`);
2669
+ lines.push('```');
2670
+ lines.push('');
2671
+ lines.push('### 2. Inspect parsed + raw adapter state');
2672
+ lines.push('```bash');
2673
+ lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/debug/${type}`);
2674
+ lines.push(`curl -sS http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/status`);
2675
+ lines.push('```');
2676
+ lines.push('');
2677
+ lines.push('### 3. Send a rich test prompt');
2678
+ lines.push('```bash');
2679
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/send \\`);
2680
+ lines.push(' -H "Content-Type: application/json" \\');
2681
+ lines.push(` -d '{"type":"${type}","text":"Write a short python snippet, include a markdown table, and briefly explain what you did."}'`);
2682
+ lines.push('```');
2683
+ lines.push('');
2684
+ lines.push('### 4. If approval appears, resolve it');
2685
+ lines.push('```bash');
2686
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/resolve \\`);
2687
+ lines.push(' -H "Content-Type: application/json" \\');
2688
+ lines.push(` -d '{"type":"${type}","buttonIndex":0}'`);
2689
+ lines.push('```');
2690
+ lines.push('');
2691
+ lines.push('### 5. Stop the CLI when finished');
2692
+ lines.push('```bash');
2693
+ lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/cli/stop \\`);
2694
+ lines.push(' -H "Content-Type: application/json" \\');
2695
+ lines.push(` -d '{"type":"${type}"}'`);
2696
+ lines.push('```');
2697
+ lines.push('');
2698
+
2699
+ lines.push('## Required Validation');
2700
+ lines.push('1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.');
2701
+ lines.push('2. Confirm `parseOutput` produces a stable transcript without duplicating past turns when the PTY redraws.');
2702
+ lines.push('3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.');
2703
+ lines.push('4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.');
2704
+ lines.push('5. Re-run the debug endpoints after edits. Do NOT finish until the parsed result looks correct.');
2705
+ lines.push('');
2706
+
2707
+ if (userComment) {
2708
+ lines.push('## ⚠️ User Instructions (HIGH PRIORITY)');
2709
+ lines.push('The user has provided the following additional instructions. Follow them strictly:');
2710
+ lines.push('');
2711
+ lines.push(userComment);
2712
+ lines.push('');
2713
+ }
2714
+
2715
+ lines.push('Start NOW. Launch the CLI, inspect PTY state, edit the scripts, and verify via the CLI debug endpoints.');
2716
+
2717
+ return lines.join('\n');
2718
+ }
2719
+
2510
2720
  private handleAutoImplSSE(type: string, req: http.IncomingMessage, res: http.ServerResponse): void {
2511
2721
  res.writeHead(200, {
2512
2722
  'Content-Type': 'text/event-stream',
@@ -2531,7 +2741,7 @@ export class DevServer {
2531
2741
  if (this.autoImplProcess) {
2532
2742
  this.autoImplProcess.kill('SIGTERM');
2533
2743
  setTimeout(() => { if (this.autoImplProcess) this.autoImplProcess.kill('SIGKILL'); }, 3000);
2534
- this.sendAutoImplSSE({ event: 'complete', data: { success: false, exitCode: -1, message: '⛔ 사용자에 의해 중단됨' } });
2744
+ this.sendAutoImplSSE({ event: 'complete', data: { success: false, exitCode: -1, message: '⛔ Aborted by user' } });
2535
2745
  this.autoImplProcess = null;
2536
2746
  this.autoImplStatus.running = false;
2537
2747
  this.json(res, 200, { cancelled: true });
@@ -51,7 +51,7 @@ import type { ProviderInstance, ProviderState, AcpProviderState, ProviderErrorRe
51
51
  import { StatusMonitor } from './status-monitor.js';
52
52
  import { LOG } from '../logging/logger.js';
53
53
 
54
- // ─── Internal Display Types (dashboard) ────────────────────────────
54
+ // ─── Internal Display Types (for dashboard) ────────────────────────────
55
55
 
56
56
  interface AcpMessage {
57
57
  role: 'user' | 'assistant' | 'system';
@@ -81,15 +81,25 @@ export class CliProviderInstance implements ProviderInstance {
81
81
  }
82
82
 
83
83
  getState(): ProviderState {
84
- const adapterStatus = this.adapter.getStatus();
84
+ const rawStatus = this.adapter.getStatus();
85
+ const parsedStatus = this.adapter.getScriptParsedStatus();
86
+
87
+ // Prefer rich script parsed status if available
88
+ const adapterStatus = parsedStatus ? {
89
+ ...rawStatus,
90
+ messages: parsedStatus.messages || rawStatus.messages,
91
+ activeModal: parsedStatus.activeModal || rawStatus.activeModal,
92
+ } : rawStatus;
93
+
85
94
  const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
86
95
 
87
- // Message truncate (recent 50, 2000 char limit)
88
- const recentMessages = adapterStatus.messages.slice(-50).map(m => ({
89
- role: m.role,
90
- content: m.content.length > 2000 ? m.content.slice(0, 2000) + '\n... (truncated)' : m.content,
91
- timestamp: m.timestamp,
92
- }));
96
+ // Preserve rich message objects, just truncate extremely long text strings
97
+ const recentMessages = adapterStatus.messages.slice(-50).map((m: any) => {
98
+ const content = typeof m.content === 'string' && m.content.length > 8000
99
+ ? m.content.slice(0, 8000) + '\n... (truncated)'
100
+ : m.content;
101
+ return { ...m, content };
102
+ });
93
103
 
94
104
  // generating during partial response add
95
105
  const partial = this.adapter.getPartialResponse();
@@ -98,8 +108,9 @@ export class CliProviderInstance implements ProviderInstance {
98
108
  if (cleaned && cleaned !== '(generating...)') {
99
109
  recentMessages.push({
100
110
  role: 'assistant',
101
- content: (cleaned.length > 2000 ? cleaned.slice(0, 2000) + '...' : cleaned) + '...',
111
+ content: (cleaned.length > 8000 ? cleaned.slice(0, 8000) + '...' : cleaned) + '...',
102
112
  timestamp: Date.now(),
113
+ meta: { streaming: true },
103
114
  });
104
115
  }
105
116
  }
@@ -142,6 +153,8 @@ export class CliProviderInstance implements ProviderInstance {
142
153
  this.adapter.sendMessage(data.text);
143
154
  } else if (event === 'server_connected' && data?.serverConn) {
144
155
  this.adapter.setServerConn(data.serverConn);
156
+ } else if (event === 'resolve_action' && data) {
157
+ this.adapter.resolveAction(data);
145
158
  }
146
159
  }
147
160
 
@@ -1141,8 +1141,9 @@ export class ProviderLoader {
1141
1141
  }
1142
1142
 
1143
1143
  private compareVersions(a: string, b: string): number {
1144
- const pa = a.split('.').map(Number);
1145
- const pb = b.split('.').map(Number);
1144
+ const normalize = (v: string) => v.split(/[-_+]/)[0].split('.').map(x => parseInt(x, 10) || 0);
1145
+ const pa = normalize(a);
1146
+ const pb = normalize(b);
1146
1147
  for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
1147
1148
  const va = pa[i] || 0;
1148
1149
  const vb = pb[i] || 0;
@@ -1,43 +0,0 @@
1
- /**
2
- * Cline — list_models
3
- * 드롭다운에서 사용 가능한 모델 목록 + 현재 선택된 모델 반환
4
- * → { models: string[], current: string }
5
- */
6
- (async () => {
7
- try {
8
- const inner = document.querySelector('iframe');
9
- const doc = inner?.contentDocument || inner?.contentWindow?.document;
10
- if (!doc) return JSON.stringify({ models: [], current: '', error: 'no doc' });
11
-
12
- // 현재 모델: mode-switch 또는 model selector에서 읽기
13
- let current = '';
14
- const modeSwitch = doc.querySelector('[data-testid="mode-switch"]');
15
- if (modeSwitch) current = (modeSwitch.textContent || '').trim();
16
- if (!current) {
17
- const modelSel = doc.querySelector('[data-testid*="model"], [aria-label*="model" i]');
18
- if (modelSel) current = (modelSel.textContent || '').trim();
19
- }
20
-
21
- // 드롭다운 트리거 찾기
22
- const trigger = doc.querySelector('[data-testid="model-selector"], [data-testid*="model-dropdown"], [data-testid="dropdown-trigger"]');
23
- if (!trigger) return JSON.stringify({ models: [], current, error: 'no model trigger' });
24
-
25
- // 드롭다운 열기
26
- trigger.click();
27
- await new Promise(r => setTimeout(r, 300));
28
-
29
- // 옵션 수집
30
- const options = doc.querySelectorAll('[data-testid*="dropdown-option"], [role="option"], [class*="dropdown"] [class*="item"], [class*="listbox"] [class*="option"]');
31
- const models = [];
32
- for (const opt of options) {
33
- const text = (opt.textContent || '').trim();
34
- if (text && text.length > 1 && text.length < 100) models.push(text);
35
- }
36
-
37
- // 닫기
38
- doc.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
39
- if (trigger.click) trigger.click(); // fallback close
40
-
41
- return JSON.stringify({ models: [...new Set(models)], current });
42
- } catch (e) { return JSON.stringify({ models: [], current: '', error: e.message }); }
43
- })()
@@ -1,35 +0,0 @@
1
- /**
2
- * Cline — list_modes
3
- * 모드 selector에서 사용 가능한 모드 목록 + 현재 모드 반환
4
- * → { modes: string[], current: string }
5
- */
6
- (async () => {
7
- try {
8
- const inner = document.querySelector('iframe');
9
- const doc = inner?.contentDocument || inner?.contentWindow?.document;
10
- if (!doc) return JSON.stringify({ modes: [], current: '', error: 'no doc' });
11
-
12
- // 현재 모드
13
- const trigger = doc.querySelector('[data-testid="mode-selector-trigger"], [data-testid="mode-switch"]');
14
- if (!trigger) return JSON.stringify({ modes: [], current: '', error: 'no mode trigger' });
15
- const current = (trigger.textContent || '').trim();
16
-
17
- // 드롭다운 열기
18
- trigger.click();
19
- await new Promise(r => setTimeout(r, 300));
20
-
21
- // 옵션 수집
22
- const options = doc.querySelectorAll('[data-testid*="mode-option"], [role="option"], [class*="dropdown"] [class*="item"], [class*="listbox"] [class*="option"]');
23
- const modes = [];
24
- for (const opt of options) {
25
- const text = (opt.textContent || '').trim();
26
- if (text && text.length > 1 && text.length < 50) modes.push(text);
27
- }
28
-
29
- // 닫기
30
- doc.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
31
- if (trigger.click) trigger.click(); // fallback close
32
-
33
- return JSON.stringify({ modes: [...new Set(modes)], current });
34
- } catch (e) { return JSON.stringify({ modes: [], current: '', error: e.message }); }
35
- })()
@@ -1,62 +0,0 @@
1
- /**
2
- * PearAI — webview_list_sessions (webview iframe 내부에서 실행)
3
- *
4
- * PearAI(Roo Code/Cline 기반) 히스토리 뷰에서 세션 목록을 추출.
5
- * 각 항목은 data-testid="task-item-{UUID}" 로 식별됨.
6
- */
7
- (() => {
8
- try {
9
- // ─── 히스토리 항목: data-testid="task-item-*" ───
10
- const taskItems = document.querySelectorAll('[data-testid^="task-item-"]');
11
-
12
- if (taskItems.length > 0) {
13
- const sessions = [];
14
- for (let i = 0; i < taskItems.length; i++) {
15
- const item = taskItems[i];
16
- if (!item) continue;
17
-
18
- const testId = item.getAttribute('data-testid') || '';
19
- const taskId = testId.replace('task-item-', '');
20
-
21
- // 전체 텍스트에서 제목 추출
22
- const fullText = (item.textContent || '').trim();
23
-
24
- // 구조: "MARCH 16, 1:31 AM 173 B test123 Tokens:10.4k 229"
25
- // 전략: Tokens: 앞의 마지막 의미있는 텍스트를 제목으로 사용
26
- let title = '';
27
- let date = '';
28
-
29
- // 날짜 추출
30
- const dateMatch = fullText.match(/^([A-Z]+\s+\d+,\s*\d+:\d+\s*[AP]M)/);
31
- if (dateMatch) date = dateMatch[1];
32
-
33
- // 제목 추출: 날짜와 크기(B/kB) 뒤, Tokens: 앞
34
- const titleMatch = fullText.match(/[AP]M[\d.\s]*[kMG]?B\s*(.*?)(?:Tokens:|$)/s);
35
- if (titleMatch && titleMatch[1]) {
36
- title = titleMatch[1].trim();
37
- }
38
-
39
- // fallback: 첫 80자
40
- if (!title) {
41
- title = fullText.substring(0, 80);
42
- }
43
-
44
- sessions.push({
45
- id: taskId,
46
- title: title.substring(0, 100),
47
- date: date,
48
- active: false
49
- });
50
- }
51
- return JSON.stringify({ sessions: sessions });
52
- }
53
-
54
- // ─── 히스토리 뷰가 열려 있지 않음 ───
55
- return JSON.stringify({
56
- sessions: [],
57
- note: 'History view not open. Toggle history first.'
58
- });
59
- } catch (e) {
60
- return JSON.stringify({ sessions: [], error: String(e.message || e) });
61
- }
62
- })()
@@ -1,49 +0,0 @@
1
- /**
2
- * PearAI — webview_new_session (webview iframe 내부에서 실행)
3
- *
4
- * Roo Code/Cline 기반 PearAI에서 새 세션(태스크)을 시작합니다.
5
- * 1) "New Task" 텍스트를 가진 버튼 클릭 시도
6
- * 2) 실패 시, vscode postMessage API로 newTask 명령 전송 시도
7
- * 3) 실패 시, chat-text-area를 초기화하여 새 세션 상태로 진입
8
- */
9
- (() => {
10
- try {
11
- // Strategy 1: Find "New Task" button text
12
- const buttons = document.querySelectorAll('button, [role="button"]');
13
- for (const btn of buttons) {
14
- const text = (btn.textContent || '').trim();
15
- if (text.includes('Start New Task') || text.includes('New Task') || text.includes('New Chat')) {
16
- btn.click();
17
- return JSON.stringify({ created: true, method: 'button', text });
18
- }
19
- }
20
-
21
- // Strategy 2: Look for a "+" (plus/add) button that might create new tasks
22
- for (const btn of buttons) {
23
- const title = btn.getAttribute('title') || '';
24
- const ariaLabel = btn.getAttribute('aria-label') || '';
25
- if (title.includes('New') || ariaLabel.includes('New') ||
26
- title.includes('new') || ariaLabel.includes('new')) {
27
- btn.click();
28
- return JSON.stringify({ created: true, method: 'title', title: title || ariaLabel });
29
- }
30
- }
31
-
32
- // Strategy 3: Use vscode API to post message for new task
33
- if (typeof acquireVsCodeApi !== 'undefined') {
34
- const vscode = acquireVsCodeApi();
35
- vscode.postMessage({ type: 'newTask' });
36
- return JSON.stringify({ created: true, method: 'vscodeApi' });
37
- }
38
-
39
- // Strategy 4: If already in empty state (no messages), report as already new
40
- const messages = document.querySelectorAll('[class*="message"], [class*="chat-row"]');
41
- if (messages.length === 0) {
42
- return JSON.stringify({ created: true, method: 'alreadyNew', note: 'No messages - already in new session state' });
43
- }
44
-
45
- return JSON.stringify({ created: false, error: 'New Task button not found' });
46
- } catch (e) {
47
- return JSON.stringify({ created: false, error: e.message });
48
- }
49
- })()