@dyyz1993/create-agent 2.1.0 → 2.1.2

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 (349) hide show
  1. package/package.json +5 -4
  2. package/src/__tests__/cli.test.ts +2 -0
  3. package/src/__tests__/copy.test.ts +110 -122
  4. package/src/__tests__/create-args.test.ts +113 -0
  5. package/src/__tests__/templates.test.ts +29 -3
  6. package/src/__tests__/update.test.ts +129 -0
  7. package/src/cli.ts +30 -32
  8. package/src/commands/create.ts +83 -24
  9. package/src/commands/update.ts +174 -0
  10. package/src/commands/workspace.ts +26 -6
  11. package/src/lib/copy.ts +233 -93
  12. package/src/lib/templates.ts +12 -0
  13. package/templates/agent/.husky/commit-msg +4 -0
  14. package/templates/agent/.husky/pre-commit +11 -0
  15. package/templates/agent/.husky/pre-push +6 -0
  16. package/templates/agent/.prettierignore +6 -0
  17. package/templates/agent/.prettierrc +9 -0
  18. package/templates/agent/CHANGELOG.md +15 -0
  19. package/templates/agent/commitlint.config.js +8 -0
  20. package/templates/agent/package.json +19 -4
  21. package/templates/agent/src/gateway/__tests__/ws-handler-token.test.ts +53 -39
  22. package/templates/agent/src/mainview/App.tsx +14 -12
  23. package/templates/agent/src/mainview/__tests__/hooks/use-rpc-init.test.ts +194 -190
  24. package/templates/agent/src/mainview/components/bash/BashPanel.tsx +210 -189
  25. package/templates/agent/src/mainview/components/chat/ChatPanel.tsx +45 -20
  26. package/templates/agent/src/mainview/components/common/ThemeToggle.tsx +41 -21
  27. package/templates/agent/src/mainview/components/debug/DebugPanel.tsx +181 -114
  28. package/templates/agent/src/mainview/components/debug/__tests__/DebugPanel.test.tsx +80 -80
  29. package/templates/agent/src/mainview/components/diff/__tests__/DiffViewerPanel.test.tsx +61 -58
  30. package/templates/agent/src/mainview/components/feed/FeedPanel.tsx +43 -41
  31. package/templates/agent/src/mainview/components/file-preview/FilePreviewOverlay.tsx +69 -50
  32. package/templates/agent/src/mainview/components/file-preview/VirtualizedCodeView.tsx +31 -18
  33. package/templates/agent/src/mainview/components/git/GitPanel.tsx +731 -490
  34. package/templates/agent/src/mainview/components/git/__tests__/GitPanel.test.tsx +157 -139
  35. package/templates/agent/src/mainview/components/layout/AppLayout.tsx +210 -161
  36. package/templates/agent/src/mainview/components/layout/__tests__/AppLayout.test.tsx +130 -122
  37. package/templates/agent/src/mainview/components/rules/RulesPanel.tsx +119 -109
  38. package/templates/agent/src/mainview/components/search/SearchPanel.tsx +123 -117
  39. package/templates/agent/src/mainview/components/search/__tests__/SearchPanel.test.tsx +64 -44
  40. package/templates/agent/src/mainview/components/sidebar/__tests__/PinButton.test.tsx +38 -38
  41. package/templates/agent/src/mainview/components/todo/TodoPanel.tsx +40 -38
  42. package/templates/agent/src/mainview/components/todo/__tests__/TodoPanel.test.tsx +72 -72
  43. package/templates/agent/src/mainview/lib/i18n/locales/en.json +175 -155
  44. package/templates/agent/src/mainview/lib/i18n/locales/zh.json +173 -155
  45. package/templates/agent/src/mainview/stores/use-app-store.ts +96 -86
  46. package/templates/agent/src/mainview/stores/use-explorer-store.ts +292 -275
  47. package/templates/agent/src/mainview/types/index.ts +23 -22
  48. package/templates/agent/src/mainview/utils/file-icon.tsx +17 -21
  49. package/templates/agent/src/shared/handlers/chat.ts +53 -53
  50. package/templates/agent/src/shared/handlers/debug.ts +13 -3
  51. package/templates/browser-agent/.env.example +19 -0
  52. package/templates/browser-agent/.husky/commit-msg +4 -0
  53. package/templates/browser-agent/.husky/pre-commit +11 -0
  54. package/templates/browser-agent/.husky/pre-push +6 -0
  55. package/templates/browser-agent/.prettierignore +6 -0
  56. package/templates/browser-agent/.prettierrc +9 -0
  57. package/templates/browser-agent/AGENTS.md +396 -0
  58. package/templates/browser-agent/CHANGELOG.md +15 -0
  59. package/templates/browser-agent/LICENSE +21 -0
  60. package/templates/browser-agent/README.md +103 -0
  61. package/templates/browser-agent/commitlint.config.js +8 -0
  62. package/templates/browser-agent/electrobun.config.ts +27 -0
  63. package/templates/browser-agent/electron/main.js +46 -0
  64. package/templates/browser-agent/electron/preload.js +5 -0
  65. package/templates/browser-agent/electron-builder.json +40 -0
  66. package/templates/browser-agent/eslint.config.mjs +79 -0
  67. package/templates/browser-agent/llms.txt +24 -0
  68. package/templates/browser-agent/package.json +140 -0
  69. package/templates/browser-agent/postcss.config.js +6 -0
  70. package/templates/browser-agent/scripts/dev.ts +138 -0
  71. package/templates/browser-agent/src/__tests__/hybrid-mode.test.ts +126 -0
  72. package/templates/browser-agent/src/__tests__/server-config-security.test.ts +55 -0
  73. package/templates/browser-agent/src/__tests__/server-config.test.ts +59 -0
  74. package/templates/browser-agent/src/bun/index.ts +130 -0
  75. package/templates/browser-agent/src/bun/three.d.ts +1 -0
  76. package/templates/browser-agent/src/gateway/http-routes.ts +1 -0
  77. package/templates/browser-agent/src/gateway/ipc-transport.ts +68 -0
  78. package/templates/browser-agent/src/gateway/sse-transport.ts +221 -0
  79. package/templates/browser-agent/src/mainview/App.tsx +45 -0
  80. package/templates/browser-agent/src/mainview/__tests__/hooks/use-rpc-init.test.ts +202 -0
  81. package/templates/browser-agent/src/mainview/__tests__/hooks/use-sidebar-resize.test.ts +127 -0
  82. package/templates/browser-agent/src/mainview/__tests__/i18n/i18n.test.ts +49 -0
  83. package/templates/browser-agent/src/mainview/__tests__/setup.ts +40 -0
  84. package/templates/browser-agent/src/mainview/__tests__/stores/use-chat-store.test.ts +73 -0
  85. package/templates/browser-agent/src/mainview/__tests__/stores/use-sidebar-store.test.ts +61 -0
  86. package/templates/browser-agent/src/mainview/__tests__/theme-variables.test.ts +36 -0
  87. package/templates/browser-agent/src/mainview/components/assets/AssetsPanel.tsx +139 -0
  88. package/templates/browser-agent/src/mainview/components/chat/ChatPanel.tsx +219 -0
  89. package/templates/browser-agent/src/mainview/components/chat/CommandBar.tsx +184 -0
  90. package/templates/browser-agent/src/mainview/components/chat/MessageBubble.tsx +249 -0
  91. package/templates/browser-agent/src/mainview/components/chat/ToolPicker.tsx +115 -0
  92. package/templates/browser-agent/src/mainview/components/common/ErrorBoundary.tsx +1 -0
  93. package/templates/browser-agent/src/mainview/components/common/LanguageSwitcher.tsx +15 -0
  94. package/templates/browser-agent/src/mainview/components/common/ThemeToggle.tsx +45 -0
  95. package/templates/browser-agent/src/mainview/components/common/__tests__/ErrorBoundary.test.tsx +74 -0
  96. package/templates/browser-agent/src/mainview/components/common/__tests__/LanguageSwitcher.test.tsx +44 -0
  97. package/templates/browser-agent/src/mainview/components/common/__tests__/ThemeToggle.test.tsx +41 -0
  98. package/templates/browser-agent/src/mainview/components/dev/NetworkPanel.tsx +155 -0
  99. package/templates/browser-agent/src/mainview/components/layout/AppLayout.tsx +311 -0
  100. package/templates/browser-agent/src/mainview/components/onboarding/SetupWizard.tsx +310 -0
  101. package/templates/browser-agent/src/mainview/components/process/ProcessPanel.tsx +329 -0
  102. package/templates/browser-agent/src/mainview/components/sidebar/SessionSidebar.tsx +122 -0
  103. package/templates/browser-agent/src/mainview/components/sidebar/SkillSidebar.tsx +115 -0
  104. package/templates/browser-agent/src/mainview/components/topbar/TopBar.tsx +350 -0
  105. package/templates/browser-agent/src/mainview/global.d.ts +13 -0
  106. package/templates/browser-agent/src/mainview/hooks/__tests__/use-breakpoint.test.ts +151 -0
  107. package/templates/browser-agent/src/mainview/hooks/use-agent-chat.ts +157 -0
  108. package/templates/browser-agent/src/mainview/hooks/use-breakpoint.ts +68 -0
  109. package/templates/browser-agent/src/mainview/hooks/use-rpc-init.ts +71 -0
  110. package/templates/browser-agent/src/mainview/hooks/use-sidebar-resize.ts +40 -0
  111. package/templates/browser-agent/src/mainview/index.css +71 -0
  112. package/templates/browser-agent/src/mainview/index.html +12 -0
  113. package/templates/browser-agent/src/mainview/lib/api-client.ts +397 -0
  114. package/templates/browser-agent/src/mainview/lib/i18n/index.ts +30 -0
  115. package/templates/browser-agent/src/mainview/lib/i18n/locales/en.json +130 -0
  116. package/templates/browser-agent/src/mainview/lib/i18n/locales/zh.json +128 -0
  117. package/templates/browser-agent/src/mainview/lib/network-bus.ts +92 -0
  118. package/templates/browser-agent/src/mainview/lib/rpc-cache.ts +94 -0
  119. package/templates/browser-agent/src/mainview/main.tsx +18 -0
  120. package/templates/browser-agent/src/mainview/stores/__tests__/use-connection-store.test.ts +26 -0
  121. package/templates/browser-agent/src/mainview/stores/__tests__/use-locale-store.test.ts +32 -0
  122. package/templates/browser-agent/src/mainview/stores/__tests__/use-log-store.test.ts +28 -0
  123. package/templates/browser-agent/src/mainview/stores/__tests__/use-theme-store.test.ts +59 -0
  124. package/templates/browser-agent/src/mainview/stores/message-batcher.ts +25 -0
  125. package/templates/browser-agent/src/mainview/stores/use-asset-store.ts +65 -0
  126. package/templates/browser-agent/src/mainview/stores/use-chat-store.ts +200 -0
  127. package/templates/browser-agent/src/mainview/stores/use-connection-store.ts +173 -0
  128. package/templates/browser-agent/src/mainview/stores/use-locale-store.ts +27 -0
  129. package/templates/browser-agent/src/mainview/stores/use-log-store.ts +16 -0
  130. package/templates/browser-agent/src/mainview/stores/use-network-panel-store.ts +18 -0
  131. package/templates/browser-agent/src/mainview/stores/use-record-store.ts +147 -0
  132. package/templates/browser-agent/src/mainview/stores/use-session-store.ts +151 -0
  133. package/templates/browser-agent/src/mainview/stores/use-sidebar-store.ts +161 -0
  134. package/templates/browser-agent/src/mainview/stores/use-theme-store.ts +46 -0
  135. package/templates/browser-agent/src/mainview/stores/use-view-store.ts +20 -0
  136. package/templates/browser-agent/src/mainview/types/index.ts +6 -0
  137. package/templates/browser-agent/src/server-config.ts +45 -0
  138. package/templates/browser-agent/src/server.ts +78 -0
  139. package/templates/browser-agent/src/shared/handlers/__tests__/chat-concurrency.test.ts +127 -0
  140. package/templates/browser-agent/src/shared/handlers/__tests__/chat-handler.test.ts +77 -0
  141. package/templates/browser-agent/src/shared/handlers/__tests__/file-handler.test.ts +100 -0
  142. package/templates/browser-agent/src/shared/handlers/__tests__/system-handler.test.ts +55 -0
  143. package/templates/browser-agent/src/shared/handlers/__tests__/timer-handler.test.ts +77 -0
  144. package/templates/browser-agent/src/shared/handlers/browser.ts +596 -0
  145. package/templates/browser-agent/src/shared/handlers/chat.ts +213 -0
  146. package/templates/browser-agent/src/shared/handlers/file.ts +99 -0
  147. package/templates/browser-agent/src/shared/handlers/index.ts +7 -0
  148. package/templates/browser-agent/src/shared/handlers/session.ts +167 -0
  149. package/templates/browser-agent/src/shared/handlers/system.ts +27 -0
  150. package/templates/browser-agent/src/shared/handlers/timer.ts +34 -0
  151. package/templates/browser-agent/src/shared/http-routes.ts +437 -0
  152. package/templates/browser-agent/src/shared/lib/__tests__/logger.test.ts +92 -0
  153. package/templates/browser-agent/src/shared/lib/__tests__/path-security.test.ts +77 -0
  154. package/templates/browser-agent/src/shared/lib/__tests__/web-server.test.ts +203 -0
  155. package/templates/browser-agent/src/shared/lib/agent.ts +384 -0
  156. package/templates/browser-agent/src/shared/lib/cdp.ts +448 -0
  157. package/templates/browser-agent/src/shared/lib/generate.ts +111 -0
  158. package/templates/browser-agent/src/shared/lib/logger.ts +152 -0
  159. package/templates/browser-agent/src/shared/lib/mock-stream.ts +147 -0
  160. package/templates/browser-agent/src/shared/lib/path-security.ts +38 -0
  161. package/templates/browser-agent/src/shared/lib/port-registry.ts +103 -0
  162. package/templates/browser-agent/src/shared/lib/web-server.ts +127 -0
  163. package/templates/browser-agent/src/shared/lib/xhs-extract.ts +71 -0
  164. package/templates/browser-agent/src/shared/modules/browser.ts +86 -0
  165. package/templates/browser-agent/src/shared/modules/chat.ts +20 -0
  166. package/templates/browser-agent/src/shared/modules/file.ts +40 -0
  167. package/templates/browser-agent/src/shared/modules/session.ts +55 -0
  168. package/templates/browser-agent/src/shared/modules/system.ts +8 -0
  169. package/templates/browser-agent/src/shared/modules/timer.ts +11 -0
  170. package/templates/browser-agent/src/shared/register-all-handlers.ts +36 -0
  171. package/templates/browser-agent/src/shared/rpc-schema.ts +34 -0
  172. package/templates/browser-agent/tailwind.config.js +15 -0
  173. package/templates/browser-agent/tsconfig.ipc.json +14 -0
  174. package/templates/browser-agent/tsconfig.json +36 -0
  175. package/templates/browser-agent/vite.config.ts +3 -0
  176. package/templates/browser-agent/vitest.config.ts +3 -0
  177. package/templates/chat/.husky/commit-msg +4 -0
  178. package/templates/chat/.husky/pre-commit +11 -0
  179. package/templates/chat/.husky/pre-push +6 -0
  180. package/templates/chat/CHANGELOG.md +15 -0
  181. package/templates/chat/commitlint.config.js +8 -0
  182. package/templates/chat/package.json +19 -4
  183. package/templates/chat/src/mainview/__tests__/hooks/use-input-history.test.ts +125 -0
  184. package/templates/chat/src/mainview/__tests__/setup.ts +32 -29
  185. package/templates/chat/src/mainview/components/chat/ChatPanel.tsx +80 -55
  186. package/templates/chat/src/mainview/components/common/ThemeToggle.tsx +40 -20
  187. package/templates/chat/src/mainview/lib/i18n/locales/en.json +175 -155
  188. package/templates/chat/src/mainview/lib/i18n/locales/zh.json +173 -155
  189. package/templates/chat/src/shared/handlers/chat.ts +17 -19
  190. package/templates/chat/src/shared/handlers/debug.ts +12 -2
  191. package/templates/cowork/.env.example +8 -0
  192. package/templates/cowork/.prettierignore +6 -0
  193. package/templates/cowork/.prettierrc +9 -0
  194. package/templates/cowork/AGENTS.md +236 -0
  195. package/templates/cowork/CHANGELOG.md +15 -0
  196. package/templates/cowork/LICENSE +21 -0
  197. package/templates/cowork/README.md +103 -0
  198. package/templates/cowork/commitlint.config.js +8 -0
  199. package/templates/cowork/docs/CODE-VIEW-PLAN.md +637 -0
  200. package/templates/cowork/docs/CODE-VIEW-V2.md +196 -0
  201. package/templates/cowork/docs/CODE-VIEW-V4.md +150 -0
  202. package/templates/cowork/electrobun.config.ts +27 -0
  203. package/templates/cowork/eslint.config.mjs +79 -0
  204. package/templates/cowork/llms.txt +24 -0
  205. package/templates/cowork/package.json +87 -0
  206. package/templates/cowork/postcss.config.js +6 -0
  207. package/templates/cowork/scripts/dev.ts +138 -0
  208. package/templates/cowork/src/__tests__/hybrid-mode.test.ts +126 -0
  209. package/templates/cowork/src/__tests__/server-config-security.test.ts +55 -0
  210. package/templates/cowork/src/__tests__/server-config.test.ts +59 -0
  211. package/templates/cowork/src/bun/index.ts +130 -0
  212. package/templates/cowork/src/bun/three.d.ts +1 -0
  213. package/templates/cowork/src/gateway/http-routes.ts +1 -0
  214. package/templates/cowork/src/gateway/ipc-transport.ts +68 -0
  215. package/templates/cowork/src/gateway/sse-transport.ts +231 -0
  216. package/templates/cowork/src/mainview/App.tsx +45 -0
  217. package/templates/cowork/src/mainview/__tests__/hooks/use-rpc-init.test.ts +202 -0
  218. package/templates/cowork/src/mainview/__tests__/hooks/use-sidebar-resize.test.ts +127 -0
  219. package/templates/cowork/src/mainview/__tests__/i18n/i18n.test.ts +49 -0
  220. package/templates/cowork/src/mainview/__tests__/setup.ts +40 -0
  221. package/templates/cowork/src/mainview/__tests__/stores/use-chat-store.test.ts +73 -0
  222. package/templates/cowork/src/mainview/__tests__/stores/use-sidebar-store.test.ts +61 -0
  223. package/templates/cowork/src/mainview/__tests__/theme-variables.test.ts +36 -0
  224. package/templates/cowork/src/mainview/components/chat/TaskChat.tsx +311 -0
  225. package/templates/cowork/src/mainview/components/chat/__tests__/localhost-links.test.ts +76 -0
  226. package/templates/cowork/src/mainview/components/common/ErrorBoundary.tsx +1 -0
  227. package/templates/cowork/src/mainview/components/common/LanguageSwitcher.tsx +15 -0
  228. package/templates/cowork/src/mainview/components/common/ThemeToggle.tsx +45 -0
  229. package/templates/cowork/src/mainview/components/common/__tests__/ErrorBoundary.test.tsx +74 -0
  230. package/templates/cowork/src/mainview/components/common/__tests__/LanguageSwitcher.test.tsx +44 -0
  231. package/templates/cowork/src/mainview/components/common/__tests__/ThemeToggle.test.tsx +41 -0
  232. package/templates/cowork/src/mainview/components/dev/NetworkPanel.tsx +155 -0
  233. package/templates/cowork/src/mainview/components/layout/AppLayout.tsx +216 -0
  234. package/templates/cowork/src/mainview/components/right/ArtifactsPanel.tsx +54 -0
  235. package/templates/cowork/src/mainview/components/right/ContextPanel.tsx +133 -0
  236. package/templates/cowork/src/mainview/components/right/ElementPicker.tsx +206 -0
  237. package/templates/cowork/src/mainview/components/right/PreviewBlock.tsx +155 -0
  238. package/templates/cowork/src/mainview/components/right/ProgressPanel.tsx +85 -0
  239. package/templates/cowork/src/mainview/components/sidebar/TaskSidebar.tsx +211 -0
  240. package/templates/cowork/src/mainview/components/topbar/TopBar.tsx +86 -0
  241. package/templates/cowork/src/mainview/global.d.ts +13 -0
  242. package/templates/cowork/src/mainview/hooks/__tests__/use-breakpoint.test.ts +123 -0
  243. package/templates/cowork/src/mainview/hooks/use-breakpoint.ts +53 -0
  244. package/templates/cowork/src/mainview/hooks/use-rpc-init.ts +26 -0
  245. package/templates/cowork/src/mainview/hooks/use-sidebar-resize.ts +40 -0
  246. package/templates/cowork/src/mainview/index.css +89 -0
  247. package/templates/cowork/src/mainview/index.html +12 -0
  248. package/templates/cowork/src/mainview/lib/api-client.ts +404 -0
  249. package/templates/cowork/src/mainview/lib/i18n/index.ts +30 -0
  250. package/templates/cowork/src/mainview/lib/i18n/locales/en.json +130 -0
  251. package/templates/cowork/src/mainview/lib/i18n/locales/zh.json +128 -0
  252. package/templates/cowork/src/mainview/lib/network-bus.ts +92 -0
  253. package/templates/cowork/src/mainview/lib/rpc-cache.ts +94 -0
  254. package/templates/cowork/src/mainview/main.tsx +18 -0
  255. package/templates/cowork/src/mainview/stores/__tests__/use-connection-store.test.ts +26 -0
  256. package/templates/cowork/src/mainview/stores/__tests__/use-locale-store.test.ts +32 -0
  257. package/templates/cowork/src/mainview/stores/__tests__/use-log-store.test.ts +28 -0
  258. package/templates/cowork/src/mainview/stores/__tests__/use-preview-store.test.ts +193 -0
  259. package/templates/cowork/src/mainview/stores/__tests__/use-sidebar-store.test.ts +81 -0
  260. package/templates/cowork/src/mainview/stores/__tests__/use-theme-store.test.ts +59 -0
  261. package/templates/cowork/src/mainview/stores/message-batcher.ts +25 -0
  262. package/templates/cowork/src/mainview/stores/use-chat-store.ts +198 -0
  263. package/templates/cowork/src/mainview/stores/use-connection-store.ts +168 -0
  264. package/templates/cowork/src/mainview/stores/use-context-store.ts +68 -0
  265. package/templates/cowork/src/mainview/stores/use-locale-store.ts +27 -0
  266. package/templates/cowork/src/mainview/stores/use-log-store.ts +16 -0
  267. package/templates/cowork/src/mainview/stores/use-network-panel-store.ts +18 -0
  268. package/templates/cowork/src/mainview/stores/use-output-store.ts +47 -0
  269. package/templates/cowork/src/mainview/stores/use-preview-store.ts +97 -0
  270. package/templates/cowork/src/mainview/stores/use-sidebar-store.ts +272 -0
  271. package/templates/cowork/src/mainview/stores/use-task-store.ts +86 -0
  272. package/templates/cowork/src/mainview/stores/use-theme-store.ts +46 -0
  273. package/templates/cowork/src/mainview/stores/use-view-store.ts +29 -0
  274. package/templates/cowork/src/mainview/types/index.ts +6 -0
  275. package/templates/cowork/src/server-config.ts +44 -0
  276. package/templates/cowork/src/server.ts +78 -0
  277. package/templates/cowork/src/shared/handlers/__tests__/chat-concurrency.test.ts +127 -0
  278. package/templates/cowork/src/shared/handlers/__tests__/chat-handler.test.ts +77 -0
  279. package/templates/cowork/src/shared/handlers/__tests__/file-handler.test.ts +100 -0
  280. package/templates/cowork/src/shared/handlers/__tests__/preview-handler.test.ts +172 -0
  281. package/templates/cowork/src/shared/handlers/__tests__/system-handler.test.ts +55 -0
  282. package/templates/cowork/src/shared/handlers/__tests__/timer-handler.test.ts +77 -0
  283. package/templates/cowork/src/shared/handlers/chat.ts +213 -0
  284. package/templates/cowork/src/shared/handlers/context.ts +72 -0
  285. package/templates/cowork/src/shared/handlers/file.ts +99 -0
  286. package/templates/cowork/src/shared/handlers/index.ts +9 -0
  287. package/templates/cowork/src/shared/handlers/output.ts +59 -0
  288. package/templates/cowork/src/shared/handlers/preview.ts +81 -0
  289. package/templates/cowork/src/shared/handlers/system.ts +27 -0
  290. package/templates/cowork/src/shared/handlers/task.ts +101 -0
  291. package/templates/cowork/src/shared/handlers/timer.ts +34 -0
  292. package/templates/cowork/src/shared/http-routes.ts +444 -0
  293. package/templates/cowork/src/shared/lib/__tests__/logger.test.ts +92 -0
  294. package/templates/cowork/src/shared/lib/__tests__/path-security.test.ts +77 -0
  295. package/templates/cowork/src/shared/lib/__tests__/web-server.test.ts +203 -0
  296. package/templates/cowork/src/shared/lib/logger.ts +152 -0
  297. package/templates/cowork/src/shared/lib/path-security.ts +38 -0
  298. package/templates/cowork/src/shared/lib/port-registry.ts +103 -0
  299. package/templates/cowork/src/shared/lib/web-server.ts +127 -0
  300. package/templates/cowork/src/shared/modules/chat.ts +20 -0
  301. package/templates/cowork/src/shared/modules/context.ts +32 -0
  302. package/templates/cowork/src/shared/modules/file.ts +40 -0
  303. package/templates/cowork/src/shared/modules/output.ts +20 -0
  304. package/templates/cowork/src/shared/modules/preview.ts +44 -0
  305. package/templates/cowork/src/shared/modules/system.ts +8 -0
  306. package/templates/cowork/src/shared/modules/task.ts +31 -0
  307. package/templates/cowork/src/shared/modules/timer.ts +11 -0
  308. package/templates/cowork/src/shared/register-all-handlers.ts +36 -0
  309. package/templates/cowork/src/shared/rpc-schema.ts +38 -0
  310. package/templates/cowork/tailwind.config.js +15 -0
  311. package/templates/cowork/test-upload.txt +0 -0
  312. package/templates/cowork/tsconfig.ipc.json +14 -0
  313. package/templates/cowork/tsconfig.json +36 -0
  314. package/templates/cowork/vite.config.ts +3 -0
  315. package/templates/cowork/vitest.config.ts +3 -0
  316. package/templates/general/.husky/commit-msg +4 -0
  317. package/templates/general/.husky/pre-commit +11 -0
  318. package/templates/general/.husky/pre-push +6 -0
  319. package/templates/general/CHANGELOG.md +15 -0
  320. package/templates/general/commitlint.config.js +8 -0
  321. package/templates/general/package.json +19 -4
  322. package/templates/general/src/mainview/__tests__/hooks/use-input-history.test.ts +125 -0
  323. package/templates/general/src/mainview/__tests__/setup.ts +32 -29
  324. package/templates/general/src/mainview/components/chat/ChatPanel.tsx +80 -55
  325. package/templates/general/src/mainview/components/common/ThemeToggle.tsx +40 -20
  326. package/templates/general/src/mainview/components/debug/DebugPanel.tsx +170 -156
  327. package/templates/general/src/mainview/components/debug/__tests__/DebugPanel.test.tsx +169 -0
  328. package/templates/general/src/mainview/components/explorer/ConfirmDialog.tsx +42 -42
  329. package/templates/general/src/mainview/components/explorer/ContextMenu.tsx +72 -67
  330. package/templates/general/src/mainview/components/feed/FeedPanel.tsx +7 -5
  331. package/templates/general/src/mainview/components/file-preview/FilePreviewOverlay.tsx +64 -45
  332. package/templates/general/src/mainview/components/file-preview/VirtualizedCodeView.tsx +24 -7
  333. package/templates/general/src/mainview/components/git/GitPanel.tsx +700 -473
  334. package/templates/general/src/mainview/components/layout/AppLayout.tsx +123 -114
  335. package/templates/general/src/mainview/components/search/SearchPanel.tsx +15 -19
  336. package/templates/general/src/mainview/lib/i18n/locales/en.json +175 -155
  337. package/templates/general/src/mainview/lib/i18n/locales/zh.json +173 -155
  338. package/templates/general/src/mainview/stores/__tests__/use-explorer-store.test.ts +259 -0
  339. package/templates/general/src/mainview/stores/__tests__/use-feed-store.test.ts +160 -0
  340. package/templates/general/src/mainview/stores/__tests__/use-git-store.test.ts +313 -0
  341. package/templates/general/src/mainview/stores/__tests__/use-notification-store.test.ts +115 -0
  342. package/templates/general/src/mainview/stores/__tests__/use-sidebar-store.test.ts +120 -0
  343. package/templates/general/src/mainview/stores/use-explorer-store.ts +277 -260
  344. package/templates/general/src/mainview/types/index.ts +21 -20
  345. package/templates/general/src/shared/handlers/chat.ts +1 -1
  346. package/templates/general/src/shared/handlers/debug.ts +12 -2
  347. package/templates/shared/components/ErrorBoundary.tsx +0 -1
  348. package/templates/shared/vite-base.config.ts +8 -7
  349. /package/templates/{shared → browser-agent}/test-upload.txt +0 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * 任务侧栏 — 所有 Tab 共享同一套任务列表
3
+ *
4
+ * V4:Chat / Code / Cowork 三个 Tab 的左侧面板完全一致,
5
+ * 都显示 New task 按钮 + 任务列表 + 状态色标签。
6
+ * Tab 仅影响中间/右侧内容,左侧保持统一。
7
+ */
8
+ import { useEffect } from 'react';
9
+ import {
10
+ Plus,
11
+ Circle,
12
+ CheckCircle2,
13
+ AlertCircle,
14
+ Clock,
15
+ Loader2,
16
+ type LucideIcon,
17
+ } from 'lucide-react';
18
+ import { useTaskStore, type TaskStatus } from '../../stores/use-task-store';
19
+ import { useViewStore, type CenterTab } from '../../stores/use-view-store';
20
+
21
+ const STATUS_CONFIG: Record<
22
+ TaskStatus,
23
+ { icon: LucideIcon; color: string; bg: string; label: string }
24
+ > = {
25
+ queued: {
26
+ icon: Clock,
27
+ color: 'text-slate-400',
28
+ bg: 'bg-slate-100 dark:bg-slate-700/50',
29
+ label: 'Queued',
30
+ },
31
+ analyzing: {
32
+ icon: Loader2,
33
+ color: 'text-blue-500',
34
+ bg: 'bg-blue-100 dark:bg-blue-900/30',
35
+ label: 'Analyzing',
36
+ },
37
+ executing: {
38
+ icon: Loader2,
39
+ color: 'text-indigo-500',
40
+ bg: 'bg-indigo-100 dark:bg-indigo-900/30',
41
+ label: 'Executing',
42
+ },
43
+ waiting_input: {
44
+ icon: AlertCircle,
45
+ color: 'text-amber-500',
46
+ bg: 'bg-amber-100 dark:bg-amber-900/30',
47
+ label: 'Waiting',
48
+ },
49
+ review: {
50
+ icon: Circle,
51
+ color: 'text-purple-500',
52
+ bg: 'bg-purple-100 dark:bg-purple-900/30',
53
+ label: 'Review',
54
+ },
55
+ completed: {
56
+ icon: CheckCircle2,
57
+ color: 'text-green-600',
58
+ bg: 'bg-green-100 dark:bg-green-900/30',
59
+ label: 'Done',
60
+ },
61
+ failed: {
62
+ icon: AlertCircle,
63
+ color: 'text-red-500',
64
+ bg: 'bg-red-100 dark:bg-red-900/30',
65
+ label: 'Failed',
66
+ },
67
+ };
68
+
69
+ interface TaskSidebarProps {
70
+ collapsed?: boolean;
71
+ }
72
+
73
+ export function TaskSidebar({ collapsed }: TaskSidebarProps) {
74
+ const tasks = useTaskStore((s) => s.tasks);
75
+ const currentTaskId = useTaskStore((s) => s.currentTaskId);
76
+ const fetchTasks = useTaskStore((s) => s.fetchTasks);
77
+ const createTask = useTaskStore((s) => s.createTask);
78
+ const selectTask = useTaskStore((s) => s.selectTask);
79
+
80
+ const centerTab = useViewStore((s) => s.centerTab);
81
+ const setCenterTab = useViewStore((s) => s.setCenterTab);
82
+
83
+ useEffect(() => {
84
+ fetchTasks();
85
+ }, []);
86
+
87
+ // ── 图标条模式 ──
88
+ if (collapsed) {
89
+ return (
90
+ <div className="py-2 px-1.5 flex flex-col items-center gap-1">
91
+ <button
92
+ onClick={() => createTask('新任务')}
93
+ title="新建任务"
94
+ className="w-9 h-9 flex items-center justify-center rounded-lg bg-indigo-100 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400 hover:bg-indigo-200 dark:hover:bg-indigo-800/40 active:scale-95 transition-all"
95
+ >
96
+ <Plus className="w-4 h-4" />
97
+ </button>
98
+ <div className="w-5 h-px bg-[var(--color-border-secondary)] my-1" />
99
+ {tasks.slice(0, 8).map((t) => {
100
+ const cfg = STATUS_CONFIG[t.status] ?? STATUS_CONFIG.queued;
101
+ const Icon = cfg.icon;
102
+ return (
103
+ <button
104
+ key={t.id}
105
+ onClick={() => selectTask(t.id)}
106
+ title={t.title}
107
+ className={`w-9 h-9 flex items-center justify-center rounded-lg transition-all active:scale-95 ${
108
+ t.id === currentTaskId
109
+ ? 'bg-[var(--color-bg-active)]'
110
+ : 'hover:bg-[var(--color-bg-hover)]'
111
+ }`}
112
+ >
113
+ <Icon
114
+ className={`w-4 h-4 ${cfg.color} ${t.status === 'executing' || t.status === 'analyzing' ? 'animate-spin' : ''}`}
115
+ />
116
+ </button>
117
+ );
118
+ })}
119
+ </div>
120
+ );
121
+ }
122
+
123
+ // ── 完整模式(三个 Tab 共享同一套任务列表) ──
124
+ return (
125
+ <div className="flex flex-col h-full">
126
+ {/* Tab 切换 */}
127
+ <div className="flex items-center gap-1 px-3 py-2.5 border-b border-[var(--color-border-secondary)]">
128
+ {(['chat', 'code', 'cowork'] as CenterTab[]).map((tab) => (
129
+ <button
130
+ key={tab}
131
+ onClick={() => setCenterTab(tab)}
132
+ className={`flex-1 px-3 py-1.5 text-[13px] font-medium rounded-lg transition-all ${
133
+ centerTab === tab
134
+ ? 'bg-[var(--color-bg-active)] text-[var(--color-text-primary)]'
135
+ : 'text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)]'
136
+ }`}
137
+ >
138
+ {tab === 'chat' ? 'Chat' : tab === 'code' ? 'Code' : 'Cowork'}
139
+ </button>
140
+ ))}
141
+ </div>
142
+
143
+ {/* New task 按钮(三个 Tab 共享) */}
144
+ <div className="px-3 pt-3 pb-2">
145
+ <button
146
+ onClick={() => createTask('新任务')}
147
+ className="w-full flex items-center gap-2 px-3 py-2 rounded-lg bg-[var(--color-bg-primary)] border border-[var(--color-border-secondary)] text-[var(--color-text-primary)] hover:border-[var(--color-text-accent)] hover:shadow-sm transition-all text-[13px] font-medium"
148
+ >
149
+ <Plus className="w-4 h-4 text-[var(--color-text-accent)]" />
150
+ New task
151
+ </button>
152
+ </div>
153
+
154
+ {/* 任务列表(三个 Tab 共享) */}
155
+ <div className="flex-1 overflow-auto px-2 pt-2 space-y-1">
156
+ {tasks.map((task) => {
157
+ const cfg = STATUS_CONFIG[task.status] ?? STATUS_CONFIG.queued;
158
+ const Icon = cfg.icon;
159
+ const isActive = task.id === currentTaskId;
160
+ return (
161
+ <button
162
+ key={task.id}
163
+ onClick={() => selectTask(task.id)}
164
+ className={`w-full text-left px-3 py-2.5 rounded-lg transition-all ${
165
+ isActive ? 'bg-[var(--color-bg-active)]' : 'hover:bg-[var(--color-bg-hover)]'
166
+ }`}
167
+ >
168
+ <div className="flex items-start gap-2.5">
169
+ <div
170
+ className={`w-6 h-6 rounded-md flex items-center justify-center flex-shrink-0 mt-0.5 ${cfg.bg}`}
171
+ >
172
+ <Icon
173
+ className={`w-3.5 h-3.5 ${cfg.color} ${task.status === 'executing' || task.status === 'analyzing' ? 'animate-spin' : ''}`}
174
+ />
175
+ </div>
176
+ <div className="flex-1 min-w-0">
177
+ <div
178
+ className={`text-[13px] leading-snug truncate ${isActive ? 'font-medium text-[var(--color-text-primary)]' : 'text-[var(--color-text-secondary)]'}`}
179
+ >
180
+ {task.title}
181
+ </div>
182
+ <div className="flex items-center gap-1.5 mt-1">
183
+ <span className={`text-[11px] font-medium ${cfg.color}`}>{cfg.label}</span>
184
+ {task.progress?.steps && (
185
+ <span className="text-[11px] text-[var(--color-text-tertiary)]">
186
+ · {task.progress.steps.filter((s) => s.status === 'done').length}/
187
+ {task.progress.steps.length}
188
+ </span>
189
+ )}
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </button>
194
+ );
195
+ })}
196
+ {tasks.length === 0 && (
197
+ <div className="px-3 py-8 text-center">
198
+ <p className="text-sm text-[var(--color-text-tertiary)]">暂无任务</p>
199
+ </div>
200
+ )}
201
+ </div>
202
+
203
+ {/* 底部提示 */}
204
+ <div className="px-3 py-2.5 border-t border-[var(--color-border-secondary)]">
205
+ <p className="text-[11px] text-[var(--color-text-tertiary)] leading-relaxed">
206
+ These tasks run locally and aren't synced across devices
207
+ </p>
208
+ </div>
209
+ </div>
210
+ );
211
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * 顶栏 — 侧栏 toggle + Logo + 右栏 toggle + 用户头像
3
+ */
4
+ import { PanelLeft, PanelLeftOpen, PanelRight, PanelRightOpen } from 'lucide-react';
5
+ import { useSidebarStore, useRightPanelStore } from '../../stores/use-sidebar-store';
6
+ import { useViewStore } from '../../stores/use-view-store';
7
+
8
+ export function TopBar() {
9
+ // 左栏
10
+ const sbSidebarMode = useSidebarStore((s) => s.sidebarMode);
11
+ const sbCycleMode = useSidebarStore((s) => s.cycleSidebarMode);
12
+ const sbDrawerOpen = useSidebarStore((s) => s.drawerOpen);
13
+ const sbSetDrawerOpen = useSidebarStore((s) => s.setDrawerOpen);
14
+ const sbBreakpoint = useSidebarStore((s) => s.breakpoint);
15
+ const sidebarActive = sbSidebarMode !== 'hidden' || sbDrawerOpen;
16
+
17
+ // 右栏
18
+ const rpMode = useRightPanelStore((s) => s.mode);
19
+ const rpToggle = useRightPanelStore((s) => s.toggleMode);
20
+ const centerTab = useViewStore((s) => s.centerTab);
21
+ const rightPanelToggleable = centerTab !== 'chat' && sbBreakpoint !== 'mobile';
22
+
23
+ const handleSidebarToggle = (): void => {
24
+ if (sbBreakpoint === 'mobile' || sbBreakpoint === 'tablet') {
25
+ sbSetDrawerOpen(!sbDrawerOpen);
26
+ } else {
27
+ sbCycleMode();
28
+ }
29
+ };
30
+
31
+ return (
32
+ <div className="h-11 flex items-center justify-between px-3 bg-[var(--color-bg-primary)] border-b border-[var(--color-border-secondary)] flex-shrink-0 z-10">
33
+ <div className="flex items-center gap-2.5">
34
+ {/* 左栏 toggle */}
35
+ <button
36
+ onClick={handleSidebarToggle}
37
+ title={sbSidebarMode === 'hidden' && !sbDrawerOpen ? '展开侧栏' : '收起侧栏'}
38
+ className={`p-1.5 rounded-lg transition-colors ${
39
+ sidebarActive
40
+ ? 'text-[var(--color-text-accent)] bg-[var(--color-accent)]/10'
41
+ : 'text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)]'
42
+ }`}
43
+ >
44
+ {sbSidebarMode === 'hidden' && !sbDrawerOpen ? (
45
+ <PanelLeftOpen className="w-[18px] h-[18px]" />
46
+ ) : (
47
+ <PanelLeft className="w-[18px] h-[18px]" />
48
+ )}
49
+ </button>
50
+
51
+ <div className="flex items-center gap-1.5">
52
+ <div className="w-6 h-6 rounded-md bg-gradient-to-br from-orange-400 to-rose-500 flex items-center justify-center">
53
+ <span className="text-white text-xs font-bold">C</span>
54
+ </div>
55
+ <span className="text-sm font-semibold text-[var(--color-text-primary)]">Cowork</span>
56
+ </div>
57
+ </div>
58
+
59
+ {/* 右侧 */}
60
+ <div className="flex items-center gap-2">
61
+ {/* 右栏 toggle(Chat 模式下隐藏) */}
62
+ {rightPanelToggleable && (
63
+ <button
64
+ onClick={rpToggle}
65
+ title={rpMode === 'full' ? '收起右侧面板' : '展开右侧面板'}
66
+ className={`p-1.5 rounded-lg transition-colors ${
67
+ rpMode === 'full'
68
+ ? 'text-[var(--color-text-accent)] bg-[var(--color-accent)]/10'
69
+ : 'text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-hover)]'
70
+ }`}
71
+ >
72
+ {rpMode === 'hidden' ? (
73
+ <PanelRightOpen className="w-[18px] h-[18px]" />
74
+ ) : (
75
+ <PanelRight className="w-[18px] h-[18px]" />
76
+ )}
77
+ </button>
78
+ )}
79
+
80
+ <div className="w-7 h-7 rounded-full bg-gradient-to-br from-indigo-400 to-purple-500 flex items-center justify-center text-white text-xs font-semibold">
81
+ SW
82
+ </div>
83
+ </div>
84
+ </div>
85
+ );
86
+ }
@@ -0,0 +1,13 @@
1
+ declare global {
2
+ interface Window {
3
+ __electrobun?: {
4
+ receiveMessageFromBun: (msg: unknown) => void;
5
+ };
6
+ __electrobunBunBridge?: {
7
+ postMessage: (msg: string) => void;
8
+ };
9
+ /** Desktop IPC receiver: Bun calls this via executeJavascript */
10
+ __piAgentIPC?: (msg: unknown) => void;
11
+ }
12
+ }
13
+ export {};
@@ -0,0 +1,123 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { renderHook, act } from '@testing-library/react';
3
+
4
+ const mockSetBreakpoint = vi.fn();
5
+ const mockSetRightMode = vi.fn();
6
+
7
+ vi.mock('../../stores/use-sidebar-store', () => ({
8
+ useSidebarStore: {
9
+ getState: () => ({
10
+ breakpoint: 'desktop',
11
+ _setBreakpoint: mockSetBreakpoint,
12
+ }),
13
+ },
14
+ useRightPanelStore: {
15
+ getState: () => ({
16
+ mode: 'full',
17
+ setMode: mockSetRightMode,
18
+ }),
19
+ },
20
+ }));
21
+
22
+ describe('useBreakpointSync', () => {
23
+ let observerCallback: ResizeObserverCallback;
24
+ let mockObserve: ReturnType<typeof vi.fn>;
25
+ let mockDisconnect: ReturnType<typeof vi.fn>;
26
+
27
+ beforeEach(() => {
28
+ vi.resetModules();
29
+ vi.clearAllMocks();
30
+
31
+ mockObserve = vi.fn();
32
+ mockDisconnect = vi.fn();
33
+
34
+ class MockResizeObserver {
35
+ constructor(cb: ResizeObserverCallback) {
36
+ observerCallback = cb;
37
+ }
38
+ observe = mockObserve;
39
+ disconnect = mockDisconnect;
40
+ unobserve = vi.fn();
41
+ }
42
+ globalThis.ResizeObserver = MockResizeObserver as unknown as typeof ResizeObserver;
43
+ });
44
+
45
+ it('should create ResizeObserver and observe documentElement', async () => {
46
+ const { useBreakpointSync } = await import('../../hooks/use-breakpoint');
47
+ renderHook(() => useBreakpointSync());
48
+ expect(mockObserve).toHaveBeenCalledWith(document.documentElement);
49
+ });
50
+
51
+ it('should set mobile breakpoint for width < 768', async () => {
52
+ const { useBreakpointSync } = await import('../../hooks/use-breakpoint');
53
+ renderHook(() => useBreakpointSync());
54
+
55
+ act(() => {
56
+ observerCallback(
57
+ [
58
+ {
59
+ target: document.documentElement,
60
+ contentRect: { width: 500, height: 800 } as DOMRectReadOnly,
61
+ borderBoxSize: [] as unknown,
62
+ contentBoxSize: [] as unknown,
63
+ },
64
+ ],
65
+ {} as ResizeObserver,
66
+ );
67
+ });
68
+
69
+ await new Promise((r) => setTimeout(r, 200));
70
+ expect(mockSetBreakpoint).toHaveBeenCalledWith('mobile');
71
+ });
72
+
73
+ it('should set tablet breakpoint for 768 <= width < 1024', async () => {
74
+ const { useBreakpointSync } = await import('../../hooks/use-breakpoint');
75
+ renderHook(() => useBreakpointSync());
76
+
77
+ act(() => {
78
+ observerCallback(
79
+ [
80
+ {
81
+ target: document.documentElement,
82
+ contentRect: { width: 900, height: 600 } as DOMRectReadOnly,
83
+ borderBoxSize: [] as unknown,
84
+ contentBoxSize: [] as unknown,
85
+ },
86
+ ],
87
+ {} as ResizeObserver,
88
+ );
89
+ });
90
+
91
+ await new Promise((r) => setTimeout(r, 200));
92
+ expect(mockSetBreakpoint).toHaveBeenCalledWith('tablet');
93
+ });
94
+
95
+ it('should set wide breakpoint for width >= 1280', async () => {
96
+ const { useBreakpointSync } = await import('../../hooks/use-breakpoint');
97
+ renderHook(() => useBreakpointSync());
98
+
99
+ act(() => {
100
+ observerCallback(
101
+ [
102
+ {
103
+ target: document.documentElement,
104
+ contentRect: { width: 1400, height: 900 } as DOMRectReadOnly,
105
+ borderBoxSize: [] as unknown,
106
+ contentBoxSize: [] as unknown,
107
+ },
108
+ ],
109
+ {} as ResizeObserver,
110
+ );
111
+ });
112
+
113
+ await new Promise((r) => setTimeout(r, 200));
114
+ expect(mockSetBreakpoint).toHaveBeenCalledWith('wide');
115
+ });
116
+
117
+ it('should disconnect observer on unmount', async () => {
118
+ const { useBreakpointSync } = await import('../../hooks/use-breakpoint');
119
+ const { unmount } = renderHook(() => useBreakpointSync());
120
+ unmount();
121
+ expect(mockDisconnect).toHaveBeenCalled();
122
+ });
123
+ });
@@ -0,0 +1,53 @@
1
+ import { useEffect } from 'react';
2
+ import { useSidebarStore, useRightPanelStore, type Breakpoint } from '../stores/use-sidebar-store';
3
+
4
+ function getBreakpoint(width: number): Breakpoint {
5
+ if (width < 768) return 'mobile';
6
+ if (width < 1024) return 'tablet';
7
+ if (width < 1280) return 'desktop';
8
+ return 'wide';
9
+ }
10
+
11
+ /**
12
+ * 单一 ResizeObserver,同步 breakpoint 到 store。
13
+ *
14
+ * 仅在断点**变化**时调整面板,不覆盖用户的 sidebarMode/rightPanelMode 手动设置。
15
+ */
16
+ export function useBreakpointSync() {
17
+ useEffect(() => {
18
+ const applyBreakpoint = (bp: Breakpoint): void => {
19
+ const rp = useRightPanelStore.getState();
20
+
21
+ // 移动端/平板自动收起右栏
22
+ if (bp === 'mobile' || bp === 'tablet') {
23
+ if (rp.mode !== 'hidden') rp.setMode('hidden');
24
+ }
25
+ };
26
+
27
+ let timer: ReturnType<typeof setTimeout>;
28
+ const obs = new ResizeObserver((entries) => {
29
+ clearTimeout(timer);
30
+ timer = setTimeout(() => {
31
+ for (const entry of entries) {
32
+ const bp = getBreakpoint(entry.contentRect.width);
33
+ const current = useSidebarStore.getState().breakpoint;
34
+ if (bp !== current) {
35
+ useSidebarStore.getState()._setBreakpoint(bp);
36
+ applyBreakpoint(bp);
37
+ }
38
+ }
39
+ }, 150);
40
+ });
41
+ obs.observe(document.documentElement);
42
+
43
+ // 初始也应用一次
44
+ const initBp = getBreakpoint(document.documentElement.clientWidth);
45
+ useSidebarStore.getState()._setBreakpoint(initBp);
46
+ applyBreakpoint(initBp);
47
+
48
+ return () => {
49
+ clearTimeout(timer);
50
+ obs.disconnect();
51
+ };
52
+ }, []);
53
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * RPC 初始化 Hook — 建立连接 + 加载初始数据
3
+ */
4
+ import { useEffect } from "react";
5
+ import { useConnectionStore } from "../stores/use-connection-store";
6
+ import { useTaskStore } from "../stores/use-task-store";
7
+ import { useContextStore } from "../stores/use-context-store";
8
+ import { useOutputStore } from "../stores/use-output-store";
9
+
10
+ export function useRpcInit() {
11
+ const ready = useConnectionStore((s) => s.ready);
12
+ const initializeConnection = useConnectionStore((s) => s.initializeConnection);
13
+
14
+ // 初始化连接
15
+ useEffect(() => {
16
+ initializeConnection();
17
+ }, [initializeConnection]);
18
+
19
+ // 连接就绪后加载数据
20
+ useEffect(() => {
21
+ if (!ready) return;
22
+ useTaskStore.getState().fetchTasks();
23
+ useContextStore.getState().fetchAll();
24
+ useOutputStore.getState().fetchOutputs();
25
+ }, [ready]);
26
+ }
@@ -0,0 +1,40 @@
1
+ import { useCallback, useRef } from "react";
2
+ import { useSidebarStore } from "../stores/use-sidebar-store";
3
+
4
+ export function useSidebarResize() {
5
+ const sidebarWidth = useSidebarStore((s) => s.sidebarWidth);
6
+ const setSidebarWidth = useSidebarStore((s) => s.setSidebarWidth);
7
+
8
+ const resizingRef = useRef(false);
9
+ const startXRef = useRef(0);
10
+ const startWidthRef = useRef(0);
11
+
12
+ const handleResizeStart = useCallback(
13
+ (e: React.MouseEvent) => {
14
+ e.preventDefault();
15
+ resizingRef.current = true;
16
+ startXRef.current = e.clientX;
17
+ startWidthRef.current = sidebarWidth;
18
+ document.body.style.cursor = "col-resize";
19
+ document.body.style.userSelect = "none";
20
+
21
+ const onMove = (ev: MouseEvent) => {
22
+ if (!resizingRef.current) return;
23
+ const delta = ev.clientX - startXRef.current;
24
+ setSidebarWidth(startWidthRef.current + delta);
25
+ };
26
+ const onUp = () => {
27
+ resizingRef.current = false;
28
+ document.body.style.cursor = "";
29
+ document.body.style.userSelect = "";
30
+ window.removeEventListener("mousemove", onMove);
31
+ window.removeEventListener("mouseup", onUp);
32
+ };
33
+ window.addEventListener("mousemove", onMove);
34
+ window.addEventListener("mouseup", onUp);
35
+ },
36
+ [sidebarWidth, setSidebarWidth]
37
+ );
38
+
39
+ return { sidebarWidth, handleResizeStart };
40
+ }
@@ -0,0 +1,89 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ :root {
6
+ --color-bg-primary: #ffffff;
7
+ --color-bg-secondary: #f9fafb;
8
+ --color-bg-tertiary: #f3f4f6;
9
+ --color-bg-input: #f9fafb;
10
+ --color-bg-hover: #f3f4f6;
11
+ --color-bg-active: #eef2ff;
12
+ --color-bg-sidebar: #f9fafb;
13
+ --color-bg-panel: #f9fafb;
14
+ --color-bg-overlay: rgba(0, 0, 0, 0.4);
15
+
16
+ --color-text-primary: #111827;
17
+ --color-text-secondary: #4b5563;
18
+ --color-text-tertiary: #9ca3af;
19
+ --color-text-placeholder: #6b7280;
20
+ --color-text-accent: #4f46e5;
21
+ --color-text-success: #16a34a;
22
+ --color-text-error: #dc2626;
23
+ --color-text-info: #0891b2;
24
+
25
+ --color-border-primary: #e5e7eb;
26
+ --color-border-secondary: #f3f4f6;
27
+
28
+ --color-accent: #4f46e5;
29
+ --color-accent-hover: #4338ca;
30
+
31
+ --color-badge-bg: #eef2ff;
32
+ --color-badge-text: #3730a3;
33
+
34
+ /* Cowork 专用色 */
35
+ --color-cowork-instruction-bg: #faf7f0;
36
+
37
+ /* 阴影 */
38
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.04);
39
+ --shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.06), 0 1px 2px -1px rgb(0 0 0 / 0.06);
40
+ --shadow-popover: 0 4px 6px -1px rgb(0 0 0 / 0.08), 0 2px 4px -2px rgb(0 0 0 / 0.06);
41
+ }
42
+
43
+ .dark {
44
+ --color-bg-primary: #0f172a;
45
+ --color-bg-secondary: #1e293b;
46
+ --color-bg-tertiary: #334155;
47
+ --color-bg-input: #1e293b;
48
+ --color-bg-hover: #334155;
49
+ --color-bg-active: #312e81;
50
+ --color-bg-sidebar: #1e293b;
51
+ --color-bg-panel: #1e293b;
52
+ --color-bg-overlay: rgba(0, 0, 0, 0.6);
53
+
54
+ --color-text-primary: #f1f5f9;
55
+ --color-text-secondary: #cbd5e1;
56
+ --color-text-tertiary: #64748b;
57
+ --color-text-placeholder: #94a3b8;
58
+ --color-text-accent: #818cf8;
59
+ --color-text-success: #4ade80;
60
+ --color-text-error: #f87171;
61
+ --color-text-info: #22d3ee;
62
+
63
+ --color-border-primary: #334155;
64
+ --color-border-secondary: #1e293b;
65
+
66
+ --color-accent: #6366f1;
67
+ --color-accent-hover: #4f46e5;
68
+
69
+ --color-badge-bg: #312e81;
70
+ --color-badge-text: #a5b4fc;
71
+
72
+ /* Cowork 专用色 */
73
+ --color-cowork-instruction-bg: #292524;
74
+
75
+ /* 阴影 */
76
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.2);
77
+ --shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.3);
78
+ --shadow-popover: 0 4px 6px -1px rgb(0 0 0 / 0.4), 0 2px 4px -2px rgb(0 0 0 / 0.3);
79
+ }
80
+
81
+ /* 侧边栏宽度过渡动画(三态折叠切换时平滑) */
82
+ .sidebar-container {
83
+ transition: width 200ms ease;
84
+ }
85
+
86
+ /* 拖拽 resize 时禁用动画,保证跟手 */
87
+ .sidebar-container.dragging {
88
+ transition: none;
89
+ }
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Browser Agent</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="./main.tsx"></script>
11
+ </body>
12
+ </html>