yo-bug 0.1.0

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 (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -0
  3. package/bin/cli.ts +17 -0
  4. package/bin/install.ts +34 -0
  5. package/bin/mcp.ts +2 -0
  6. package/dist/bin/cli.d.ts +3 -0
  7. package/dist/bin/cli.d.ts.map +1 -0
  8. package/dist/bin/cli.js +19 -0
  9. package/dist/bin/cli.js.map +1 -0
  10. package/dist/bin/install.d.ts +3 -0
  11. package/dist/bin/install.d.ts.map +1 -0
  12. package/dist/bin/install.js +28 -0
  13. package/dist/bin/install.js.map +1 -0
  14. package/dist/bin/mcp.d.ts +3 -0
  15. package/dist/bin/mcp.d.ts.map +1 -0
  16. package/dist/bin/mcp.js +3 -0
  17. package/dist/bin/mcp.js.map +1 -0
  18. package/dist/src/detect/dev-server.d.ts +11 -0
  19. package/dist/src/detect/dev-server.d.ts.map +1 -0
  20. package/dist/src/detect/dev-server.js +92 -0
  21. package/dist/src/detect/dev-server.js.map +1 -0
  22. package/dist/src/detect/spawn-dev.d.ts +4 -0
  23. package/dist/src/detect/spawn-dev.d.ts.map +1 -0
  24. package/dist/src/detect/spawn-dev.js +37 -0
  25. package/dist/src/detect/spawn-dev.js.map +1 -0
  26. package/dist/src/install/detect-ai-tool.d.ts +7 -0
  27. package/dist/src/install/detect-ai-tool.d.ts.map +1 -0
  28. package/dist/src/install/detect-ai-tool.js +38 -0
  29. package/dist/src/install/detect-ai-tool.js.map +1 -0
  30. package/dist/src/install/write-mcp-config.d.ts +6 -0
  31. package/dist/src/install/write-mcp-config.d.ts.map +1 -0
  32. package/dist/src/install/write-mcp-config.js +47 -0
  33. package/dist/src/install/write-mcp-config.js.map +1 -0
  34. package/dist/src/mcp/index.d.ts +2 -0
  35. package/dist/src/mcp/index.d.ts.map +1 -0
  36. package/dist/src/mcp/index.js +263 -0
  37. package/dist/src/mcp/index.js.map +1 -0
  38. package/dist/src/mcp/tools/checklist.d.ts +22 -0
  39. package/dist/src/mcp/tools/checklist.d.ts.map +1 -0
  40. package/dist/src/mcp/tools/checklist.js +58 -0
  41. package/dist/src/mcp/tools/checklist.js.map +1 -0
  42. package/dist/src/mcp/tools/get-feedback.d.ts +13 -0
  43. package/dist/src/mcp/tools/get-feedback.d.ts.map +1 -0
  44. package/dist/src/mcp/tools/get-feedback.js +27 -0
  45. package/dist/src/mcp/tools/get-feedback.js.map +1 -0
  46. package/dist/src/mcp/tools/list-feedbacks.d.ts +20 -0
  47. package/dist/src/mcp/tools/list-feedbacks.d.ts.map +1 -0
  48. package/dist/src/mcp/tools/list-feedbacks.js +29 -0
  49. package/dist/src/mcp/tools/list-feedbacks.js.map +1 -0
  50. package/dist/src/mcp/tools/resolve-feedback.d.ts +8 -0
  51. package/dist/src/mcp/tools/resolve-feedback.d.ts.map +1 -0
  52. package/dist/src/mcp/tools/resolve-feedback.js +28 -0
  53. package/dist/src/mcp/tools/resolve-feedback.js.map +1 -0
  54. package/dist/src/mcp/tools/start-session.d.ts +11 -0
  55. package/dist/src/mcp/tools/start-session.d.ts.map +1 -0
  56. package/dist/src/mcp/tools/start-session.js +56 -0
  57. package/dist/src/mcp/tools/start-session.js.map +1 -0
  58. package/dist/src/mcp/tools/stop-session.d.ts +6 -0
  59. package/dist/src/mcp/tools/stop-session.d.ts.map +1 -0
  60. package/dist/src/mcp/tools/stop-session.js +80 -0
  61. package/dist/src/mcp/tools/stop-session.js.map +1 -0
  62. package/dist/src/mcp/tools/test-history.d.ts +33 -0
  63. package/dist/src/mcp/tools/test-history.d.ts.map +1 -0
  64. package/dist/src/mcp/tools/test-history.js +66 -0
  65. package/dist/src/mcp/tools/test-history.js.map +1 -0
  66. package/dist/src/server/feedback-api.d.ts +4 -0
  67. package/dist/src/server/feedback-api.d.ts.map +1 -0
  68. package/dist/src/server/feedback-api.js +152 -0
  69. package/dist/src/server/feedback-api.js.map +1 -0
  70. package/dist/src/server/html-injector.d.ts +10 -0
  71. package/dist/src/server/html-injector.d.ts.map +1 -0
  72. package/dist/src/server/html-injector.js +34 -0
  73. package/dist/src/server/html-injector.js.map +1 -0
  74. package/dist/src/server/proxy-server.d.ts +8 -0
  75. package/dist/src/server/proxy-server.d.ts.map +1 -0
  76. package/dist/src/server/proxy-server.js +87 -0
  77. package/dist/src/server/proxy-server.js.map +1 -0
  78. package/dist/src/server/sdk-serve.d.ts +3 -0
  79. package/dist/src/server/sdk-serve.d.ts.map +1 -0
  80. package/dist/src/server/sdk-serve.js +20 -0
  81. package/dist/src/server/sdk-serve.js.map +1 -0
  82. package/dist/src/storage/store.d.ts +21 -0
  83. package/dist/src/storage/store.d.ts.map +1 -0
  84. package/dist/src/storage/store.js +138 -0
  85. package/dist/src/storage/store.js.map +1 -0
  86. package/dist/src/storage/types.d.ts +74 -0
  87. package/dist/src/storage/types.d.ts.map +1 -0
  88. package/dist/src/storage/types.js +2 -0
  89. package/dist/src/storage/types.js.map +1 -0
  90. package/dist/vibe-feedback.js +399 -0
  91. package/package.json +67 -0
  92. package/src/client/annotation-mode/canvas-editor.ts +178 -0
  93. package/src/client/annotation-mode/history.ts +32 -0
  94. package/src/client/annotation-mode/region-selector.ts +123 -0
  95. package/src/client/annotation-mode/screenshot.ts +17 -0
  96. package/src/client/annotation-mode/toolbar.ts +139 -0
  97. package/src/client/annotation-mode/tools/arrow.ts +57 -0
  98. package/src/client/annotation-mode/tools/base-tool.ts +25 -0
  99. package/src/client/annotation-mode/tools/circle.ts +37 -0
  100. package/src/client/annotation-mode/tools/freehand.ts +23 -0
  101. package/src/client/annotation-mode/tools/rect.ts +32 -0
  102. package/src/client/annotation-mode/tools/text.ts +93 -0
  103. package/src/client/api/client.ts +48 -0
  104. package/src/client/capture/action-recorder.ts +157 -0
  105. package/src/client/capture/console-interceptor.ts +65 -0
  106. package/src/client/capture/context-buffer.ts +23 -0
  107. package/src/client/capture/error-interceptor.ts +52 -0
  108. package/src/client/capture/network-interceptor.ts +143 -0
  109. package/src/client/core/event-bus.ts +20 -0
  110. package/src/client/core/i18n.ts +83 -0
  111. package/src/client/core/sdk.ts +373 -0
  112. package/src/client/core/shadow-host.ts +27 -0
  113. package/src/client/element-mode/highlighter.ts +79 -0
  114. package/src/client/element-mode/inspector.ts +73 -0
  115. package/src/client/element-mode/selector.ts +22 -0
  116. package/src/client/index.ts +10 -0
  117. package/src/client/styles/sdk.css.ts +222 -0
  118. package/src/client/ui/checklist-panel.ts +279 -0
  119. package/src/client/ui/feedback-panel.ts +149 -0
  120. package/src/client/ui/floating-button.ts +103 -0
  121. package/src/client/ui/toast.ts +17 -0
  122. package/src/client/ui/verify-panel.ts +111 -0
  123. package/src/detect/dev-server.ts +110 -0
  124. package/src/detect/spawn-dev.ts +50 -0
  125. package/src/install/detect-ai-tool.ts +49 -0
  126. package/src/install/write-mcp-config.ts +49 -0
  127. package/src/mcp/index.ts +327 -0
  128. package/src/mcp/tools/checklist.ts +61 -0
  129. package/src/mcp/tools/get-feedback.ts +34 -0
  130. package/src/mcp/tools/list-feedbacks.ts +37 -0
  131. package/src/mcp/tools/resolve-feedback.ts +34 -0
  132. package/src/mcp/tools/start-session.ts +65 -0
  133. package/src/mcp/tools/stop-session.ts +93 -0
  134. package/src/mcp/tools/test-history.ts +97 -0
  135. package/src/server/feedback-api.ts +164 -0
  136. package/src/server/html-injector.ts +41 -0
  137. package/src/server/proxy-server.ts +107 -0
  138. package/src/server/sdk-serve.ts +24 -0
  139. package/src/storage/store.ts +172 -0
  140. package/src/storage/types.ts +68 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 vibe-feedback contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # yo-bug 🐛
2
+
3
+ **"Yo, bug!"** — Point at bugs, AI fixes them.
4
+
5
+ MCP Server that gives AI coding assistants QA superpowers. One install, then your AI handles the entire test-feedback-fix loop.
6
+
7
+ In vibe coding, the bottleneck is testing: humans find bugs but struggle to describe them. yo-bug solves this by letting users point, click, and annotate — while the AI automatically receives element locations, console errors, network failures, action recordings, and annotated screenshots.
8
+
9
+ ## What it does
10
+
11
+ | For the Human | For the AI |
12
+ |---|---|
13
+ | Click a broken element → done | Gets: CSS selector + computed styles + React/Vue component name |
14
+ | Draw a circle on a screenshot → done | Gets: annotated screenshot as image content |
15
+ | Just use the app normally | Gets: last 100 user actions (clicks, inputs, navigation) |
16
+ | Check off a test list | Gets: which tests passed/failed with linked feedback |
17
+
18
+ The AI drives the entire workflow through MCP tools. Humans never need to learn commands, configure proxies, or modify their code.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npx yo-bug install
24
+
25
+ # That's it. Your AI now has QA superpowers.
26
+ ```
27
+
28
+ This auto-detects your AI tool (Claude Code / Cursor / Windsurf) and writes the MCP config. One time, done forever.
29
+
30
+ ## How it works
31
+
32
+ ```
33
+ AI writes code
34
+ → AI calls start_test_session()
35
+ → Browser opens with test overlay injected (zero code changes)
36
+ → AI pushes a test checklist (8 QA dimensions, 40+ sub-scenarios)
37
+ → Human tests, clicks problems, checks off items
38
+ → AI calls list_feedbacks() → sees everything
39
+ → AI fixes → calls resolve_feedback() → browser asks human to verify
40
+ → Loop until done
41
+ ```
42
+
43
+ ## MCP Tools (9 total)
44
+
45
+ ### Session Control
46
+ | Tool | Description |
47
+ |---|---|
48
+ | `start_test_session(port?, open?)` | Start test mode: auto-detect dev server, launch reverse proxy with SDK injection, open browser |
49
+ | `stop_test_session()` | Stop test mode, return session summary (feedback stats, checklist results, weak dimensions) |
50
+
51
+ ### Feedback
52
+ | Tool | Description |
53
+ |---|---|
54
+ | `list_feedbacks(status?, type?, limit?)` | List submitted feedback (filter by status: open/verify/resolved) |
55
+ | `get_feedback(id)` | Full details: element info, console errors, network errors, action steps, annotated screenshot |
56
+ | `resolve_feedback(id)` | Mark as fixed → pushes verification request to browser → human confirms |
57
+
58
+ ### Test Checklist
59
+ | Tool | Description |
60
+ |---|---|
61
+ | `create_checklist(title, items)` | Push structured test checklist to browser. Items have step, expected result, priority, and dimension |
62
+ | `get_checklist_status()` | See which items passed/failed and any user feedback |
63
+
64
+ ### Test History
65
+ | Tool | Description |
66
+ |---|---|
67
+ | `save_test_record(module, ...)` | Save test results per module. Accumulates history for future reference |
68
+ | `get_test_history(module)` | Get historical test records. Shows frequently failing scenarios |
69
+
70
+ ## 8 QA Test Dimensions
71
+
72
+ The `create_checklist` tool embeds professional QA methodology. AI is guided to systematically cover:
73
+
74
+ 1. **Happy path** — Core functionality works end-to-end
75
+ 2. **Empty/boundary** — Empty inputs, special chars, max length, zero/negative values
76
+ 3. **Error states** — Offline, server errors, timeouts, recovery
77
+ 4. **Duplicate ops** — Double-click, re-submit, concurrent requests
78
+ 5. **State recovery** — Refresh, back/forward, deep links, tab close/reopen
79
+ 6. **Loading/async** — Loading states, failed loads, stale data
80
+ 7. **Responsive** — 375px mobile width, touch targets, overflow
81
+ 8. **Interaction detail** — Tab order, Enter/Escape, disabled states, focus
82
+
83
+ Each dimension has detailed sub-scenario templates that the AI selects from based on actual code changes.
84
+
85
+ ## Three Feedback Modes
86
+
87
+ Users choose how to report issues:
88
+
89
+ | Mode | Shortcut | How it works |
90
+ |---|---|---|
91
+ | **Quick** | `Alt+Q` | Click an element → instantly flagged with full context. One click, done. |
92
+ | **Describe** | `Alt+D` | Click an element → fill a form with problem type and description |
93
+ | **Screenshot** | `Alt+S` | Drag to select screen region → annotate with arrows/shapes/text → submit |
94
+
95
+ Other shortcuts: `Alt+X` toggle test mode, `Esc` exit.
96
+
97
+ ## Auto-Captured Context
98
+
99
+ Every feedback submission automatically includes:
100
+
101
+ - **Console errors** — last 50 `console.error`/`console.warn` entries with stack traces
102
+ - **Network failures** — failed `fetch`/`XHR` requests with status, URL, duration
103
+ - **Unhandled exceptions** — `window.onerror` + `unhandledrejection`
104
+ - **Action recording** — last 100 user actions (clicks, inputs, keypresses, navigation) with timestamps
105
+ - **Element info** — CSS selector, tag, text content, bounding rect, computed styles, React/Vue component name
106
+
107
+ ## Verify-Fix Flow
108
+
109
+ When AI calls `resolve_feedback()`, instead of silently marking it done:
110
+
111
+ 1. Browser shows a "Verify Fix" card to the user
112
+ 2. User clicks "Fixed" or "Still broken"
113
+ 3. Status updates accordingly — AI knows if the fix actually worked
114
+
115
+ ## i18n
116
+
117
+ SDK auto-detects `<html lang="...">`:
118
+ - `zh-*` → Chinese interface
119
+ - Everything else → English interface
120
+
121
+ MCP tool descriptions are in English (AI translates to user's language naturally).
122
+
123
+ ## Architecture
124
+
125
+ ```
126
+ Browser → Reverse Proxy (localhost:3695) → Dev Server (localhost:5173)
127
+
128
+ ├─ Auto-injects SDK into HTML responses
129
+ ├─ WebSocket passthrough (HMR works normally)
130
+ ├─ Feedback API (POST/GET)
131
+ ├─ Checklist API (push/poll/update)
132
+ └─ Verify API (push/confirm)
133
+
134
+ MCP Server (stdio) → AI Tool (Claude Code / Cursor / Windsurf)
135
+
136
+ ├─ start/stop_test_session → controls proxy lifecycle
137
+ ├─ feedback tools → reads user submissions
138
+ ├─ checklist tools → pushes test plans, reads results
139
+ └─ history tools → persists test records per module
140
+ ```
141
+
142
+ The proxy auto-detects dev server framework (Vite, Next.js, CRA, Webpack, Nuxt, Angular, Svelte, Astro) and port. If the dev server is already running, it connects. If not, it starts one.
143
+
144
+ ## Security
145
+
146
+ - All data stays local (`~/.yo-bug/`)
147
+ - Feedback IDs validated against path traversal
148
+ - Input fields whitelist-filtered and length-limited
149
+ - Network interceptor uses exact pathname matching (no substring false positives)
150
+ - No data sent to any external service
151
+
152
+ ## Requirements
153
+
154
+ - Node.js >= 18
155
+ - Any MCP-compatible AI tool
156
+ - Any web application running in a browser
157
+
158
+ ## License
159
+
160
+ MIT
package/bin/cli.ts ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ const command = process.argv[2];
4
+
5
+ if (command === 'mcp') {
6
+ // Start MCP server (stdio mode)
7
+ import('../src/mcp/index.js');
8
+ } else if (command === 'install') {
9
+ // Install MCP config to AI tools
10
+ import('./install.js');
11
+ } else {
12
+ console.log('yo-bug — AI Agent 的测试之眼\n');
13
+ console.log('用法:');
14
+ console.log(' npx yo-bug install 安装 MCP 到你的 AI 工具');
15
+ console.log(' npx yo-bug mcp 启动 MCP Server(由 AI 工具自动调用)');
16
+ console.log('\n安装后,AI 会自动获得测试模式能力,你不需要其他操作。');
17
+ }
package/bin/install.ts ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ import { detectAITools } from '../src/install/detect-ai-tool.js';
3
+ import { writeMcpConfig } from '../src/install/write-mcp-config.js';
4
+
5
+ async function main() {
6
+ console.log('yo-bug — 安装 MCP Server\n');
7
+
8
+ const tools = await detectAITools();
9
+ const detected = tools.filter((t) => t.detected);
10
+
11
+ if (detected.length === 0) {
12
+ console.log('未检测到任何 AI 工具(Claude Code / Cursor / Windsurf)。');
13
+ console.log('请先安装至少一个 AI 编程工具后再运行此命令。\n');
14
+ console.log('手动配置方法:');
15
+ console.log(' 在 AI 工具的 MCP 配置中添加:');
16
+ console.log(' {');
17
+ console.log(' "command": "npx",');
18
+ console.log(' "args": ["yo-bug", "mcp"]');
19
+ console.log(' }');
20
+ process.exit(1);
21
+ }
22
+
23
+ console.log(`检测到 ${detected.length} 个 AI 工具:\n`);
24
+
25
+ for (const tool of detected) {
26
+ const result = await writeMcpConfig(tool);
27
+ console.log(` ${result.success ? '✓' : '✗'} ${result.message}`);
28
+ }
29
+
30
+ console.log('\n安装完成!重启你的 AI 工具后即可使用 yo-bug。');
31
+ console.log('AI 会自动获得 start_test_session 等工具,无需其他操作。');
32
+ }
33
+
34
+ main().catch(console.error);
package/bin/mcp.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../src/mcp/index.js';
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ declare const command: string;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";AAEA,QAAA,MAAM,OAAO,QAAkB,CAAC"}
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ const command = process.argv[2];
4
+ if (command === 'mcp') {
5
+ // Start MCP server (stdio mode)
6
+ import('../src/mcp/index.js');
7
+ }
8
+ else if (command === 'install') {
9
+ // Install MCP config to AI tools
10
+ import('./install.js');
11
+ }
12
+ else {
13
+ console.log('yo-bug — AI Agent 的测试之眼\n');
14
+ console.log('用法:');
15
+ console.log(' npx yo-bug install 安装 MCP 到你的 AI 工具');
16
+ console.log(' npx yo-bug mcp 启动 MCP Server(由 AI 工具自动调用)');
17
+ console.log('\n安装后,AI 会自动获得测试模式能力,你不需要其他操作。');
18
+ }
19
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";;AAEA,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;IACtB,gCAAgC;IAChC,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAChC,CAAC;KAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;IACjC,iCAAiC;IACjC,MAAM,CAAC,cAAc,CAAC,CAAC;AACzB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnB,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../bin/install.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import { detectAITools } from '../src/install/detect-ai-tool.js';
3
+ import { writeMcpConfig } from '../src/install/write-mcp-config.js';
4
+ async function main() {
5
+ console.log('yo-bug — 安装 MCP Server\n');
6
+ const tools = await detectAITools();
7
+ const detected = tools.filter((t) => t.detected);
8
+ if (detected.length === 0) {
9
+ console.log('未检测到任何 AI 工具(Claude Code / Cursor / Windsurf)。');
10
+ console.log('请先安装至少一个 AI 编程工具后再运行此命令。\n');
11
+ console.log('手动配置方法:');
12
+ console.log(' 在 AI 工具的 MCP 配置中添加:');
13
+ console.log(' {');
14
+ console.log(' "command": "npx",');
15
+ console.log(' "args": ["yo-bug", "mcp"]');
16
+ console.log(' }');
17
+ process.exit(1);
18
+ }
19
+ console.log(`检测到 ${detected.length} 个 AI 工具:\n`);
20
+ for (const tool of detected) {
21
+ const result = await writeMcpConfig(tool);
22
+ console.log(` ${result.success ? '✓' : '✗'} ${result.message}`);
23
+ }
24
+ console.log('\n安装完成!重启你的 AI 工具后即可使用 yo-bug。');
25
+ console.log('AI 会自动获得 start_test_session 等工具,无需其他操作。');
26
+ }
27
+ main().catch(console.error);
28
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../bin/install.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAExC,MAAM,KAAK,GAAG,MAAM,aAAa,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAEjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,OAAO,QAAQ,CAAC,MAAM,aAAa,CAAC,CAAC;IAEjD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;AACzD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import '../src/mcp/index.js';
3
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../bin/mcp.ts"],"names":[],"mappings":";AACA,OAAO,qBAAqB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import '../src/mcp/index.js';
3
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../bin/mcp.ts"],"names":[],"mappings":";AACA,OAAO,qBAAqB,CAAC"}
@@ -0,0 +1,11 @@
1
+ interface DevServerInfo {
2
+ framework: string;
3
+ port: number;
4
+ command: string;
5
+ isRunning: boolean;
6
+ }
7
+ export declare function detectDevServer(cwd: string, manualPort?: number): Promise<DevServerInfo>;
8
+ export declare function isPortInUse(port: number): Promise<boolean>;
9
+ export declare function waitForPort(port: number, timeout?: number): Promise<boolean>;
10
+ export {};
11
+ //# sourceMappingURL=dev-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../src/detect/dev-server.ts"],"names":[],"mappings":"AAIA,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAaD,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CAqDxB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB1D;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,SAAQ,GACd,OAAO,CAAC,OAAO,CAAC,CAOlB"}
@@ -0,0 +1,92 @@
1
+ import fs from 'fs/promises';
2
+ import net from 'net';
3
+ import path from 'path';
4
+ const FRAMEWORK_PORTS = {
5
+ vite: { port: 5173, keywords: ['vite'] },
6
+ next: { port: 3000, keywords: ['next'] },
7
+ 'create-react-app': { port: 3000, keywords: ['react-scripts'] },
8
+ webpack: { port: 8080, keywords: ['webpack serve', 'webpack-dev-server'] },
9
+ nuxt: { port: 3000, keywords: ['nuxt'] },
10
+ angular: { port: 4200, keywords: ['ng serve'] },
11
+ svelte: { port: 5173, keywords: ['svelte-kit', 'vite'] },
12
+ astro: { port: 4321, keywords: ['astro'] },
13
+ };
14
+ export async function detectDevServer(cwd, manualPort) {
15
+ // Read package.json
16
+ let devCommand = '';
17
+ let framework = 'unknown';
18
+ let port = manualPort || 0;
19
+ try {
20
+ const pkgPath = path.join(cwd, 'package.json');
21
+ const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf-8'));
22
+ const scripts = pkg.scripts || {};
23
+ // Check "dev" or "start" scripts
24
+ devCommand = scripts.dev || scripts.start || '';
25
+ // Match framework
26
+ for (const [name, info] of Object.entries(FRAMEWORK_PORTS)) {
27
+ if (info.keywords.some((kw) => devCommand.includes(kw))) {
28
+ framework = name;
29
+ if (!manualPort)
30
+ port = info.port;
31
+ break;
32
+ }
33
+ }
34
+ // Also check dependencies for framework detection
35
+ if (framework === 'unknown') {
36
+ const allDeps = {
37
+ ...pkg.dependencies,
38
+ ...pkg.devDependencies,
39
+ };
40
+ for (const [name, info] of Object.entries(FRAMEWORK_PORTS)) {
41
+ if (info.keywords.some((kw) => kw in allDeps)) {
42
+ framework = name;
43
+ if (!manualPort)
44
+ port = info.port;
45
+ break;
46
+ }
47
+ }
48
+ }
49
+ }
50
+ catch {
51
+ // No package.json found
52
+ }
53
+ // Default port
54
+ if (!port)
55
+ port = 3000;
56
+ // Check if port is already in use
57
+ const isRunning = await isPortInUse(port);
58
+ return {
59
+ framework,
60
+ port,
61
+ command: devCommand,
62
+ isRunning,
63
+ };
64
+ }
65
+ export function isPortInUse(port) {
66
+ return new Promise((resolve) => {
67
+ const socket = new net.Socket();
68
+ socket.setTimeout(1000);
69
+ socket.on('connect', () => {
70
+ socket.destroy();
71
+ resolve(true);
72
+ });
73
+ socket.on('timeout', () => {
74
+ socket.destroy();
75
+ resolve(false);
76
+ });
77
+ socket.on('error', () => {
78
+ resolve(false);
79
+ });
80
+ socket.connect(port, '127.0.0.1');
81
+ });
82
+ }
83
+ export async function waitForPort(port, timeout = 30000) {
84
+ const start = Date.now();
85
+ while (Date.now() - start < timeout) {
86
+ if (await isPortInUse(port))
87
+ return true;
88
+ await new Promise((r) => setTimeout(r, 500));
89
+ }
90
+ return false;
91
+ }
92
+ //# sourceMappingURL=dev-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../../src/detect/dev-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function spawnDevServer(cwd: string, command: string, port: number): Promise<boolean>;
2
+ export declare function killDevServer(): void;
3
+ export declare function isDevServerSpawned(): boolean;
4
+ //# sourceMappingURL=spawn-dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-dev.d.ts","sourceRoot":"","sources":["../../../src/detect/spawn-dev.ts"],"names":[],"mappings":"AAKA,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CA6BlB;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C"}
@@ -0,0 +1,37 @@
1
+ import { spawn } from 'child_process';
2
+ import { waitForPort } from './dev-server.js';
3
+ let devProcess = null;
4
+ export async function spawnDevServer(cwd, command, port) {
5
+ const isWindows = process.platform === 'win32';
6
+ const npmCmd = isWindows ? 'npm.cmd' : 'npm';
7
+ // Use the detected script name (e.g., "dev" or "start")
8
+ const scriptName = command.includes('start') ? 'start' : 'dev';
9
+ devProcess = spawn(npmCmd, ['run', scriptName], {
10
+ cwd,
11
+ shell: isWindows,
12
+ stdio: 'pipe', // Don't inherit — we're an MCP server using stdio
13
+ env: { ...process.env },
14
+ });
15
+ devProcess.stdout?.on('data', () => {
16
+ // Silently consume output — MCP server uses stdio
17
+ });
18
+ devProcess.stderr?.on('data', () => {
19
+ // Silently consume stderr
20
+ });
21
+ devProcess.on('error', () => {
22
+ // Silently handle — MCP server uses stdio, can't write to stderr
23
+ });
24
+ // Wait for the port to become available
25
+ const ready = await waitForPort(port, 30000);
26
+ return ready;
27
+ }
28
+ export function killDevServer() {
29
+ if (devProcess) {
30
+ devProcess.kill();
31
+ devProcess = null;
32
+ }
33
+ }
34
+ export function isDevServerSpawned() {
35
+ return devProcess !== null && !devProcess.killed;
36
+ }
37
+ //# sourceMappingURL=spawn-dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-dev.js","sourceRoot":"","sources":["../../../src/detect/spawn-dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,IAAI,UAAU,GAAwB,IAAI,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,OAAe,EACf,IAAY;IAEZ,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;IAC/C,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IAE7C,wDAAwD;IACxD,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAE/D,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE;QAC9C,GAAG;QACH,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,MAAM,EAAE,kDAAkD;QACjE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;KACxB,CAAC,CAAC;IAEH,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACjC,kDAAkD;IACpD,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;QACjC,0BAA0B;IAC5B,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAC1B,iEAAiE;IACnE,CAAC,CAAC,CAAC;IAEH,wCAAwC;IACxC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,UAAU,EAAE,CAAC;QACf,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,UAAU,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;AACnD,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface AITool {
2
+ name: string;
3
+ configPath: string;
4
+ detected: boolean;
5
+ }
6
+ export declare function detectAITools(): Promise<AITool[]>;
7
+ //# sourceMappingURL=detect-ai-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-ai-tool.d.ts","sourceRoot":"","sources":["../../../src/install/detect-ai-tool.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAID,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BvD"}
@@ -0,0 +1,38 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ const HOME = process.env.HOME || process.env.USERPROFILE || '';
4
+ export async function detectAITools() {
5
+ const tools = [];
6
+ // Claude Code
7
+ const claudeDir = path.join(HOME, '.claude');
8
+ tools.push({
9
+ name: 'Claude Code',
10
+ configPath: path.join(claudeDir, 'settings.json'),
11
+ detected: await dirExists(claudeDir),
12
+ });
13
+ // Cursor
14
+ const cursorDir = path.join(HOME, '.cursor');
15
+ tools.push({
16
+ name: 'Cursor',
17
+ configPath: path.join(cursorDir, 'mcp.json'),
18
+ detected: await dirExists(cursorDir),
19
+ });
20
+ // Windsurf
21
+ const windsurfDir = path.join(HOME, '.windsurf');
22
+ tools.push({
23
+ name: 'Windsurf',
24
+ configPath: path.join(windsurfDir, 'mcp.json'),
25
+ detected: await dirExists(windsurfDir),
26
+ });
27
+ return tools;
28
+ }
29
+ async function dirExists(dir) {
30
+ try {
31
+ const stat = await fs.stat(dir);
32
+ return stat.isDirectory();
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ //# sourceMappingURL=detect-ai-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-ai-tool.js","sourceRoot":"","sources":["../../../src/install/detect-ai-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,cAAc;IACd,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,aAAa;QACnB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC;QACjD,QAAQ,EAAE,MAAM,SAAS,CAAC,SAAS,CAAC;KACrC,CAAC,CAAC;IAEH,SAAS;IACT,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;QAC5C,QAAQ,EAAE,MAAM,SAAS,CAAC,SAAS,CAAC;KACrC,CAAC,CAAC;IAEH,WAAW;IACX,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACjD,KAAK,CAAC,IAAI,CAAC;QACT,IAAI,EAAE,UAAU;QAChB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC;QAC9C,QAAQ,EAAE,MAAM,SAAS,CAAC,WAAW,CAAC;KACvC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { AITool } from './detect-ai-tool.js';
2
+ export declare function writeMcpConfig(tool: AITool): Promise<{
3
+ success: boolean;
4
+ message: string;
5
+ }>;
6
+ //# sourceMappingURL=write-mcp-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-mcp-config.d.ts","sourceRoot":"","sources":["../../../src/install/write-mcp-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAOlD,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAuCjG"}
@@ -0,0 +1,47 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ const MCP_SERVER_CONFIG = {
4
+ command: 'npx',
5
+ args: ['yo-bug', 'mcp'],
6
+ };
7
+ export async function writeMcpConfig(tool) {
8
+ try {
9
+ // Ensure directory exists
10
+ await fs.mkdir(path.dirname(tool.configPath), { recursive: true });
11
+ // Read existing config
12
+ let config = {};
13
+ try {
14
+ const content = await fs.readFile(tool.configPath, 'utf-8');
15
+ config = JSON.parse(content);
16
+ }
17
+ catch {
18
+ // File doesn't exist or invalid JSON — start fresh
19
+ }
20
+ // Check if already configured
21
+ if (tool.name === 'Claude Code') {
22
+ config.mcpServers = config.mcpServers || {};
23
+ if (config.mcpServers['yo-bug']) {
24
+ return { success: true, message: `${tool.name}: 已配置,跳过。` };
25
+ }
26
+ config.mcpServers['yo-bug'] = {
27
+ type: 'stdio',
28
+ ...MCP_SERVER_CONFIG,
29
+ };
30
+ }
31
+ else {
32
+ // Cursor / Windsurf format
33
+ config.mcpServers = config.mcpServers || {};
34
+ if (config.mcpServers['yo-bug']) {
35
+ return { success: true, message: `${tool.name}: 已配置,跳过。` };
36
+ }
37
+ config.mcpServers['yo-bug'] = MCP_SERVER_CONFIG;
38
+ }
39
+ // Write config
40
+ await fs.writeFile(tool.configPath, JSON.stringify(config, null, 2), 'utf-8');
41
+ return { success: true, message: `${tool.name}: MCP 配置已写入 ${tool.configPath}` };
42
+ }
43
+ catch (err) {
44
+ return { success: false, message: `${tool.name}: 写入失败 — ${err.message}` };
45
+ }
46
+ }
47
+ //# sourceMappingURL=write-mcp-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-mcp-config.js","sourceRoot":"","sources":["../../../src/install/write-mcp-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,iBAAiB,GAAG;IACxB,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;CACxB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,IAAI,CAAC;QACH,0BAA0B;QAC1B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEnE,uBAAuB;QACvB,IAAI,MAAM,GAAQ,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC5D,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;QAED,8BAA8B;QAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;YAC5C,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,WAAW,EAAE,CAAC;YAC7D,CAAC;YACD,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG;gBAC5B,IAAI,EAAE,OAAO;gBACb,GAAG,iBAAiB;aACrB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,2BAA2B;YAC3B,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;YAC5C,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,WAAW,EAAE,CAAC;YAC7D,CAAC;YACD,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CAAC;QAClD,CAAC;QAED,eAAe;QACf,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,eAAe,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;IAClF,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,YAAY,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;IAC5E,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/index.ts"],"names":[],"mappings":""}